ENH: StateHandler as wxEvtHandler and attach child
Change-Id: I1183b97983907f297888d81809be60e3016ae305
This commit is contained in:
parent
2c99301fe6
commit
b96ca57fde
|
@ -61,18 +61,7 @@ void SpinInput::Create(wxWindow *parent,
|
||||||
text_ctrl->SetBackgroundColour(background_color.colorForStates(state_handler.states()));
|
text_ctrl->SetBackgroundColour(background_color.colorForStates(state_handler.states()));
|
||||||
text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states()));
|
text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states()));
|
||||||
text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
|
text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
|
||||||
text_ctrl->Bind(wxEVT_SET_FOCUS, [this](auto &e) {
|
state_handler.attach_child(text_ctrl);
|
||||||
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);
|
|
||||||
});
|
|
||||||
text_ctrl->Bind(wxEVT_KILL_FOCUS, &SpinInput::onTextLostFocus, this);
|
text_ctrl->Bind(wxEVT_KILL_FOCUS, &SpinInput::onTextLostFocus, this);
|
||||||
text_ctrl->Bind(wxEVT_TEXT_ENTER, &SpinInput::onTextEnter, this);
|
text_ctrl->Bind(wxEVT_TEXT_ENTER, &SpinInput::onTextEnter, this);
|
||||||
text_ctrl->Bind(wxEVT_KEY_DOWN, &SpinInput::keyPressed, this);
|
text_ctrl->Bind(wxEVT_KEY_DOWN, &SpinInput::keyPressed, this);
|
||||||
|
|
|
@ -5,24 +5,44 @@ wxDEFINE_EVENT(EVT_ENABLE_CHANGED, wxCommandEvent);
|
||||||
StateHandler::StateHandler(wxWindow * owner)
|
StateHandler::StateHandler(wxWindow * owner)
|
||||||
: owner_(owner)
|
: owner_(owner)
|
||||||
{
|
{
|
||||||
|
owner_->PushEventHandler(this);
|
||||||
if (owner->IsEnabled())
|
if (owner->IsEnabled())
|
||||||
states_ |= Enabled;
|
states_ |= Enabled;
|
||||||
if (owner->HasFocus())
|
if (owner->HasFocus())
|
||||||
states_ |= Focused;
|
states_ |= Focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StateHandler::~StateHandler() { owner_->RemoveEventHandler(this); }
|
||||||
|
|
||||||
void StateHandler::attach(StateColor const &color)
|
void StateHandler::attach(StateColor const &color)
|
||||||
{
|
{
|
||||||
colors_.push_back(&color);
|
colors_.push_back(&color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StateHandler::attach(std::vector<StateColor const *> const & colors)
|
void StateHandler::attach(std::vector<StateColor const *> const & colors)
|
||||||
{
|
{
|
||||||
colors_.insert(colors_.end(), colors.begin(), colors.end());
|
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()
|
void StateHandler::update_binds()
|
||||||
{
|
{
|
||||||
int bind_states = 0;
|
int bind_states = parent_ ? (parent_->bind_states_ & ~Enabled) : 0;
|
||||||
for (auto c : colors_) {
|
for (auto c : colors_) {
|
||||||
bind_states |= c->states();
|
bind_states |= c->states();
|
||||||
}
|
}
|
||||||
|
@ -35,45 +55,68 @@ void StateHandler::update_binds()
|
||||||
int s = states[i];
|
int s = states[i];
|
||||||
if (diff & s) {
|
if (diff & s) {
|
||||||
if (bind_states & s) {
|
if (bind_states & s) {
|
||||||
owner_->Bind(events[i], &StateHandler::changed, this);
|
Bind(events[i], &StateHandler::changed, this);
|
||||||
if (events2[i])
|
if (events2[i])
|
||||||
owner_->Bind(events2[i], &StateHandler::changed, this);
|
Bind(events2[i], &StateHandler::changed, this);
|
||||||
} else {
|
} else {
|
||||||
owner_->Unbind(events[i], &StateHandler::changed, this);
|
Unbind(events[i], &StateHandler::changed, this);
|
||||||
if (events2[i])
|
if (events2[i])
|
||||||
owner_->Unbind(events2[i], &StateHandler::changed, this);
|
owner_->Unbind(events2[i], &StateHandler::changed, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bind_states_ = bind_states;
|
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();
|
event.Skip();
|
||||||
wxEventType events[] = {EVT_ENABLE_CHANGED, wxEVT_CHECKBOX, wxEVT_SET_FOCUS, wxEVT_ENTER_WINDOW, wxEVT_LEFT_DOWN};
|
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};
|
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
|
// 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) {
|
for (int i = 0; i < 5; ++i) {
|
||||||
if (events2[i]) {
|
if (events2[i]) {
|
||||||
if (event.GetEventType() == events[i]) {
|
if (event.GetEventType() == events[i]) {
|
||||||
states |= 1 << i;
|
states_ |= 1 << i;
|
||||||
break;
|
break;
|
||||||
} else if (event.GetEventType() == events2[i]) {
|
} else if (event.GetEventType() == events2[i]) {
|
||||||
states &= ~(1 << i);
|
states_ &= ~(1 << i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (event.GetEventType() == events[i]) {
|
if (event.GetEventType() == events[i]) {
|
||||||
states ^= (1 << i);
|
states_ ^= (1 << i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (old != (states2_ | states_))
|
if (old != states_ && (old | states2_) != (states_ | states2_)) {
|
||||||
owner_->Refresh();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,24 +26,36 @@ public:
|
||||||
public:
|
public:
|
||||||
StateHandler(wxWindow * owner);
|
StateHandler(wxWindow * owner);
|
||||||
|
|
||||||
|
~StateHandler();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void attach(StateColor const & color);
|
void attach(StateColor const & color);
|
||||||
|
|
||||||
void attach(std::vector<StateColor const *> const & colors);
|
void attach(std::vector<StateColor const *> const & colors);
|
||||||
|
|
||||||
|
void attach_child(wxWindow *child);
|
||||||
|
|
||||||
|
void remove_child(wxWindow *child);
|
||||||
|
|
||||||
void update_binds();
|
void update_binds();
|
||||||
|
|
||||||
int states() const { return states_ | states2_; }
|
int states() const { return states_ | states2_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void changed(wxEvent & event);
|
StateHandler(StateHandler * parent, wxWindow *owner);
|
||||||
|
|
||||||
|
void changed(wxEvent &event);
|
||||||
|
|
||||||
|
void changed(int state2);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxWindow * owner_;
|
wxWindow * owner_;
|
||||||
std::vector<StateColor const *> colors_;
|
std::vector<StateColor const *> colors_;
|
||||||
int bind_states_ = 0;
|
int bind_states_ = 0;
|
||||||
int states_ = 0;
|
int states_ = 0;
|
||||||
int states2_ = 0;
|
int states2_ = 0; // from children
|
||||||
|
std::vector<std::unique_ptr<StateHandler>> children_;
|
||||||
|
StateHandler * parent_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !slic3r_GUI_StateHandler_hpp_
|
#endif // !slic3r_GUI_StateHandler_hpp_
|
||||||
|
|
|
@ -60,18 +60,7 @@ void TextInput::Create(wxWindow * parent,
|
||||||
text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
|
text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
|
||||||
text_ctrl->SetBackgroundColour(background_color.colorForStates(state_handler.states()));
|
text_ctrl->SetBackgroundColour(background_color.colorForStates(state_handler.states()));
|
||||||
text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states()));
|
text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states()));
|
||||||
text_ctrl->Bind(wxEVT_SET_FOCUS, [this](auto &e) {
|
state_handler.attach_child(text_ctrl);
|
||||||
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);
|
|
||||||
});
|
|
||||||
text_ctrl->Bind(wxEVT_KILL_FOCUS, [this](auto &e) {
|
text_ctrl->Bind(wxEVT_KILL_FOCUS, [this](auto &e) {
|
||||||
OnEdit();
|
OnEdit();
|
||||||
e.SetId(GetId());
|
e.SetId(GetId());
|
||||||
|
|
Loading…
Reference in New Issue