diff --git a/src/slic3r/GUI/Widgets/SpinInput.cpp b/src/slic3r/GUI/Widgets/SpinInput.cpp index e54a5db00..036ee9e00 100644 --- a/src/slic3r/GUI/Widgets/SpinInput.cpp +++ b/src/slic3r/GUI/Widgets/SpinInput.cpp @@ -61,18 +61,7 @@ void SpinInput::Create(wxWindow *parent, text_ctrl->SetBackgroundColour(background_color.colorForStates(state_handler.states())); text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states())); text_ctrl->SetInitialSize(text_ctrl->GetBestSize()); - text_ctrl->Bind(wxEVT_SET_FOCUS, [this](auto &e) { - e.SetId(GetId()); - ProcessEventLocally(e); - }); - text_ctrl->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) { - e.SetId(GetId()); - ProcessEventLocally(e); - }); - text_ctrl->Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) { - e.SetId(GetId()); - ProcessEventLocally(e); - }); + state_handler.attach_child(text_ctrl); text_ctrl->Bind(wxEVT_KILL_FOCUS, &SpinInput::onTextLostFocus, this); text_ctrl->Bind(wxEVT_TEXT_ENTER, &SpinInput::onTextEnter, this); text_ctrl->Bind(wxEVT_KEY_DOWN, &SpinInput::keyPressed, this); diff --git a/src/slic3r/GUI/Widgets/StateHandler.cpp b/src/slic3r/GUI/Widgets/StateHandler.cpp index 20e826390..72616ed8f 100644 --- a/src/slic3r/GUI/Widgets/StateHandler.cpp +++ b/src/slic3r/GUI/Widgets/StateHandler.cpp @@ -5,24 +5,44 @@ wxDEFINE_EVENT(EVT_ENABLE_CHANGED, wxCommandEvent); StateHandler::StateHandler(wxWindow * owner) : owner_(owner) { + owner_->PushEventHandler(this); if (owner->IsEnabled()) states_ |= Enabled; if (owner->HasFocus()) states_ |= Focused; } +StateHandler::~StateHandler() { owner_->RemoveEventHandler(this); } + void StateHandler::attach(StateColor const &color) { colors_.push_back(&color); } + void StateHandler::attach(std::vector const & colors) { colors_.insert(colors_.end(), colors.begin(), colors.end()); } +void StateHandler::attach_child(wxWindow *child) +{ + auto ch = new StateHandler(this, child); + children_.emplace_back(ch); + ch->update_binds(); + states2_ |= ch->states(); +} + +void StateHandler::remove_child(wxWindow *child) +{ + children_.erase(std::remove_if(children_.begin(), children_.end(), + [child](auto &c) { return c->owner_ == child; }), children_.end()); + states2_ = 0; + for (auto & c : children_) states2_ |= c->states(); +} + void StateHandler::update_binds() { - int bind_states = 0; + int bind_states = parent_ ? (parent_->bind_states_ & ~Enabled) : 0; for (auto c : colors_) { bind_states |= c->states(); } @@ -35,45 +55,68 @@ void StateHandler::update_binds() int s = states[i]; if (diff & s) { if (bind_states & s) { - owner_->Bind(events[i], &StateHandler::changed, this); + Bind(events[i], &StateHandler::changed, this); if (events2[i]) - owner_->Bind(events2[i], &StateHandler::changed, this); + Bind(events2[i], &StateHandler::changed, this); } else { - owner_->Unbind(events[i], &StateHandler::changed, this); + Unbind(events[i], &StateHandler::changed, this); if (events2[i]) owner_->Unbind(events2[i], &StateHandler::changed, this); } } } bind_states_ = bind_states; - owner_->Refresh(); + for (auto &c : children_) c->update_binds(); } -void StateHandler::changed(wxEvent & event) +StateHandler::StateHandler(StateHandler *parent, wxWindow *owner) + : StateHandler(owner) +{ + states_ &= ~Enabled; + parent_ = parent; +} + +void StateHandler::changed(wxEvent &event) { event.Skip(); wxEventType events[] = {EVT_ENABLE_CHANGED, wxEVT_CHECKBOX, wxEVT_SET_FOCUS, wxEVT_ENTER_WINDOW, wxEVT_LEFT_DOWN}; wxEventType events2[] = {{0}, {0}, wxEVT_KILL_FOCUS, wxEVT_LEAVE_WINDOW, wxEVT_LEFT_UP}; - int old = states2_ | states_; + int old = states_; // some events are from another window (ex: text_ctrl of TextInput), save state in states2_ to avoid conflicts - int & states = event.GetEventObject() == owner_ ? states_ : states2_; for (int i = 0; i < 5; ++i) { if (events2[i]) { if (event.GetEventType() == events[i]) { - states |= 1 << i; + states_ |= 1 << i; break; } else if (event.GetEventType() == events2[i]) { - states &= ~(1 << i); + states_ &= ~(1 << i); break; } } else { if (event.GetEventType() == events[i]) { - states ^= (1 << i); + states_ ^= (1 << i); break; } } } - if (old != (states2_ | states_)) - owner_->Refresh(); + if (old != states_ && (old | states2_) != (states_ | states2_)) { + if (parent_) + parent_->changed(states_ | states2_); + else + owner_->Refresh(); + } +} + +void StateHandler::changed(int) +{ + int old = states2_; + states2_ = 0; + for (auto &c : children_) states2_ |= c->states(); + if (old != states2_ && (old | states_) != (states_ | states2_)) { + if (parent_) + parent_->changed(states_ | states2_); + else + owner_->Refresh(); + } } diff --git a/src/slic3r/GUI/Widgets/StateHandler.hpp b/src/slic3r/GUI/Widgets/StateHandler.hpp index 669ed20e3..9ef155c7d 100644 --- a/src/slic3r/GUI/Widgets/StateHandler.hpp +++ b/src/slic3r/GUI/Widgets/StateHandler.hpp @@ -26,24 +26,36 @@ public: public: StateHandler(wxWindow * owner); + ~StateHandler(); + public: void attach(StateColor const & color); void attach(std::vector const & colors); + void attach_child(wxWindow *child); + + void remove_child(wxWindow *child); + void update_binds(); int states() const { return states_ | states2_; } private: - void changed(wxEvent & event); + StateHandler(StateHandler * parent, wxWindow *owner); + + void changed(wxEvent &event); + + void changed(int state2); private: wxWindow * owner_; std::vector colors_; int bind_states_ = 0; int states_ = 0; - int states2_ = 0; + int states2_ = 0; // from children + std::vector> children_; + StateHandler * parent_ = nullptr; }; #endif // !slic3r_GUI_StateHandler_hpp_ diff --git a/src/slic3r/GUI/Widgets/TextInput.cpp b/src/slic3r/GUI/Widgets/TextInput.cpp index 446948e54..4fa86179e 100644 --- a/src/slic3r/GUI/Widgets/TextInput.cpp +++ b/src/slic3r/GUI/Widgets/TextInput.cpp @@ -60,18 +60,7 @@ void TextInput::Create(wxWindow * parent, text_ctrl->SetInitialSize(text_ctrl->GetBestSize()); text_ctrl->SetBackgroundColour(background_color.colorForStates(state_handler.states())); text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states())); - text_ctrl->Bind(wxEVT_SET_FOCUS, [this](auto &e) { - e.SetId(GetId()); - ProcessEventLocally(e); - }); - text_ctrl->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) { - e.SetId(GetId()); - ProcessEventLocally(e); - }); - text_ctrl->Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) { - e.SetId(GetId()); - ProcessEventLocally(e); - }); + state_handler.attach_child(text_ctrl); text_ctrl->Bind(wxEVT_KILL_FOCUS, [this](auto &e) { OnEdit(); e.SetId(GetId());