mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
42b9c241f3
for consistency with SymbolFontRef
206 lines
8.0 KiB
C++
206 lines
8.0 KiB
C++
//+----------------------------------------------------------------------------+
|
|
//| Description: Magic Set Editor - Program to make card games |
|
|
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
|
|
//| License: GNU General Public License 2 or later (see file COPYING) |
|
|
//+----------------------------------------------------------------------------+
|
|
|
|
#pragma once
|
|
|
|
// ----------------------------------------------------------------------------- : Includes
|
|
|
|
#include <util/prec.hpp>
|
|
#include <util/defaultable.hpp>
|
|
#include <data/field.hpp>
|
|
#include <data/font.hpp>
|
|
#include <gfx/gfx.hpp> // for ImageCombine
|
|
#include <script/scriptable.hpp>
|
|
#include <script/image.hpp>
|
|
#include <wx/image.h>
|
|
#include <mutex>
|
|
|
|
// ----------------------------------------------------------------------------- : ChoiceField
|
|
|
|
DECLARE_POINTER_TYPE(ChoiceField);
|
|
DECLARE_POINTER_TYPE(ChoiceStyle);
|
|
DECLARE_POINTER_TYPE(ChoiceValue);
|
|
|
|
/// A field that contains a list of choices
|
|
class ChoiceField : public Field {
|
|
public:
|
|
ChoiceField();
|
|
DECLARE_FIELD_TYPE(Choice);
|
|
|
|
class Choice;
|
|
typedef intrusive_ptr<Choice> ChoiceP;
|
|
|
|
ChoiceP choices; ///< A choice group of possible choices
|
|
OptionalScript script; ///< Script to apply to all values
|
|
OptionalScript default_script; ///< Script that generates the default value
|
|
String initial; ///< Initial choice of a new value, or ""
|
|
String default_name; ///< Name of "default" value
|
|
map<String,Color> choice_colors; ///< Colors for the various choices (when color_cardlist)
|
|
map<String,Color> choice_colors_cardlist; ///< Colors for the various choices, for in the card list
|
|
bool is_slider = false; ///< Should the UI be displayed as a slider?
|
|
|
|
void initDependencies(Context&, const Dependency&) const override;
|
|
void after_reading(Version ver) override;
|
|
};
|
|
|
|
|
|
enum ChoiceChoiceType {
|
|
CHOICE_TYPE_CHECK,
|
|
CHOICE_TYPE_RADIO
|
|
};
|
|
|
|
/// An item that can be chosen for this field
|
|
class ChoiceField::Choice : public IntrusivePtrBase<ChoiceField::Choice> {
|
|
public:
|
|
Choice();
|
|
Choice(const String& name);
|
|
|
|
String name; ///< Name/value of the item
|
|
String default_name; ///< A default item, if this is a group and default_name.empty() there is no default
|
|
vector<ChoiceP> choices; ///< Choices and sub groups in this group
|
|
bool line_below; ///< Show a line after this item?
|
|
Scriptable<bool> enabled; ///< Is this item enabled?
|
|
ChoiceChoiceType type; ///< How should this item be shown, only for multiple choice fields
|
|
/// First item-id in this group (can be the default item)
|
|
/** Item-ids are consecutive integers, a group uses all ids [first_id..lastId()).
|
|
* The top level group has first_id 0.
|
|
*/
|
|
int first_id;
|
|
|
|
/// Is this a group?
|
|
bool isGroup() const;
|
|
/// Can this Choice itself be chosen?
|
|
/** For a single choice this is always true, for a group only if it has a default choice */
|
|
bool hasDefault() const;
|
|
|
|
/// Initialize the first_id of children
|
|
/** @pre first_id is set
|
|
* Returns lastId()
|
|
*/
|
|
int initIds();
|
|
/// Number of choices in this group (and subgroups), 1 if it is not a group
|
|
/** The default choice also counts */
|
|
int choiceCount() const;
|
|
/// item-id just beyond the end of this group
|
|
int lastId() const;
|
|
|
|
/// item-id of a choice, given the internal name
|
|
/** If the id is not in this group, returns -1 */
|
|
int choiceId(const String& name) const;
|
|
/// Internal name of a choice
|
|
/** The internal name is formed by concatenating the names of all parents, separated by spaces.
|
|
* Returns "" if id is not in this group
|
|
*/
|
|
String choiceName(int id) const;
|
|
/// Formated name of a choice.
|
|
/** Intended for use in menu structures, so it doesn't include the group name for children.
|
|
* Returns "" if id is not in this group.
|
|
*/
|
|
String choiceNameNice(int id) const;
|
|
|
|
DECLARE_REFLECTION();
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------- : ChoiceStyle
|
|
|
|
// How should the menu for a choice look?
|
|
enum ChoicePopupStyle
|
|
{ POPUP_MENU
|
|
, POPUP_DROPDOWN
|
|
, POPUP_DROPDOWN_IN_PLACE
|
|
};
|
|
|
|
String popup_style_to_string(const ChoicePopupStyle&);
|
|
|
|
// How should a choice value be rendered?
|
|
enum ChoiceRenderStyle
|
|
{ RENDER_TEXT = 0x01 // render the name as text
|
|
, RENDER_IMAGE = 0x10 // render an image
|
|
, RENDER_HIDDEN = 0x20 // don't render anything, only have a menu
|
|
, RENDER_CHECKLIST = 0x100 // render as a checklist, intended for multiple choice
|
|
, RENDER_LIST = 0x200 // render as a list of images/text, intended for multiple choice
|
|
, RENDER_BOTH = RENDER_TEXT | RENDER_IMAGE
|
|
, RENDER_HIDDEN_IMAGE = RENDER_HIDDEN | RENDER_IMAGE
|
|
, RENDER_TEXT_CHECKLIST = RENDER_CHECKLIST | RENDER_TEXT
|
|
, RENDER_IMAGE_CHECKLIST = RENDER_CHECKLIST | RENDER_IMAGE
|
|
, RENDER_BOTH_CHECKLIST = RENDER_CHECKLIST | RENDER_BOTH
|
|
, RENDER_TEXT_LIST = RENDER_LIST | RENDER_TEXT
|
|
, RENDER_IMAGE_LIST = RENDER_LIST | RENDER_IMAGE
|
|
, RENDER_BOTH_LIST = RENDER_LIST | RENDER_BOTH
|
|
};
|
|
|
|
String render_style_to_string(const ChoiceRenderStyle&);
|
|
|
|
enum ThumbnailStatus
|
|
{ THUMB_NOT_MADE // there is no image
|
|
, THUMB_OK // image is ok
|
|
, THUMB_CHANGED // there is an image, but it may need to be updated
|
|
};
|
|
|
|
class ChoiceThumbnail {
|
|
public:
|
|
ThumbnailStatus status = THUMB_NOT_MADE;
|
|
wxBitmap bitmap;
|
|
std::recursive_mutex mutex;
|
|
};
|
|
using ChoiceThumbnailLock = std::lock_guard<std::recursive_mutex>;
|
|
|
|
// vector of thumbnails without a copy constructor
|
|
class ChoiceThumbnails : public std::vector<ChoiceThumbnail> {
|
|
public:
|
|
ChoiceThumbnails() {}
|
|
ChoiceThumbnails(ChoiceThumbnails const&) {} // don't copy
|
|
inline void resize(size_t n) {
|
|
// rebuilds the vector in one go, doesn't require move or copy constructor
|
|
std::vector<ChoiceThumbnail>::operator = (std::vector<ChoiceThumbnail>(n));
|
|
}
|
|
};
|
|
|
|
/// The Style for a ChoiceField
|
|
class ChoiceStyle : public Style {
|
|
public:
|
|
ChoiceStyle(const ChoiceFieldP& field);
|
|
DECLARE_STYLE_TYPE(Choice);
|
|
|
|
ChoicePopupStyle popup_style; ///< Style of popups/menus
|
|
ChoiceRenderStyle render_style; ///< Style of rendering
|
|
FontRef font; ///< Font for drawing text (when RENDER_TEXT)
|
|
CachedScriptableImage image; ///< Image to draw (when RENDER_IMAGE)
|
|
map<String,ScriptableImage> choice_images; ///< Images for the various choices (when RENDER_IMAGE)
|
|
bool choice_images_initialized;
|
|
ImageCombine combine; ///< Combining mode for drawing the images
|
|
Alignment alignment; ///< Alignment of images
|
|
ChoiceThumbnails thumbnails; ///< Thumbnails for the choices
|
|
// information from image rendering
|
|
double content_width, content_height; ///< Size of the rendered image/text
|
|
|
|
/// Initialize image from choice_images
|
|
void initImage();
|
|
|
|
int update(Context&) override;
|
|
void initDependencies(Context&, const Dependency&) const override;
|
|
void checkContentDependencies(Context&, const Dependency&) const override;
|
|
void invalidate() override;
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------- : ChoiceValue
|
|
|
|
/// The Value in a ChoiceField
|
|
class ChoiceValue : public Value {
|
|
public:
|
|
/// Create a value for the given field
|
|
/** If initial_first_choice then the first choice should be used in the absence of
|
|
an explicit initial value
|
|
*/
|
|
ChoiceValue(const ChoiceFieldP& field, bool initial_first_choice = true);
|
|
DECLARE_VALUE_TYPE(Choice, Defaultable<String>);
|
|
|
|
ValueType value; /// The name of the selected choice
|
|
|
|
bool update(Context&) override;
|
|
};
|
|
|