Commit 60760f6f authored by twanvl's avatar twanvl

Added drop down list box, specialization for color editor; todo: proper...

Added drop down list box, specialization for color editor; todo: proper positioning & sizing, redrawing the arrow button
parent 61126b1f
......@@ -7,6 +7,7 @@
// ----------------------------------------------------------------------------- : Includes
#include <data/field/color.hpp>
#include <script/script.hpp>
DECLARE_TYPEOF_COLLECTION(ColorField::ChoiceP);
......@@ -23,6 +24,13 @@ String ColorField::typeName() const {
return _("color");
}
void ColorField::initDependencies(Context& ctx, const Dependency& dep) const {
Field ::initDependencies(ctx, dep);
script .initDependencies(ctx, dep);
default_script.initDependencies(ctx, dep);
}
IMPLEMENT_REFLECTION(ColorField) {
REFLECT_BASE(Field);
REFLECT(script);
......@@ -67,6 +75,11 @@ String ColorValue::toString() const {
}
return _("<color>");
}
bool ColorValue::update(Context& ctx) {
Value::update(ctx);
return field().default_script.invokeOnDefault(ctx, value)
| field(). script.invokeOn(ctx, value);
}
IMPLEMENT_REFLECTION_NAMELESS(ColorValue) {
REFLECT_NAMELESS(value);
......
......@@ -34,7 +34,9 @@ class ColorField : public Field {
vector<ChoiceP> choices; ///< Color choices available
bool allow_custom; ///< Are colors not in the list of choices allowed?
String default_name; ///< Name of "default" value
virtual void initDependencies(Context&, const Dependency&) const;
private:
DECLARE_REFLECTION();
};
......@@ -77,6 +79,7 @@ class ColorValue : public Value {
Defaultable<Color> value; ///< The value
virtual String toString() const;
virtual bool update(Context&);
private:
DECLARE_REFLECTION();
......
This diff is collapsed.
//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
//| Copyright: (C) 2001 - 2006 Twan van Laarhoven |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
#ifndef HEADER_GUI_DROP_DOWN_LIST
#define HEADER_GUI_DROP_DOWN_LIST
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <util/rotation.hpp>
#include <wx/popupwin.h> // undocumented: wxPopupWindow
class ValueViewer;
// ----------------------------------------------------------------------------- : DropDownList
/// A popup/drop down window displaying a list of items
/** This class is an abstract base for various drop down lists */
class DropDownList : public wxPopupWindow {
public:
/// Create a drop down list, possibly a sub menu
/** the viewer will be notified to redraw its drop down icon */
DropDownList(Window* parent, bool is_submenu = false, ValueViewer* viewer = nullptr);
/// Show the editor
/** if in_place, then shows the list at the position pos */
void show(bool in_place, wxPoint pos);
/// Close the list, optionally send an onSelect event
void hide(bool event);
// --------------------------------------------------- : Parent control
/// Takes all keyboard events from a FieldEditor
void onCharInParent(wxKeyEvent&);
/// Takes a mouse event from the parent, show/hide as appropriate
void onMouseInParent(wxMouseEvent&, bool open_in_place);
protected:
// --------------------------------------------------- : Selection
static const size_t NO_SELECTION = (size_t)-1;
/// Signal that the list is closed and something is selected
virtual void select(size_t selection) = 0;
/// When the list is being opened, what should be selected?
virtual size_t selection() const = 0;
// --------------------------------------------------- : Item information
/// Number of items
virtual size_t itemCount() const = 0;
/// Text of an item
virtual String itemText(size_t item) const = 0;
/// Draw an icon at the specified location
virtual void drawIcon(DC& dc, int x, int y, size_t item, bool selected) const = 0;
/// Is there a line below an item?
virtual bool lineBelow(size_t item) const { return false; }
/// Should the item be highlighted?
virtual bool highlightItem(size_t item) const { return false; }
// An extra menu that pops up from an item, or null if there is no popup menu
virtual DropDownList* popup(size_t item) const { return nullptr; }
// --------------------------------------------------- : Layout
static const int marginW = 1;
static const int marginH = 1;
// may be changed by derived class
int text_offset; ///< Vertical distance between top of item and text
RealSize item_size; ///< Size of an item;
RealSize icon_size; ///< Size of icons;
private:
// --------------------------------------------------- : Data
size_t selected_item; ///< The item that is selected, or NO_SELECTION
bool mouse_down; ///< Is the mouse pressed?
DropDownList* open_sub_menu; ///< The sub menu that is currently shown, if any
DropDownList* parent_menu; ///< The parent menu, only applies to sub menus
ValueViewer* viewer; ///< The parent viewer object (optional)
// --------------------------------------------------- : Events
DECLARE_EVENT_TABLE();
void onPaint(wxPaintEvent&);
void onLeftDown(wxMouseEvent&);
void onLeftUp (wxMouseEvent&);
void onMotion (wxMouseEvent&);
// --------------------------------------------------- : Privates
/// Return the y coordinate of an item
int itemPosition(size_t item) const;
void realHide();
void hideSubMenu();
bool showSubMenu();
bool showSubMenu(size_t item, int y);
void draw(DC& dc);
void drawItem(DC& dc, int y, size_t item);
void redrawArrowOnParent();
};
// ----------------------------------------------------------------------------- : EOF
#endif
......@@ -10,6 +10,7 @@
#include <util/error.hpp>
#include <util/rotation.hpp>
#include <wx/mstream.h>
#include <wx/renderer.h>
#if wxUSE_UXTHEME
#include <wx/msw/uxtheme.h>
......@@ -138,3 +139,23 @@ void draw_control_border(Window* win, DC& dc, const wxRect& rect) {
draw3DBorder(dc, rect.x - 1, rect.y - 1, rect.x + rect.width, rect.y + rect.height);
#endif
}
// portable, based on wxRendererGeneric::DrawComboBoxDropButton
void draw_menu_arrow(Window* win, DC& dc, const wxRect& rect, bool active) {
wxPoint pt[] =
{ wxPoint(0, 0)
, wxPoint(4, 4)
, wxPoint(0, 8)
};
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(wxSystemSettings::GetColour(active ? wxSYS_COLOUR_HIGHLIGHTTEXT : wxSYS_COLOUR_WINDOWTEXT));
dc.DrawPolygon(3, pt, rect.x + rect.width - 6, rect.y + (rect.height - 9) / 2);
}
void draw_drop_down_arrow(Window* win, DC& dc, const wxRect& rect, bool active) {
wxRendererNative& rn = wxRendererNative::GetDefault();
int w = wxSystemSettings::GetMetric(wxSYS_VSCROLL_ARROW_X); // drop down arrow is same size
rn.DrawComboBoxDropButton(win, dc,
wxRect(rect.x + rect.width - w, rect.y, w, rect.height)
, active ? wxCONTROL_PRESSED : 0);
}
......@@ -45,5 +45,10 @@ Image load_resource_image(const String& name);
/** Based on wxRendererXP::DrawComboBoxDropButton */
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);
void draw_drop_down_arrow(Window* win, DC& dc, const wxRect& rect, bool active);
// ----------------------------------------------------------------------------- : EOF
#endif
......@@ -9,3 +9,5 @@
#include <gui/value/choice.hpp>
// ----------------------------------------------------------------------------- :
IMPLEMENT_VALUE_EDITOR(Choice) {}
......@@ -7,5 +7,143 @@
// ----------------------------------------------------------------------------- : Includes
#include <gui/value/color.hpp>
#include <gui/drop_down_list.hpp>
#include <gui/util.hpp>
#include <wx/colordlg.h>
// ----------------------------------------------------------------------------- :
DECLARE_TYPEOF_COLLECTION(ColorField::ChoiceP);
// ----------------------------------------------------------------------------- : DropDownColorList
// A drop down list of color choices
class DropDownColorList : public DropDownList {
public:
DropDownColorList(Window* parent, ColorValueEditor& cve);
protected:
virtual size_t itemCount() const;
virtual bool lineBelow(size_t item) const;
virtual String itemText(size_t item) const;
virtual void drawIcon(DC& dc, int x, int y, size_t item, bool selected) const;
virtual void select(size_t item);
virtual size_t selection() const;
private:
ColorValueEditor& cve;
mutable Color default_color;
inline const ColorField& field() const { return cve.field(); }
// // default, custom item
bool hasDefault() const { return field().default_script; }
bool hasCustom() const { return field().allow_custom; }
};
DropDownColorList::DropDownColorList(Window* parent, ColorValueEditor& cve)
: DropDownList(parent, false, &cve)
, cve(cve)
{
icon_size.width = 25;
if (item_size.height < 16) {
text_offset = (16 - item_size.height) / 2;
item_size.height = 16;
}
}
size_t DropDownColorList::itemCount() const {
return cve.field().choices.size() + hasDefault() + hasCustom();
}
bool DropDownColorList::lineBelow(size_t item) const {
return (item == 0 && hasDefault()) // below default item
|| (item == itemCount() - 2 && hasCustom()); // above custom item
}
String DropDownColorList::itemText(size_t item) const {
if (item == 0 && hasDefault()) {
return field().default_name;
} else if (item == itemCount()-1 && hasCustom()) {
return _("Custom...");
} else {
return field().choices[item - hasDefault()]->name;
}
}
void DropDownColorList::drawIcon(DC& dc, int x, int y, size_t item, bool selected) const {
Color col;
if (item == 0 && hasDefault()) { // default
col = default_color;
} else if (item == itemCount()-1 && hasCustom()) { // custom color
col = cve.value().value();
} else {
col = field().choices[item - hasDefault()]->color;
}
// draw a rectangle with the right color
dc.SetPen(wxSystemSettings::GetColour(selected ? wxSYS_COLOUR_HIGHLIGHTTEXT : wxSYS_COLOUR_WINDOWTEXT));
dc.SetBrush(col);
dc.DrawRectangle(x+1, y+1, icon_size.width-2, item_size.height-2);
}
size_t DropDownColorList::selection() const {
// find selected color
size_t selection = hasCustom() ? itemCount() - 1 : NO_SELECTION;
size_t i = 0;
FOR_EACH_CONST(c, field().choices) {
if (c->color == cve.value().value()) {
selection = i + hasDefault();
break;
}
i++;
}
// has default item?
if (hasDefault() && cve.value().value.isDefault()) {
// default is selected
default_color = cve.value().value();
return 0;
} else if (hasDefault()) {
// evaluate script to find default color
default_color = *field().default_script.invoke(cve.viewer.getContext());
}
return selection;
}
void DropDownColorList::select(size_t item) {
if (item == 0 && hasDefault()) {
cve.change( Defaultable<Color>());
} else if (item == itemCount() - 1 && hasCustom()) {
cve.changeCustom();
} else {
cve.change(field().choices[item - hasDefault()]->color);
}
}
// ----------------------------------------------------------------------------- : ColorValueEditor
IMPLEMENT_VALUE_EDITOR(Color)
, drop_down(new DropDownColorList(&editor(), *this))
{}
void ColorValueEditor::onLeftDown(const RealPoint& pos, wxMouseEvent& ev) {
drop_down->onMouseInParent(ev, !nativeLook());
}
void ColorValueEditor::onChar(wxKeyEvent& ev) {
drop_down->onCharInParent(ev);
}
void ColorValueEditor::onLoseFocus() {
drop_down->hide(false);
}
void ColorValueEditor::drawSelection(RotatedDC& dc) {
if (nativeLook()) {
draw_drop_down_arrow(&editor(), dc.getDC(), style().getRect().grow(1), drop_down->IsShown());
}
}
void ColorValueEditor::determineSize() {
style().height = 20;
}
void ColorValueEditor::change(const Defaultable<Color>& c) {
// getSet().actions.add(new ColorChangeAction(value(), c));
}
void ColorValueEditor::changeCustom() {
Color c = wxGetColourFromUser(0, value().value());
if (c.Ok()) change(c);
}
......@@ -13,12 +13,30 @@
#include <gui/value/editor.hpp>
#include <render/value/color.hpp>
DECLARE_POINTER_TYPE(DropDownList);
// ----------------------------------------------------------------------------- : ColorValueEditor
/// An editor 'control' for editing ColorValues
class ColorValueEditor : public ColorValueViewer, public ValueEditor {
public:
DECLARE_VALUE_EDITOR(Color);
// --------------------------------------------------- : Events
virtual void onLeftDown(const RealPoint& pos, wxMouseEvent& ev);
virtual void onChar(wxKeyEvent& ev);
virtual void onLoseFocus();
virtual void drawSelection(RotatedDC& dc);
virtual void determineSize();
private:
DropDownListP drop_down;
friend class DropDownColorList;
/// Change the color
void change(const Defaultable<Color>& c);
/// Change to a custom color
void changeCustom();
};
// ----------------------------------------------------------------------------- : EOF
......
......@@ -109,9 +109,7 @@ class ValueEditor {
// ----------------------------------------------------------------------------- : Utility
#define DECLARE_VALUE_EDITOR(Type) \
Type##ValueEditor(DataEditor& parent, const Type##StyleP& style) \
: Type##ValueViewer(parent, style) \
{} \
Type##ValueEditor(DataEditor& parent, const Type##StyleP& style); \
virtual ValueEditor* getEditor() { return this; } \
private: \
inline DataEditor& editor() const { \
......@@ -119,5 +117,9 @@ class ValueEditor {
} \
public:
#define IMPLEMENT_VALUE_EDITOR(Type) \
Type##ValueEditor::Type##ValueEditor(DataEditor& parent, const Type##StyleP& style) \
: Type##ValueViewer(parent, style)
// ----------------------------------------------------------------------------- : EOF
#endif
......@@ -9,3 +9,5 @@
#include <gui/value/image.hpp>
// ----------------------------------------------------------------------------- :
IMPLEMENT_VALUE_EDITOR(Image) {}
......@@ -9,3 +9,5 @@
#include <gui/value/multiple_choice.hpp>
// ----------------------------------------------------------------------------- :
IMPLEMENT_VALUE_EDITOR(MultipleChoice) {}
......@@ -9,3 +9,5 @@
#include <gui/value/symbol.hpp>
// ----------------------------------------------------------------------------- :
IMPLEMENT_VALUE_EDITOR(Symbol) {}
......@@ -9,3 +9,5 @@
#include <gui/value/text.hpp>
// ----------------------------------------------------------------------------- :
IMPLEMENT_VALUE_EDITOR(Text) {}
......@@ -574,6 +574,12 @@
<File
RelativePath=".\gui\about_window.hpp">
</File>
<File
RelativePath=".\gui\drop_down_list.cpp">
</File>
<File
RelativePath=".\gui\drop_down_list.hpp">
</File>
<File
RelativePath=".\gui\new_window.cpp">
</File>
......
......@@ -20,6 +20,7 @@ void store(const ScriptValueP& val, double& var) { var = *val; }
void store(const ScriptValueP& val, bool& var) { var = static_cast<int>(*val); }
void store(const ScriptValueP& val, Color& var) { var = *val; }
void store(const ScriptValueP& val, Defaultable<String>& var) { var.assign(*val); }
void store(const ScriptValueP& val, Defaultable<Color>& var) { var.assign(*val); }
// ----------------------------------------------------------------------------- : OptionalScript
......
......@@ -27,6 +27,7 @@ void store(const ScriptValueP& val, double& var);
void store(const ScriptValueP& val, bool& var);
void store(const ScriptValueP& val, Color& var);
void store(const ScriptValueP& val, Defaultable<String>& var);
void store(const ScriptValueP& val, Defaultable<Color>& var);
// ----------------------------------------------------------------------------- : OptionalScript
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment