diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 074609659..df2812102 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -25,6 +25,8 @@ our $last_config; our $VALUE_CHANGE_EVENT = Wx::NewEventType; # 2) To inform about a preset selection change or a "modified" status change. our $PRESETS_CHANGED_EVENT = Wx::NewEventType; +# 3) To inform about a change of object selection +our $OBJECT_SELECTION_CHANGED_EVENT = Wx::NewEventType; sub new { my ($class, %params) = @_; @@ -113,7 +115,9 @@ sub _init_tabpanel { }); if (!$self->{no_plater}) { - $panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel), L("Plater")); + $panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel, + event_object_selection_changed => $OBJECT_SELECTION_CHANGED_EVENT, + ), L("Plater")); if (!$self->{no_controller}) { $panel->AddPage($self->{controller} = Slic3r::GUI::Controller->new($panel), L("Controller")); } @@ -168,6 +172,20 @@ sub _init_tabpanel { } } }); + + # The following event is emited by the C++ Tab implementation on config value change. + EVT_COMMAND($self, -1, $OBJECT_SELECTION_CHANGED_EVENT, sub { + my ($self, $event) = @_; + my $obj_idx = $event->GetInt; + print "obj_idx = $obj_idx\n"; + $self->{plater}->select_object($obj_idx < 0 ? undef: $obj_idx); + + $self->{plater}->{canvas}->Refresh; + $self->{plater}->{canvas3D}->deselect_volumes if $self->{canvas3D}; + $self->{plater}->{canvas3D}->Render if $self->{canvas3D}; + }); + + Slic3r::GUI::create_preset_tabs($self->{no_controller}, $VALUE_CHANGE_EVENT, $PRESETS_CHANGED_EVENT); $self->{options_tabs} = {}; for my $tab_name (qw(print filament printer)) { diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 7f0dbedb0..94975e60b 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -47,7 +47,7 @@ use constant PROCESS_DELAY => 0.5 * 1000; # milliseconds my $PreventListEvents = 0; sub new { - my ($class, $parent) = @_; + my ($class, $parent, %params) = @_; my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); $self->{config} = Slic3r::Config::new_from_defaults_keys([qw( bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width variable_layer_height @@ -55,6 +55,10 @@ sub new { nozzle_diameter single_extruder_multi_material wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width wipe_tower_rotation_angle extruder_colour filament_colour max_print_height )]); + + # store input params + $self->{event_object_selection_changed} = $params{event_object_selection_changed}; + # C++ Slic3r::Model with Perl extensions in Slic3r/Model.pm $self->{model} = Slic3r::Model->new; # C++ Slic3r::Print with Perl extensions in Slic3r/Print.pm @@ -411,8 +415,16 @@ sub new { my $frequently_changed_parameters_sizer = Wx::BoxSizer->new(wxVERTICAL); Slic3r::GUI::add_frequently_changed_parameters($self->{right_panel}, $frequently_changed_parameters_sizer, $presets); + my $expert_mode_part_sizer = Wx::BoxSizer->new(wxVERTICAL); - Slic3r::GUI::add_expert_mode_part($self->{right_panel}, $expert_mode_part_sizer); + print "Plater event = ".$self->{event_object_selection_changed}."\n"; + Slic3r::GUI::add_expert_mode_part($self->{right_panel}, $expert_mode_part_sizer, $self->{event_object_selection_changed}); + if ($expert_mode_part_sizer->IsShown(2)==1) + { + $expert_mode_part_sizer->Layout; + $expert_mode_part_sizer->Show(2, 0); # ? Why doesn't work + $self->{right_panel}->Layout; + } my $object_info_sizer; { @@ -535,7 +547,7 @@ sub new { } }; # Show the box initially, let it be shown after the slicing is finished. - $self->{"print_info_box_show"}->(0); + #$self->{"print_info_box_show"}->(0); my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL); $hsizer->Add($self->{preview_notebook}, 1, wxEXPAND | wxTOP, 1); @@ -2095,6 +2107,7 @@ sub selection_changed { sub select_object { my ($self, $obj_idx) = @_; + print "obj_idx = $obj_idx\n"; # remove current selection foreach my $o (0..$#{$self->{objects}}) { $PreventListEvents = 1; @@ -2104,7 +2117,7 @@ sub select_object { } # Unselect all objects in the list on c++ side - Slic3r::GUI::unselect_objects(); + #Slic3r::GUI::unselect_objects(); if (defined $obj_idx) { $self->{objects}->[$obj_idx]->selected(1); @@ -2118,6 +2131,7 @@ sub select_object { Slic3r::GUI::select_current_object($obj_idx); } else { # TODO: deselect all in list + Slic3r::GUI::unselect_objects(); } $self->selection_changed(1); } @@ -2125,6 +2139,7 @@ sub select_object { sub selected_object { my ($self) = @_; my $obj_idx = first { $self->{objects}[$_]->selected } 0..$#{ $self->{objects} }; + print "selected obj_idx = $obj_idx\n"; return defined $obj_idx ? ($obj_idx, $self->{objects}[$obj_idx]) : undef; } diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 4a8fbb6e7..9f119a956 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -141,6 +141,7 @@ wxSizer *m_sizer_part_buttons = nullptr; wxDataViewCtrl *m_objects_ctrl = nullptr; MyObjectTreeModel *m_objects_model = nullptr; wxCollapsiblePane *m_collpane_settings = nullptr; +int m_event_object_selection_changed = 0; wxFont g_small_font; wxFont g_bold_font; @@ -895,11 +896,24 @@ wxBoxSizer* content_objects_list(wxWindow *win) wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE); m_objects_ctrl->AppendColumn(column02); - m_objects_ctrl->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [](wxEvent& evt) + m_objects_ctrl->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [](wxEvent& event) { wxWindowUpdateLocker noUpdates(g_right_panel); auto item = m_objects_ctrl->GetSelection(); - if (!item) return; + int obj_idx = -1; + if (!item) + unselect_objects(); + else + obj_idx = m_objects_model->GetIdByItem(item); + + if (m_event_object_selection_changed > 0) { + wxCommandEvent event(m_event_object_selection_changed); + event.SetInt(obj_idx); + g_wxMainFrame->ProcessWindowEvent(event); + } + + if (obj_idx < 0) return; + // m_objects_ctrl->SetSize(m_objects_ctrl->GetBestSize()); // TODO override GetBestSize(), than use it auto show_obj_sizer = m_objects_model->GetParent(item) == wxDataViewItem(0); m_sizer_object_buttons->Show(show_obj_sizer); @@ -908,6 +922,14 @@ wxBoxSizer* content_objects_list(wxWindow *win) m_collpane_settings->Show(true); }); + m_objects_ctrl->Bind(wxEVT_KEY_DOWN, [](wxKeyEvent& event) + { + if (event.GetKeyCode() == WXK_TAB) + m_objects_ctrl->Navigate(event.ShiftDown() ? wxNavigationKeyEvent::IsBackward : wxNavigationKeyEvent::IsForward); + else + event.Skip(); + }); + return objects_sz; } @@ -1088,15 +1110,29 @@ void set_object_scale(int idx, int scale) void unselect_objects() { m_objects_ctrl->UnselectAll(); + if (m_sizer_object_buttons->IsShown(1)) + m_sizer_object_buttons->Show(false); + if (m_sizer_part_buttons->IsShown(1)) + m_sizer_part_buttons->Show(false); + if (m_collpane_settings->IsShown()) + m_collpane_settings->Show(false); } void select_current_object(int idx) { + m_objects_ctrl->UnselectAll(); + if (idx < 0) return; m_objects_ctrl->Select(m_objects_model->GetItemById(idx)); + + if (!m_sizer_object_buttons->IsShown(1)) + m_sizer_object_buttons->Show(true); + if (!m_collpane_settings->IsShown()) + m_collpane_settings->Show(true); } -void add_expert_mode_part(wxWindow* parent, wxBoxSizer* sizer) +void add_expert_mode_part(wxWindow* parent, wxBoxSizer* sizer, int event_object_selection_changed) { + m_event_object_selection_changed = event_object_selection_changed; wxWindowUpdateLocker noUpdates(parent); auto btn_grid_sizer = new wxGridSizer(1, 3, 2, 2); @@ -1135,8 +1171,7 @@ void add_expert_mode_part(wxWindow* parent, wxBoxSizer* sizer) })); // *** Object/Part Settings *** - m_collpane_settings = add_collapsible_pane(parent, sizer, "Settings:", content_settings); - m_collpane_settings->Hide(); // ? TODO why doesn't work? + m_collpane_settings = add_collapsible_pane(parent, sizer, "Settings", content_settings); add_btn->Bind(wxEVT_BUTTON, [](wxEvent& ) { diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp index 6cb8ac1f0..4c01622f0 100644 --- a/xs/src/slic3r/GUI/GUI.hpp +++ b/xs/src/slic3r/GUI/GUI.hpp @@ -190,7 +190,7 @@ void unselect_objects(); // Select current object in the list on c++ side void select_current_object(int idx); -void add_expert_mode_part(wxWindow* parent, wxBoxSizer* sizer); +void add_expert_mode_part(wxWindow* parent, wxBoxSizer* sizer, int event_object_selection_changed); void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer); // Update view mode according to selected menu void update_mode(); diff --git a/xs/src/slic3r/GUI/wxExtensions.cpp b/xs/src/slic3r/GUI/wxExtensions.cpp index 351c631db..cf232847b 100644 --- a/xs/src/slic3r/GUI/wxExtensions.cpp +++ b/xs/src/slic3r/GUI/wxExtensions.cpp @@ -452,6 +452,18 @@ wxDataViewItem MyObjectTreeModel::GetItemById(int obj_idx) } +int MyObjectTreeModel::GetIdByItem(wxDataViewItem& item) +{ + wxASSERT(item.IsOk()); + + MyObjectTreeModelNode *node = (MyObjectTreeModelNode*)item.GetID(); + auto it = find(m_objects.begin(), m_objects.end(), node); + if (it == m_objects.end()) + return -1; + + return it - m_objects.begin(); +} + wxString MyObjectTreeModel::GetName(const wxDataViewItem &item) const { MyObjectTreeModelNode *node = (MyObjectTreeModelNode*)item.GetID(); diff --git a/xs/src/slic3r/GUI/wxExtensions.hpp b/xs/src/slic3r/GUI/wxExtensions.hpp index 078ea48ed..2ae5cf6d1 100644 --- a/xs/src/slic3r/GUI/wxExtensions.hpp +++ b/xs/src/slic3r/GUI/wxExtensions.hpp @@ -253,6 +253,7 @@ public: wxDataViewItem Delete(const wxDataViewItem &item); void DeleteAll(); wxDataViewItem GetItemById(int obj_idx); + int GetIdByItem(wxDataViewItem& item); bool IsEmpty() { return m_objects.empty(); } // helper method for wxLog diff --git a/xs/xsp/GUI.xsp b/xs/xsp/GUI.xsp index 51eb36fa8..a744e6dcd 100644 --- a/xs/xsp/GUI.xsp +++ b/xs/xsp/GUI.xsp @@ -87,9 +87,9 @@ void add_frequently_changed_parameters(SV *ui_parent, SV *ui_sizer, SV *ui_p_siz (wxBoxSizer*)wxPli_sv_2_object(aTHX_ ui_sizer, "Wx::BoxSizer"), (wxFlexGridSizer*)wxPli_sv_2_object(aTHX_ ui_p_sizer, "Wx::FlexGridSizer")); %}; -void add_expert_mode_part(SV *ui_parent, SV *ui_sizer) +void add_expert_mode_part(SV *ui_parent, SV *ui_sizer, int event) %code%{ Slic3r::GUI::add_expert_mode_part((wxWindow*)wxPli_sv_2_object(aTHX_ ui_parent, "Wx::Window"), - (wxBoxSizer*)wxPli_sv_2_object(aTHX_ ui_sizer, "Wx::BoxSizer")); %}; + (wxBoxSizer*)wxPli_sv_2_object(aTHX_ ui_sizer, "Wx::BoxSizer"), event); %}; void set_objects_from_perl( SV *ui_parent, SV *frequently_changed_parameters_sizer,