diff --git a/src/data/field/choice.cpp b/src/data/field/choice.cpp index 10fbae1d..8d2f5e38 100644 --- a/src/data/field/choice.cpp +++ b/src/data/field/choice.cpp @@ -212,11 +212,14 @@ IMPLEMENT_REFLECTION_ENUM(ChoicePopupStyle) { } IMPLEMENT_REFLECTION_ENUM(ChoiceRenderStyle) { - VALUE_N("text", RENDER_TEXT); - VALUE_N("image", RENDER_IMAGE); - VALUE_N("both", RENDER_BOTH); - VALUE_N("hidden", RENDER_HIDDEN); - VALUE_N("image hidden", RENDER_HIDDEN_IMAGE); + VALUE_N("text", RENDER_TEXT); + VALUE_N("image", RENDER_IMAGE); + VALUE_N("both", RENDER_BOTH); + VALUE_N("hidden", RENDER_HIDDEN); + VALUE_N("image hidden", RENDER_HIDDEN_IMAGE); + VALUE_N("checklist", RENDER_TEXT_CHECKLIST); + VALUE_N("image checklist", RENDER_IMAGE_CHECKLIST); + VALUE_N("both checklist", RENDER_BOTH_CHECKLIST); } IMPLEMENT_REFLECTION(ChoiceStyle) { diff --git a/src/data/field/choice.hpp b/src/data/field/choice.hpp index 082f6f4e..779dcbfd 100644 --- a/src/data/field/choice.hpp +++ b/src/data/field/choice.hpp @@ -103,11 +103,15 @@ enum 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_BOTH = RENDER_TEXT | RENDER_IMAGE -, RENDER_HIDDEN = 0x20 // don't render anything, only have a menu -, RENDER_HIDDEN_IMAGE = RENDER_HIDDEN | RENDER_IMAGE +{ 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_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 }; /// The Style for a ChoiceField @@ -147,9 +151,9 @@ class ChoiceStyle : public Style { /// The Value in a ChoiceField class ChoiceValue : public Value { public: - inline ChoiceValue(const ChoiceFieldP& field) + inline ChoiceValue(const ChoiceFieldP& field, bool initial_empty = false) : Value(field) - , value(field->initial.empty() + , value(field->initial.empty() && !initial_empty ? field->choices->choiceName(0) // first choice : field->initial, true) {} diff --git a/src/data/field/multiple_choice.cpp b/src/data/field/multiple_choice.cpp index 1b2590f5..6e619070 100644 --- a/src/data/field/multiple_choice.cpp +++ b/src/data/field/multiple_choice.cpp @@ -51,3 +51,22 @@ IMPLEMENT_REFLECTION(MultipleChoiceStyle) { IMPLEMENT_REFLECTION_NAMELESS(MultipleChoiceValue) { REFLECT_BASE(ChoiceValue); } + +void MultipleChoiceValue::get(vector& out) const { + // split the value + out.clear(); + bool is_new = true; + FOR_EACH_CONST(c, value()) { + if (c == _(',')) { + is_new = true; + } else if (is_new) { + if (c != _(' ')) { // ignore whitespace after , + is_new = false; + out.push_back(String(1, c)); + } + } else { + assert(!out.empty()); + out.back() += c; + } + } +} diff --git a/src/data/field/multiple_choice.hpp b/src/data/field/multiple_choice.hpp index 7778362f..78905454 100644 --- a/src/data/field/multiple_choice.hpp +++ b/src/data/field/multiple_choice.hpp @@ -57,13 +57,13 @@ class MultipleChoiceStyle : public ChoiceStyle { */ class MultipleChoiceValue : public ChoiceValue { public: - inline MultipleChoiceValue(const MultipleChoiceFieldP& field) : ChoiceValue(field) {} + inline MultipleChoiceValue(const MultipleChoiceFieldP& field) : ChoiceValue(field, true) {} DECLARE_HAS_FIELD(MultipleChoice); // no extra data /// Splits the value, stores the selected choices in the out parameter - void get(vector& out); + void get(vector& out) const; private: DECLARE_REFLECTION(); diff --git a/src/data/game.cpp b/src/data/game.cpp index 663e371a..9f21bc63 100644 --- a/src/data/game.cpp +++ b/src/data/game.cpp @@ -40,6 +40,7 @@ IMPLEMENT_REFLECTION(Game) { REFLECT_BASE(Packaged); REFLECT(init_script); REFLECT(set_fields); + REFLECT(default_set_style); REFLECT(card_fields); REFLECT(statistics_dimensions); REFLECT(statistics_categories); diff --git a/src/data/game.hpp b/src/data/game.hpp index d24af7e1..4282846b 100644 --- a/src/data/game.hpp +++ b/src/data/game.hpp @@ -16,6 +16,7 @@ #include DECLARE_POINTER_TYPE(Field); +DECLARE_POINTER_TYPE(Style); DECLARE_POINTER_TYPE(Game); DECLARE_POINTER_TYPE(StatsDimension); DECLARE_POINTER_TYPE(StatsCategory); @@ -33,9 +34,10 @@ class Game : public Packaged { public: Game(); - OptionalScript init_script; ///< Script of variables available to other scripts in this game - vector set_fields; ///< Fields for set information - vector card_fields; ///< Fields on each card + OptionalScript init_script; ///< Script of variables available to other scripts in this game + vector set_fields; ///< Fields for set information + IndexMap default_set_style; ///< Default style for the set fields, because it is often the same + vector card_fields; ///< Fields on each card vector statistics_dimensions; ///< (Additional) statistics dimensions vector statistics_categories; ///< (Additional) statistics categories @@ -44,9 +46,9 @@ class Game : public Packaged { vector keyword_modes; ///< Modes of keywords vector keywords; ///< Keywords for use in text - Dependencies dependent_scripts_cards; ///< scripts that depend on the card list - Dependencies dependent_scripts_keywords; ///< scripts that depend on the keywords - bool dependencies_initialized; ///< are the script dependencies comming from this game all initialized? + Dependencies dependent_scripts_cards; ///< scripts that depend on the card list + Dependencies dependent_scripts_keywords; ///< scripts that depend on the keywords + bool dependencies_initialized; ///< are the script dependencies comming from this game all initialized? /// Loads the game with a particular name, for example "magic" static GameP byName(const String& name); diff --git a/src/gui/about_window.cpp b/src/gui/about_window.cpp index 912829c8..0d7b2022 100644 --- a/src/gui/about_window.cpp +++ b/src/gui/about_window.cpp @@ -16,7 +16,7 @@ AboutWindow::AboutWindow(Window* parent) : wxDialog(parent, wxID_ANY, _TITLE_("about"), wxDefaultPosition, wxSize(510,340), wxCLIP_CHILDREN | wxDEFAULT_DIALOG_STYLE | wxTAB_TRAVERSAL) , logo (load_resource_image(_("about"))) - , logo2(load_resource_image(_("two"))) + , logo2(load_resource_image(_("two_beta"))) { // init controls wxControl* ok_button = new HoverButton(this, wxID_OK, _("btn_ok")); diff --git a/src/gui/util.cpp b/src/gui/util.cpp index 8178ecea..095719a9 100644 --- a/src/gui/util.cpp +++ b/src/gui/util.cpp @@ -197,3 +197,14 @@ void draw_drop_down_arrow(Window* win, DC& dc, const wxRect& rect, bool active) wxRect(rect.x + rect.width - w, rect.y, w, rect.height) , active ? wxCONTROL_PRESSED : 0); } + +void draw_checkbox(Window* win, DC& dc, const wxRect& rect, bool checked) { + // TODO: Windows version? + // portable + dc.SetPen(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height); + if (checked) { + dc.DrawCheckMark(rect); + } +} diff --git a/src/gui/util.hpp b/src/gui/util.hpp index 8174c3e2..36c9dce4 100644 --- a/src/gui/util.hpp +++ b/src/gui/util.hpp @@ -57,7 +57,11 @@ void draw_control_border(Window* win, DC& dc, const wxRect& rect); /// Draws an arrow for a menu item indicating it has a sub menu void draw_menu_arrow(Window* win, DC& dc, const wxRect& rect, bool active); +/// Draws a drop down arrow corresponding to that used by a combo box void draw_drop_down_arrow(Window* win, DC& dc, const wxRect& rect, bool active); +/// Draws a check box +void draw_checkbox(Window* win, DC& dc, const wxRect& rect, bool checked); + // ----------------------------------------------------------------------------- : EOF #endif diff --git a/src/gui/value/multiple_choice.cpp b/src/gui/value/multiple_choice.cpp index 77482151..8420950a 100644 --- a/src/gui/value/multiple_choice.cpp +++ b/src/gui/value/multiple_choice.cpp @@ -8,6 +8,13 @@ #include -// ----------------------------------------------------------------------------- : +// ----------------------------------------------------------------------------- : MultipleChoiceValueEditor IMPLEMENT_VALUE_EDITOR(MultipleChoice) {} + +void MultipleChoiceValueEditor::determineSize(bool force_fit) { + if (!nativeLook()) return; + // height depends on number of items and item height + int item_count = field().choices->lastId(); + style().height = item_count * 20; +} diff --git a/src/gui/value/multiple_choice.hpp b/src/gui/value/multiple_choice.hpp index 4fa76774..ae8b38a4 100644 --- a/src/gui/value/multiple_choice.hpp +++ b/src/gui/value/multiple_choice.hpp @@ -19,6 +19,8 @@ class MultipleChoiceValueEditor : public MultipleChoiceValueViewer, public ValueEditor { public: DECLARE_VALUE_EDITOR(MultipleChoice); + + virtual void determineSize(bool force_fit); }; // ----------------------------------------------------------------------------- : EOF diff --git a/src/render/value/choice.cpp b/src/render/value/choice.cpp index 0f104d07..678f8960 100644 --- a/src/render/value/choice.cpp +++ b/src/render/value/choice.cpp @@ -45,13 +45,13 @@ void ChoiceValueViewer::draw(RotatedDC& dc) { align_in_rect(style().alignment, RealSize(i->image.GetWidth(), i->image.GetHeight()), style().getRect()), i->combine == COMBINE_NORMAL ? style().combine : i->combine ); - margin = i->image.GetWidth() + 1; + margin = dc.trInvS(i->image.GetWidth()) + 1; } } } if (style().render_style & RENDER_TEXT) { // draw text - dc.DrawText(capitalize(value().value()), + dc.DrawText(tr(*viewer.stylesheet, value().value(), capitalize(value().value())), align_in_rect(ALIGN_MIDDLE_LEFT, RealSize(0, dc.GetCharHeight()), style().getRect()) + RealSize(margin, 0) ); } diff --git a/src/render/value/multiple_choice.cpp b/src/render/value/multiple_choice.cpp index a055a30f..b97eb252 100644 --- a/src/render/value/multiple_choice.cpp +++ b/src/render/value/multiple_choice.cpp @@ -7,9 +7,68 @@ // ----------------------------------------------------------------------------- : Includes #include +#include +#include +#include + +DECLARE_TYPEOF_COLLECTION(String); // ----------------------------------------------------------------------------- : MultipleChoiceValueViewer void MultipleChoiceValueViewer::draw(RotatedDC& dc) { - // TODO + drawFieldBorder(dc); + if (style().render_style & RENDER_HIDDEN) return; + RealPoint pos = style().getPos(); + // selected choices + vector selected; + value().get(selected); + if (style().render_style & RENDER_CHECKLIST) { + // render all choices + int end = field().choices->lastId(); + vector::iterator select_it = selected.begin(); + for (int i = 0 ; i < end ; ++i) { + String choice = field().choices->choiceName(i); + bool active = select_it != selected.end() && *select_it == choice; + if (active) select_it++; + drawChoice(dc, pos, choice, active); + } + } else { + // render only selected choices + FOR_EACH(choice, selected) { + drawChoice(dc, pos, choice); + } + } +} + +void MultipleChoiceValueViewer::drawChoice(RotatedDC& dc, RealPoint& pos, const String& choice, bool active) { + double margin = 0, height = 0; + if (nativeLook() && (style().render_style & RENDER_CHECKLIST)) { + height = 10; + margin = 11; + wxRect rect = dc.tr(RealRect(pos,RealSize(10,10))); + draw_checkbox(nullptr, dc.getDC(), rect, active); // TODO + } + if (style().render_style & RENDER_IMAGE) { + map::iterator it = style().choice_images.find(cannocial_name_form(choice)); + if (it != style().choice_images.end()) { + ScriptImageP i = it->second.update(viewer.getContext(), *viewer.stylesheet, 0, 0); + if (i) { + // TODO : alignment? + dc.DrawImage(i->image, pos, i->combine == COMBINE_NORMAL ? style().combine : i->combine); + margin += dc.trInvS(i->image.GetWidth()) + 1; + height = max(height, dc.trInvS(i->image.GetHeight())); + } + } + } + if (style().render_style & RENDER_TEXT) { + // draw text + // TODO: alignment + dc.DrawText(tr(*viewer.stylesheet, choice, capitalize(choice)), pos + RealSize(margin, 0)); + // TODO: determine size + } + if (style().direction == HORIZONTAL) { + pos.x += margin + style().spacing; + } else { + pos.y += height + style().spacing; + } } diff --git a/src/render/value/multiple_choice.hpp b/src/render/value/multiple_choice.hpp index 429b7c7a..8de59a49 100644 --- a/src/render/value/multiple_choice.hpp +++ b/src/render/value/multiple_choice.hpp @@ -21,6 +21,8 @@ class MultipleChoiceValueViewer : public ValueViewer { DECLARE_VALUE_VIEWER(MultipleChoice) : ValueViewer(parent,style) {} virtual void draw(RotatedDC& dc); + private: + void drawChoice(RotatedDC& dc, RealPoint& pos, const String& choice, bool active = true); }; // ----------------------------------------------------------------------------- : EOF