diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index fad3fa35ff..4e0906ab8d 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -125,7 +125,7 @@ #include "ParamsDialog.hpp" #include "Widgets/Label.hpp" #include "Widgets/RoundedRectangle.hpp" -#include "Widgets/RadioBox.hpp" +#include "Widgets/RadioGroup.hpp" #include "Widgets/CheckBox.hpp" #include "Widgets/Button.hpp" @@ -10744,23 +10744,12 @@ bool Plater::preview_zip_archive(const boost::filesystem::path& archive_path) return true; } -class RadioBox; -class RadioSelector -{ -public: - int m_select_id; - int m_groupid; - RadioBox *m_radiobox; -}; -WX_DECLARE_LIST(RadioSelector, RadioSelectorList); - #define PROJECT_DROP_DIALOG_SELECT_PLANE_SIZE wxSize(FromDIP(350), FromDIP(120)) class ProjectDropDialog : public DPIDialog { private: wxColour m_def_color = wxColour(255, 255, 255); - RadioSelectorList m_radio_group; int m_action{1}; bool m_remember_choice{false}; @@ -10773,12 +10762,9 @@ public: wxStaticText *m_fname_s; StaticBox * m_panel_select; - void select_radio(int index); - void on_select_radio(wxMouseEvent &event); void on_select_ok(wxCommandEvent &event); void on_select_cancel(wxCommandEvent &event); - int get_select_radio(int groupid); int get_action() const { return m_action; } void set_action(int index) { m_action = index; } @@ -10796,6 +10782,7 @@ ProjectDropDialog::ProjectDropDialog(const std::string &filename) wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) + , m_action(2) { // def setting SetBackgroundColour(m_def_color); @@ -10818,7 +10805,7 @@ ProjectDropDialog::ProjectDropDialog(const std::string &filename) m_fname_title = new wxStaticText(this, wxID_ANY, _L("Please select an action"), wxDefaultPosition, wxDefaultSize, 0); m_fname_title->Wrap(-1); - m_fname_title->SetFont(::Label::Body_13); + m_fname_title->SetFont(::Label::Body_14); m_fname_title->SetForegroundColour(wxColour(107, 107, 107)); m_fname_title->SetBackgroundColour(wxColour(255, 255, 255)); @@ -10826,7 +10813,7 @@ ProjectDropDialog::ProjectDropDialog(const std::string &filename) m_sizer_fline->Add(0, 0, 0, wxEXPAND | wxLEFT, 5); m_fname_f = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0); - m_fname_f->SetFont(::Label::Head_13); + m_fname_f->SetFont(::Label::Head_14); m_fname_f->Wrap(-1); m_fname_f->SetForegroundColour(wxColour(38, 46, 48)); @@ -10835,43 +10822,25 @@ ProjectDropDialog::ProjectDropDialog(const std::string &filename) m_sizer_name->Add(m_sizer_fline, 1, wxEXPAND, 0); m_fname_s = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0); - m_fname_s->SetFont(::Label::Head_13); + m_fname_s->SetFont(::Label::Head_14); m_fname_s->Wrap(-1); m_fname_s->SetForegroundColour(wxColour(38, 46, 48)); m_sizer_name->Add(m_fname_s, 1, wxALL, 0); - m_sizer_main->Add(m_sizer_name, 1, wxEXPAND | wxLEFT | wxRIGHT, 40); + m_sizer_main->Add(m_sizer_name, 1, wxEXPAND | wxLEFT | wxRIGHT, 20); - m_sizer_main->Add(0, 0, 0, wxEXPAND | wxTOP, 5); + auto radio_group = new RadioGroup(this, { + _L("Open as project"), // 0 + _L("Import geometry only") // 1 + }, wxVERTICAL); + radio_group->SetMinSize(wxSize(FromDIP(300),-1)); + radio_group->SetSelection(get_action() - 1); + radio_group->Bind(wxEVT_COMMAND_RADIOBOX_SELECTED, [this, radio_group](wxCommandEvent &e) { + set_action(radio_group->GetSelection() + 1); + }); - m_panel_select = new StaticBox(this, wxID_ANY, wxDefaultPosition, PROJECT_DROP_DIALOG_SELECT_PLANE_SIZE); - StateColor box_colour(std::pair(wxColour("#F8F8F8"), StateColor::Normal)); - StateColor box_border_colour(std::pair(wxColour(*wxWHITE), StateColor::Normal)); - - m_panel_select->SetBackgroundColor(box_colour); - m_panel_select->SetBorderColor(box_border_colour); - m_panel_select->SetCornerRadius(5); - - wxBoxSizer *m_sizer_select_h = new wxBoxSizer(wxHORIZONTAL); - - wxBoxSizer *m_sizer_select_v = new wxBoxSizer(wxVERTICAL); - - - auto select_f = create_item_radiobox(_L("Open as project"), m_panel_select, 1, 0); - auto select_s = create_item_radiobox(_L("Import geometry only"), m_panel_select, 2, 0); - //auto select_t = create_item_radiobox(_L("Import presets only"), m_panel_select,3, 0); - - m_sizer_select_v->Add(select_f, 0, wxEXPAND, 5); - m_sizer_select_v->Add(select_s, 0, wxEXPAND, 5); - //m_sizer_select_v->Add(select_t, 0, wxEXPAND, 5); - select_radio(2); - - m_sizer_select_h->Add(m_sizer_select_v, 0, wxALIGN_CENTER | wxLEFT, 22); - - m_panel_select->SetSizer(m_sizer_select_h); - m_panel_select->Layout(); - m_sizer_main->Add(m_panel_select, 0, wxEXPAND | wxLEFT | wxRIGHT, 40); + m_sizer_main->Add(radio_group, 0, wxEXPAND | wxLEFT | wxRIGHT, 20); m_sizer_main->Add(0, 0, 0, wxEXPAND | wxTOP, 10); @@ -10923,34 +10892,6 @@ ProjectDropDialog::ProjectDropDialog(const std::string &filename) wxGetApp().UpdateDlgDarkUI(this); } -wxBoxSizer *ProjectDropDialog ::create_item_radiobox(wxString title, wxWindow *parent, int select_id, int groupid) -{ - wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL); - auto radiobox = new RadioBox(parent); - - radiobox->SetBackgroundColour(wxColour(248,248,248)); - sizer->Add(radiobox, 0, wxALL, 5); - sizer->Add(0, 0, 0, wxEXPAND | wxLEFT, 5); - auto text = new wxStaticText(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, 0); - text->Wrap(-1); - text->SetForegroundColour(wxColour(107, 107, 107)); - text->SetBackgroundColour(wxColour(248,248,248)); - sizer->Add(text, 0, wxALL, 5); - - radiobox->Bind(wxEVT_LEFT_DOWN, &ProjectDropDialog::on_select_radio, this); - text->Bind(wxEVT_LEFT_DOWN, [this, radiobox](auto &e) { - e.SetId(radiobox->GetId()); - on_select_radio(e); - }); - - RadioSelector *rs = new RadioSelector; - rs->m_groupid = groupid; - rs->m_radiobox = radiobox; - rs->m_select_id = select_id; - m_radio_group.Append(rs); - - return sizer; -} wxBoxSizer *ProjectDropDialog::create_remember_checkbox(wxString title, wxWindow *parent, wxString tooltip) { wxBoxSizer *m_sizer_checkbox = new wxBoxSizer(wxHORIZONTAL); @@ -10977,63 +10918,6 @@ wxBoxSizer *ProjectDropDialog::create_remember_checkbox(wxString title, wxWindow return m_sizer_checkbox; } -void ProjectDropDialog::select_radio(int index) -{ - m_action = index; - RadioSelectorList::compatibility_iterator it = m_radio_group.GetFirst(); - auto groupid = 0; - - while (it) { - RadioSelector *rs = it->GetData(); - if (rs->m_select_id == index) groupid = rs->m_groupid; - it = it->GetNext(); - } - - it = m_radio_group.GetFirst(); - while (it) { - RadioSelector *rs = it->GetData(); - if (rs->m_groupid == groupid && rs->m_select_id == index) rs->m_radiobox->SetValue(true); - if (rs->m_groupid == groupid && rs->m_select_id != index) rs->m_radiobox->SetValue(false); - it = it->GetNext(); - } -} - -int ProjectDropDialog::get_select_radio(int groupid) -{ - RadioSelectorList::compatibility_iterator it = m_radio_group.GetFirst(); - while (it) { - RadioSelector *rs = it->GetData(); - if (rs->m_groupid == groupid && rs->m_radiobox->GetValue()) { return rs->m_select_id; } - it = it->GetNext(); - } - - return 0; -} -void ProjectDropDialog::on_select_radio(wxMouseEvent &event) -{ - RadioSelectorList::compatibility_iterator it = m_radio_group.GetFirst(); - auto groupid = 0; - - while (it) { - RadioSelector *rs = it->GetData(); - if (rs->m_radiobox->GetId() == event.GetId()) groupid = rs->m_groupid; - it = it->GetNext(); - } - - it = m_radio_group.GetFirst(); - while (it) { - RadioSelector *rs = it->GetData(); - if (rs->m_groupid == groupid && rs->m_radiobox->GetId() == event.GetId()) { - set_action(rs->m_select_id); - rs->m_radiobox->SetValue(true); - } - - - if (rs->m_groupid == groupid && rs->m_radiobox->GetId() != event.GetId()) rs->m_radiobox->SetValue(false); - it = it->GetNext(); - } -} - void ProjectDropDialog::on_select_ok(wxCommandEvent &event) { if (m_remember_choice) { diff --git a/src/slic3r/GUI/SavePresetDialog.cpp b/src/slic3r/GUI/SavePresetDialog.cpp index 0918226d5b..2a7b29d7c5 100644 --- a/src/slic3r/GUI/SavePresetDialog.cpp +++ b/src/slic3r/GUI/SavePresetDialog.cpp @@ -9,8 +9,6 @@ #include #include #include -// BBS: add radio button for project embedded preset logic -#include #include "libslic3r/PresetBundle.hpp" @@ -56,7 +54,7 @@ SavePresetDialog::Item::Item(Preset::Type type, const std::string &suffix, wxBox } wxStaticText *label_top = new wxStaticText(m_parent, wxID_ANY, from_u8((boost::format(_utf8(L("Save %s as"))) % into_u8(tab->title())).str())); - label_top->SetFont(::Label::Body_13); + label_top->SetFont(::Label::Body_14); label_top->SetForegroundColour(wxColour(38,46,48)); @@ -105,70 +103,20 @@ SavePresetDialog::Item::Item(Preset::Type type, const std::string &suffix, wxBox if (m_type == Preset::TYPE_PRINTER) m_parent->add_info_for_edit_ph_printer(sizer); - // BBS: add project embedded presets logic - wxBoxSizer *radio_sizer = new wxBoxSizer(wxHORIZONTAL); + // ORCA RadioGroup + m_radio_group = new RadioGroup(m_parent, { + _L("User Preset"), // 0 + _L("Preset Inside Project") // 1 + }, wxVERTICAL); - wxBoxSizer *m_sizer_left = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(m_radio_group, 0, wxEXPAND | wxTOP | wxLEFT, BORDER_W); - m_sizer_left->Add(0, 0, 0, wxLEFT, 25); - - m_radio_user = new RadioBox(parent); - m_radio_user->SetBackgroundColour(SAVE_PRESET_DIALOG_DEF_COLOUR); - - m_sizer_left->Add(m_radio_user, 0, wxALIGN_CENTER, 0); - - m_sizer_left->Add(0, 0, 0, wxLEFT, 10); - - auto m_left_text = new wxStaticText(parent, wxID_ANY, _L("User Preset"), wxDefaultPosition, wxDefaultSize, 0); - m_left_text->Wrap(-1); - m_left_text->SetFont(::Label::Body_13); - m_left_text->SetForegroundColour(wxColour(107,107,107)); - m_sizer_left->Add(m_left_text, 0, wxALIGN_CENTER, 0); - - radio_sizer->Add(m_sizer_left, 1, wxALIGN_CENTER, 5); - - wxBoxSizer *m_sizer_right = new wxBoxSizer(wxHORIZONTAL); - - m_sizer_right->Add(0, 0, 0, wxLEFT, 15); - - m_radio_project = new RadioBox(parent); - m_radio_project->SetBackgroundColour(SAVE_PRESET_DIALOG_DEF_COLOUR); - - m_sizer_right->Add(m_radio_project, 0, wxALIGN_CENTER, 0); - - m_sizer_right->Add(0, 0, 0, wxLEFT, 10); - - auto m_right_text = new wxStaticText(parent, wxID_ANY, _L("Preset Inside Project"), wxDefaultPosition, wxDefaultSize, 0); - m_right_text->SetForegroundColour(wxColour(107,107,107)); - m_right_text->SetFont(::Label::Body_13); - m_right_text->Wrap(-1); - m_sizer_right->Add(m_right_text, 0, wxALIGN_CENTER, 0); - - radio_sizer->Add(m_sizer_right, 1, wxEXPAND, 5); - - sizer->Add(radio_sizer, 0, wxEXPAND | wxTOP, BORDER_W); - - auto radio_clicked = [this](wxMouseEvent &e) { - if (m_radio_user->GetId() == e.GetId()) { - m_radio_user->SetValue(true); - m_radio_project->SetValue(false); - m_save_to_project = false; - } - - if (m_radio_project->GetId() == e.GetId()) { - m_radio_user->SetValue(false); - m_radio_project->SetValue(true); - m_save_to_project = true; - } - }; - m_radio_user->Bind(wxEVT_LEFT_DOWN, radio_clicked); - m_radio_project->Bind(wxEVT_LEFT_DOWN, radio_clicked); + m_radio_group->Bind(wxEVT_COMMAND_RADIOBOX_SELECTED, [this](wxCommandEvent &e) { + m_save_to_project = m_radio_group->GetSelection() == 1; + }); bool is_project_embedded = m_presets->get_edited_preset().is_project_embedded; - if (is_project_embedded) - m_radio_project->SetValue(true); - else - m_radio_user->SetValue(true); + m_radio_group->SetSelection(is_project_embedded ? 1 : 0); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", create item: type" << Preset::get_type_string(m_type) << ", preset " << m_preset_name << ", is_project_embedded = " << is_project_embedded; @@ -240,22 +188,18 @@ void SavePresetDialog::Item::update() } // BBS: add project embedded presets logic - if (existing) { + if (existing) { // ORCA RadioGroup if (existing->is_project_embedded) { - m_radio_project->SetValue(true); + m_radio_group->SetSelection(1); m_save_to_project = true; } else { - m_radio_user->SetValue(true); + m_radio_group->SetSelection(0); m_save_to_project = false; } - m_radio_user->Disable(); - m_radio_project->Disable(); + m_radio_group->Disable(); } else { - m_radio_user->Enable(); - m_radio_project->Enable(); - - m_radio_user->SetValue(!m_save_to_project); - m_radio_project->SetValue(m_save_to_project); + m_radio_group->Enable(); + m_radio_group->SetSelection(m_save_to_project ? 1 : 0); } m_valid_label->SetLabel(info_line); diff --git a/src/slic3r/GUI/SavePresetDialog.hpp b/src/slic3r/GUI/SavePresetDialog.hpp index 748635a6ee..618bfb49c8 100644 --- a/src/slic3r/GUI/SavePresetDialog.hpp +++ b/src/slic3r/GUI/SavePresetDialog.hpp @@ -6,7 +6,7 @@ #include "libslic3r/Preset.hpp" #include "wxExtensions.hpp" #include "GUI_Utils.hpp" -#include "Widgets/RadioBox.hpp" +#include "Widgets/RadioGroup.hpp" #include "Widgets/Button.hpp" #include "Widgets/RoundedRectangle.hpp" #include "Widgets/Label.hpp" @@ -69,9 +69,8 @@ class SavePresetDialog : public DPIDialog PresetCollection* m_presets {nullptr}; //BBS: add project embedded preset relate logic - RadioBox * m_radio_user{nullptr}; - RadioBox * m_radio_project{nullptr}; bool m_save_to_project {false}; + RadioGroup* m_radio_group; // ORCA void update(); }; diff --git a/src/slic3r/GUI/Widgets/Button.cpp b/src/slic3r/GUI/Widgets/Button.cpp index 8ebddd95b6..f0ba5e967d 100644 --- a/src/slic3r/GUI/Widgets/Button.cpp +++ b/src/slic3r/GUI/Widgets/Button.cpp @@ -133,7 +133,10 @@ bool Button::Enable(bool enable) return result; } -void Button::SetCanFocus(bool canFocus) { this->canFocus = canFocus; } +void Button::SetCanFocus(bool canFocus) { + StaticBox::SetCanFocus(canFocus); + this->canFocus = canFocus; +} void Button::SetValue(bool state) { diff --git a/src/slic3r/GUI/Widgets/LabeledStaticBox.cpp b/src/slic3r/GUI/Widgets/LabeledStaticBox.cpp index e87f98a98b..6e2357cf43 100644 --- a/src/slic3r/GUI/Widgets/LabeledStaticBox.cpp +++ b/src/slic3r/GUI/Widgets/LabeledStaticBox.cpp @@ -75,6 +75,7 @@ bool LabeledStaticBox::Create( SetForegroundColour( text_color.colorForStates(state_handler.states())); SetBorderColor( border_color.colorForStates(state_handler.states())); SetCanFocus(false); + DisableFocusFromKeyboard(); return true; } diff --git a/src/slic3r/GUI/Widgets/RadioGroup.cpp b/src/slic3r/GUI/Widgets/RadioGroup.cpp index 879481bb63..a5f63a9ac0 100644 --- a/src/slic3r/GUI/Widgets/RadioGroup.cpp +++ b/src/slic3r/GUI/Widgets/RadioGroup.cpp @@ -8,14 +8,15 @@ RadioGroup::RadioGroup( long direction, int row_col_limit ) - : wxPanel(parent, wxID_ANY) + : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNO_BORDER) // ensure wxTAB_TRAVERSAL not applied by default , m_on( this, "radio_on" , 18) , m_off( this, "radio_off" , 18) , m_on_hover( this, "radio_on_hover" , 18) , m_off_hover(this, "radio_off_hover", 18) - , m_disabled( this, "radio_off_hover", 18) + , m_disabled( this, "radio_disabled" , 18) , m_selectedIndex(0) , m_focused(false) + , m_enabled(true) { Create(parent, labels, direction, row_col_limit); } @@ -28,102 +29,103 @@ void RadioGroup::Create( ) { m_labels = labels; + m_item_count = m_labels.size(); + auto bg = parent->GetBackgroundColour(); this->SetBackgroundColour(bg); + + m_text_color = StateColor( + std::pair(wxColour("#6B6A6A"), (int)StateColor::Disabled), + std::pair(wxColour("#363636"), (int)StateColor::Enabled) + ); + + m_focus_color = StateColor( + std::pair(bg , (int)StateColor::NotFocused), + std::pair(wxColour("#009688"), (int)StateColor::Focused) + ); + auto bmp_size = m_on.GetBmpSize(); - int item_count = m_labels.size(); - int item_limit = row_col_limit < 0 ? 1 : row_col_limit > item_count ? item_count : row_col_limit; - int count = (int(item_count / item_limit) + (item_count % item_limit)); + int item_limit = row_col_limit < 0 ? 1 : row_col_limit > m_item_count ? m_item_count : row_col_limit; + int count = (int(m_item_count / item_limit) + (m_item_count % item_limit)); int rows = (direction & wxHORIZONTAL) ? item_limit : count; int cols = (direction & wxHORIZONTAL) ? count : item_limit; wxFlexGridSizer* f_sizer = new wxFlexGridSizer(rows, cols, 0, 0); SetDoubleBuffered(true); - AcceptsFocusFromKeyboard(); - Bind(wxEVT_SET_FOCUS ,([this](wxFocusEvent e) {m_focused = true ;Refresh(); e.Skip();})); - Bind(wxEVT_KILL_FOCUS,([this](wxFocusEvent e) {m_focused = false;Refresh(); e.Skip();})); - Bind(wxEVT_PAINT,([this](wxPaintEvent e) { - wxPaintDC dc(this); - dc.Clear(); - dc.SetPen(wxPen(StateColor::darkModeColorFor(wxColour("#009688")), 1, wxPENSTYLE_SOLID)); - dc.SetBrush(*wxTRANSPARENT_BRUSH); - dc.DrawRectangle( - m_focused ? wxRect( - m_radioButtons[GetSelection()]->GetRect().GetTopLeft() - wxPoint(1, 3), - m_labelButtons[GetSelection()]->GetRect().GetBottomRight() + wxPoint(4, 1) - ) : wxRect(0,0,0,0) - ); - if (m_focused) // Required to take focus again since Refresh causing lossing focus - SetFocus(); - })); - // DPIDialog's uses wxEVT_CHAR_HOOK - Bind(wxEVT_CHAR_HOOK, ([this](wxKeyEvent&e){ - int k = e.GetKeyCode(); - bool is_next = (k == WXK_DOWN || k == WXK_RIGHT); - bool is_prev = (k == WXK_LEFT || k == WXK_UP); - if(m_focused){ - if (is_next) SelectNext(); - else if (is_prev) SelectPrevious(); - e.Skip(!(is_next || is_prev)); - }else{ - e.Skip(); - } - })); - - for (int i = 0; i < item_count; ++i){ + for (int i = 0; i < m_item_count; ++i){ auto rb = new wxStaticBitmap(this, wxID_ANY, m_off.bmp(), wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxNO_BORDER); m_radioButtons.push_back(rb); - rb->Bind(wxEVT_LEFT_DOWN ,([this, i](wxMouseEvent e) {OnClick(i) ; e.Skip();})); + rb->Bind(wxEVT_LEFT_DOWN ,([this, i](wxMouseEvent e) {SetSelection(i, true) ; e.Skip();})); rb->Bind(wxEVT_ENTER_WINDOW,([this, i](wxMouseEvent e) {SetRadioIcon(i, true) ; e.Skip();})); rb->Bind(wxEVT_LEAVE_WINDOW,([this, i](wxMouseEvent e) { // prevent removing hover effect while switching between button and its text - if(wxFindWindowAtPoint(wxGetMousePosition())->GetId() != m_labelButtons[i]->GetId()) + auto win = wxFindWindowAtPoint(wxGetMousePosition()); + if(!win || win->GetId() != m_labelButtons[i]->GetId()) SetRadioIcon(i, false); e.Skip(); })); - auto tx = new wxStaticText(this, wxID_ANY, " " + m_labels[i], wxDefaultPosition, wxDefaultSize); - tx->SetForegroundColour(wxColour("#363636")); + auto tx = new Button(this, m_labels[i]); + if(i != 0) // one focusable control must exist. wxPanel starts taking focus if there is no focusable control + tx->SetCanFocus(false); + tx->SetPaddingSize(FromDIP(wxSize(5,2))); + tx->SetBackgroundColor(bg); + tx->SetCornerRadius(0); + tx->SetBorderWidth(FromDIP(1)); + tx->SetBorderColor(m_focus_color); tx->SetFont(Label::Body_14); - m_labelButtons.push_back(tx); - tx->Bind(wxEVT_LEFT_DOWN ,([this, i](wxMouseEvent e) {OnClick(i) ; e.Skip();})); - tx->Bind(wxEVT_ENTER_WINDOW,([this, i](wxMouseEvent e) {SetRadioIcon(i, true) ; e.Skip();})); - tx->Bind(wxEVT_LEAVE_WINDOW,([this, i](wxMouseEvent e) { + tx->SetTextColor(m_text_color); + tx->Bind(wxEVT_BUTTON ,([this, i](wxCommandEvent e) {SetSelection(i, true) ; e.Skip();})); + tx->Bind(wxEVT_ENTER_WINDOW,([this, i](wxMouseEvent e) {SetRadioIcon(i, true) ; e.Skip();})); + tx->Bind(wxEVT_LEAVE_WINDOW,([this, i](wxMouseEvent e) { // prevent removing hover effect while switching between button and its text - if(wxFindWindowAtPoint(wxGetMousePosition())->GetId() != m_radioButtons[i]->GetId()) + auto win = wxFindWindowAtPoint(wxGetMousePosition()); + if(!win || win->GetId() != m_radioButtons[i]->GetId()) SetRadioIcon(i, false); e.Skip(); })); + tx->Bind(wxEVT_CHAR_HOOK, ([this, tx](wxKeyEvent&e){ + if(tx->HasFocus()){ + int k = e.GetKeyCode(); + bool is_next = (k == WXK_DOWN || k == WXK_RIGHT); + bool is_prev = (k == WXK_LEFT || k == WXK_UP); + if (is_next) SelectNext(); + else if (is_prev) SelectPrevious(); + e.Skip(!(is_next || is_prev)); + }else{ + e.Skip(); + } + })); + m_labelButtons.push_back(tx); wxBoxSizer* radio_sizer = new wxBoxSizer(wxHORIZONTAL); - radio_sizer->Add(rb, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 1); - radio_sizer->Add(tx, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, this->FromDIP(15)); + radio_sizer->Add(rb, 0, wxALIGN_CENTER_VERTICAL); + radio_sizer->Add(tx, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, this->FromDIP(10)); f_sizer->Add(radio_sizer, 0, wxTOP | wxBOTTOM, this->FromDIP(4)); } SetSelection(m_selectedIndex); SetSizer(f_sizer); } -void RadioGroup::OnClick(int i) +void RadioGroup::SetSelection(int index, bool focus) { - m_focused = true; // prevents 2 time refresh - SetSelection(i); -} - -void RadioGroup::SetSelection(int index) -{ - if (index >= 0 && index < static_cast(m_labels.size())){ + if (index >= 0 && index < m_item_count){ + int prev_index = m_selectedIndex; + if(index != prev_index){ // prevent no focusable item on first creation. wxPanel starts taking focus if there is no focusable control + m_labelButtons[index]->SetCanFocus(true); + m_labelButtons[prev_index]->SetCanFocus(false); + } + if(focus) + m_labelButtons[index]->SetFocus(); m_selectedIndex = index; - for (size_t i = 0; i < m_labels.size(); ++i) - SetRadioIcon(i, HasFocus() && i == m_selectedIndex); + for (size_t i = 0; i < m_item_count; ++i) + SetRadioIcon(i, m_labelButtons[index]->HasFocus() && i == m_selectedIndex); wxCommandEvent evt(wxEVT_COMMAND_RADIOBOX_SELECTED, GetId()); evt.SetInt(index); evt.SetString(m_labels[index]); GetEventHandler()->ProcessEvent(evt); - - Refresh(); // refresh on every change } } @@ -134,16 +136,47 @@ int RadioGroup::GetSelection() void RadioGroup::SelectNext(bool focus) { - SetSelection(m_selectedIndex + 1 > (m_radioButtons.size() - 1) ? 0 : m_selectedIndex + 1); + SetSelection(m_selectedIndex + 1 > (m_radioButtons.size() - 1) ? 0 : m_selectedIndex + 1, focus); } void RadioGroup::SelectPrevious(bool focus) { - SetSelection(m_selectedIndex - 1 < 0 ? (m_radioButtons.size() - 1) : m_selectedIndex - 1); + SetSelection(m_selectedIndex - 1 < 0 ? (m_radioButtons.size() - 1) : m_selectedIndex - 1, focus); } void RadioGroup::SetRadioIcon(int i, bool hover) { - auto icon = m_selectedIndex == i ? (hover ? m_on_hover : m_on) : (hover ? m_off_hover : m_off); + auto icon = !m_enabled ? m_disabled : m_selectedIndex == i ? (hover ? m_on_hover : m_on) : (hover ? m_off_hover : m_off); m_radioButtons[i]->SetBitmap(icon.bmp()); +} + +bool RadioGroup::Enable(bool enable) +{ + m_enabled = enable; + bool result = wxPanel::Enable(enable); + + if (result) { + for (size_t i = 0; i < m_item_count; ++i){ + SetRadioIcon(i, false); + m_labelButtons[i]->Enable(enable); // normally disabling parent should do this but not + } + + wxCommandEvent e(EVT_ENABLE_CHANGED); + e.SetEventObject(this); + GetEventHandler()->ProcessEvent(e); + } + + return result; +}; + +// is focused + +bool RadioGroup::Disable() {return RadioGroup::Enable(false);}; + +bool RadioGroup::IsEnabled(){return m_enabled;}; + +void RadioGroup::SetRadioTooltip(int i, wxString tooltip) +{ + m_radioButtons[i]->SetToolTip(tooltip); + m_labelButtons[i]->SetToolTip(tooltip); } \ No newline at end of file diff --git a/src/slic3r/GUI/Widgets/RadioGroup.hpp b/src/slic3r/GUI/Widgets/RadioGroup.hpp index f3e14aa3aa..93dc1df73f 100644 --- a/src/slic3r/GUI/Widgets/RadioGroup.hpp +++ b/src/slic3r/GUI/Widgets/RadioGroup.hpp @@ -10,6 +10,8 @@ #include #include +#include "Button.hpp" + class RadioGroup : public wxPanel { @@ -32,32 +34,41 @@ public: int GetSelection(); - void SetSelection(int index); + void SetSelection(int index, bool focus = false); void SelectNext(bool focus = true); void SelectPrevious(bool focus = true); + bool Enable(bool enable = true) override; + + bool IsEnabled(); + + bool Disable(); + + void SetRadioTooltip(int i, wxString tooltip); + private: std::vector m_labels; std::vector m_radioButtons; - std::vector m_labelButtons; + std::vector m_labelButtons; int m_selectedIndex; + int m_item_count; bool m_focused; + bool m_enabled; + + StateColor m_focus_color; + StateColor m_text_color; + ScalableBitmap m_on; ScalableBitmap m_off; ScalableBitmap m_on_hover; ScalableBitmap m_off_hover; ScalableBitmap m_disabled; - void OnClick(int i); - - void UpdateFocus(bool focus); - void SetRadioIcon(int i, bool hover); - void OnKeyDown(wxKeyEvent& e); }; -#endif // !slic3r_GUI_RADIOGROUP_hpp_ +#endif // !slic3r_GUI_RADIOGROUP_hpp_ \ No newline at end of file