Merge remote-tracking branch 'origin/new_main_page_ui' into dev

This commit is contained in:
YuSanka 2018-08-24 15:01:26 +02:00
commit 8b148a4fe4
42 changed files with 4600 additions and 217 deletions

View File

@ -26,6 +26,14 @@ our $appController;
our $VALUE_CHANGE_EVENT = Wx::NewEventType; our $VALUE_CHANGE_EVENT = Wx::NewEventType;
# 2) To inform about a preset selection change or a "modified" status change. # 2) To inform about a preset selection change or a "modified" status change.
our $PRESETS_CHANGED_EVENT = Wx::NewEventType; our $PRESETS_CHANGED_EVENT = Wx::NewEventType;
# 3) To inform about a change of object selection
our $OBJECT_SELECTION_CHANGED_EVENT = Wx::NewEventType;
# 4) To inform about a change of object settings
our $OBJECT_SETTINGS_CHANGED_EVENT = Wx::NewEventType;
# 5) To inform about a remove of object
our $OBJECT_REMOVE_EVENT = Wx::NewEventType;
# 6) To inform about a update of the scene
our $UPDATE_SCENE_EVENT = Wx::NewEventType;
sub new { sub new {
my ($class, %params) = @_; my ($class, %params) = @_;
@ -114,6 +122,8 @@ sub new {
$self->update_ui_from_settings; $self->update_ui_from_settings;
Slic3r::GUI::update_mode();
return $self; return $self;
} }
@ -133,7 +143,12 @@ sub _init_tabpanel {
}); });
if (!$self->{no_plater}) { 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,
event_object_settings_changed => $OBJECT_SETTINGS_CHANGED_EVENT,
event_remove_object => $OBJECT_REMOVE_EVENT,
event_update_scene => $UPDATE_SCENE_EVENT,
), L("Plater"));
if (!$self->{no_controller}) { if (!$self->{no_controller}) {
$panel->AddPage($self->{controller} = Slic3r::GUI::Controller->new($panel), L("Controller")); $panel->AddPage($self->{controller} = Slic3r::GUI::Controller->new($panel), L("Controller"));
} }
@ -192,6 +207,40 @@ sub _init_tabpanel {
} }
} }
}); });
# The following event is emited by the C++ Tab implementation on object selection change.
EVT_COMMAND($self, -1, $OBJECT_SELECTION_CHANGED_EVENT, sub {
my ($self, $event) = @_;
my $obj_idx = $event->GetId;
my $child = $event->GetInt == 1 ? 1 : undef;
$self->{plater}->select_object($obj_idx < 0 ? undef: $obj_idx, $child);
$self->{plater}->item_changed_selection($obj_idx);
});
# The following event is emited by the C++ GUI implementation on object settings change.
EVT_COMMAND($self, -1, $OBJECT_SETTINGS_CHANGED_EVENT, sub {
my ($self, $event) = @_;
my $line = $event->GetString;
my ($obj_idx, $parts_changed, $part_settings_changed) = split('',$line);
$self->{plater}->changed_object_settings($obj_idx, $parts_changed, $part_settings_changed);
});
# The following event is emited by the C++ GUI implementation on object remove.
EVT_COMMAND($self, -1, $OBJECT_REMOVE_EVENT, sub {
my ($self, $event) = @_;
$self->{plater}->remove();
});
# The following event is emited by the C++ GUI implementation on extruder change for object.
EVT_COMMAND($self, -1, $UPDATE_SCENE_EVENT, sub {
my ($self, $event) = @_;
$self->{plater}->update();
});
Slic3r::GUI::create_preset_tabs($self->{no_controller}, $VALUE_CHANGE_EVENT, $PRESETS_CHANGED_EVENT); Slic3r::GUI::create_preset_tabs($self->{no_controller}, $VALUE_CHANGE_EVENT, $PRESETS_CHANGED_EVENT);
$self->{options_tabs} = {}; $self->{options_tabs} = {};
for my $tab_name (qw(print filament sla_material printer)) { for my $tab_name (qw(print filament sla_material printer)) {

View File

@ -49,7 +49,7 @@ my $PreventListEvents = 0;
our $appController; our $appController;
sub new { sub new {
my ($class, $parent) = @_; my ($class, $parent, %params) = @_;
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
$self->{config} = Slic3r::Config::new_from_defaults_keys([qw( $self->{config} = Slic3r::Config::new_from_defaults_keys([qw(
bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width variable_layer_height bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width variable_layer_height
@ -57,6 +57,13 @@ sub new {
nozzle_diameter single_extruder_multi_material wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width 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 printer_model wipe_tower_rotation_angle extruder_colour filament_colour max_print_height printer_model
)]); )]);
# store input params
$self->{event_object_selection_changed} = $params{event_object_selection_changed};
$self->{event_object_settings_changed} = $params{event_object_settings_changed};
$self->{event_remove_object} = $params{event_remove_object};
$self->{event_update_scene} = $params{event_update_scene};
# C++ Slic3r::Model with Perl extensions in Slic3r/Model.pm # C++ Slic3r::Model with Perl extensions in Slic3r/Model.pm
$self->{model} = Slic3r::Model->new; $self->{model} = Slic3r::Model->new;
# C++ Slic3r::Print with Perl extensions in Slic3r/Print.pm # C++ Slic3r::Print with Perl extensions in Slic3r/Print.pm
@ -74,7 +81,7 @@ sub new {
}); });
# Initialize preview notebook # Initialize preview notebook
$self->{preview_notebook} = Wx::Notebook->new($self, -1, wxDefaultPosition, [335,335], wxNB_BOTTOM); $self->{preview_notebook} = Wx::Notebook->new($self, -1, wxDefaultPosition, [-1,335], wxNB_BOTTOM);
# Initialize handlers for canvases # Initialize handlers for canvases
my $on_select_object = sub { my $on_select_object = sub {
@ -128,7 +135,9 @@ sub new {
} }
$_->set_scaling_factor($scale) for @{ $model_object->instances }; $_->set_scaling_factor($scale) for @{ $model_object->instances };
$self->{list}->SetItem($obj_idx, 2, ($model_object->instances->[0]->scaling_factor * 100) . "%"); # Set object scale on c++ side
Slic3r::GUI::set_object_scale($obj_idx, $model_object->instances->[0]->scaling_factor * 100);
# $object->transform_thumbnail($self->{model}, $obj_idx); # $object->transform_thumbnail($self->{model}, $obj_idx);
#update print and start background processing #update print and start background processing
@ -362,37 +371,12 @@ sub new {
# } # }
### Panel for right column ### Panel for right column
$self->{right_panel} = Wx::Panel->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); # $self->{right_panel} = Wx::Panel->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
$self->{right_panel} = Wx::ScrolledWindow->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
### Scrolled Window for info boxes $self->{right_panel}->SetScrollbars(0, 1, 1, 1);
my $scrolled_window_sizer = $self->{scrolled_window_sizer} = Wx::BoxSizer->new(wxVERTICAL);
$scrolled_window_sizer->SetMinSize([310, -1]);
my $scrolled_window_panel = $self->{scrolled_window_panel} = Wx::ScrolledWindow->new($self->{right_panel}, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
$scrolled_window_panel->SetSizer($scrolled_window_sizer);
$scrolled_window_panel->SetScrollbars(1, 1, 1, 1);
$self->{list} = Wx::ListView->new($scrolled_window_panel, -1, wxDefaultPosition, wxDefaultSize,
wxLC_SINGLE_SEL | wxLC_REPORT | wxBORDER_SUNKEN | wxTAB_TRAVERSAL | wxWANTS_CHARS );
$self->{list}->InsertColumn(0, L("Name"), wxLIST_FORMAT_LEFT, 145);
$self->{list}->InsertColumn(1, L("Copies"), wxLIST_FORMAT_CENTER, 45);
$self->{list}->InsertColumn(2, L("Scale"), wxLIST_FORMAT_CENTER, wxLIST_AUTOSIZE_USEHEADER);
EVT_LIST_ITEM_SELECTED($self, $self->{list}, \&list_item_selected);
EVT_LIST_ITEM_DESELECTED($self, $self->{list}, \&list_item_deselected);
EVT_LIST_ITEM_ACTIVATED($self, $self->{list}, \&list_item_activated);
EVT_KEY_DOWN($self->{list}, sub {
my ($list, $event) = @_;
if ($event->GetKeyCode == WXK_TAB) {
$list->Navigate($event->ShiftDown ? &Wx::wxNavigateBackward : &Wx::wxNavigateForward);
} elsif ($event->GetKeyCode == WXK_DELETE ||
($event->GetKeyCode == WXK_BACK && &Wx::wxMAC) ) {
$self->remove;
} else {
$event->Skip;
}
});
# right pane buttons # right pane buttons
$self->{btn_export_gcode} = Wx::Button->new($self->{right_panel}, -1, L("Export G-code…"), wxDefaultPosition, [-1, 30], wxBU_LEFT); $self->{btn_export_gcode} = Wx::Button->new($self->{right_panel}, -1, L("Export G-code…"), wxDefaultPosition, [-1, 30], wxNO_BORDER);#, wxBU_LEFT);
$self->{btn_reslice} = Wx::Button->new($self->{right_panel}, -1, L("Slice now"), wxDefaultPosition, [-1, 30], wxBU_LEFT); $self->{btn_reslice} = Wx::Button->new($self->{right_panel}, -1, L("Slice now"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
$self->{btn_print} = Wx::Button->new($self->{right_panel}, -1, L("Print…"), wxDefaultPosition, [-1, 30], wxBU_LEFT); $self->{btn_print} = Wx::Button->new($self->{right_panel}, -1, L("Print…"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
$self->{btn_send_gcode} = Wx::Button->new($self->{right_panel}, -1, L("Send to printer"), wxDefaultPosition, [-1, 30], wxBU_LEFT); $self->{btn_send_gcode} = Wx::Button->new($self->{right_panel}, -1, L("Send to printer"), wxDefaultPosition, [-1, 30], wxBU_LEFT);
@ -460,6 +444,7 @@ sub new {
# } else { # } else {
# EVT_BUTTON($self, $self->{btn_add}, sub { $self->add; }); # EVT_BUTTON($self, $self->{btn_add}, sub { $self->add; });
# EVT_BUTTON($self, $self->{btn_remove}, sub { $self->remove() }); # explicitly pass no argument to remove # EVT_BUTTON($self, $self->{btn_remove}, sub { $self->remove() }); # explicitly pass no argument to remove
# EVT_BUTTON($self, $self->{btn_remove}, sub { Slic3r::GUI::remove_obj() }); # explicitly pass no argument to remove
# EVT_BUTTON($self, $self->{btn_reset}, sub { $self->reset; }); # EVT_BUTTON($self, $self->{btn_reset}, sub { $self->reset; });
# EVT_BUTTON($self, $self->{btn_arrange}, sub { $self->arrange; }); # EVT_BUTTON($self, $self->{btn_arrange}, sub { $self->arrange; });
# EVT_BUTTON($self, $self->{btn_increase}, sub { $self->increase; }); # EVT_BUTTON($self, $self->{btn_increase}, sub { $self->increase; });
@ -476,7 +461,7 @@ sub new {
$_->SetDropTarget(Slic3r::GUI::Plater::DropTarget->new($self)) $_->SetDropTarget(Slic3r::GUI::Plater::DropTarget->new($self))
for grep defined($_), for grep defined($_),
$self, $self->{canvas3D}, $self->{preview3D}, $self->{list}; $self, $self->{canvas3D}, $self->{preview3D}, $self->{list};
# $self, $self->{canvas}, $self->{canvas3D}, $self->{preview3D}, $self->{list}; # $self, $self->{canvas}, $self->{canvas3D}, $self->{preview3D};
EVT_COMMAND($self, -1, $PROGRESS_BAR_EVENT, sub { EVT_COMMAND($self, -1, $PROGRESS_BAR_EVENT, sub {
my ($self, $event) = @_; my ($self, $event) = @_;
@ -555,15 +540,32 @@ sub new {
$presets->Layout; $presets->Layout;
} }
my $frequently_changed_parameters_sizer = $self->{frequently_changed_parameters_sizer} = Wx::BoxSizer->new(wxHORIZONTAL); my $frequently_changed_parameters_sizer = $self->{frequently_changed_parameters_sizer} = Wx::BoxSizer->new(wxVERTICAL);
Slic3r::GUI::add_frequently_changed_parameters($self->{right_panel}, $frequently_changed_parameters_sizer, $presets); 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,
$self->{model},
$self->{event_object_selection_changed},
$self->{event_object_settings_changed},
$self->{event_remove_object},
$self->{event_update_scene});
# 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; my $object_info_sizer;
{ {
my $box = Wx::StaticBox->new($scrolled_window_panel, -1, L("Info")); # my $box = Wx::StaticBox->new($scrolled_window_panel, -1, L("Info"));
my $box = Wx::StaticBox->new($self->{right_panel}, -1, L("Info"));
$box->SetFont($Slic3r::GUI::small_bold_font);
$object_info_sizer = Wx::StaticBoxSizer->new($box, wxVERTICAL); $object_info_sizer = Wx::StaticBoxSizer->new($box, wxVERTICAL);
$object_info_sizer->SetMinSize([300,-1]); $object_info_sizer->SetMinSize([300,-1]);
my $grid_sizer = Wx::FlexGridSizer->new(3, 4, 5, 5); #!my $grid_sizer = Wx::FlexGridSizer->new(3, 4, 5, 5);
my $grid_sizer = Wx::FlexGridSizer->new(2, 4, 5, 5);
$grid_sizer->SetFlexibleDirection(wxHORIZONTAL); $grid_sizer->SetFlexibleDirection(wxHORIZONTAL);
$grid_sizer->AddGrowableCol(1, 1); $grid_sizer->AddGrowableCol(1, 1);
$grid_sizer->AddGrowableCol(3, 1); $grid_sizer->AddGrowableCol(3, 1);
@ -578,28 +580,45 @@ sub new {
); );
while (my $field = shift @info) { while (my $field = shift @info) {
my $label = shift @info; my $label = shift @info;
my $text = Wx::StaticText->new($scrolled_window_panel, -1, "$label:", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); # my $text = Wx::StaticText->new($scrolled_window_panel, -1, "$label:", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
my $text = Wx::StaticText->new($self->{right_panel}, -1, "$label:", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
$text->SetFont($Slic3r::GUI::small_font); $text->SetFont($Slic3r::GUI::small_font);
$grid_sizer->Add($text, 0); #!$grid_sizer->Add($text, 0);
$self->{"object_info_$field"} = Wx::StaticText->new($scrolled_window_panel, -1, "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); # $self->{"object_info_$field"} = Wx::StaticText->new($scrolled_window_panel, -1, "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
$self->{"object_info_$field"} = Wx::StaticText->new($self->{right_panel}, -1, "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
$self->{"object_info_$field"}->SetFont($Slic3r::GUI::small_font); $self->{"object_info_$field"}->SetFont($Slic3r::GUI::small_font);
if ($field eq 'manifold') { if ($field eq 'manifold') {
$self->{object_info_manifold_warning_icon} = Wx::StaticBitmap->new($scrolled_window_panel, -1, Wx::Bitmap->new(Slic3r::var("error.png"), wxBITMAP_TYPE_PNG)); # $self->{object_info_manifold_warning_icon} = Wx::StaticBitmap->new($scrolled_window_panel, -1, Wx::Bitmap->new(Slic3r::var("error.png"), wxBITMAP_TYPE_PNG));
$self->{object_info_manifold_warning_icon}->Hide; $self->{object_info_manifold_warning_icon} = Wx::StaticBitmap->new($self->{right_panel}, -1, Wx::Bitmap->new(Slic3r::var("error.png"), wxBITMAP_TYPE_PNG));
#$self->{object_info_manifold_warning_icon}->Hide;
$self->{"object_info_manifold_warning_icon_show"} = sub {
if ($self->{object_info_manifold_warning_icon}->IsShown() != $_[0]) {
Slic3r::GUI::set_show_manifold_warning_icon($_[0]);
my $mode = wxTheApp->{app_config}->get("view_mode");
return if ($mode eq "" || $mode eq "simple");
$self->{object_info_manifold_warning_icon}->Show($_[0]);
$self->Layout
}
};
$self->{"object_info_manifold_warning_icon_show"}->(0);
my $h_sizer = Wx::BoxSizer->new(wxHORIZONTAL); my $h_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
$h_sizer->Add($self->{object_info_manifold_warning_icon}, 0); $h_sizer->Add($text, 0);
$h_sizer->Add($self->{"object_info_$field"}, 0); $h_sizer->Add($self->{object_info_manifold_warning_icon}, 0, wxLEFT, 2);
$grid_sizer->Add($h_sizer, 0, wxEXPAND); $h_sizer->Add($self->{"object_info_$field"}, 0, wxLEFT, 2);
#!$grid_sizer->Add($h_sizer, 0, wxEXPAND);
$object_info_sizer->Add($h_sizer, 0, wxEXPAND|wxTOP, 4);
} else { } else {
$grid_sizer->Add($text, 0);
$grid_sizer->Add($self->{"object_info_$field"}, 0); $grid_sizer->Add($self->{"object_info_$field"}, 0);
} }
} }
} }
my $print_info_sizer = $self->{print_info_sizer} = Wx::StaticBoxSizer->new( my $print_info_sizer = $self->{print_info_sizer} = Wx::StaticBoxSizer->new(
Wx::StaticBox->new($scrolled_window_panel, -1, L("Sliced Info")), wxVERTICAL); # Wx::StaticBox->new($scrolled_window_panel, -1, L("Sliced Info")), wxVERTICAL);
Wx::StaticBox->new($self->{right_panel}, -1, L("Sliced Info")), wxVERTICAL);
$print_info_sizer->SetMinSize([300,-1]); $print_info_sizer->SetMinSize([300,-1]);
my $buttons_sizer = Wx::BoxSizer->new(wxHORIZONTAL); my $buttons_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
@ -609,22 +628,27 @@ sub new {
$buttons_sizer->Add($self->{btn_reslice}, 0, wxALIGN_RIGHT, 0); $buttons_sizer->Add($self->{btn_reslice}, 0, wxALIGN_RIGHT, 0);
$buttons_sizer->Add($self->{btn_print}, 0, wxALIGN_RIGHT, 0); $buttons_sizer->Add($self->{btn_print}, 0, wxALIGN_RIGHT, 0);
$buttons_sizer->Add($self->{btn_send_gcode}, 0, wxALIGN_RIGHT, 0); $buttons_sizer->Add($self->{btn_send_gcode}, 0, wxALIGN_RIGHT, 0);
$buttons_sizer->Add($self->{btn_export_gcode}, 0, wxALIGN_RIGHT, 0);
$scrolled_window_sizer->Add($self->{list}, 1, wxEXPAND, 5); # $scrolled_window_sizer->Add($self->{list}, 1, wxEXPAND, 5);
$scrolled_window_sizer->Add($object_info_sizer, 0, wxEXPAND, 0); # $scrolled_window_sizer->Add($object_info_sizer, 0, wxEXPAND, 0);
$scrolled_window_sizer->Add($print_info_sizer, 0, wxEXPAND, 0); # $scrolled_window_sizer->Add($print_info_sizer, 0, wxEXPAND, 0);
#$buttons_sizer->Add($self->{btn_export_gcode}, 0, wxALIGN_RIGHT, 0);
### Sizer for info boxes
my $info_sizer = $self->{info_sizer} = Wx::BoxSizer->new(wxVERTICAL);
$info_sizer->SetMinSize([318, -1]);
$info_sizer->Add($object_info_sizer, 0, wxEXPAND | wxBOTTOM, 5);
$info_sizer->Add($print_info_sizer, 0, wxEXPAND | wxBOTTOM, 5);
my $right_sizer = Wx::BoxSizer->new(wxVERTICAL); my $right_sizer = Wx::BoxSizer->new(wxVERTICAL);
$right_sizer->SetMinSize([320,-1]);
$right_sizer->Add($presets, 0, wxEXPAND | wxTOP, 10) if defined $presets;
$right_sizer->Add($frequently_changed_parameters_sizer, 0, wxEXPAND | wxTOP, 0) if defined $frequently_changed_parameters_sizer;
$right_sizer->Add($buttons_sizer, 0, wxEXPAND | wxBOTTOM, 5);
$right_sizer->Add($scrolled_window_panel, 1, wxEXPAND | wxALL, 1);
# Show the box initially, let it be shown after the slicing is finished.
$self->print_info_box_show(0);
$self->{right_panel}->SetSizer($right_sizer); $self->{right_panel}->SetSizer($right_sizer);
$right_sizer->SetMinSize([320, -1]);
$right_sizer->Add($presets, 0, wxEXPAND | wxTOP, 10) if defined $presets;
$right_sizer->Add($frequently_changed_parameters_sizer, 1, wxEXPAND | wxTOP, 0) if defined $frequently_changed_parameters_sizer;
$right_sizer->Add($expert_mode_part_sizer, 0, wxEXPAND | wxTOP, 10) if defined $expert_mode_part_sizer;
$right_sizer->Add($buttons_sizer, 0, wxEXPAND | wxBOTTOM | wxTOP, 10);
$right_sizer->Add($info_sizer, 0, wxEXPAND | wxLEFT, 20);
$right_sizer->Add($self->{btn_export_gcode}, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 20);
my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL); my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL);
$hsizer->Add($self->{preview_notebook}, 1, wxEXPAND | wxTOP, 1); $hsizer->Add($self->{preview_notebook}, 1, wxEXPAND | wxTOP, 1);
@ -637,6 +661,18 @@ sub new {
$sizer->SetSizeHints($self); $sizer->SetSizeHints($self);
$self->SetSizer($sizer); $self->SetSizer($sizer);
# Send sizers/buttons to C++
Slic3r::GUI::set_objects_from_perl( $self->{right_panel},
$frequently_changed_parameters_sizer,
$expert_mode_part_sizer,
$info_sizer,
$self->{btn_export_gcode},
$self->{btn_export_stl},
$self->{btn_reslice},
$self->{btn_print},
$self->{btn_send_gcode},
$self->{object_info_manifold_warning_icon} );
} }
# Last correct selected item for each preset # Last correct selected item for each preset
@ -647,6 +683,7 @@ sub new {
} }
$self->update_ui_from_settings(); $self->update_ui_from_settings();
$self->Layout;
return $self; return $self;
} }
@ -921,12 +958,10 @@ sub load_model_objects {
foreach my $obj_idx (@obj_idx) { foreach my $obj_idx (@obj_idx) {
my $object = $self->{objects}[$obj_idx]; my $object = $self->{objects}[$obj_idx];
my $model_object = $self->{model}->objects->[$obj_idx]; my $model_object = $self->{model}->objects->[$obj_idx];
$self->{list}->InsertStringItem($obj_idx, $object->name);
$self->{list}->SetItemFont($obj_idx, Wx::Font->new(10, wxDEFAULT, wxNORMAL, wxNORMAL)) # Add object to list on c++ side
if $self->{list}->can('SetItemFont'); # legacy code for wxPerl < 0.9918 not supporting SetItemFont() Slic3r::GUI::add_object_to_list($object->name, $model_object);
$self->{list}->SetItem($obj_idx, 1, $model_object->instances_count);
$self->{list}->SetItem($obj_idx, 2, ($model_object->instances->[0]->scaling_factor * 100) . "%");
# $self->reset_thumbnail($obj_idx); # $self->reset_thumbnail($obj_idx);
} }
@ -936,8 +971,6 @@ sub load_model_objects {
# zoom to objects # zoom to objects
Slic3r::GUI::_3DScene::zoom_to_volumes($self->{canvas3D}) if $self->{canvas3D}; Slic3r::GUI::_3DScene::zoom_to_volumes($self->{canvas3D}) if $self->{canvas3D};
$self->{list}->Update;
$self->{list}->Select($obj_idx[-1], 1);
$self->object_list_changed; $self->object_list_changed;
$self->schedule_background_process; $self->schedule_background_process;
@ -972,7 +1005,8 @@ sub remove {
splice @{$self->{objects}}, $obj_idx, 1; splice @{$self->{objects}}, $obj_idx, 1;
$self->{model}->delete_object($obj_idx); $self->{model}->delete_object($obj_idx);
$self->{print}->delete_object($obj_idx); $self->{print}->delete_object($obj_idx);
$self->{list}->DeleteItem($obj_idx); # Delete object from list on c++ side
Slic3r::GUI::delete_object_from_list();
$self->object_list_changed; $self->object_list_changed;
$self->select_object(undef); $self->select_object(undef);
@ -992,7 +1026,8 @@ sub reset {
@{$self->{objects}} = (); @{$self->{objects}} = ();
$self->{model}->clear_objects; $self->{model}->clear_objects;
$self->{print}->clear_objects; $self->{print}->clear_objects;
$self->{list}->DeleteAllItems; # Delete all objects from list on c++ side
Slic3r::GUI::delete_all_objects_from_list();
$self->object_list_changed; $self->object_list_changed;
$self->select_object(undef); $self->select_object(undef);
@ -1014,7 +1049,8 @@ sub increase {
); );
$self->{print}->objects->[$obj_idx]->add_copy($instance->offset); $self->{print}->objects->[$obj_idx]->add_copy($instance->offset);
} }
$self->{list}->SetItem($obj_idx, 1, $model_object->instances_count); # Set conut of object on c++ side
Slic3r::GUI::set_object_count($obj_idx, $model_object->instances_count);
# only autoarrange if user has autocentering enabled # only autoarrange if user has autocentering enabled
$self->stop_background_process; $self->stop_background_process;
@ -1042,7 +1078,8 @@ sub decrease {
$model_object->delete_last_instance; $model_object->delete_last_instance;
$self->{print}->objects->[$obj_idx]->delete_last_copy; $self->{print}->objects->[$obj_idx]->delete_last_copy;
} }
$self->{list}->SetItem($obj_idx, 1, $model_object->instances_count); # Set conut of object on c++ side
Slic3r::GUI::set_object_count($obj_idx, $model_object->instances_count);
} elsif (defined $copies_asked) { } elsif (defined $copies_asked) {
# The "decrease" came from the "set number of copies" dialog. # The "decrease" came from the "set number of copies" dialog.
$self->remove; $self->remove;
@ -1051,11 +1088,7 @@ sub decrease {
$self->resume_background_process; $self->resume_background_process;
return; return;
} }
if ($self->{objects}[$obj_idx]) {
$self->{list}->Select($obj_idx, 0);
$self->{list}->Select($obj_idx, 1);
}
$self->update; $self->update;
$self->schedule_background_process; $self->schedule_background_process;
} }
@ -1153,6 +1186,7 @@ sub rotate {
# $model_object->center_around_origin; # $model_object->center_around_origin;
# $self->reset_thumbnail($obj_idx); # $self->reset_thumbnail($obj_idx);
} }
Slic3r::GUI::update_rotation_value(deg2rad($angle), $axis == X ? "x" : ($axis == Y ? "y" : "z"));
# update print and start background processing # update print and start background processing
$self->{print}->add_model_object($model_object, $obj_idx); $self->{print}->add_model_object($model_object, $obj_idx);
@ -1243,8 +1277,9 @@ sub changescale {
$scale = $self->_get_number_from_user(L('Enter the scale % for the selected object:'), L('Scale'), L('Invalid scaling value entered'), $model_instance->scaling_factor*100, 1); $scale = $self->_get_number_from_user(L('Enter the scale % for the selected object:'), L('Scale'), L('Invalid scaling value entered'), $model_instance->scaling_factor*100, 1);
return if ! defined($scale) || $scale eq ''; return if ! defined($scale) || $scale eq '';
} }
$self->{list}->SetItem($obj_idx, 2, "$scale%"); # Set object scale on c++ side
Slic3r::GUI::set_object_scale($obj_idx, $scale);
$scale /= 100; # turn percent into factor $scale /= 100; # turn percent into factor
my $variation = $scale / $model_instance->scaling_factor; my $variation = $scale / $model_instance->scaling_factor;
@ -1687,9 +1722,15 @@ sub on_export_completed {
# Fill in the "Sliced info" box with the result of the G-code generator. # Fill in the "Sliced info" box with the result of the G-code generator.
sub print_info_box_show { sub print_info_box_show {
my ($self, $show) = @_; my ($self, $show) = @_;
my $scrolled_window_panel = $self->{scrolled_window_panel}; # my $scrolled_window_panel = $self->{scrolled_window_panel};
my $scrolled_window_sizer = $self->{scrolled_window_sizer}; # my $scrolled_window_sizer = $self->{scrolled_window_sizer};
return if (!$show && ($scrolled_window_sizer->IsShown(2) == $show)); # return if (!$show && ($scrolled_window_sizer->IsShown(2) == $show));
my $panel = $self->{right_panel};
my $sizer = $self->{info_sizer};
return if (!$show && ($sizer->IsShown(2) == $show));
Slic3r::GUI::set_show_print_info($show);
return if (wxTheApp->{app_config}->get("view_mode") eq "simple");
if ($show) { if ($show) {
my $print_info_sizer = $self->{print_info_sizer}; my $print_info_sizer = $self->{print_info_sizer};
@ -1716,17 +1757,23 @@ sub print_info_box_show {
while ( my $label = shift @info) { while ( my $label = shift @info) {
my $value = shift @info; my $value = shift @info;
next if $value eq "N/A"; next if $value eq "N/A";
my $text = Wx::StaticText->new($scrolled_window_panel, -1, "$label:", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); # my $text = Wx::StaticText->new($scrolled_window_panel, -1, "$label:", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
my $text = Wx::StaticText->new($panel, -1, "$label:", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
$text->SetFont($Slic3r::GUI::small_font); $text->SetFont($Slic3r::GUI::small_font);
$grid_sizer->Add($text, 0); $grid_sizer->Add($text, 0);
my $field = Wx::StaticText->new($scrolled_window_panel, -1, $value, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); # my $field = Wx::StaticText->new($scrolled_window_panel, -1, $value, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
my $field = Wx::StaticText->new($panel, -1, $value, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
$field->SetFont($Slic3r::GUI::small_font); $field->SetFont($Slic3r::GUI::small_font);
$grid_sizer->Add($field, 0); $grid_sizer->Add($field, 0);
} }
} }
$scrolled_window_sizer->Show(2, $show); # $scrolled_window_sizer->Show(2, $show);
$scrolled_window_panel->Layout; # $scrolled_window_panel->Layout;
$sizer->Show(1, $show);
#? $self->Layout;
#? $panel->Refresh;
} }
sub do_print { sub do_print {
@ -2058,32 +2105,18 @@ sub on_config_change {
$self->schedule_background_process; $self->schedule_background_process;
} }
sub list_item_deselected { sub item_changed_selection{
my ($self, $event) = @_; my ($self, $obj_idx) = @_;
return if $PreventListEvents;
$self->{_lecursor} = Wx::BusyCursor->new();
if ($self->{list}->GetFirstSelected == -1) {
$self->select_object(undef);
# $self->{canvas}->Refresh;
Slic3r::GUI::_3DScene::deselect_volumes($self->{canvas3D}) if $self->{canvas3D};
Slic3r::GUI::_3DScene::render($self->{canvas3D}) if $self->{canvas3D};
}
undef $self->{_lecursor};
}
sub list_item_selected {
my ($self, $event) = @_;
return if $PreventListEvents;
$self->{_lecursor} = Wx::BusyCursor->new();
my $obj_idx = $event->GetIndex;
$self->select_object($obj_idx);
# $self->{canvas}->Refresh; # $self->{canvas}->Refresh;
if ($self->{canvas3D}) { if ($self->{canvas3D}) {
my $selections = $self->collect_selections; Slic3r::GUI::_3DScene::deselect_volumes($self->{canvas3D});
Slic3r::GUI::_3DScene::update_volumes_selection($self->{canvas3D}, \@$selections); if ($obj_idx >= 0){
my $selections = $self->collect_selections;
Slic3r::GUI::_3DScene::update_volumes_selection($self->{canvas3D}, \@$selections);
}
Slic3r::GUI::_3DScene::render($self->{canvas3D}); Slic3r::GUI::_3DScene::render($self->{canvas3D});
} }
undef $self->{_lecursor};
} }
sub collect_selections { sub collect_selections {
@ -2095,6 +2128,7 @@ sub collect_selections {
return $selections; return $selections;
} }
# doesn't used now
sub list_item_activated { sub list_item_activated {
my ($self, $event, $obj_idx) = @_; my ($self, $event, $obj_idx) = @_;
@ -2195,6 +2229,31 @@ sub object_settings_dialog {
} }
} }
sub changed_object_settings {
my ($self, $obj_idx, $parts_changed, $part_settings_changed) = @_;
# update thumbnail since parts may have changed
if ($parts_changed) {
# recenter and re-align to Z = 0
my $model_object = $self->{model}->objects->[$obj_idx];
$model_object->center_around_origin;
$self->reset_thumbnail($obj_idx);
}
# update print
if ($parts_changed || $part_settings_changed) {
$self->stop_background_process;
$self->{print}->reload_object($obj_idx);
$self->schedule_background_process;
$self->{canvas}->reload_scene if $self->{canvas};
my $selections = $self->collect_selections;
Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections);
Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 0);
} else {
$self->resume_background_process;
}
}
# Called to update various buttons depending on whether there are any objects or # Called to update various buttons depending on whether there are any objects or
# whether background processing (export of a G-code, sending to Octoprint, forced background re-slicing) is active. # whether background processing (export of a G-code, sending to Octoprint, forced background re-slicing) is active.
sub object_list_changed { sub object_list_changed {
@ -2296,7 +2355,8 @@ sub selection_changed {
$self->{object_info_facets}->SetLabel(sprintf(L('%d (%d shells)'), $model_object->facets_count, $stats->{number_of_parts})); $self->{object_info_facets}->SetLabel(sprintf(L('%d (%d shells)'), $model_object->facets_count, $stats->{number_of_parts}));
if (my $errors = sum(@$stats{qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)})) { if (my $errors = sum(@$stats{qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)})) {
$self->{object_info_manifold}->SetLabel(sprintf(L("Auto-repaired (%d errors)"), $errors)); $self->{object_info_manifold}->SetLabel(sprintf(L("Auto-repaired (%d errors)"), $errors));
$self->{object_info_manifold_warning_icon}->Show; #$self->{object_info_manifold_warning_icon}->Show;
$self->{"object_info_manifold_warning_icon_show"}->(1);
# we don't show normals_fixed because we never provide normals # we don't show normals_fixed because we never provide normals
# to admesh, so it generates normals for all facets # to admesh, so it generates normals for all facets
@ -2306,7 +2366,8 @@ sub selection_changed {
$self->{object_info_manifold_warning_icon}->SetToolTipString($message); $self->{object_info_manifold_warning_icon}->SetToolTipString($message);
} else { } else {
$self->{object_info_manifold}->SetLabel(L("Yes")); $self->{object_info_manifold}->SetLabel(L("Yes"));
$self->{object_info_manifold_warning_icon}->Hide; #$self->{object_info_manifold_warning_icon}->Hide;
$self->{"object_info_manifold_warning_icon_show"}->(0);
$self->{object_info_manifold}->SetToolTipString(""); $self->{object_info_manifold}->SetToolTipString("");
$self->{object_info_manifold_warning_icon}->SetToolTipString(""); $self->{object_info_manifold_warning_icon}->SetToolTipString("");
} }
@ -2315,7 +2376,8 @@ sub selection_changed {
} }
} else { } else {
$self->{"object_info_$_"}->SetLabel("") for qw(size volume facets materials manifold); $self->{"object_info_$_"}->SetLabel("") for qw(size volume facets materials manifold);
$self->{object_info_manifold_warning_icon}->Hide; #$self->{object_info_manifold_warning_icon}->Hide;
$self->{"object_info_manifold_warning_icon_show"}->(0);
$self->{object_info_manifold}->SetToolTipString(""); $self->{object_info_manifold}->SetToolTipString("");
$self->{object_info_manifold_warning_icon}->SetToolTipString(""); $self->{object_info_manifold_warning_icon}->SetToolTipString("");
} }
@ -2328,26 +2390,21 @@ sub selection_changed {
} }
sub select_object { sub select_object {
my ($self, $obj_idx) = @_; my ($self, $obj_idx, $child) = @_;
# remove current selection # remove current selection
foreach my $o (0..$#{$self->{objects}}) { foreach my $o (0..$#{$self->{objects}}) {
$PreventListEvents = 1;
$self->{objects}->[$o]->selected(0); $self->{objects}->[$o]->selected(0);
$self->{list}->Select($o, 0);
$PreventListEvents = 0;
} }
if (defined $obj_idx) { if (defined $obj_idx) {
$self->{objects}->[$obj_idx]->selected(1); $self->{objects}->[$obj_idx]->selected(1);
# We use this flag to avoid circular event handling # Select current object in the list on c++ side, if item isn't child
# Select() happens to fire a wxEVT_LIST_ITEM_SELECTED on Windows, if (!defined $child){
# whose event handler calls this method again and again and again Slic3r::GUI::select_current_object($obj_idx);}
$PreventListEvents = 1;
$self->{list}->Select($obj_idx, 1);
$PreventListEvents = 0;
} else { } else {
# TODO: deselect all in list # Unselect all objects in the list on c++ side
Slic3r::GUI::unselect_objects();
} }
$self->selection_changed(1); $self->selection_changed(1);
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 B

BIN
resources/icons/erase.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
resources/icons/lambda.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

BIN
resources/icons/lambda_.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 B

BIN
resources/icons/object.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1017 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 521 B

BIN
resources/icons/split.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1021 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 B

View File

@ -211,6 +211,10 @@ add_library(libslic3r_gui STATIC
${LIBDIR}/slic3r/GUI/PresetHints.hpp ${LIBDIR}/slic3r/GUI/PresetHints.hpp
${LIBDIR}/slic3r/GUI/GUI.cpp ${LIBDIR}/slic3r/GUI/GUI.cpp
${LIBDIR}/slic3r/GUI/GUI.hpp ${LIBDIR}/slic3r/GUI/GUI.hpp
${LIBDIR}/slic3r/GUI/GUI_ObjectParts.cpp
${LIBDIR}/slic3r/GUI/GUI_ObjectParts.hpp
${LIBDIR}/slic3r/GUI/LambdaObjectDialog.cpp
${LIBDIR}/slic3r/GUI/LambdaObjectDialog.hpp
${LIBDIR}/slic3r/GUI/Tab.cpp ${LIBDIR}/slic3r/GUI/Tab.cpp
${LIBDIR}/slic3r/GUI/Tab.hpp ${LIBDIR}/slic3r/GUI/Tab.hpp
${LIBDIR}/slic3r/GUI/TabIface.cpp ${LIBDIR}/slic3r/GUI/TabIface.cpp

View File

@ -258,6 +258,11 @@ const Vec3d& GLVolume::get_origin() const
return m_origin; return m_origin;
} }
float GLVolume::get_angle_z()
{
return m_angle_z;
}
void GLVolume::set_origin(const Vec3d& origin) void GLVolume::set_origin(const Vec3d& origin)
{ {
if (m_origin != origin) if (m_origin != origin)

View File

@ -323,6 +323,7 @@ public:
// Sets render color in dependence of current state // Sets render color in dependence of current state
void set_render_color(); void set_render_color();
float get_angle_z();
const Vec3d& get_origin() const; const Vec3d& get_origin() const;
void set_origin(const Vec3d& origin); void set_origin(const Vec3d& origin);
void set_angle_z(float angle_z); void set_angle_z(float angle_z);

View File

@ -132,7 +132,11 @@ namespace Slic3r { namespace GUI {
break; break;
} }
double val; double val;
str.ToCDouble(&val); if(!str.ToCDouble(&val))
{
show_error(m_parent, _(L("Input value contains incorrect symbol(s).\nUse, please, only digits")));
set_value(double_to_string(val), true);
}
if (m_opt.min > val || val > m_opt.max) if (m_opt.min > val || val > m_opt.max)
{ {
show_error(m_parent, _(L("Input value is out of range"))); show_error(m_parent, _(L("Input value is out of range")));
@ -330,9 +334,7 @@ void SpinCtrl::BUILD() {
break; break;
} }
const int min_val = m_opt_id == "standby_temperature_delta" ? const int min_val = m_opt.min == INT_MIN ? 0: m_opt.min;
-500 : m_opt.min > 0 ?
m_opt.min : 0;
const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647; const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647;
auto temp = new wxSpinCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, auto temp = new wxSpinCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size,
@ -558,8 +560,11 @@ boost::any& Choice::get_value()
// boost::any m_value; // boost::any m_value;
wxString ret_str = static_cast<wxComboBox*>(window)->GetValue(); wxString ret_str = static_cast<wxComboBox*>(window)->GetValue();
if (m_opt_id == "support") // options from right panel
return m_value = boost::any(ret_str);//ret_str; std::vector <std::string> right_panel_options{ "support", "scale_unit" };
for (auto rp_option: right_panel_options)
if (m_opt_id == rp_option)
return m_value = boost::any(ret_str);
if (m_opt.type != coEnum) if (m_opt.type != coEnum)
/*m_value = */get_value_by_opt_type(ret_str); /*m_value = */get_value_by_opt_type(ret_str);
@ -705,6 +710,69 @@ void StaticText::BUILD()
temp->SetToolTip(get_tooltip_text(legend)); temp->SetToolTip(get_tooltip_text(legend));
} }
void SliderCtrl::BUILD()
{
auto size = wxSize(wxDefaultSize);
if (m_opt.height >= 0) size.SetHeight(m_opt.height);
if (m_opt.width >= 0) size.SetWidth(m_opt.width);
auto temp = new wxBoxSizer(wxHORIZONTAL);
auto def_val = static_cast<ConfigOptionInt*>(m_opt.default_value)->value;
auto min = m_opt.min == INT_MIN ? 0 : m_opt.min;
auto max = m_opt.max == INT_MAX ? 100 : m_opt.max;
m_slider = new wxSlider(m_parent, wxID_ANY, def_val * m_scale,
min * m_scale, max * m_scale,
wxDefaultPosition, size);
wxSize field_size(40, -1);
m_textctrl = new wxTextCtrl(m_parent, wxID_ANY, wxString::Format("%d", m_slider->GetValue()/m_scale),
wxDefaultPosition, field_size);
temp->Add(m_slider, 1, wxEXPAND | wxALIGN_CENTER_VERTICAL, 0);
temp->Add(m_textctrl, 0, wxALIGN_CENTER_VERTICAL, 0);
m_slider->Bind(wxEVT_SLIDER, ([this](wxCommandEvent e) {
if (!m_disable_change_event){
int val = boost::any_cast<int>(get_value());
m_textctrl->SetLabel(wxString::Format("%d", val));
on_change_field();
}
}), m_slider->GetId());
m_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) {
std::string value = e.GetString().utf8_str().data();
if (is_matched(value, "^-?\\d+(\\.\\d*)?$")){
m_disable_change_event = true;
m_slider->SetValue(stoi(value)*m_scale);
m_disable_change_event = false;
on_change_field();
}
}), m_textctrl->GetId());
m_sizer = dynamic_cast<wxSizer*>(temp);
}
void SliderCtrl::set_value(const boost::any& value, bool change_event)
{
m_disable_change_event = !change_event;
m_slider->SetValue(boost::any_cast<int>(value)*m_scale);
int val = boost::any_cast<int>(get_value());
m_textctrl->SetLabel(wxString::Format("%d", val));
m_disable_change_event = false;
}
boost::any& SliderCtrl::get_value()
{
// int ret_val;
// x_textctrl->GetValue().ToDouble(&val);
return m_value = int(m_slider->GetValue()/m_scale);
}
} // GUI } // GUI
} // Slic3r } // Slic3r

View File

@ -196,6 +196,10 @@ public:
return false; return false;
} }
void set_side_text_ptr(wxStaticText* side_text) {
m_side_text = side_text;
}
protected: protected:
MyButton* m_Undo_btn = nullptr; MyButton* m_Undo_btn = nullptr;
// Bitmap and Tooltip text for m_Undo_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one. // Bitmap and Tooltip text for m_Undo_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
@ -210,6 +214,8 @@ protected:
// Color for Label. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one. // Color for Label. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one.
const wxColour* m_label_color = nullptr; const wxColour* m_label_color = nullptr;
wxStaticText* m_side_text = nullptr;
// current value // current value
boost::any m_value; boost::any m_value;
@ -221,7 +227,7 @@ protected:
inline bool is_bad_field(const t_field& obj) { return obj->getSizer() == nullptr && obj->getWindow() == nullptr; } inline bool is_bad_field(const t_field& obj) { return obj->getSizer() == nullptr && obj->getWindow() == nullptr; }
/// Covenience function to determine whether this field is a valid window field. /// Covenience function to determine whether this field is a valid window field.
inline bool is_window_field(const t_field& obj) { return !is_bad_field(obj) && obj->getWindow() != nullptr; } inline bool is_window_field(const t_field& obj) { return !is_bad_field(obj) && obj->getWindow() != nullptr && obj->getSizer() == nullptr; }
/// Covenience function to determine whether this field is a valid sizer field. /// Covenience function to determine whether this field is a valid sizer field.
inline bool is_sizer_field(const t_field& obj) { return !is_bad_field(obj) && obj->getSizer() != nullptr; } inline bool is_sizer_field(const t_field& obj) { return !is_bad_field(obj) && obj->getSizer() != nullptr; }
@ -415,11 +421,44 @@ public:
boost::any& get_value()override { return m_value; } boost::any& get_value()override { return m_value; }
void enable() override { dynamic_cast<wxColourPickerCtrl*>(window)->Enable(); }; void enable() override { dynamic_cast<wxStaticText*>(window)->Enable(); };
void disable() override{ dynamic_cast<wxColourPickerCtrl*>(window)->Disable(); }; void disable() override{ dynamic_cast<wxStaticText*>(window)->Disable(); };
wxWindow* getWindow() override { return window; } wxWindow* getWindow() override { return window; }
}; };
class SliderCtrl : public Field {
using Field::Field;
public:
SliderCtrl(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
SliderCtrl(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
~SliderCtrl() {}
wxSizer* m_sizer{ nullptr };
wxTextCtrl* m_textctrl{ nullptr };
wxSlider* m_slider{ nullptr };
int m_scale = 10;
void BUILD() override;
void set_value(const int value, bool change_event = false);
void set_value(const boost::any& value, bool change_event = false);
boost::any& get_value() override;
void enable() override {
m_slider->Enable();
m_textctrl->Enable();
m_textctrl->SetEditable(true);
}
void disable() override{
m_slider->Disable();
m_textctrl->Disable();
m_textctrl->SetEditable(false);
}
wxSizer* getSizer() override { return m_sizer; }
wxWindow* getWindow() override { return dynamic_cast<wxWindow*>(m_slider); }
};
} // GUI } // GUI
} // Slic3r } // Slic3r

View File

@ -2950,7 +2950,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_mouse.set_start_position_2D_as_invalid(); m_mouse.set_start_position_2D_as_invalid();
#endif #endif
} }
else if (evt.Leaving())
{
// to remove hover when mouse goes out of this canvas
m_mouse.position = Pointf((coordf_t)pos.x, (coordf_t)pos.y);
render();
}
else if (evt.Leaving()) else if (evt.Leaving())
{ {
// to remove hover on objects when the mouse goes out of this canvas // to remove hover on objects when the mouse goes out of this canvas
@ -3184,6 +3190,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
} }
const Vec3d& size = bb.size(); const Vec3d& size = bb.size();
m_on_update_geometry_info_callback.call(size(0), size(1), size(2), m_gizmos.get_scale()); m_on_update_geometry_info_callback.call(size(0), size(1), size(2), m_gizmos.get_scale());
update_scale_values(size, m_gizmos.get_scale());
update_rotation_value(volumes[0]->get_angle_z(), "z");
} }
if ((m_gizmos.get_current_type() != Gizmos::Rotate) && (volumes.size() > 1)) if ((m_gizmos.get_current_type() != Gizmos::Rotate) && (volumes.size() > 1))
@ -3284,6 +3292,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
case Gizmos::Scale: case Gizmos::Scale:
{ {
m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale()); m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale());
Slic3r::GUI::update_settings_value();
break; break;
} }
case Gizmos::Rotate: case Gizmos::Rotate:

View File

@ -38,6 +38,8 @@
#include <wx/msgdlg.h> #include <wx/msgdlg.h>
#include <wx/settings.h> #include <wx/settings.h>
#include <wx/display.h> #include <wx/display.h>
#include <wx/collpane.h>
#include <wx/wupdlock.h>
#include "wxExtensions.hpp" #include "wxExtensions.hpp"
@ -53,12 +55,15 @@
#include "PresetBundle.hpp" #include "PresetBundle.hpp"
#include "UpdateDialogs.hpp" #include "UpdateDialogs.hpp"
#include "FirmwareDialog.hpp" #include "FirmwareDialog.hpp"
#include "GUI_ObjectParts.hpp"
#include "../Utils/PresetUpdater.hpp" #include "../Utils/PresetUpdater.hpp"
#include "../Config/Snapshot.hpp" #include "../Config/Snapshot.hpp"
#include "3DScene.hpp" #include "3DScene.hpp"
#include "libslic3r/I18N.hpp" #include "libslic3r/I18N.hpp"
#include "Model.hpp"
#include "LambdaObjectDialog.hpp"
namespace Slic3r { namespace GUI { namespace Slic3r { namespace GUI {
@ -123,10 +128,26 @@ wxLocale* g_wxLocale;
wxFont g_small_font; wxFont g_small_font;
wxFont g_bold_font; wxFont g_bold_font;
std::shared_ptr<ConfigOptionsGroup> m_optgroup; std::vector <std::shared_ptr<ConfigOptionsGroup>> m_optgroups;
double m_brim_width = 0.0; double m_brim_width = 0.0;
size_t m_label_width = 100;
wxButton* g_wiping_dialog_button = nullptr; wxButton* g_wiping_dialog_button = nullptr;
//showed/hided controls according to the view mode
wxWindow *g_right_panel = nullptr;
wxBoxSizer *g_frequently_changed_parameters_sizer = nullptr;
wxBoxSizer *g_expert_mode_part_sizer = nullptr;
wxBoxSizer *g_scrolled_window_sizer = nullptr;
wxBoxSizer *g_object_list_sizer = nullptr;
wxButton *g_btn_export_gcode = nullptr;
wxButton *g_btn_export_stl = nullptr;
wxButton *g_btn_reslice = nullptr;
wxButton *g_btn_print = nullptr;
wxButton *g_btn_send_gcode = nullptr;
wxStaticBitmap *g_manifold_warning_icon = nullptr;
bool g_show_print_info = false;
bool g_show_manifold_warning_icon = false;
static void init_label_colours() static void init_label_colours()
{ {
auto luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); auto luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
@ -206,6 +227,39 @@ void set_3DScene(_3DScene *scene)
g_3DScene = scene; g_3DScene = scene;
} }
void set_objects_from_perl( wxWindow* parent, wxBoxSizer *frequently_changed_parameters_sizer,
wxBoxSizer *expert_mode_part_sizer, wxBoxSizer *scrolled_window_sizer,
wxButton *btn_export_gcode,
wxButton *btn_export_stl, wxButton *btn_reslice,
wxButton *btn_print, wxButton *btn_send_gcode,
wxStaticBitmap *manifold_warning_icon)
{
g_right_panel = parent;
g_frequently_changed_parameters_sizer = frequently_changed_parameters_sizer;
g_expert_mode_part_sizer = expert_mode_part_sizer;
g_scrolled_window_sizer = scrolled_window_sizer;
g_btn_export_gcode = btn_export_gcode;
g_btn_export_stl = btn_export_stl;
g_btn_reslice = btn_reslice;
g_btn_print = btn_print;
g_btn_send_gcode = btn_send_gcode;
g_manifold_warning_icon = manifold_warning_icon;
}
void set_show_print_info(bool show)
{
g_show_print_info = show;
}
void set_show_manifold_warning_icon(bool show)
{
g_show_manifold_warning_icon = show;
}
void set_objects_list_sizer(wxBoxSizer *objects_list_sizer){
g_object_list_sizer = objects_list_sizer;
}
std::vector<Tab *>& get_tabs_list() std::vector<Tab *>& get_tabs_list()
{ {
return g_tabs_list; return g_tabs_list;
@ -332,10 +386,21 @@ enum ConfigMenuIDs {
ConfigMenuTakeSnapshot, ConfigMenuTakeSnapshot,
ConfigMenuUpdate, ConfigMenuUpdate,
ConfigMenuPreferences, ConfigMenuPreferences,
ConfigMenuModeSimple,
ConfigMenuModeExpert,
ConfigMenuLanguage, ConfigMenuLanguage,
ConfigMenuFlashFirmware, ConfigMenuFlashFirmware,
ConfigMenuCnt, ConfigMenuCnt,
}; };
ConfigMenuIDs get_view_mode()
{
if (!g_AppConfig->has("view_mode"))
return ConfigMenuModeSimple;
const auto mode = g_AppConfig->get("view_mode");
return mode == "expert" ? ConfigMenuModeExpert : ConfigMenuModeSimple;
}
static wxString dots("", wxConvUTF8); static wxString dots("", wxConvUTF8);
@ -353,8 +418,15 @@ void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_l
// local_menu->Append(config_id_base + ConfigMenuUpdate, _(L("Check for updates")), _(L("Check for configuration updates"))); // local_menu->Append(config_id_base + ConfigMenuUpdate, _(L("Check for updates")), _(L("Check for configuration updates")));
local_menu->AppendSeparator(); local_menu->AppendSeparator();
local_menu->Append(config_id_base + ConfigMenuPreferences, _(L("Preferences"))+dots+"\tCtrl+,", _(L("Application preferences"))); local_menu->Append(config_id_base + ConfigMenuPreferences, _(L("Preferences"))+dots+"\tCtrl+,", _(L("Application preferences")));
local_menu->Append(config_id_base + ConfigMenuLanguage, _(L("Change Application Language"))); local_menu->AppendSeparator();
auto mode_menu = new wxMenu();
mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeSimple, _(L("&Simple")), _(L("Simple View Mode")));
mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeExpert, _(L("&Expert")), _(L("Expert View Mode")));
mode_menu->Check(config_id_base + get_view_mode(), true);
local_menu->AppendSubMenu(mode_menu, _(L("&Mode")), _(L("Slic3r View Mode")));
local_menu->AppendSeparator(); local_menu->AppendSeparator();
local_menu->Append(config_id_base + ConfigMenuLanguage, _(L("Change Application Language")));
local_menu->AppendSeparator();
local_menu->Append(config_id_base + ConfigMenuFlashFirmware, _(L("Flash printer firmware")), _(L("Upload a firmware image into an Arduino based printer"))); local_menu->Append(config_id_base + ConfigMenuFlashFirmware, _(L("Flash printer firmware")), _(L("Upload a firmware image into an Arduino based printer")));
// TODO: for when we're able to flash dictionaries // TODO: for when we're able to flash dictionaries
// local_menu->Append(config_id_base + FirmwareMenuDict, _(L("Flash language file")), _(L("Upload a language dictionary file into a Prusa printer"))); // local_menu->Append(config_id_base + FirmwareMenuDict, _(L("Flash language file")), _(L("Upload a language dictionary file into a Prusa printer")));
@ -421,6 +493,13 @@ void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_l
break; break;
} }
}); });
mode_menu->Bind(wxEVT_MENU, [config_id_base](wxEvent& event) {
std::string mode = event.GetId() - config_id_base == ConfigMenuModeExpert ?
"expert" : "simple";
g_AppConfig->set("view_mode", mode);
g_AppConfig->save();
update_mode();
});
menu->Append(local_menu, _(L("&Configuration"))); menu->Append(local_menu, _(L("&Configuration")));
} }
@ -429,6 +508,26 @@ void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_languag
add_config_menu(menu, event_preferences_changed, event_language_change); add_config_menu(menu, event_preferences_changed, event_language_change);
} }
void open_model(wxWindow *parent, wxArrayString& input_files){
t_file_wild_card vec_FILE_WILDCARDS = get_file_wild_card();
std::vector<std::string> file_types = { "known", "stl", "obj", "amf", "3mf", "prusa" };
wxString MODEL_WILDCARD;
for (auto file_type : file_types)
MODEL_WILDCARD += vec_FILE_WILDCARDS.at(file_type) + "|";
auto dlg_title = _(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"));
auto dialog = new wxFileDialog(parent /*? parent : GetTopWindow(g_wxMainFrame)*/, dlg_title,
g_AppConfig->get_last_dir(), "",
MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
if (dialog->ShowModal() != wxID_OK) {
dialog->Destroy();
return ;
}
dialog->GetPaths(input_files);
dialog->Destroy();
}
// This is called when closing the application, when loading a config file or when starting the config wizard // This is called when closing the application, when loading a config file or when starting the config wizard
// to notify the user whether he is aware that some preset changes will be lost. // to notify the user whether he is aware that some preset changes will be lost.
bool check_unsaved_changes() bool check_unsaved_changes()
@ -757,6 +856,22 @@ unsigned get_colour_approx_luma(const wxColour &colour)
)); ));
} }
wxWindow* get_right_panel(){
return g_right_panel;
}
wxFrame* get_main_frame() {
return g_wxMainFrame;
}
wxNotebook * get_tab_panel() {
return g_wxTabPanel;
}
const size_t& label_width(){
return m_label_width;
}
void create_combochecklist(wxComboCtrl* comboCtrl, std::string text, std::string items, bool initial_value) void create_combochecklist(wxComboCtrl* comboCtrl, std::string text, std::string items, bool initial_value)
{ {
if (comboCtrl == nullptr) if (comboCtrl == nullptr)
@ -825,14 +940,37 @@ wxString from_u8(const std::string &str)
return wxString::FromUTF8(str.c_str()); return wxString::FromUTF8(str.c_str());
} }
void add_expert_mode_part( wxWindow* parent, wxBoxSizer* sizer,
Model &model,
int event_object_selection_changed,
int event_object_settings_changed,
int event_remove_object,
int event_update_scene)
{
set_event_object_selection_changed(event_object_selection_changed);
set_event_object_settings_changed(event_object_settings_changed);
set_event_remove_object(event_remove_object);
set_event_update_scene(event_update_scene);
set_objects_from_model(model);
init_mesh_icons();
// wxWindowUpdateLocker noUpdates(parent);
// add_objects_list(parent, sizer);
// add_collapsible_panes(parent, sizer);
}
void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer) void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer)
{ {
DynamicPrintConfig* config = &g_PresetBundle->prints.get_edited_preset().config; DynamicPrintConfig* config = &g_PresetBundle->prints.get_edited_preset().config;
m_optgroup = std::make_shared<ConfigOptionsGroup>(parent, "", config); std::shared_ptr<ConfigOptionsGroup> optgroup = std::make_shared<ConfigOptionsGroup>(parent, "", config);
const wxArrayInt& ar = preset_sizer->GetColWidths(); const wxArrayInt& ar = preset_sizer->GetColWidths();
m_optgroup->label_width = ar.IsEmpty() ? 100 : ar.front()-4; // doesn't work m_label_width = ar.IsEmpty() ? 100 : ar.front()-4;
m_optgroup->m_on_change = [config](t_config_option_key opt_key, boost::any value){ optgroup->label_width = m_label_width;
//Frequently changed parameters
optgroup->m_on_change = [config](t_config_option_key opt_key, boost::any value){
TabPrint* tab_print = nullptr; TabPrint* tab_print = nullptr;
for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++i) { for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++i) {
Tab *tab = dynamic_cast<Tab*>(g_wxTabPanel->GetPage(i)); Tab *tab = dynamic_cast<Tab*>(g_wxTabPanel->GetPage(i));
@ -847,7 +985,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
return; return;
if (opt_key == "fill_density"){ if (opt_key == "fill_density"){
value = m_optgroup->get_config_value(*config, opt_key); value = m_optgroups[ogFrequentlyChangingParameters]->get_config_value(*config, opt_key);
tab_print->set_value(opt_key, value); tab_print->set_value(opt_key, value);
tab_print->update(); tab_print->update();
} }
@ -870,14 +1008,14 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
} }
else{ //(opt_key == "support") else{ //(opt_key == "support")
const wxString& selection = boost::any_cast<wxString>(value); const wxString& selection = boost::any_cast<wxString>(value);
auto support_material = selection == _("None") ? false : true; auto support_material = selection == _("None") ? false : true;
new_conf.set_key_value("support_material", new ConfigOptionBool(support_material)); new_conf.set_key_value("support_material", new ConfigOptionBool(support_material));
if (selection == _("Everywhere")) if (selection == _("Everywhere"))
new_conf.set_key_value("support_material_buildplate_only", new ConfigOptionBool(false)); new_conf.set_key_value("support_material_buildplate_only", new ConfigOptionBool(false));
else if (selection == _("Support on build plate only")) else if (selection == _("Support on build plate only"))
new_conf.set_key_value("support_material_buildplate_only", new ConfigOptionBool(true)); new_conf.set_key_value("support_material_buildplate_only", new ConfigOptionBool(true));
} }
tab_print->load_config(new_conf); tab_print->load_config(new_conf);
} }
@ -885,10 +1023,10 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
tab_print->update_dirty(); tab_print->update_dirty();
}; };
Option option = m_optgroup->get_option("fill_density"); Option option = optgroup->get_option("fill_density");
option.opt.sidetext = ""; option.opt.sidetext = "";
option.opt.full_width = true; option.opt.full_width = true;
m_optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
ConfigOptionDef def; ConfigOptionDef def;
@ -907,7 +1045,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
def.default_value = new ConfigOptionStrings { selection }; def.default_value = new ConfigOptionStrings { selection };
option = Option(def, "support"); option = Option(def, "support");
option.opt.full_width = true; option.opt.full_width = true;
m_optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
m_brim_width = config->opt_float("brim_width"); m_brim_width = config->opt_float("brim_width");
def.label = L("Brim"); def.label = L("Brim");
@ -916,7 +1054,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
def.gui_type = ""; def.gui_type = "";
def.default_value = new ConfigOptionBool{ m_brim_width > 0.0 ? true : false }; def.default_value = new ConfigOptionBool{ m_brim_width > 0.0 ? true : false };
option = Option(def, "brim"); option = Option(def, "brim");
m_optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
Line line = { "", "" }; Line line = { "", "" };
@ -942,16 +1080,93 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
})); }));
return sizer; return sizer;
}; };
m_optgroup->append_line(line); optgroup->append_line(line);
sizer->Add(optgroup->sizer, 0, wxEXPAND | wxBOTTOM, 2);
m_optgroups.push_back(optgroup);// ogFrequentlyChangingParameters
sizer->Add(m_optgroup->sizer, 1, wxEXPAND | wxBOTTOM, 2); // Object List
add_objects_list(parent, sizer);
// Frequently Object Settings
add_object_settings(parent, sizer);
} }
ConfigOptionsGroup* get_optgroup() void show_frequently_changed_parameters(bool show)
{ {
return m_optgroup.get(); g_frequently_changed_parameters_sizer->Show(show);
if (!show) return;
for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++i) {
Tab *tab = dynamic_cast<Tab*>(g_wxTabPanel->GetPage(i));
if (!tab)
continue;
tab->update_wiping_button_visibility();
break;
}
}
void show_buttons(bool show)
{
g_btn_export_stl->Show(show);
g_btn_reslice->Show(show);
for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++i) {
TabPrinter *tab = dynamic_cast<TabPrinter*>(g_wxTabPanel->GetPage(i));
if (!tab)
continue;
g_btn_print->Show(show && !tab->m_config->opt_string("serial_port").empty());
g_btn_send_gcode->Show(show && !tab->m_config->opt_string("octoprint_host").empty());
break;
}
}
void show_info_sizer(bool show)
{
g_scrolled_window_sizer->Show(static_cast<size_t>(0), show);
g_scrolled_window_sizer->Show(1, show && g_show_print_info);
g_manifold_warning_icon->Show(show && g_show_manifold_warning_icon);
}
void update_mode()
{
wxWindowUpdateLocker noUpdates(g_right_panel);
// TODO There is a not the best place of it!
//*** Update style of the "Export G-code" button****
if (g_btn_export_gcode->GetFont() != bold_font()){
g_btn_export_gcode->SetBackgroundColour(wxColour(252, 77, 1));
g_btn_export_gcode->SetFont(bold_font());
}
// ***********************************
ConfigMenuIDs mode = get_view_mode();
// show_frequently_changed_parameters(mode >= ConfigMenuModeRegular);
// g_expert_mode_part_sizer->Show(mode == ConfigMenuModeExpert);
g_object_list_sizer->Show(mode == ConfigMenuModeExpert);
show_info_sizer(mode == ConfigMenuModeExpert);
show_buttons(mode == ConfigMenuModeExpert);
// TODO There is a not the best place of it!
// *** Update showing of the collpane_settings
// show_collpane_settings(mode == ConfigMenuModeExpert);
// *************************
g_right_panel->GetParent()->Layout();
g_right_panel->Layout();
}
bool is_expert_mode(){
return get_view_mode() == ConfigMenuModeExpert;
}
ConfigOptionsGroup* get_optgroup(size_t i)
{
return m_optgroups[i].get();
}
std::vector <std::shared_ptr<ConfigOptionsGroup>>& get_optgroups() {
return m_optgroups;
} }
wxButton* get_wiping_dialog_button() wxButton* get_wiping_dialog_button()

View File

@ -5,6 +5,7 @@
#include <vector> #include <vector>
#include "PrintConfig.hpp" #include "PrintConfig.hpp"
#include "../../libslic3r/Utils.hpp" #include "../../libslic3r/Utils.hpp"
#include "GUI_ObjectParts.hpp"
#include <wx/intl.h> #include <wx/intl.h>
#include <wx/string.h> #include <wx/string.h>
@ -12,7 +13,6 @@
class wxApp; class wxApp;
class wxWindow; class wxWindow;
class wxFrame; class wxFrame;
class wxFont;
class wxMenuBar; class wxMenuBar;
class wxNotebook; class wxNotebook;
class wxComboCtrl; class wxComboCtrl;
@ -24,6 +24,8 @@ class wxBoxSizer;
class wxFlexGridSizer; class wxFlexGridSizer;
class wxButton; class wxButton;
class wxFileDialog; class wxFileDialog;
class wxStaticBitmap;
class wxFont;
namespace Slic3r { namespace Slic3r {
@ -67,15 +69,15 @@ typedef std::map<std::string, std::string> t_file_wild_card;
inline t_file_wild_card& get_file_wild_card() { inline t_file_wild_card& get_file_wild_card() {
static t_file_wild_card FILE_WILDCARDS; static t_file_wild_card FILE_WILDCARDS;
if (FILE_WILDCARDS.empty()){ if (FILE_WILDCARDS.empty()){
FILE_WILDCARDS["known"] = "Known files (*.stl, *.obj, *.amf, *.xml, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.prusa;*.PRUSA"; FILE_WILDCARDS["known"] = "Known files (*.stl, *.obj, *.amf, *.xml, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.prusa;*.PRUSA";
FILE_WILDCARDS["stl"] = "STL files (*.stl)|*.stl;*.STL"; FILE_WILDCARDS["stl"] = "STL files (*.stl)|*.stl;*.STL";
FILE_WILDCARDS["obj"] = "OBJ files (*.obj)|*.obj;*.OBJ"; FILE_WILDCARDS["obj"] = "OBJ files (*.obj)|*.obj;*.OBJ";
FILE_WILDCARDS["amf"] = "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML"; FILE_WILDCARDS["amf"] = "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML";
FILE_WILDCARDS["3mf"] = "3MF files (*.3mf)|*.3mf;*.3MF;"; FILE_WILDCARDS["3mf"] = "3MF files (*.3mf)|*.3mf;*.3MF;";
FILE_WILDCARDS["prusa"] = "Prusa Control files (*.prusa)|*.prusa;*.PRUSA"; FILE_WILDCARDS["prusa"] = "Prusa Control files (*.prusa)|*.prusa;*.PRUSA";
FILE_WILDCARDS["ini"] = "INI files *.ini|*.ini;*.INI"; FILE_WILDCARDS["ini"] = "INI files *.ini|*.ini;*.INI";
FILE_WILDCARDS["gcode"] = "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC"; FILE_WILDCARDS["gcode"] = "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC";
FILE_WILDCARDS["svg"] = "SVG files *.svg|*.svg;*.SVG"; FILE_WILDCARDS["svg"] = "SVG files *.svg|*.svg;*.SVG";
} }
return FILE_WILDCARDS; return FILE_WILDCARDS;
} }
@ -100,11 +102,26 @@ void set_app_config(AppConfig *app_config);
void set_preset_bundle(PresetBundle *preset_bundle); void set_preset_bundle(PresetBundle *preset_bundle);
void set_preset_updater(PresetUpdater *updater); void set_preset_updater(PresetUpdater *updater);
void set_3DScene(_3DScene *scene); void set_3DScene(_3DScene *scene);
void set_objects_from_perl( wxWindow* parent,
wxBoxSizer *frequently_changed_parameters_sizer,
wxBoxSizer *expert_mode_part_sizer,
wxBoxSizer *scrolled_window_sizer,
wxButton *btn_export_gcode,
wxButton *btn_export_stl,
wxButton *btn_reslice,
wxButton *btn_print,
wxButton *btn_send_gcode,
wxStaticBitmap *manifold_warning_icon);
void set_show_print_info(bool show);
void set_show_manifold_warning_icon(bool show);
void set_objects_list_sizer(wxBoxSizer *objects_list_sizer);
AppConfig* get_app_config(); AppConfig* get_app_config();
wxApp* get_app(); wxApp* get_app();
PresetBundle* get_preset_bundle(); PresetBundle* get_preset_bundle();
wxNotebook* get_tab_panel(); wxFrame* get_main_frame();
wxNotebook * get_tab_panel();
wxNotebook* get_tab_panel();
const wxColour& get_label_clr_modified(); const wxColour& get_label_clr_modified();
const wxColour& get_label_clr_sys(); const wxColour& get_label_clr_sys();
@ -116,6 +133,11 @@ void set_label_clr_sys(const wxColour& clr);
const wxFont& small_font(); const wxFont& small_font();
const wxFont& bold_font(); const wxFont& bold_font();
void open_model(wxWindow *parent, wxArrayString& input_files);
wxWindow* get_right_panel();
const size_t& label_width();
Tab* get_tab(const std::string& name); Tab* get_tab(const std::string& name);
const std::vector<PresetTab>& get_preset_tabs(); const std::vector<PresetTab>& get_preset_tabs();
@ -161,6 +183,8 @@ void save_language();
void get_installed_languages(wxArrayString & names, wxArrayLong & identifiers); void get_installed_languages(wxArrayString & names, wxArrayLong & identifiers);
// select language from the list of installed languages // select language from the list of installed languages
bool select_language(wxArrayString & names, wxArrayLong & identifiers); bool select_language(wxArrayString & names, wxArrayLong & identifiers);
// update right panel of the Plater according to view mode
void update_mode();
std::vector<Tab *>& get_tabs_list(); std::vector<Tab *>& get_tabs_list();
bool checked_tab(Tab* tab); bool checked_tab(Tab* tab);
@ -180,13 +204,22 @@ wxString L_str(const std::string &str);
// Return wxString from std::string in UTF8 // Return wxString from std::string in UTF8
wxString from_u8(const std::string &str); wxString from_u8(const std::string &str);
void add_expert_mode_part( wxWindow* parent, wxBoxSizer* sizer,
Model &model,
int event_object_selection_changed,
int event_object_settings_changed,
int event_remove_object,
int event_update_scene);
void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer); void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer);
// Update view mode according to selected menu
void update_mode();
bool is_expert_mode();
// Callback to trigger a configuration update timer on the Plater. // Callback to trigger a configuration update timer on the Plater.
static PerlCallback g_on_request_update_callback; static PerlCallback g_on_request_update_callback;
ConfigOptionsGroup* get_optgroup(); ConfigOptionsGroup* get_optgroup(size_t i);
std::vector <std::shared_ptr<ConfigOptionsGroup>>& get_optgroups();
wxButton* get_wiping_dialog_button(); wxButton* get_wiping_dialog_button();
void add_export_option(wxFileDialog* dlg, const std::string& format); void add_export_option(wxFileDialog* dlg, const std::string& format);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,126 @@
#ifndef slic3r_GUI_ObjectParts_hpp_
#define slic3r_GUI_ObjectParts_hpp_
class wxWindow;
class wxSizer;
class wxBoxSizer;
class wxString;
class wxArrayString;
class wxMenu;
class wxDataViewEvent;
class wxKeyEvent;
namespace Slic3r {
class ModelObject;
class Model;
namespace GUI {
enum ogGroup{
ogFrequentlyChangingParameters,
ogFrequentlyObjectSettings,
ogCurrentSettings
// ogObjectSettings,
// ogObjectMovers,
// ogPartSettings
};
enum LambdaTypeIDs{
LambdaTypeBox,
LambdaTypeCylinder,
LambdaTypeSphere,
LambdaTypeSlab
};
struct OBJECT_PARAMETERS
{
LambdaTypeIDs type = LambdaTypeBox;
double dim[3];// = { 1.0, 1.0, 1.0 };
int cyl_r = 1;
int cyl_h = 1;
double sph_rho = 1.0;
double slab_h = 1.0;
double slab_z = 0.0;
};
void add_collapsible_panes(wxWindow* parent, wxBoxSizer* sizer);
void add_objects_list(wxWindow* parent, wxBoxSizer* sizer);
void add_object_settings(wxWindow* parent, wxBoxSizer* sizer);
void show_collpane_settings(bool expert_mode);
wxMenu *create_add_settings_popupmenu(bool is_part);
wxMenu *create_add_part_popupmenu();
wxMenu *create_part_settings_popupmenu();
// Add object to the list
//void add_object(const std::string &name);
void add_object_to_list(const std::string &name, ModelObject* model_object);
// Delete object from the list
void delete_object_from_list();
// Delete all objects from the list
void delete_all_objects_from_list();
// Set count of object on c++ side
void set_object_count(int idx, int count);
// Set object scale on c++ side
void set_object_scale(int idx, int scale);
// Unselect all objects in the list on c++ side
void unselect_objects();
// Select current object in the list on c++ side
void select_current_object(int idx);
// Remove objects/sub-object from the list
void remove();
void object_ctrl_selection_changed();
void object_ctrl_context_menu();
void object_ctrl_key_event(wxKeyEvent& event);
void object_ctrl_item_value_change(wxDataViewEvent& event);
void show_context_menu();
void init_mesh_icons();
void set_event_object_selection_changed(const int& event);
void set_event_object_settings_changed(const int& event);
void set_event_remove_object(const int& event);
void set_event_update_scene(const int& event);
void set_objects_from_model(Model &model);
bool is_parts_changed();
bool is_part_settings_changed();
void load_part( wxWindow* parent, ModelObject* model_object,
wxArrayString& part_names, const bool is_modifier);
void load_lambda(wxWindow* parent, ModelObject* model_object,
wxArrayString& part_names, const bool is_modifier);
void on_btn_load(wxWindow* parent, bool is_modifier = false, bool is_lambda = false);
void on_btn_del();
void on_btn_split(const bool split_part);
void on_btn_move_up();
void on_btn_move_down();
void parts_changed(int obj_idx);
void part_selection_changed();
void update_settings_value();
// show/hide "Extruder" column for Objects List
void set_extruder_column_hidden(bool hide);
// update extruder in current config
void update_extruder_in_config(const wxString& selection);
// update scale values after scale unit changing or "gizmos"
void update_scale_values();
void update_scale_values(const Pointf3& size, float scale);
// update rotation values object selection changing
void update_rotation_values();
// update rotation value after "gizmos"
void update_rotation_value(const double angle, const std::string& axis);
void on_begin_drag(wxDataViewEvent &event);
void on_drop_possible(wxDataViewEvent &event);
void on_drop(wxDataViewEvent &event);
// update extruder column for objects_ctrl according to extruders count
void update_objects_list_extruder_column(const int extruders_count);
} //namespace GUI
} //namespace Slic3r
#endif //slic3r_GUI_ObjectParts_hpp_

View File

@ -0,0 +1,176 @@
#include "LambdaObjectDialog.hpp"
#include <wx/window.h>
#include <wx/button.h>
#include "OptionsGroup.hpp"
namespace Slic3r
{
namespace GUI
{
static wxString dots("", wxConvUTF8);
LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
{
Create(parent, wxID_ANY, _(L("Lambda Object")),
wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
// instead of double dim[3] = { 1.0, 1.0, 1.0 };
object_parameters.dim[0] = 1.0;
object_parameters.dim[1] = 1.0;
object_parameters.dim[2] = 1.0;
sizer = new wxBoxSizer(wxVERTICAL);
// modificator options
m_modificator_options_book = new wxChoicebook( this, wxID_ANY, wxDefaultPosition,
wxDefaultSize, wxCHB_TOP);
sizer->Add(m_modificator_options_book, 1, wxEXPAND| wxALL, 10);
auto optgroup = init_modificator_options_page(_(L("Box")));
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
int opt_id = opt_key == "l" ? 0 :
opt_key == "w" ? 1 :
opt_key == "h" ? 2 : -1;
if (opt_id < 0) return;
object_parameters.dim[opt_id] = boost::any_cast<double>(value);
};
ConfigOptionDef def;
def.width = 70;
def.type = coFloat;
def.default_value = new ConfigOptionFloat{ 1.0 };
def.label = L("L");
Option option(def, "l");
optgroup->append_single_option_line(option);
def.label = L("W");
option = Option(def, "w");
optgroup->append_single_option_line(option);
def.label = L("H");
option = Option(def, "h");
optgroup->append_single_option_line(option);
optgroup = init_modificator_options_page(_(L("Cylinder")));
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
int val = boost::any_cast<int>(value);
if (opt_key == "cyl_r")
object_parameters.cyl_r = val;
else if (opt_key == "cyl_h")
object_parameters.cyl_h = val;
else return;
};
def.type = coInt;
def.default_value = new ConfigOptionInt{ 1 };
def.label = L("Radius");
option = Option(def, "cyl_r");
optgroup->append_single_option_line(option);
def.label = L("Height");
option = Option(def, "cyl_h");
optgroup->append_single_option_line(option);
optgroup = init_modificator_options_page(_(L("Sphere")));
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
if (opt_key == "sph_rho")
object_parameters.sph_rho = boost::any_cast<double>(value);
else return;
};
def.type = coFloat;
def.default_value = new ConfigOptionFloat{ 1.0 };
def.label = L("Rho");
option = Option(def, "sph_rho");
optgroup->append_single_option_line(option);
optgroup = init_modificator_options_page(_(L("Slab")));
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
double val = boost::any_cast<double>(value);
if (opt_key == "slab_z")
object_parameters.slab_z = val;
else if (opt_key == "slab_h")
object_parameters.slab_h = val;
else return;
};
def.label = L("H");
option = Option(def, "slab_h");
optgroup->append_single_option_line(option);
def.label = L("Initial Z");
option = Option(def, "slab_z");
optgroup->append_single_option_line(option);
Bind(wxEVT_CHOICEBOOK_PAGE_CHANGED, ([this](wxCommandEvent e)
{
auto page_idx = m_modificator_options_book->GetSelection();
if (page_idx < 0) return;
switch (page_idx)
{
case 0:
object_parameters.type = LambdaTypeBox;
break;
case 1:
object_parameters.type = LambdaTypeCylinder;
break;
case 2:
object_parameters.type = LambdaTypeSphere;
break;
case 3:
object_parameters.type = LambdaTypeSlab;
break;
default:
break;
}
}));
auto button_sizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
wxButton* btn_OK = static_cast<wxButton*>(FindWindowById(wxID_OK, this));
btn_OK->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
// validate user input
if (!CanClose())return;
EndModal(wxID_OK);
Destroy();
});
wxButton* btn_CANCEL = static_cast<wxButton*>(FindWindowById(wxID_CANCEL, this));
btn_CANCEL->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
// validate user input
if (!CanClose())return;
EndModal(wxID_CANCEL);
Destroy();
});
sizer->Add(button_sizer, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10);
SetSizer(sizer);
sizer->Fit(this);
sizer->SetSizeHints(this);
}
// Called from the constructor.
// Create a panel for a rectangular / circular / custom bed shape.
ConfigOptionsGroupShp LambdaObjectDialog::init_modificator_options_page(wxString title){
auto panel = new wxPanel(m_modificator_options_book);
ConfigOptionsGroupShp optgroup;
optgroup = std::make_shared<ConfigOptionsGroup>(panel, _(L("Add")) + " " +title + " " +dots);
optgroup->label_width = 100;
m_optgroups.push_back(optgroup);
panel->SetSizerAndFit(optgroup->sizer);
m_modificator_options_book->AddPage(panel, title);
return optgroup;
}
} //namespace GUI
} //namespace Slic3r

View File

@ -0,0 +1,35 @@
#ifndef slic3r_LambdaObjectDialog_hpp_
#define slic3r_LambdaObjectDialog_hpp_
#include "GUI.hpp"
#include <wx/dialog.h>
#include <wx/sizer.h>
#include <wx/choicebk.h>
namespace Slic3r
{
namespace GUI
{
using ConfigOptionsGroupShp = std::shared_ptr<ConfigOptionsGroup>;
class LambdaObjectDialog : public wxDialog
{
wxChoicebook* m_modificator_options_book;
std::vector <ConfigOptionsGroupShp> m_optgroups;
public:
LambdaObjectDialog(wxWindow* parent);
~LambdaObjectDialog(){}
bool CanClose() { return true; } // ???
OBJECT_PARAMETERS& ObjectParameters(){ return object_parameters; }
ConfigOptionsGroupShp init_modificator_options_page(wxString title);
// Note whether the window was already closed, so a pending update is not executed.
bool m_already_closed = false;
OBJECT_PARAMETERS object_parameters;
wxBoxSizer* sizer = nullptr;
};
} //namespace GUI
} //namespace Slic3r
#endif //slic3r_LambdaObjectDialog_hpp_

View File

@ -30,6 +30,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
opt.gui_type.compare("i_enum_closed") == 0) { opt.gui_type.compare("i_enum_closed") == 0) {
m_fields.emplace(id, STDMOVE(Choice::Create<Choice>(parent(), opt, id))); m_fields.emplace(id, STDMOVE(Choice::Create<Choice>(parent(), opt, id)));
} else if (opt.gui_type.compare("slider") == 0) { } else if (opt.gui_type.compare("slider") == 0) {
m_fields.emplace(id, STDMOVE(SliderCtrl::Create<SliderCtrl>(parent(), opt, id)));
} else if (opt.gui_type.compare("i_spin") == 0) { // Spinctrl } else if (opt.gui_type.compare("i_spin") == 0) { // Spinctrl
} else if (opt.gui_type.compare("legend") == 0) { // StaticText } else if (opt.gui_type.compare("legend") == 0) { // StaticText
m_fields.emplace(id, STDMOVE(StaticText::Create<StaticText>(parent(), opt, id))); m_fields.emplace(id, STDMOVE(StaticText::Create<StaticText>(parent(), opt, id)));
@ -88,17 +89,23 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
if (!this->m_disabled) if (!this->m_disabled)
this->back_to_sys_value(opt_id); this->back_to_sys_value(opt_id);
}; };
if (!m_show_modified_btns) {
field->m_Undo_btn->Hide();
field->m_Undo_to_sys_btn->Hide();
}
// if (nonsys_btn_icon != nullptr)
// field->set_nonsys_btn_icon(*nonsys_btn_icon);
// assign function objects for callbacks, etc. // assign function objects for callbacks, etc.
return field; return field;
} }
void OptionsGroup::add_undo_buttuns_to_sizer(wxSizer* sizer, const t_field& field)
{
if (!m_show_modified_btns) {
field->m_Undo_btn->Hide();
field->m_Undo_to_sys_btn->Hide();
return;
}
sizer->Add(field->m_Undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL);
sizer->Add(field->m_Undo_btn, 0, wxALIGN_CENTER_VERTICAL);
}
void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* = nullptr*/) { void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* = nullptr*/) {
//! if (line.sizer != nullptr || (line.widget != nullptr && line.full_width > 0)){ //! if (line.sizer != nullptr || (line.widget != nullptr && line.full_width > 0)){
if ( (line.sizer != nullptr || line.widget != nullptr) && line.full_width){ if ( (line.sizer != nullptr || line.widget != nullptr) && line.full_width){
@ -133,8 +140,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
const auto& field = build_field(option); const auto& field = build_field(option);
auto btn_sizer = new wxBoxSizer(wxHORIZONTAL); auto btn_sizer = new wxBoxSizer(wxHORIZONTAL);
btn_sizer->Add(field->m_Undo_to_sys_btn); add_undo_buttuns_to_sizer(btn_sizer, field);
btn_sizer->Add(field->m_Undo_btn);
tmp_sizer->Add(btn_sizer, 0, wxEXPAND | wxALL, 0); tmp_sizer->Add(btn_sizer, 0, wxEXPAND | wxALL, 0);
if (is_window_field(field)) if (is_window_field(field))
tmp_sizer->Add(field->getWindow(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5); tmp_sizer->Add(field->getWindow(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5);
@ -149,6 +155,18 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
m_panel->Layout(); m_panel->Layout();
#endif /* __WXGTK__ */ #endif /* __WXGTK__ */
// if we have an extra column, build it
if (extra_column) {
if (extra_column) {
grid_sizer->Add(extra_column(parent(), line), 0, wxALIGN_CENTER_VERTICAL, 0);
}
else {
// if the callback provides no sizer for the extra cell, put a spacer
grid_sizer->AddSpacer(1);
}
}
// Build a label if we have it // Build a label if we have it
wxStaticText* label=nullptr; wxStaticText* label=nullptr;
if (label_width != 0) { if (label_width != 0) {
@ -163,7 +181,8 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
wxDefaultPosition, wxSize(label_width, -1), label_style); wxDefaultPosition, wxSize(label_width, -1), label_style);
label->SetFont(label_font); label->SetFont(label_font);
label->Wrap(label_width); // avoid a Linux/GTK bug label->Wrap(label_width); // avoid a Linux/GTK bug
grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5); grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) |
(m_flag == ogSIDE_OPTIONS_VERTICAL ? wxTOP : wxALIGN_CENTER_VERTICAL), 5);
if (line.label_tooltip.compare("") != 0) if (line.label_tooltip.compare("") != 0)
label->SetToolTip(line.label_tooltip); label->SetToolTip(line.label_tooltip);
} }
@ -177,28 +196,35 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
return; return;
} }
// if we have a single option with no sidetext just add it directly to the grid sizer // If we're here, we have more than one option or a single option with sidetext
auto sizer = new wxBoxSizer(wxHORIZONTAL); // so we need a horizontal sizer to arrange these things
grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM|wxTOP|wxLEFT), staticbox ? 0 : 1); auto sizer = new wxBoxSizer(m_flag == ogSIDE_OPTIONS_VERTICAL ? wxVERTICAL : wxHORIZONTAL);
grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1);
// If we have a single option with no sidetext just add it directly to the grid sizer
if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 && if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 &&
option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0) { option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0) {
const auto& option = option_set.front(); const auto& option = option_set.front();
const auto& field = build_field(option, label); const auto& field = build_field(option, label);
sizer->Add(field->m_Undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL); add_undo_buttuns_to_sizer(sizer, field);
sizer->Add(field->m_Undo_btn, 0, wxALIGN_CENTER_VERTICAL);
if (is_window_field(field)) if (is_window_field(field))
sizer->Add(field->getWindow(), option.opt.full_width ? 1 : 0, (option.opt.full_width ? wxEXPAND : 0) | sizer->Add(field->getWindow(), option.opt.full_width ? 1 : 0, (option.opt.full_width ? wxEXPAND : 0) |
wxBOTTOM | wxTOP | wxALIGN_CENTER_VERTICAL, (wxOSX||!staticbox) ? 0 : 2); wxBOTTOM | wxTOP | wxALIGN_CENTER_VERTICAL, (wxOSX||!staticbox) ? 0 : 2);
if (is_sizer_field(field)) if (is_sizer_field(field))
sizer->Add(field->getSizer(), 0, (option.opt.full_width ? wxEXPAND : 0) | wxALIGN_CENTER_VERTICAL, 0); sizer->Add(field->getSizer(), 1, (option.opt.full_width ? wxEXPAND : 0) | wxALIGN_CENTER_VERTICAL, 0);
return; return;
} }
// if we're here, we have more than one option or a single option with sidetext for (auto opt : option_set) {
// so we need a horizontal sizer to arrange these things
for (auto opt : option_set) {
ConfigOptionDef option = opt.opt; ConfigOptionDef option = opt.opt;
wxSizer* sizer_tmp;
if (m_flag == ogSIDE_OPTIONS_VERTICAL){
auto sz = new wxFlexGridSizer(1, 3, 2, 2);
sz->RemoveGrowableCol(2);
sizer_tmp = sz;
}
else
sizer_tmp = sizer;
// add label if any // add label if any
if (option.label != "") { if (option.label != "") {
wxString str_label = _(option.label); wxString str_label = _(option.label);
@ -208,34 +234,38 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
// L_str(option.label); // L_str(option.label);
label = new wxStaticText(parent(), wxID_ANY, str_label + ":", wxDefaultPosition, wxDefaultSize); label = new wxStaticText(parent(), wxID_ANY, str_label + ":", wxDefaultPosition, wxDefaultSize);
label->SetFont(label_font); label->SetFont(label_font);
sizer->Add(label, 0, wxALIGN_CENTER_VERTICAL, 0); sizer_tmp->Add(label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 0);
} }
// add field // add field
const Option& opt_ref = opt; const Option& opt_ref = opt;
auto& field = build_field(opt_ref, label); auto& field = build_field(opt_ref, label);
sizer->Add(field->m_Undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL); add_undo_buttuns_to_sizer(sizer_tmp, field);
sizer->Add(field->m_Undo_btn, 0, wxALIGN_CENTER_VERTICAL, 0);
is_sizer_field(field) ? is_sizer_field(field) ?
sizer->Add(field->getSizer(), 0, wxALIGN_CENTER_VERTICAL, 0) : sizer_tmp->Add(field->getSizer(), 0, wxALIGN_CENTER_VERTICAL, 0) :
sizer->Add(field->getWindow(), 0, wxALIGN_CENTER_VERTICAL, 0); sizer_tmp->Add(field->getWindow(), 0, wxALIGN_CENTER_VERTICAL, 0);
// add sidetext if any // add sidetext if any
if (option.sidetext != "") { if (option.sidetext != "") {
auto sidetext = new wxStaticText(parent(), wxID_ANY, _(option.sidetext), wxDefaultPosition, wxDefaultSize); auto sidetext = new wxStaticText( parent(), wxID_ANY, _(option.sidetext), wxDefaultPosition,
wxSize(sidetext_width, -1)/*wxDefaultSize*/, wxALIGN_LEFT);
sidetext->SetFont(sidetext_font); sidetext->SetFont(sidetext_font);
sizer->Add(sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4); sizer_tmp->Add(sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, m_flag == ogSIDE_OPTIONS_VERTICAL ? 0 : 4);
field->set_side_text_ptr(sidetext);
} }
// add side widget if any // add side widget if any
if (opt.side_widget != nullptr) { if (opt.side_widget != nullptr) {
sizer->Add(opt.side_widget(parent())/*!.target<wxWindow>()*/, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 1); //! requires verification sizer_tmp->Add(opt.side_widget(parent())/*!.target<wxWindow>()*/, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 1); //! requires verification
} }
if (opt.opt_id != option_set.back().opt_id) //! istead of (opt != option_set.back()) if (opt.opt_id != option_set.back().opt_id && m_flag != ogSIDE_OPTIONS_VERTICAL) //! istead of (opt != option_set.back())
{ {
sizer->AddSpacer(6); sizer_tmp->AddSpacer(6);
} }
if (m_flag == ogSIDE_OPTIONS_VERTICAL)
sizer->Add(sizer_tmp, 0, wxALIGN_RIGHT|wxALL, 0);
} }
// add extra sizers if any // add extra sizers if any
for (auto extra_widget : line.get_extra_widgets()) { for (auto extra_widget : line.get_extra_widgets()) {
@ -259,7 +289,7 @@ void OptionsGroup::on_change_OG(const t_config_option_key& opt_id, const boost::
Option ConfigOptionsGroup::get_option(const std::string& opt_key, int opt_index /*= -1*/) Option ConfigOptionsGroup::get_option(const std::string& opt_key, int opt_index /*= -1*/)
{ {
if (!m_config->has(opt_key)) { if (!m_config->has(opt_key)) {
std::cerr << "No " << opt_key << " in ConfigOptionsGroup config."; std::cerr << "No " << opt_key << " in ConfigOptionsGroup config.\n";
} }
std::string opt_id = opt_index == -1 ? opt_key : opt_key + "#" + std::to_string(opt_index); std::string opt_id = opt_index == -1 ? opt_key : opt_key + "#" + std::to_string(opt_index);

View File

@ -26,9 +26,13 @@
namespace Slic3r { namespace GUI { namespace Slic3r { namespace GUI {
enum ogDrawFlag{
ogDEFAULT,
ogSIDE_OPTIONS_VERTICAL
};
/// Widget type describes a function object that returns a wxWindow (our widget) and accepts a wxWidget (parent window). /// Widget type describes a function object that returns a wxWindow (our widget) and accepts a wxWidget (parent window).
using widget_t = std::function<wxSizer*(wxWindow*)>;//!std::function<wxWindow*(wxWindow*)>; using widget_t = std::function<wxSizer*(wxWindow*)>;//!std::function<wxWindow*(wxWindow*)>;
using column_t = std::function<wxSizer*(const Line&)>;
//auto default_label_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT); //GetSystemColour //auto default_label_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT); //GetSystemColour
//auto modified_label_clr = *new wxColour(254, 189, 101); //auto modified_label_clr = *new wxColour(254, 189, 101);
@ -71,10 +75,13 @@ private:
std::vector<widget_t> m_extra_widgets;//! {std::vector<widget_t>()}; std::vector<widget_t> m_extra_widgets;//! {std::vector<widget_t>()};
}; };
using column_t = std::function<wxWindow*(wxWindow* parent, const Line&)>;//std::function<wxSizer*(const Line&)>;
using t_optionfield_map = std::map<t_config_option_key, t_field>; using t_optionfield_map = std::map<t_config_option_key, t_field>;
using t_opt_map = std::map< std::string, std::pair<std::string, int> >; using t_opt_map = std::map< std::string, std::pair<std::string, int> >;
class OptionsGroup { class OptionsGroup {
wxStaticBox* stb;
public: public:
const bool staticbox {true}; const bool staticbox {true};
const wxString title {wxString("")}; const wxString title {wxString("")};
@ -88,8 +95,7 @@ public:
wxFont sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; wxFont sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
int sidetext_width{ -1 };
// std::function<const wxBitmap&()> nonsys_btn_icon{ nullptr };
/// Returns a copy of the pointer of the parent wxWindow. /// Returns a copy of the pointer of the parent wxWindow.
/// Accessor function is because users are not allowed to change the parent /// Accessor function is because users are not allowed to change the parent
@ -101,6 +107,11 @@ public:
return m_parent; return m_parent;
#endif /* __WXGTK__ */ #endif /* __WXGTK__ */
} }
#ifdef __WXGTK__
wxWindow* get_parent() const {
return m_parent;
}
#endif /* __WXGTK__ */
void append_line(const Line& line, wxStaticText** colored_Label = nullptr); void append_line(const Line& line, wxStaticText** colored_Label = nullptr);
Line create_single_option_line(const Option& option) const; Line create_single_option_line(const Option& option) const;
@ -124,23 +135,39 @@ public:
return out; return out;
} }
bool set_side_text(const t_config_option_key& opt_key, const wxString& side_text) {
if (m_fields.find(opt_key) == m_fields.end()) return false;
auto st = m_fields.at(opt_key)->m_side_text;
if (!st) return false;
st->SetLabel(side_text);
return true;
}
void set_name(const wxString& new_name) {
stb->SetLabel(new_name);
}
inline void enable() { for (auto& field : m_fields) field.second->enable(); } inline void enable() { for (auto& field : m_fields) field.second->enable(); }
inline void disable() { for (auto& field : m_fields) field.second->disable(); } inline void disable() { for (auto& field : m_fields) field.second->disable(); }
void set_flag(ogDrawFlag flag) { m_flag = flag; }
void set_grid_vgap(int gap) { m_grid_sizer->SetVGap(gap); }
void set_show_modified_btns_val(bool show) { void set_show_modified_btns_val(bool show) {
m_show_modified_btns = show; m_show_modified_btns = show;
} }
OptionsGroup(wxWindow* _parent, const wxString& title, bool is_tab_opt=false) : OptionsGroup( wxWindow* _parent, const wxString& title, bool is_tab_opt = false,
m_parent(_parent), title(title), m_show_modified_btns(is_tab_opt), staticbox(title!="") { ogDrawFlag flag = ogDEFAULT, column_t extra_clmn = nullptr) :
auto stb = new wxStaticBox(_parent, wxID_ANY, title); m_parent(_parent), title(title), m_show_modified_btns(is_tab_opt),
staticbox(title!=""), m_flag(flag), extra_column(extra_clmn){
stb = new wxStaticBox(_parent, wxID_ANY, title);
stb->SetFont(bold_font()); stb->SetFont(bold_font());
sizer = (staticbox ? new wxStaticBoxSizer(stb/*new wxStaticBox(_parent, wxID_ANY, title)*/, wxVERTICAL) : new wxBoxSizer(wxVERTICAL)); sizer = (staticbox ? new wxStaticBoxSizer(stb, wxVERTICAL) : new wxBoxSizer(wxVERTICAL));
auto num_columns = 1U; auto num_columns = 1U;
if (label_width != 0) num_columns++; if (label_width != 0) num_columns++;
if (extra_column != nullptr) num_columns++; if (extra_column != nullptr) num_columns++;
m_grid_sizer = new wxFlexGridSizer(0, num_columns, 0,0); m_grid_sizer = new wxFlexGridSizer(0, num_columns, 1,0);
static_cast<wxFlexGridSizer*>(m_grid_sizer)->SetFlexibleDirection(wxHORIZONTAL); static_cast<wxFlexGridSizer*>(m_grid_sizer)->SetFlexibleDirection(wxBOTH/*wxHORIZONTAL*/);
static_cast<wxFlexGridSizer*>(m_grid_sizer)->AddGrowableCol(label_width != 0); static_cast<wxFlexGridSizer*>(m_grid_sizer)->AddGrowableCol(label_width != 0);
#ifdef __WXGTK__ #ifdef __WXGTK__
m_panel = new wxPanel( _parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_panel = new wxPanel( _parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
@ -164,6 +191,8 @@ protected:
// "true" if option is created in preset tabs // "true" if option is created in preset tabs
bool m_show_modified_btns{ false }; bool m_show_modified_btns{ false };
ogDrawFlag m_flag{ ogDEFAULT };
// This panel is needed for correct showing of the ToolTips for Button, StaticText and CheckBox // This panel is needed for correct showing of the ToolTips for Button, StaticText and CheckBox
// Tooltips on GTK doesn't work inside wxStaticBoxSizer unless you insert a panel // Tooltips on GTK doesn't work inside wxStaticBoxSizer unless you insert a panel
// inside it before you insert the other controls. // inside it before you insert the other controls.
@ -177,6 +206,7 @@ protected:
const t_field& build_field(const t_config_option_key& id, const ConfigOptionDef& opt, wxStaticText* label = nullptr); const t_field& build_field(const t_config_option_key& id, const ConfigOptionDef& opt, wxStaticText* label = nullptr);
const t_field& build_field(const t_config_option_key& id, wxStaticText* label = nullptr); const t_field& build_field(const t_config_option_key& id, wxStaticText* label = nullptr);
const t_field& build_field(const Option& opt, wxStaticText* label = nullptr); const t_field& build_field(const Option& opt, wxStaticText* label = nullptr);
void add_undo_buttuns_to_sizer(wxSizer* sizer, const t_field& field);
virtual void on_kill_focus (){}; virtual void on_kill_focus (){};
virtual void on_change_OG(const t_config_option_key& opt_id, const boost::any& value); virtual void on_change_OG(const t_config_option_key& opt_id, const boost::any& value);
@ -186,8 +216,9 @@ protected:
class ConfigOptionsGroup: public OptionsGroup { class ConfigOptionsGroup: public OptionsGroup {
public: public:
ConfigOptionsGroup(wxWindow* parent, const wxString& title, DynamicPrintConfig* _config = nullptr, bool is_tab_opt = false) : ConfigOptionsGroup( wxWindow* parent, const wxString& title, DynamicPrintConfig* _config = nullptr,
OptionsGroup(parent, title, is_tab_opt), m_config(_config) {} bool is_tab_opt = false, ogDrawFlag flag = ogDEFAULT, column_t extra_clmn = nullptr) :
OptionsGroup(parent, title, is_tab_opt, flag, extra_clmn), m_config(_config) {}
/// reference to libslic3r config, non-owning pointer (?). /// reference to libslic3r config, non-owning pointer (?).
DynamicPrintConfig* m_config {nullptr}; DynamicPrintConfig* m_config {nullptr};

View File

@ -687,8 +687,8 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
} }
if (opt_key == "fill_density") if (opt_key == "fill_density")
{ {
boost::any val = get_optgroup()->get_config_value(*m_config, opt_key); boost::any val = get_optgroup(ogFrequentlyChangingParameters)->get_config_value(*m_config, opt_key);
get_optgroup()->set_value(opt_key, val); get_optgroup(ogFrequentlyChangingParameters)->set_value(opt_key, val);
} }
if (opt_key == "support_material" || opt_key == "support_material_buildplate_only") if (opt_key == "support_material" || opt_key == "support_material_buildplate_only")
{ {
@ -697,12 +697,12 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
m_config->opt_bool("support_material_buildplate_only") ? m_config->opt_bool("support_material_buildplate_only") ?
_("Support on build plate only") : _("Support on build plate only") :
_("Everywhere"); _("Everywhere");
get_optgroup()->set_value("support", new_selection); get_optgroup(ogFrequentlyChangingParameters)->set_value("support", new_selection);
} }
if (opt_key == "brim_width") if (opt_key == "brim_width")
{ {
bool val = m_config->opt_float("brim_width") > 0.0 ? true : false; bool val = m_config->opt_float("brim_width") > 0.0 ? true : false;
get_optgroup()->set_value("brim", val); get_optgroup(ogFrequentlyChangingParameters)->set_value("brim", val);
} }
if (opt_key == "wipe_tower" || opt_key == "single_extruder_multi_material" || opt_key == "extruders_count" ) if (opt_key == "wipe_tower" || opt_key == "single_extruder_multi_material" || opt_key == "extruders_count" )
@ -719,10 +719,8 @@ void Tab::update_wiping_button_visibility() {
bool multiple_extruders = dynamic_cast<ConfigOptionFloats*>((m_preset_bundle->printers.get_edited_preset().config).option("nozzle_diameter"))->values.size() > 1; bool multiple_extruders = dynamic_cast<ConfigOptionFloats*>((m_preset_bundle->printers.get_edited_preset().config).option("nozzle_diameter"))->values.size() > 1;
bool single_extruder_mm = dynamic_cast<ConfigOptionBool*>( (m_preset_bundle->printers.get_edited_preset().config).option("single_extruder_multi_material"))->value; bool single_extruder_mm = dynamic_cast<ConfigOptionBool*>( (m_preset_bundle->printers.get_edited_preset().config).option("single_extruder_multi_material"))->value;
if (wipe_tower_enabled && multiple_extruders && single_extruder_mm) get_wiping_dialog_button()->Show(wipe_tower_enabled && multiple_extruders && single_extruder_mm);
get_wiping_dialog_button()->Show();
else get_wiping_dialog_button()->Hide();
(get_wiping_dialog_button()->GetParent())->Layout(); (get_wiping_dialog_button()->GetParent())->Layout();
} }
@ -789,18 +787,18 @@ void Tab::update_preset_description_line()
void Tab::update_frequently_changed_parameters() void Tab::update_frequently_changed_parameters()
{ {
boost::any value = get_optgroup()->get_config_value(*m_config, "fill_density"); boost::any value = get_optgroup(ogFrequentlyChangingParameters)->get_config_value(*m_config, "fill_density");
get_optgroup()->set_value("fill_density", value); get_optgroup(ogFrequentlyChangingParameters)->set_value("fill_density", value);
wxString new_selection = !m_config->opt_bool("support_material") ? wxString new_selection = !m_config->opt_bool("support_material") ?
_("None") : _("None") :
m_config->opt_bool("support_material_buildplate_only") ? m_config->opt_bool("support_material_buildplate_only") ?
_("Support on build plate only") : _("Support on build plate only") :
_("Everywhere"); _("Everywhere");
get_optgroup()->set_value("support", new_selection); get_optgroup(ogFrequentlyChangingParameters)->set_value("support", new_selection);
bool val = m_config->opt_float("brim_width") > 0.0 ? true : false; bool val = m_config->opt_float("brim_width") > 0.0 ? true : false;
get_optgroup()->set_value("brim", val); get_optgroup(ogFrequentlyChangingParameters)->set_value("brim", val);
update_wiping_button_visibility(); update_wiping_button_visibility();
} }
@ -1478,7 +1476,7 @@ void TabPrinter::build_fff()
Line line{ _(L("Bed shape")), "" }; Line line{ _(L("Bed shape")), "" };
line.widget = [this](wxWindow* parent){ line.widget = [this](wxWindow* parent){
auto btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); auto btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
// btn->SetFont(Slic3r::GUI::small_font); btn->SetFont(Slic3r::GUI::small_font());
btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("printer_empty.png")), wxBITMAP_TYPE_PNG)); btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("printer_empty.png")), wxBITMAP_TYPE_PNG));
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
@ -1546,7 +1544,7 @@ void TabPrinter::build_fff()
auto serial_test = [this](wxWindow* parent){ auto serial_test = [this](wxWindow* parent){
auto btn = m_serial_test_btn = new wxButton(parent, wxID_ANY, auto btn = m_serial_test_btn = new wxButton(parent, wxID_ANY,
_(L("Test")), wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); _(L("Test")), wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
// btn->SetFont($Slic3r::GUI::small_font); btn->SetFont(Slic3r::GUI::small_font());
btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("wrench.png")), wxBITMAP_TYPE_PNG)); btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("wrench.png")), wxBITMAP_TYPE_PNG));
auto sizer = new wxBoxSizer(wxHORIZONTAL); auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn); sizer->Add(btn);
@ -1832,6 +1830,7 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){
build_extruder_pages(); build_extruder_pages();
reload_config(); reload_config();
on_value_change("extruders_count", extruders_count); on_value_change("extruders_count", extruders_count);
update_objects_list_extruder_column(extruders_count);
} }
void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::string opt_key) void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::string opt_key)
@ -2174,7 +2173,7 @@ void Tab::load_current_preset()
// checking out if this Tab exists till this moment // checking out if this Tab exists till this moment
if (!checked_tab(this)) if (!checked_tab(this))
return; return;
update_tab_ui(); update_tab_ui();
// update show/hide tabs // update show/hide tabs
if (m_name == "printer"){ if (m_name == "printer"){

View File

@ -267,11 +267,11 @@ public:
void on_value_change(const std::string& opt_key, const boost::any& value); void on_value_change(const std::string& opt_key, const boost::any& value);
void update_wiping_button_visibility();
protected: protected:
void on_presets_changed(); void on_presets_changed();
void update_preset_description_line(); void update_preset_description_line();
void update_frequently_changed_parameters(); void update_frequently_changed_parameters();
void update_wiping_button_visibility();
void update_tab_presets(wxComboCtrl* ui, bool show_incompatible); void update_tab_presets(wxComboCtrl* ui, bool show_incompatible);
void fill_icon_descriptions(); void fill_icon_descriptions();
void set_tooltips_text(); void set_tooltips_text();

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,14 @@
#include <wx/checklst.h> #include <wx/checklst.h>
#include <wx/combo.h> #include <wx/combo.h>
#include <wx/dataview.h> #include <wx/dataview.h>
#include <wx/dc.h>
#include <wx/collpane.h>
#include <wx/wupdlock.h>
#include <wx/button.h>
#include <wx/slider.h>
#include <vector>
#include <set>
class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup
{ {
@ -65,4 +73,568 @@ public:
void SetItemsCnt(int cnt) { m_cnt_open_items = cnt; } void SetItemsCnt(int cnt) { m_cnt_open_items = cnt; }
}; };
// *** PrusaCollapsiblePane ***
// ----------------------------------------------------------------------------
class PrusaCollapsiblePane : public wxCollapsiblePane
{
public:
PrusaCollapsiblePane() {}
PrusaCollapsiblePane(wxWindow *parent,
wxWindowID winid,
const wxString& label,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxCP_DEFAULT_STYLE,
const wxValidator& val = wxDefaultValidator,
const wxString& name = wxCollapsiblePaneNameStr)
{
Create(parent, winid, label, pos, size, style, val, name);
}
~PrusaCollapsiblePane() {}
void OnStateChange(const wxSize& sz); //override/hide of OnStateChange from wxCollapsiblePane
virtual bool Show(bool show = true) override {
wxCollapsiblePane::Show(show);
OnStateChange(GetBestSize());
return true;
}
};
// *** PrusaCollapsiblePaneMSW *** used only #ifdef __WXMSW__
// ----------------------------------------------------------------------------
#ifdef __WXMSW__
class PrusaCollapsiblePaneMSW : public PrusaCollapsiblePane//wxCollapsiblePane
{
wxButton* m_pDisclosureTriangleButton = nullptr;
wxBitmap m_bmp_close;
wxBitmap m_bmp_open;
public:
PrusaCollapsiblePaneMSW() {}
PrusaCollapsiblePaneMSW( wxWindow *parent,
wxWindowID winid,
const wxString& label,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxCP_DEFAULT_STYLE,
const wxValidator& val = wxDefaultValidator,
const wxString& name = wxCollapsiblePaneNameStr)
{
Create(parent, winid, label, pos, size, style, val, name);
}
~PrusaCollapsiblePaneMSW() {}
bool Create(wxWindow *parent,
wxWindowID id,
const wxString& label,
const wxPoint& pos,
const wxSize& size,
long style,
const wxValidator& val,
const wxString& name);
void UpdateBtnBmp();
void SetLabel(const wxString &label) override;
bool Layout() override;
void Collapse(bool collapse) override;
};
#endif //__WXMSW__
// *****************************************************************************
// ----------------------------------------------------------------------------
// PrusaObjectDataViewModelNode: a node inside PrusaObjectDataViewModel
// ----------------------------------------------------------------------------
class PrusaObjectDataViewModelNode;
WX_DEFINE_ARRAY_PTR(PrusaObjectDataViewModelNode*, MyObjectTreeModelNodePtrArray);
class PrusaObjectDataViewModelNode
{
PrusaObjectDataViewModelNode* m_parent;
MyObjectTreeModelNodePtrArray m_children;
wxIcon m_empty_icon;
public:
PrusaObjectDataViewModelNode(const wxString &name, int instances_count=1, int scale=100) {
m_parent = NULL;
m_name = name;
m_copy = wxString::Format("%d", instances_count);
m_scale = wxString::Format("%d%%", scale);
m_type = "object";
m_volume_id = -1;
#ifdef __WXGTK__
// it's necessary on GTK because of control have to know if this item will be container
// in another case you couldn't to add subitem for this item
// it will be produce "segmentation fault"
m_container = true;
#endif //__WXGTK__
set_object_action_icon();
}
PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent,
const wxString& sub_obj_name,
const wxIcon& icon,
const wxString& extruder,
const int volume_id=-1) {
m_parent = parent;
m_name = sub_obj_name;
m_copy = wxEmptyString;
m_scale = wxEmptyString;
m_icon = icon;
m_type = "volume";
m_volume_id = volume_id;
m_extruder = extruder;
set_part_action_icon();
}
~PrusaObjectDataViewModelNode()
{
// free all our children nodes
size_t count = m_children.GetCount();
for (size_t i = 0; i < count; i++)
{
PrusaObjectDataViewModelNode *child = m_children[i];
delete child;
}
}
wxString m_name;
wxIcon& m_icon = m_empty_icon;
wxString m_copy;
wxString m_scale;
std::string m_type;
int m_volume_id;
bool m_container = false;
wxString m_extruder = "default";
wxBitmap m_action_icon;
bool IsContainer() const
{
return m_container;
}
PrusaObjectDataViewModelNode* GetParent()
{
return m_parent;
}
MyObjectTreeModelNodePtrArray& GetChildren()
{
return m_children;
}
PrusaObjectDataViewModelNode* GetNthChild(unsigned int n)
{
return m_children.Item(n);
}
void Insert(PrusaObjectDataViewModelNode* child, unsigned int n)
{
m_children.Insert(child, n);
}
void Append(PrusaObjectDataViewModelNode* child)
{
if (!m_container)
m_container = true;
m_children.Add(child);
}
void RemoveAllChildren()
{
if (GetChildCount() == 0)
return;
for (size_t id = GetChildCount() - 1; id >= 0; --id)
{
if (m_children.Item(id)->GetChildCount() > 0)
m_children[id]->RemoveAllChildren();
auto node = m_children[id];
m_children.RemoveAt(id);
delete node;
}
}
size_t GetChildCount() const
{
return m_children.GetCount();
}
bool SetValue(const wxVariant &variant, unsigned int col)
{
switch (col)
{
case 0:{
wxDataViewIconText data;
data << variant;
m_icon = data.GetIcon();
m_name = data.GetText();
return true;}
case 1:
m_copy = variant.GetString();
return true;
case 2:
m_scale = variant.GetString();
return true;
case 3:
m_extruder = variant.GetString();
return true;
case 4:
m_action_icon << variant;
return true;
default:
printf("MyObjectTreeModel::SetValue: wrong column");
}
return false;
}
void SetIcon(const wxIcon &icon)
{
m_icon = icon;
}
void SetType(const std::string& type){
m_type = type;
}
const std::string& GetType(){
return m_type;
}
void SetVolumeId(const int& volume_id){
m_volume_id = volume_id;
}
const int& GetVolumeId(){
return m_volume_id;
}
// use this function only for childrens
void AssignAllVal(PrusaObjectDataViewModelNode& from_node)
{
// ! Don't overwrite other values because of equality of this values for all children --
m_name = from_node.m_name;
m_icon = from_node.m_icon;
m_volume_id = from_node.m_volume_id;
m_extruder = from_node.m_extruder;
}
bool SwapChildrens(int frst_id, int scnd_id) {
if (GetChildCount() < 2 ||
frst_id < 0 || frst_id >= GetChildCount() ||
scnd_id < 0 || scnd_id >= GetChildCount())
return false;
PrusaObjectDataViewModelNode new_scnd = *GetNthChild(frst_id);
PrusaObjectDataViewModelNode new_frst = *GetNthChild(scnd_id);
new_scnd.m_volume_id = m_children.Item(scnd_id)->m_volume_id;
new_frst.m_volume_id = m_children.Item(frst_id)->m_volume_id;
m_children.Item(frst_id)->AssignAllVal(new_frst);
m_children.Item(scnd_id)->AssignAllVal(new_scnd);
return true;
}
// Set action icons for node
void set_object_action_icon();
void set_part_action_icon();
};
// ----------------------------------------------------------------------------
// PrusaObjectDataViewModel
// ----------------------------------------------------------------------------
class PrusaObjectDataViewModel :public wxDataViewModel
{
std::vector<PrusaObjectDataViewModelNode*> m_objects;
public:
PrusaObjectDataViewModel(){}
~PrusaObjectDataViewModel()
{
for (auto object : m_objects)
delete object;
}
wxDataViewItem Add(wxString &name);
wxDataViewItem Add(wxString &name, int instances_count, int scale);
wxDataViewItem AddChild(const wxDataViewItem &parent_item,
const wxString &name,
const wxIcon& icon,
const int = 0,
const bool create_frst_child = true);
wxDataViewItem Delete(const wxDataViewItem &item);
void DeleteAll();
void DeleteChildren(wxDataViewItem& parent);
wxDataViewItem GetItemById(int obj_idx);
int GetIdByItem(wxDataViewItem& item);
int GetVolumeIdByItem(wxDataViewItem& item);
bool IsEmpty() { return m_objects.empty(); }
// helper method for wxLog
wxString GetName(const wxDataViewItem &item) const;
wxString GetCopy(const wxDataViewItem &item) const;
wxString GetScale(const wxDataViewItem &item) const;
wxIcon& GetIcon(const wxDataViewItem &item) const;
// helper methods to change the model
virtual unsigned int GetColumnCount() const override { return 3;}
virtual wxString GetColumnType(unsigned int col) const override{ return wxT("string"); }
virtual void GetValue(wxVariant &variant,
const wxDataViewItem &item, unsigned int col) const override;
virtual bool SetValue(const wxVariant &variant,
const wxDataViewItem &item, unsigned int col) override;
bool SetValue(const wxVariant &variant, const int item_idx, unsigned int col);
wxDataViewItem MoveChildUp(const wxDataViewItem &item);
wxDataViewItem MoveChildDown(const wxDataViewItem &item);
// For parent move child from cur_volume_id place to new_volume_id
// Remaining items will moved up/down accordingly
wxDataViewItem ReorganizeChildren(int cur_volume_id,
int new_volume_id,
const wxDataViewItem &parent);
// virtual bool IsEnabled(const wxDataViewItem &item,
// unsigned int col) const override;
virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override;
virtual bool IsContainer(const wxDataViewItem &item) const override;
virtual unsigned int GetChildren(const wxDataViewItem &parent,
wxDataViewItemArray &array) const override;
// Is the container just a header or an item with all columns
// In our case it is an item with all columns
virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; }
};
// ----------------------------------------------------------------------------
// MyCustomRenderer
// ----------------------------------------------------------------------------
class MyCustomRenderer : public wxDataViewCustomRenderer
{
public:
// This renderer can be either activatable or editable, for demonstration
// purposes. In real programs, you should select whether the user should be
// able to activate or edit the cell and it doesn't make sense to switch
// between the two -- but this is just an example, so it doesn't stop us.
explicit MyCustomRenderer(wxDataViewCellMode mode)
: wxDataViewCustomRenderer("string", mode, wxALIGN_CENTER)
{ }
virtual bool Render(wxRect rect, wxDC *dc, int state) override/*wxOVERRIDE*/
{
dc->SetBrush(*wxLIGHT_GREY_BRUSH);
dc->SetPen(*wxTRANSPARENT_PEN);
rect.Deflate(2);
dc->DrawRoundedRectangle(rect, 5);
RenderText(m_value,
0, // no offset
wxRect(dc->GetTextExtent(m_value)).CentreIn(rect),
dc,
state);
return true;
}
virtual bool ActivateCell(const wxRect& WXUNUSED(cell),
wxDataViewModel *WXUNUSED(model),
const wxDataViewItem &WXUNUSED(item),
unsigned int WXUNUSED(col),
const wxMouseEvent *mouseEvent) override/*wxOVERRIDE*/
{
wxString position;
if (mouseEvent)
position = wxString::Format("via mouse at %d, %d", mouseEvent->m_x, mouseEvent->m_y);
else
position = "from keyboard";
// wxLogMessage("MyCustomRenderer ActivateCell() %s", position);
return false;
}
virtual wxSize GetSize() const override/*wxOVERRIDE*/
{
return wxSize(60, 20);
}
virtual bool SetValue(const wxVariant &value) override/*wxOVERRIDE*/
{
m_value = value.GetString();
return true;
}
virtual bool GetValue(wxVariant &WXUNUSED(value)) const override/*wxOVERRIDE*/{ return true; }
virtual bool HasEditorCtrl() const override/*wxOVERRIDE*/{ return true; }
virtual wxWindow*
CreateEditorCtrl(wxWindow* parent,
wxRect labelRect,
const wxVariant& value) override/*wxOVERRIDE*/
{
wxTextCtrl* text = new wxTextCtrl(parent, wxID_ANY, value,
labelRect.GetPosition(),
labelRect.GetSize(),
wxTE_PROCESS_ENTER);
text->SetInsertionPointEnd();
return text;
}
virtual bool
GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value) override/*wxOVERRIDE*/
{
wxTextCtrl* text = wxDynamicCast(ctrl, wxTextCtrl);
if (!text)
return false;
value = text->GetValue();
return true;
}
private:
wxString m_value;
};
// ******************************* EXPERIMENTS **********************************************
enum SelectedSlider {
ssUndef,
ssLower,
ssHigher
};
enum TicksAction{
taOnIcon,
taAdd,
taDel
};
class PrusaDoubleSlider : public wxControl
{
public:
PrusaDoubleSlider(
wxWindow *parent,
wxWindowID id,
int lowerValue,
int higherValue,
int minValue,
int maxValue,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxSL_HORIZONTAL,
const wxValidator& val = wxDefaultValidator,
const wxString& name = wxEmptyString);
int GetLowerValue() const {
return m_lower_value;
}
int GetHigherValue() const {
return m_higher_value;
}
int GetActiveValue() const;
wxSize DoGetBestSize() const override;
void SetLowerValue(const int lower_val);
void SetHigherValue(const int higher_val);
void SetMaxValue(const int max_value);
void SetKoefForLabels(const double koef) {
m_label_koef = koef;
}
void SetSliderValues(const std::vector<double>& values) {
m_values = values;
}
void OnPaint(wxPaintEvent& ){ render();}
void OnLeftDown(wxMouseEvent& event);
void OnMotion(wxMouseEvent& event);
void OnLeftUp(wxMouseEvent& event);
void OnEnterWin(wxMouseEvent& event){ enter_window(event, true); }
void OnLeaveWin(wxMouseEvent& event){ enter_window(event, false); }
void OnWheel(wxMouseEvent& event);
void OnKeyDown(wxKeyEvent &event);
void OnKeyUp(wxKeyEvent &event);
void OnRightDown(wxMouseEvent& event);
void OnRightUp(wxMouseEvent& event);
protected:
void render();
void draw_focus_rect();
void draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoint pt_end);
void draw_scroll_line(wxDC& dc, const int lower_pos, const int higher_pos);
void draw_thumb(wxDC& dc, const wxCoord& pos_coord, const SelectedSlider& selection);
void draw_thumbs(wxDC& dc, const wxCoord& lower_pos, const wxCoord& higher_pos);
void draw_ticks(wxDC& dc);
void draw_one_layer_icon(wxDC& dc);
void draw_thumb_item(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection);
void draw_info_line_with_icon(wxDC& dc, const wxPoint& pos, SelectedSlider selection);
void draw_thumb_text(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) const;
void update_thumb_rect(const wxCoord& begin_x, const wxCoord& begin_y, const SelectedSlider& selection);
void detect_selected_slider(const wxPoint& pt, const bool is_mouse_wheel = false);
void correct_lower_value();
void correct_higher_value();
void move_current_thumb(const bool condition);
void action_tick(const TicksAction action);
void enter_window(wxMouseEvent& event, const bool enter);
bool is_point_in_rect(const wxPoint& pt, const wxRect& rect);
bool is_horizontal() const { return m_style == wxSL_HORIZONTAL; }
double get_scroll_step();
wxString get_label(const SelectedSlider& selection) const;
void get_lower_and_higher_position(int& lower_pos, int& higher_pos);
int get_value_from_position(const wxCoord x, const wxCoord y);
wxCoord get_position_from_value(const int value);
wxSize get_size();
void get_size(int *w, int *h);
private:
int m_min_value;
int m_max_value;
int m_lower_value;
int m_higher_value;
wxBitmap m_bmp_thumb_higher;
wxBitmap m_bmp_thumb_lower;
wxBitmap m_bmp_add_tick_on;
wxBitmap m_bmp_add_tick_off;
wxBitmap m_bmp_del_tick_on;
wxBitmap m_bmp_del_tick_off;
wxBitmap m_bmp_one_layer_lock_on;
wxBitmap m_bmp_one_layer_lock_off;
wxBitmap m_bmp_one_layer_unlock_on;
wxBitmap m_bmp_one_layer_unlock_off;
SelectedSlider m_selection;
bool m_is_left_down = false;
bool m_is_right_down = false;
bool m_is_one_layer = false;
bool m_is_focused = false;
bool m_is_action_icon_focesed = false;
bool m_is_one_layer_icon_focesed = false;
wxRect m_rect_lower_thumb;
wxRect m_rect_higher_thumb;
wxRect m_rect_tick_action;
wxRect m_rect_one_layer_icon;
wxSize m_thumb_size;
int m_tick_icon_dim;
int m_lock_icon_dim = 16;
long m_style;
float m_label_koef = 1.0;
// control's view variables
wxCoord SLIDER_MARGIN; // margin around slider
wxPen DARK_ORANGE_PEN;
wxPen ORANGE_PEN;
wxPen LIGHT_ORANGE_PEN;
wxPen DARK_GREY_PEN;
wxPen GREY_PEN;
wxPen LIGHT_GREY_PEN;
std::vector<wxPen*> line_pens;
std::vector<wxPen*> segm_pens;
std::set<int> m_ticks;
std::vector<double> m_values;
};
// ******************************************************************************************
#endif // slic3r_GUI_wxExtensions_hpp_ #endif // slic3r_GUI_wxExtensions_hpp_

View File

@ -87,6 +87,80 @@ 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"), (wxBoxSizer*)wxPli_sv_2_object(aTHX_ ui_sizer, "Wx::BoxSizer"),
(wxFlexGridSizer*)wxPli_sv_2_object(aTHX_ ui_p_sizer, "Wx::FlexGridSizer")); %}; (wxFlexGridSizer*)wxPli_sv_2_object(aTHX_ ui_p_sizer, "Wx::FlexGridSizer")); %};
void add_expert_mode_part( SV *ui_parent, SV *ui_sizer,
Model *model,
int event_object_selection_changed,
int event_object_settings_changed,
int event_remove_object,
int event_update_scene)
%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"),
*model,
event_object_selection_changed,
event_object_settings_changed,
event_remove_object,
event_update_scene); %};
void set_objects_from_perl( SV *ui_parent,
SV *frequently_changed_parameters_sizer,
SV *expert_mode_part_sizer,
SV *scrolled_window_sizer,
SV *btn_export_gcode,
SV *btn_export_stl,
SV *btn_reslice,
SV *btn_print,
SV *btn_send_gcode,
SV *manifold_warning_icon)
%code%{ Slic3r::GUI::set_objects_from_perl(
(wxWindow *)wxPli_sv_2_object(aTHX_ ui_parent, "Wx::Window"),
(wxBoxSizer *)wxPli_sv_2_object(aTHX_ frequently_changed_parameters_sizer, "Wx::BoxSizer"),
(wxBoxSizer *)wxPli_sv_2_object(aTHX_ expert_mode_part_sizer, "Wx::BoxSizer"),
(wxBoxSizer *)wxPli_sv_2_object(aTHX_ scrolled_window_sizer, "Wx::BoxSizer"),
(wxButton *)wxPli_sv_2_object(aTHX_ btn_export_gcode, "Wx::Button"),
(wxButton *)wxPli_sv_2_object(aTHX_ btn_export_stl, "Wx::Button"),
(wxButton *)wxPli_sv_2_object(aTHX_ btn_reslice, "Wx::Button"),
(wxButton *)wxPli_sv_2_object(aTHX_ btn_print, "Wx::Button"),
(wxButton *)wxPli_sv_2_object(aTHX_ btn_send_gcode, "Wx::Button"),
(wxStaticBitmap *)wxPli_sv_2_object(aTHX_ manifold_warning_icon, "Wx::StaticBitmap")); %};
void set_show_print_info(bool show)
%code%{ Slic3r::GUI::set_show_print_info(show); %};
void set_show_manifold_warning_icon(bool show)
%code%{ Slic3r::GUI::set_show_manifold_warning_icon(show); %};
void update_mode()
%code%{ Slic3r::GUI::update_mode(); %};
void add_object_to_list(const char *name, SV *object_model)
%code%{ Slic3r::GUI::add_object_to_list(
name,
(ModelObject *)wxPli_sv_2_object(aTHX_ object_model, "Slic3r::Model::Object") ); %};
void delete_object_from_list()
%code%{ Slic3r::GUI::delete_object_from_list(); %};
void delete_all_objects_from_list()
%code%{ Slic3r::GUI::delete_all_objects_from_list(); %};
void set_object_count(int idx, int count)
%code%{ Slic3r::GUI::set_object_count(idx, count); %};
void set_object_scale(int idx, int scale)
%code%{ Slic3r::GUI::set_object_scale(idx, scale); %};
void unselect_objects()
%code%{ Slic3r::GUI::unselect_objects(); %};
void select_current_object(int idx)
%code%{ Slic3r::GUI::select_current_object(idx); %};
void remove_obj()
%code%{ Slic3r::GUI::remove(); %};
void update_rotation_value(double angle, const char *axis)
%code%{ Slic3r::GUI::update_rotation_value(angle, axis); %};
std::string fold_utf8_to_ascii(const char *src) std::string fold_utf8_to_ascii(const char *src)
%code%{ RETVAL = Slic3r::fold_utf8_to_ascii(src); %}; %code%{ RETVAL = Slic3r::fold_utf8_to_ascii(src); %};