diff --git a/src/gui/about_window.cpp b/src/gui/about_window.cpp index c9900522..d9ad77b1 100644 --- a/src/gui/about_window.cpp +++ b/src/gui/about_window.cpp @@ -60,14 +60,101 @@ BEGIN_EVENT_TABLE(AboutWindow, wxDialog) END_EVENT_TABLE () +// ----------------------------------------------------------------------------- : Button hover effect + +HoverButtonBase::HoverButtonBase(Window* parent, int id, bool accepts_focus) + : wxControl(parent, id, wxDefaultPosition, wxDefaultSize, wxNO_BORDER ) + , hover(false), focus(false), mouse_down(false), key_down(false) + , accepts_focus(accepts_focus) +{} + +void HoverButtonBase::onMouseEnter(wxMouseEvent&) { + hover = true; + refreshIfNeeded(); + if (!help_text.empty()) set_status_text(this,help_text); +} +void HoverButtonBase::onMouseLeave(wxMouseEvent&) { + hover = false; + refreshIfNeeded(); + if (!help_text.empty()) set_status_text(this,wxEmptyString); +} +void HoverButtonBase::onFocus(wxFocusEvent&) { + focus = true; + refreshIfNeeded(); +} +void HoverButtonBase::onKillFocus(wxFocusEvent&) { + focus = false; + refreshIfNeeded(); +} +void HoverButtonBase::onLeftDown(wxMouseEvent&) { + mouse_down = true; + SetFocus(); + CaptureMouse(); + refreshIfNeeded(); +} +void HoverButtonBase::onLeftUp(wxMouseEvent&) { + if (HasCapture()) ReleaseMouse(); + mouse_down = false; + refreshIfNeeded(); + if (hover) { + onClick(); + } +} +void HoverButtonBase::onKeyDown(wxKeyEvent& ev) { + int code = ev.GetKeyCode(); + if (code == WXK_RETURN || code == WXK_SPACE) { + key_down = true; + refreshIfNeeded(); + } else { + ev.Skip(); + } +} +void HoverButtonBase::onKeyUp(wxKeyEvent& ev) { + int code = ev.GetKeyCode(); + if (code == WXK_RETURN || code == WXK_SPACE) { + key_down = false; + refreshIfNeeded(); + onClick(); + } +} + +void HoverButtonBase::onClick() { + wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED, GetId()); + evt.SetEventObject(this); + ProcessEvent(evt); +} + +bool HoverButtonBase::AcceptsFocus() const { + return wxControl::AcceptsFocus() && accepts_focus; +} + +void HoverButtonBase::refreshIfNeeded() { + Refresh(false); +} + +void HoverButtonBase::onPaint(wxPaintEvent&) { + wxPaintDC dc(this); + draw(dc); +} + +BEGIN_EVENT_TABLE(HoverButtonBase, wxControl) + EVT_ENTER_WINDOW (HoverButtonBase::onMouseEnter) + EVT_LEAVE_WINDOW (HoverButtonBase::onMouseLeave) + EVT_PAINT (HoverButtonBase::onPaint) + EVT_SET_FOCUS (HoverButtonBase::onFocus) + EVT_KILL_FOCUS (HoverButtonBase::onKillFocus) + EVT_LEFT_DOWN (HoverButtonBase::onLeftDown) + EVT_LEFT_UP (HoverButtonBase::onLeftUp) + EVT_KEY_DOWN (HoverButtonBase::onKeyDown) + EVT_KEY_UP (HoverButtonBase::onKeyUp) +END_EVENT_TABLE () + // ----------------------------------------------------------------------------- : Button with image and hover effect HoverButton::HoverButton(Window* parent, int id, const String& name, const Color& background, bool accepts_focus) - : wxControl(parent, id, wxDefaultPosition, wxDefaultSize, wxNO_BORDER ) - , hover(false), focus(false), mouse_down(false), key_down(false) + : HoverButtonBase(parent, id, accepts_focus) , background(background) - , accepts_focus(accepts_focus) , last_drawn(nullptr) { loadBitmaps(name); @@ -84,63 +171,9 @@ void HoverButton::loadBitmaps(const String& name) { Refresh(false); } -void HoverButton::onMouseEnter(wxMouseEvent&) { - hover = true; - refreshIfNeeded(); -} -void HoverButton::onMouseLeave(wxMouseEvent&) { - hover = false; - refreshIfNeeded(); -} -void HoverButton::onFocus(wxFocusEvent&) { - focus = true; - refreshIfNeeded(); -} -void HoverButton::onKillFocus(wxFocusEvent&) { - focus = false; - refreshIfNeeded(); -} -void HoverButton::onLeftDown(wxMouseEvent&) { - mouse_down = true; - SetFocus(); - CaptureMouse(); - refreshIfNeeded(); -} -void HoverButton::onLeftUp(wxMouseEvent&) { - if (HasCapture()) ReleaseMouse(); - if (mouse_down && hover) { - mouse_down = false; - refreshIfNeeded(); - wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED, GetId()); - ProcessEvent(evt); - } - mouse_down = false; -} -void HoverButton::onKeyDown(wxKeyEvent& ev) { - int code = ev.GetKeyCode(); - if (code == WXK_RETURN || code == WXK_SPACE) { - key_down = true; - refreshIfNeeded(); - } else { - ev.Skip(); - } -} -void HoverButton::onKeyUp(wxKeyEvent& ev) { - int code = ev.GetKeyCode(); - if (code == WXK_RETURN || code == WXK_SPACE) { - key_down = false; - refreshIfNeeded(); - wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED, GetId()); - ProcessEvent(evt); - } -} - wxSize HoverButton::DoGetBestSize() const { return wxSize(bg_normal.GetWidth(), bg_normal.GetHeight()); } -bool HoverButton::AcceptsFocus() const { - return wxControl::AcceptsFocus() && accepts_focus; -} const Bitmap* HoverButton::toDraw() const { return (mouse_down && hover) || key_down ? &bg_down @@ -152,10 +185,6 @@ void HoverButton::refreshIfNeeded() { if (last_drawn != toDraw()) Refresh(false); } -void HoverButton::onPaint(wxPaintEvent&) { - wxPaintDC dc(this); - draw(dc); -} void HoverButton::draw(DC& dc) { // clear background (for transparent button images) wxSize ws = GetClientSize(); @@ -169,15 +198,3 @@ void HoverButton::draw(DC& dc) { int HoverButton::drawDelta() const { return (mouse_down && hover) || key_down ? 2 : 0; } - -BEGIN_EVENT_TABLE(HoverButton, wxControl) - EVT_ENTER_WINDOW (HoverButton::onMouseEnter) - EVT_LEAVE_WINDOW (HoverButton::onMouseLeave) - EVT_PAINT (HoverButton::onPaint) - EVT_SET_FOCUS (HoverButton::onFocus) - EVT_KILL_FOCUS (HoverButton::onKillFocus) - EVT_LEFT_DOWN (HoverButton::onLeftDown) - EVT_LEFT_UP (HoverButton::onLeftUp) - EVT_KEY_DOWN (HoverButton::onKeyDown) - EVT_KEY_UP (HoverButton::onKeyUp) -END_EVENT_TABLE () diff --git a/src/gui/about_window.hpp b/src/gui/about_window.hpp index 86785961..a1921169 100644 --- a/src/gui/about_window.hpp +++ b/src/gui/about_window.hpp @@ -28,10 +28,45 @@ class AboutWindow : public wxDialog { void draw(DC& dc); }; +// ----------------------------------------------------------------------------- : Button with hover effect + +/// A button that changes images on mouseenter/leave +class HoverButtonBase : public wxControl { + public: + HoverButtonBase(Window* parent, int id, bool accepts_focus = true); + + virtual bool AcceptsFocus() const; + + virtual void SetHelpText(const String& s) { help_text = s; } + + private: + DECLARE_EVENT_TABLE(); + + const bool accepts_focus; + + void onMouseEnter(wxMouseEvent&); + void onMouseLeave(wxMouseEvent&); + void onFocus (wxFocusEvent& ev); + void onKillFocus (wxFocusEvent& ev); + void onLeftUp (wxMouseEvent&); + void onLeftDown (wxMouseEvent&); + void onKeyDown (wxKeyEvent&); + void onKeyUp (wxKeyEvent&); + void onPaint (wxPaintEvent&); + + protected: + bool hover, focus, mouse_down, key_down; + String help_text; + + virtual void draw(DC& dc) = 0; + virtual void refreshIfNeeded(); + virtual void onClick(); +}; + // ----------------------------------------------------------------------------- : Button with image and hover effect /// A button that changes images on mouseenter/leave -class HoverButton : public wxControl { +class HoverButton : public HoverButtonBase { public: /// Create a HoverButton, name is the resource name of the images to use /** name+"_normal", name+"_hover", name+"_focus", name+"_down" @@ -42,35 +77,19 @@ class HoverButton : public wxControl { /// Load different bitmaps for this button void loadBitmaps(const String& name); - virtual bool AcceptsFocus() const; - private: - DECLARE_EVENT_TABLE(); - String bitmaps; ///< Name of the loaded bitmaps Bitmap bg_normal, bg_hover, bg_focus, bg_down; ///< Bitmaps for the states of the button - bool hover, focus, mouse_down, key_down; Color background; - const bool accepts_focus; - void onMouseEnter(wxMouseEvent&); - void onMouseLeave(wxMouseEvent&); - void onFocus (wxFocusEvent& ev); - void onKillFocus (wxFocusEvent& ev); - void onPaint (wxPaintEvent&); - void onLeftUp (wxMouseEvent&); - void onLeftDown (wxMouseEvent&); - void onKeyDown (wxKeyEvent&); - void onKeyUp (wxKeyEvent&); virtual wxSize DoGetBestSize() const; const Bitmap* last_drawn; const Bitmap* toDraw() const; - void refreshIfNeeded(); - protected: - virtual void draw(DC& dc); int drawDelta() const; + virtual void refreshIfNeeded(); + virtual void draw(DC& dc); }; diff --git a/src/gui/set/cards_panel.cpp b/src/gui/set/cards_panel.cpp index 9f2591ec..2b653208 100644 --- a/src/gui/set/cards_panel.cpp +++ b/src/gui/set/cards_panel.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -274,7 +273,7 @@ void CardsPanel::onUpdateUI(wxUpdateUIEvent& ev) { case ID_COLLAPSE_NOTES: { bool collapse = notes->GetSize().y > 0; collapse_notes->loadBitmaps(collapse ? _("btn_collapse") : _("btn_expand")); - static_cast(GetParent())->setControlStatusText(collapse_notes, collapse ? _HELP_("collapse notes") : _HELP_("expand notes")); + collapse_notes->SetHelpText(collapse ? _HELP_("collapse notes") : _HELP_("expand notes")); break; } case ID_INSERT_SYMBOL: { diff --git a/src/gui/set/random_pack_panel.cpp b/src/gui/set/random_pack_panel.cpp index 23b59c06..ab1291ad 100644 --- a/src/gui/set/random_pack_panel.cpp +++ b/src/gui/set/random_pack_panel.cpp @@ -8,9 +8,10 @@ #include #include -#include #include #include +#include +#include // HoverButtonBase #include #include #include @@ -210,15 +211,77 @@ BEGIN_EVENT_TABLE(PackTotalsPanel, wxPanel) EVT_PAINT(PackTotalsPanel::onPaint) END_EVENT_TABLE() + +// ----------------------------------------------------------------------------- : SelectableLabel + +class SelectableLabel : public HoverButtonBase { + public: + SelectableLabel(wxWindow* parent, int id, const String& label, bool interactive = true) + : HoverButtonBase(parent, id, false) + , label(label) + , interactive(interactive) + , buddy(nullptr) + {} + void draw(DC& dc) { + Color bg = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE); + Color fg = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT); + // clear background + dc.SetPen(*wxTRANSPARENT_PEN); + //dc.SetBrush(mouse_down ? wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT) + // : hover ? lerp(bg,fg,0.1) : bg); + //dc.SetTextForeground(mouse_down ? wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) : fg); + dc.SetBrush(interactive && hover ? lerp(bg,fg,0.1) : bg); + dc.SetTextForeground(fg); + wxSize size = dc.GetSize(); + dc.DrawRectangle(0,0,size.x,size.y); + // draw label + dc.SetFont(*wxNORMAL_FONT); + int w,h; + wxSize s = dc.GetSize(); + dc.GetTextExtent(label,&w,&h); + dc.DrawText(interactive && hover ? label + _("...") : label, 2, (s.y-h)/2); + } + wxSize DoGetBestSize() const { + int w,h; + wxClientDC dc(const_cast(this)); + dc.SetFont(*wxNORMAL_FONT); + dc.GetTextExtent(label,&w,&h); + return wxSize(w+6,h); + } + void setBuddy(wxWindow* buddy) { + this->buddy = buddy; + } + virtual void onClick() { + if (buddy) buddy->SetFocus(); + } + void onDoubleClick(wxMouseEvent&) { + if (interactive) HoverButtonBase::onClick(); + } + private: + String label; + bool interactive; + wxWindow* buddy; + DECLARE_EVENT_TABLE(); +}; + +BEGIN_EVENT_TABLE(SelectableLabel, HoverButtonBase) + EVT_LEFT_DCLICK(SelectableLabel::onDoubleClick) +END_EVENT_TABLE() + // ----------------------------------------------------------------------------- : PackAmountPicker -PackAmountPicker::PackAmountPicker(wxWindow* parent, wxFlexGridSizer* sizer, const PackTypeP& pack) +PackAmountPicker::PackAmountPicker(wxWindow* parent, wxFlexGridSizer* sizer, const PackTypeP& pack, bool active) : pack(pack) - , label(new wxStaticText(parent, wxID_ANY, capitalize_sentence(pack->name))) + , label(new SelectableLabel(parent, ID_PACK_TYPE, capitalize_sentence(pack->name), active)) , value(new wxSpinCtrl(parent, ID_PACK_AMOUNT, _("0"), wxDefaultPosition, wxSize(50,-1))) { - sizer->Add(label, 0, wxALIGN_CENTER_VERTICAL); + label->setBuddy(value); + sizer->Add(label, 1, wxEXPAND | wxALIGN_CENTER_VERTICAL); sizer->Add(value, 0, wxEXPAND | wxALIGN_CENTER); + if (active) { + label->SetHelpText(_("Double click to edit.")); + } + set_help_text(value, _("The number of ") + pack->name + _("s to use.")); } void PackAmountPicker::destroy(wxFlexGridSizer* sizer) { @@ -265,9 +328,10 @@ CustomPackDialog::CustomPackDialog(Window* parent, const SetP& set, const PackTy s->Add(s2, 0, wxEXPAND | wxALL, 8); wxSizer* s3 = new wxBoxSizer(wxHORIZONTAL); wxSizer* s4 = new wxStaticBoxSizer(wxHORIZONTAL, this, _LABEL_("pack selection")); - wxFlexGridSizer* packsSizer = new wxFlexGridSizer(0, 2, 4, 8); + s4->AddSpacer(2); + wxFlexGridSizer* packsSizer = new wxFlexGridSizer(0, 2, 4, 4); packsSizer->AddGrowableCol(0); - s4->Add(packsSizer, 1, wxEXPAND | wxALL & ~wxTOP, 4); + s4->Add(packsSizer, 1, wxEXPAND | wxALL & ~wxTOP & ~wxLEFT, 4); s3->Add(s4, 1, wxEXPAND, 8); wxSizer* s5 = new wxStaticBoxSizer(wxHORIZONTAL, this, _LABEL_("pack totals")); s5->Add(totals, 1, wxEXPAND | wxALL, 4); @@ -277,7 +341,7 @@ CustomPackDialog::CustomPackDialog(Window* parent, const SetP& set, const PackTy // add spin controls FOR_EACH(pack, set->game->pack_types) { if (pack->selectable) continue; // this pack is already selectable from the main UI - PackAmountPicker pick(this, packsSizer, pack); + PackAmountPicker pick(this, packsSizer, pack, false); pickers.push_back(pick); // set value if it is nonzero if (edited_pack) { @@ -358,19 +422,21 @@ void RandomPackPanel::initControls() { #else totals = new PackTotalsPanel(this, wxID_ANY); #endif - static_cast(GetParent())->setControlStatusText(seed_random, _HELP_("random seed")); - static_cast(GetParent())->setControlStatusText(seed_fixed, _HELP_("fixed seed")); - static_cast(GetParent())->setControlStatusText(seed, _HELP_("seed")); + set_help_text(seed_random, _HELP_("random seed")); + set_help_text(seed_fixed, _HELP_("fixed seed")); + set_help_text(seed, _HELP_("seed")); // init sizer wxSizer* s = new wxBoxSizer(wxHORIZONTAL); s->Add(preview, 0, wxRIGHT, 2); wxSizer* s2 = new wxBoxSizer(wxVERTICAL); wxSizer* s3 = new wxBoxSizer(wxHORIZONTAL); - wxSizer* s4 = new wxStaticBoxSizer(wxHORIZONTAL, this, _LABEL_("pack selection")); - packsSizer = new wxFlexGridSizer(0, 2, 4, 8); - packsSizer->AddGrowableCol(0); - //s4->AddSpacer(2); - s4->Add(packsSizer, 1, wxEXPAND | wxALL & ~wxTOP, 4); + wxSizer* s4 = new wxStaticBoxSizer(wxVERTICAL, this, _LABEL_("pack selection")); + wxSizer* s4b = new wxBoxSizer(wxHORIZONTAL); + packsSizer = new wxFlexGridSizer(0, 2, 4, 4); + packsSizer->AddGrowableCol(0); + s4b->Add(packsSizer, 1, wxEXPAND | wxALL & ~wxTOP & ~wxBOTTOM & ~wxLEFT, 4); + s4->Add(s4b, 1, wxEXPAND | wxLEFT, 2); + s4->Add(new wxButton(this, ID_CUSTOM_PACK, _BUTTON_("custom pack")), 0, wxEXPAND | wxALL & ~wxTOP, 4); s3->Add(s4, 1, wxEXPAND, 8); wxSizer* s5 = new wxStaticBoxSizer(wxHORIZONTAL, this, _LABEL_("pack totals")); s5->Add(totals, 1, wxEXPAND | wxALL, 4); @@ -386,7 +452,6 @@ void RandomPackPanel::initControls() { //s6->AddStretchSpacer(); //s6->Add(generate_button, 0, wxTOP | wxALIGN_RIGHT, 8); s6->Add(generate_button, 1, wxTOP | wxEXPAND, 8); - s6->Add(new wxButton(this, ID_CUSTOM_PACK, _BUTTON_("custom pack")), 1, wxTOP | wxEXPAND, 8); s3->Add(s6, 0, wxEXPAND | wxLEFT, 8); s2->Add(s3, 0, wxEXPAND | wxALL & ~wxTOP, 4); s2->Add(card_list, 1, wxEXPAND); @@ -489,7 +554,21 @@ void RandomPackPanel::onCommand(int id) { } case ID_CUSTOM_PACK: { CustomPackDialog dlg(this, set, PackTypeP()); - dlg.ShowModal(); + if (dlg.ShowModal() == wxID_OK) { + // TODO: add pack + } + break; + } + } +} +void RandomPackPanel::onPackTypeClick(wxCommandEvent& ev) { + FOR_EACH(pick,pickers) { + if (pick.label == ev.GetEventObject()) { + // edit this pack type + CustomPackDialog dlg(this, set, pick.pack); + if (dlg.ShowModal() == wxID_OK) { + // TODO: update pack + } break; } } @@ -498,7 +577,9 @@ void RandomPackPanel::onCommand(int id) { // ----------------------------------------------------------------------------- : Generating void RandomPackPanel::updateTotals() { - #if !USE_NEW_PACK_SYSTEM + #if USE_NEW_PACK_SYSTEM + generator.gen.seed((unsigned)last_seed); + #else totals->clear(); #endif int total_packs = 0; @@ -595,6 +676,7 @@ void RandomPackPanel::selectionChoices(ExportCardSelectionChoices& out) { BEGIN_EVENT_TABLE(RandomPackPanel, wxPanel) EVT_CARD_SELECT(wxID_ANY, RandomPackPanel::onCardSelect) + EVT_BUTTON (ID_PACK_TYPE, RandomPackPanel::onPackTypeClick) END_EVENT_TABLE () diff --git a/src/gui/set/random_pack_panel.hpp b/src/gui/set/random_pack_panel.hpp index 27265d12..a0003581 100644 --- a/src/gui/set/random_pack_panel.hpp +++ b/src/gui/set/random_pack_panel.hpp @@ -17,6 +17,7 @@ class CardViewer; class RandomCardList; class PackTotalsPanel; +class SelectableLabel; struct CardSelectEvent; DECLARE_POINTER_TYPE(PackType); @@ -24,12 +25,12 @@ DECLARE_POINTER_TYPE(PackType); // for lists of spin controls struct PackAmountPicker { - PackTypeP pack; - wxStaticText* label; - wxSpinCtrl* value; + PackTypeP pack; + SelectableLabel* label; + wxSpinCtrl* value; PackAmountPicker() {} - PackAmountPicker(wxWindow* parent, wxFlexGridSizer* sizer, const PackTypeP& pack); + PackAmountPicker(wxWindow* parent, wxFlexGridSizer* sizer, const PackTypeP& pack, bool active = true); void destroy(wxFlexGridSizer* sizer); }; @@ -93,6 +94,7 @@ class RandomPackPanel : public SetWindowPanel { void storeSettings(); void onCardSelect(CardSelectEvent& ev); + void onPackTypeClick(wxCommandEvent& ev); public: typedef PackItem PackItem_for_typeof; }; diff --git a/src/gui/set/window.cpp b/src/gui/set/window.cpp index b7d5d81a..400e3859 100644 --- a/src/gui/set/window.cpp +++ b/src/gui/set/window.cpp @@ -245,32 +245,6 @@ void SetWindow::selectPanel(int id) { current_panel->SetFocus(); } -// ----------------------------------------------------------------------------- : Status text for controls - -void SetWindow::setControlStatusText(wxWindow* control, const String& text) { - for (size_t i = 0 ; i < control_status_texts.size() ; ++i) { - if (control_status_texts[i].first == control) { - control_status_texts[i].second = text; - return; - } - } - control_status_texts.push_back(make_pair(control,text)); - control->Connect(wxEVT_ENTER_WINDOW,wxMouseEventHandler(SetWindow::onControlEnter),nullptr,this); - control->Connect(wxEVT_LEAVE_WINDOW,wxMouseEventHandler(SetWindow::onControlLeave),nullptr,this); -} -void SetWindow::onControlEnter(wxMouseEvent& ev) { - for (size_t i = 0 ; i < control_status_texts.size() ; ++i) { - if (control_status_texts[i].first == ev.GetEventObject()) { - SetStatusText(control_status_texts[i].second); - } - } - ev.Skip(); -} -void SetWindow::onControlLeave(wxMouseEvent& ev) { - SetStatusText(wxEmptyString); - ev.Skip(); -} - // ----------------------------------------------------------------------------- : Window managment vector SetWindow::set_windows; diff --git a/src/gui/set/window.hpp b/src/gui/set/window.hpp index 3d4606d2..8eec5b3b 100644 --- a/src/gui/set/window.hpp +++ b/src/gui/set/window.hpp @@ -70,15 +70,6 @@ class SetWindow : public wxFrame, public SetView { /// Switch this window to the new set, or open another window for it (depending on the settings) void switchSet(const SetP& new_set); - // --------------------------------------------------- : Status text for controls - public: - /// Set the status text of a control - void setControlStatusText(wxWindow* control, const String& text); - private: - vector > control_status_texts; - void onControlEnter(wxMouseEvent&); - void onControlLeave(wxMouseEvent&); - // --------------------------------------------------- : Action related protected: /// We want to respond to set changes diff --git a/src/util/window_id.hpp b/src/util/window_id.hpp index fc867949..448f7ce3 100644 --- a/src/util/window_id.hpp +++ b/src/util/window_id.hpp @@ -198,6 +198,7 @@ enum ChildMenuID { // Random pack panel , ID_PACK_AMOUNT = 8111 +, ID_PACK_TYPE , ID_SEED_RANDOM , ID_SEED_FIXED , ID_GENERATE_PACK