Merge remote-tracking branch 'origin/new_main_page_ui' into dev
@ -26,6 +26,14 @@ our $appController;
|
||||
our $VALUE_CHANGE_EVENT = Wx::NewEventType;
|
||||
# 2) To inform about a preset selection change or a "modified" status change.
|
||||
our $PRESETS_CHANGED_EVENT = Wx::NewEventType;
|
||||
# 3) To inform about a change of object selection
|
||||
our $OBJECT_SELECTION_CHANGED_EVENT = Wx::NewEventType;
|
||||
# 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 {
|
||||
my ($class, %params) = @_;
|
||||
@ -114,6 +122,8 @@ sub new {
|
||||
|
||||
$self->update_ui_from_settings;
|
||||
|
||||
Slic3r::GUI::update_mode();
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
@ -133,7 +143,12 @@ sub _init_tabpanel {
|
||||
});
|
||||
|
||||
if (!$self->{no_plater}) {
|
||||
$panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel), L("Plater"));
|
||||
$panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel,
|
||||
event_object_selection_changed => $OBJECT_SELECTION_CHANGED_EVENT,
|
||||
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}) {
|
||||
$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);
|
||||
$self->{options_tabs} = {};
|
||||
for my $tab_name (qw(print filament sla_material printer)) {
|
||||
|
@ -49,7 +49,7 @@ my $PreventListEvents = 0;
|
||||
our $appController;
|
||||
|
||||
sub new {
|
||||
my ($class, $parent) = @_;
|
||||
my ($class, $parent, %params) = @_;
|
||||
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
$self->{config} = Slic3r::Config::new_from_defaults_keys([qw(
|
||||
bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width variable_layer_height
|
||||
@ -57,6 +57,13 @@ sub new {
|
||||
nozzle_diameter single_extruder_multi_material wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width
|
||||
wipe_tower_rotation_angle extruder_colour filament_colour max_print_height 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
|
||||
$self->{model} = Slic3r::Model->new;
|
||||
# C++ Slic3r::Print with Perl extensions in Slic3r/Print.pm
|
||||
@ -74,7 +81,7 @@ sub new {
|
||||
});
|
||||
|
||||
# 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
|
||||
my $on_select_object = sub {
|
||||
@ -128,7 +135,9 @@ sub new {
|
||||
}
|
||||
$_->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);
|
||||
|
||||
#update print and start background processing
|
||||
@ -362,37 +371,12 @@ sub new {
|
||||
# }
|
||||
|
||||
### Panel for right column
|
||||
$self->{right_panel} = Wx::Panel->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
|
||||
### Scrolled Window for info boxes
|
||||
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;
|
||||
}
|
||||
});
|
||||
# $self->{right_panel} = Wx::Panel->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
$self->{right_panel} = Wx::ScrolledWindow->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
$self->{right_panel}->SetScrollbars(0, 1, 1, 1);
|
||||
|
||||
# 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_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);
|
||||
@ -460,6 +444,7 @@ sub new {
|
||||
# } else {
|
||||
# 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 { Slic3r::GUI::remove_obj() }); # explicitly pass no argument to remove
|
||||
# EVT_BUTTON($self, $self->{btn_reset}, sub { $self->reset; });
|
||||
# EVT_BUTTON($self, $self->{btn_arrange}, sub { $self->arrange; });
|
||||
# EVT_BUTTON($self, $self->{btn_increase}, sub { $self->increase; });
|
||||
@ -476,7 +461,7 @@ sub new {
|
||||
$_->SetDropTarget(Slic3r::GUI::Plater::DropTarget->new($self))
|
||||
for grep defined($_),
|
||||
$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 {
|
||||
my ($self, $event) = @_;
|
||||
@ -555,15 +540,32 @@ sub new {
|
||||
$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);
|
||||
|
||||
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 $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->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->AddGrowableCol(1, 1);
|
||||
$grid_sizer->AddGrowableCol(3, 1);
|
||||
@ -578,28 +580,45 @@ sub new {
|
||||
);
|
||||
while (my $field = 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);
|
||||
$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);
|
||||
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}->Hide;
|
||||
# $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($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);
|
||||
$h_sizer->Add($self->{object_info_manifold_warning_icon}, 0);
|
||||
$h_sizer->Add($self->{"object_info_$field"}, 0);
|
||||
$grid_sizer->Add($h_sizer, 0, wxEXPAND);
|
||||
$h_sizer->Add($text, 0);
|
||||
$h_sizer->Add($self->{object_info_manifold_warning_icon}, 0, wxLEFT, 2);
|
||||
$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 {
|
||||
$grid_sizer->Add($text, 0);
|
||||
$grid_sizer->Add($self->{"object_info_$field"}, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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]);
|
||||
|
||||
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_print}, 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($object_info_sizer, 0, wxEXPAND, 0);
|
||||
$scrolled_window_sizer->Add($print_info_sizer, 0, wxEXPAND, 0);
|
||||
# $scrolled_window_sizer->Add($self->{list}, 1, wxEXPAND, 5);
|
||||
# $scrolled_window_sizer->Add($object_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);
|
||||
$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);
|
||||
$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);
|
||||
$hsizer->Add($self->{preview_notebook}, 1, wxEXPAND | wxTOP, 1);
|
||||
@ -637,6 +661,18 @@ sub new {
|
||||
|
||||
$sizer->SetSizeHints($self);
|
||||
$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
|
||||
@ -647,6 +683,7 @@ sub new {
|
||||
}
|
||||
|
||||
$self->update_ui_from_settings();
|
||||
$self->Layout;
|
||||
|
||||
return $self;
|
||||
}
|
||||
@ -921,12 +958,10 @@ sub load_model_objects {
|
||||
foreach my $obj_idx (@obj_idx) {
|
||||
my $object = $self->{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))
|
||||
if $self->{list}->can('SetItemFont'); # legacy code for wxPerl < 0.9918 not supporting SetItemFont()
|
||||
|
||||
$self->{list}->SetItem($obj_idx, 1, $model_object->instances_count);
|
||||
$self->{list}->SetItem($obj_idx, 2, ($model_object->instances->[0]->scaling_factor * 100) . "%");
|
||||
# Add object to list on c++ side
|
||||
Slic3r::GUI::add_object_to_list($object->name, $model_object);
|
||||
|
||||
|
||||
# $self->reset_thumbnail($obj_idx);
|
||||
}
|
||||
@ -936,8 +971,6 @@ sub load_model_objects {
|
||||
# zoom to objects
|
||||
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->schedule_background_process;
|
||||
@ -972,7 +1005,8 @@ sub remove {
|
||||
splice @{$self->{objects}}, $obj_idx, 1;
|
||||
$self->{model}->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->select_object(undef);
|
||||
@ -992,7 +1026,8 @@ sub reset {
|
||||
@{$self->{objects}} = ();
|
||||
$self->{model}->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->select_object(undef);
|
||||
@ -1014,7 +1049,8 @@ sub increase {
|
||||
);
|
||||
$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
|
||||
$self->stop_background_process;
|
||||
@ -1042,7 +1078,8 @@ sub decrease {
|
||||
$model_object->delete_last_instance;
|
||||
$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) {
|
||||
# The "decrease" came from the "set number of copies" dialog.
|
||||
$self->remove;
|
||||
@ -1052,10 +1089,6 @@ sub decrease {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($self->{objects}[$obj_idx]) {
|
||||
$self->{list}->Select($obj_idx, 0);
|
||||
$self->{list}->Select($obj_idx, 1);
|
||||
}
|
||||
$self->update;
|
||||
$self->schedule_background_process;
|
||||
}
|
||||
@ -1153,6 +1186,7 @@ sub rotate {
|
||||
# $model_object->center_around_origin;
|
||||
# $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
|
||||
$self->{print}->add_model_object($model_object, $obj_idx);
|
||||
@ -1244,7 +1278,8 @@ sub changescale {
|
||||
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
|
||||
|
||||
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.
|
||||
sub print_info_box_show {
|
||||
my ($self, $show) = @_;
|
||||
my $scrolled_window_panel = $self->{scrolled_window_panel};
|
||||
my $scrolled_window_sizer = $self->{scrolled_window_sizer};
|
||||
return if (!$show && ($scrolled_window_sizer->IsShown(2) == $show));
|
||||
# my $scrolled_window_panel = $self->{scrolled_window_panel};
|
||||
# my $scrolled_window_sizer = $self->{scrolled_window_sizer};
|
||||
# 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) {
|
||||
my $print_info_sizer = $self->{print_info_sizer};
|
||||
@ -1716,17 +1757,23 @@ sub print_info_box_show {
|
||||
while ( my $label = shift @info) {
|
||||
my $value = shift @info;
|
||||
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);
|
||||
$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);
|
||||
$grid_sizer->Add($field, 0);
|
||||
}
|
||||
}
|
||||
|
||||
$scrolled_window_sizer->Show(2, $show);
|
||||
$scrolled_window_panel->Layout;
|
||||
# $scrolled_window_sizer->Show(2, $show);
|
||||
# $scrolled_window_panel->Layout;
|
||||
$sizer->Show(1, $show);
|
||||
|
||||
#? $self->Layout;
|
||||
#? $panel->Refresh;
|
||||
}
|
||||
|
||||
sub do_print {
|
||||
@ -2058,32 +2105,18 @@ sub on_config_change {
|
||||
$self->schedule_background_process;
|
||||
}
|
||||
|
||||
sub list_item_deselected {
|
||||
my ($self, $event) = @_;
|
||||
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 item_changed_selection{
|
||||
my ($self, $obj_idx) = @_;
|
||||
|
||||
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;
|
||||
if ($self->{canvas3D}) {
|
||||
Slic3r::GUI::_3DScene::deselect_volumes($self->{canvas3D});
|
||||
if ($obj_idx >= 0){
|
||||
my $selections = $self->collect_selections;
|
||||
Slic3r::GUI::_3DScene::update_volumes_selection($self->{canvas3D}, \@$selections);
|
||||
}
|
||||
Slic3r::GUI::_3DScene::render($self->{canvas3D});
|
||||
}
|
||||
undef $self->{_lecursor};
|
||||
}
|
||||
|
||||
sub collect_selections {
|
||||
@ -2095,6 +2128,7 @@ sub collect_selections {
|
||||
return $selections;
|
||||
}
|
||||
|
||||
# doesn't used now
|
||||
sub list_item_activated {
|
||||
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
|
||||
# whether background processing (export of a G-code, sending to Octoprint, forced background re-slicing) is active.
|
||||
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}));
|
||||
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_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
|
||||
# to admesh, so it generates normals for all facets
|
||||
@ -2306,7 +2366,8 @@ sub selection_changed {
|
||||
$self->{object_info_manifold_warning_icon}->SetToolTipString($message);
|
||||
} else {
|
||||
$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_warning_icon}->SetToolTipString("");
|
||||
}
|
||||
@ -2315,7 +2376,8 @@ sub selection_changed {
|
||||
}
|
||||
} else {
|
||||
$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_warning_icon}->SetToolTipString("");
|
||||
}
|
||||
@ -2328,26 +2390,21 @@ sub selection_changed {
|
||||
}
|
||||
|
||||
sub select_object {
|
||||
my ($self, $obj_idx) = @_;
|
||||
my ($self, $obj_idx, $child) = @_;
|
||||
|
||||
# remove current selection
|
||||
foreach my $o (0..$#{$self->{objects}}) {
|
||||
$PreventListEvents = 1;
|
||||
$self->{objects}->[$o]->selected(0);
|
||||
$self->{list}->Select($o, 0);
|
||||
$PreventListEvents = 0;
|
||||
}
|
||||
|
||||
if (defined $obj_idx) {
|
||||
$self->{objects}->[$obj_idx]->selected(1);
|
||||
# We use this flag to avoid circular event handling
|
||||
# Select() happens to fire a wxEVT_LIST_ITEM_SELECTED on Windows,
|
||||
# whose event handler calls this method again and again and again
|
||||
$PreventListEvents = 1;
|
||||
$self->{list}->Select($obj_idx, 1);
|
||||
$PreventListEvents = 0;
|
||||
# Select current object in the list on c++ side, if item isn't child
|
||||
if (!defined $child){
|
||||
Slic3r::GUI::select_current_object($obj_idx);}
|
||||
} else {
|
||||
# TODO: deselect all in list
|
||||
# Unselect all objects in the list on c++ side
|
||||
Slic3r::GUI::unselect_objects();
|
||||
}
|
||||
$self->selection_changed(1);
|
||||
}
|
||||
|
BIN
resources/icons/add_object.png
Normal file
After Width: | Height: | Size: 829 B |
BIN
resources/icons/colorchange_add_off.png
Normal file
After Width: | Height: | Size: 600 B |
BIN
resources/icons/colorchange_add_on.png
Normal file
After Width: | Height: | Size: 695 B |
BIN
resources/icons/colorchange_delete_off.png
Normal file
After Width: | Height: | Size: 589 B |
BIN
resources/icons/colorchange_delete_on.png
Normal file
After Width: | Height: | Size: 628 B |
BIN
resources/icons/disclosure_triangle_close.png
Normal file
After Width: | Height: | Size: 212 B |
BIN
resources/icons/disclosure_triangle_open.png
Normal file
After Width: | Height: | Size: 210 B |
BIN
resources/icons/down_half_circle.png
Normal file
After Width: | Height: | Size: 506 B |
BIN
resources/icons/erase.png
Normal file
After Width: | Height: | Size: 488 B |
BIN
resources/icons/exclamation_mark_.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
resources/icons/lambda.png
Normal file
After Width: | Height: | Size: 913 B |
BIN
resources/icons/lambda_.png
Normal file
After Width: | Height: | Size: 422 B |
BIN
resources/icons/left_half_circle.png
Normal file
After Width: | Height: | Size: 518 B |
BIN
resources/icons/object.png
Normal file
After Width: | Height: | Size: 1017 B |
BIN
resources/icons/one_layer_lock_off.png
Normal file
After Width: | Height: | Size: 577 B |
BIN
resources/icons/one_layer_lock_on.png
Normal file
After Width: | Height: | Size: 528 B |
BIN
resources/icons/one_layer_unlock_off.png
Normal file
After Width: | Height: | Size: 508 B |
BIN
resources/icons/one_layer_unlock_on.png
Normal file
After Width: | Height: | Size: 483 B |
BIN
resources/icons/right_half_circle.png
Normal file
After Width: | Height: | Size: 521 B |
BIN
resources/icons/split.png
Normal file
After Width: | Height: | Size: 1021 B |
BIN
resources/icons/up_half_circle.png
Normal file
After Width: | Height: | Size: 517 B |
@ -211,6 +211,10 @@ add_library(libslic3r_gui STATIC
|
||||
${LIBDIR}/slic3r/GUI/PresetHints.hpp
|
||||
${LIBDIR}/slic3r/GUI/GUI.cpp
|
||||
${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.hpp
|
||||
${LIBDIR}/slic3r/GUI/TabIface.cpp
|
||||
|
@ -258,6 +258,11 @@ const Vec3d& GLVolume::get_origin() const
|
||||
return m_origin;
|
||||
}
|
||||
|
||||
float GLVolume::get_angle_z()
|
||||
{
|
||||
return m_angle_z;
|
||||
}
|
||||
|
||||
void GLVolume::set_origin(const Vec3d& origin)
|
||||
{
|
||||
if (m_origin != origin)
|
||||
|
@ -323,6 +323,7 @@ public:
|
||||
// Sets render color in dependence of current state
|
||||
void set_render_color();
|
||||
|
||||
float get_angle_z();
|
||||
const Vec3d& get_origin() const;
|
||||
void set_origin(const Vec3d& origin);
|
||||
void set_angle_z(float angle_z);
|
||||
|
@ -132,7 +132,11 @@ namespace Slic3r { namespace GUI {
|
||||
break;
|
||||
}
|
||||
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)
|
||||
{
|
||||
show_error(m_parent, _(L("Input value is out of range")));
|
||||
@ -330,9 +334,7 @@ void SpinCtrl::BUILD() {
|
||||
break;
|
||||
}
|
||||
|
||||
const int min_val = m_opt_id == "standby_temperature_delta" ?
|
||||
-500 : m_opt.min > 0 ?
|
||||
m_opt.min : 0;
|
||||
const int min_val = m_opt.min == INT_MIN ? 0: m_opt.min;
|
||||
const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647;
|
||||
|
||||
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;
|
||||
wxString ret_str = static_cast<wxComboBox*>(window)->GetValue();
|
||||
|
||||
if (m_opt_id == "support")
|
||||
return m_value = boost::any(ret_str);//ret_str;
|
||||
// options from right panel
|
||||
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)
|
||||
/*m_value = */get_value_by_opt_type(ret_str);
|
||||
@ -705,6 +710,69 @@ void StaticText::BUILD()
|
||||
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
|
||||
} // Slic3r
|
||||
|
||||
|
@ -196,6 +196,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
void set_side_text_ptr(wxStaticText* side_text) {
|
||||
m_side_text = side_text;
|
||||
}
|
||||
|
||||
protected:
|
||||
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.
|
||||
@ -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.
|
||||
const wxColour* m_label_color = nullptr;
|
||||
|
||||
wxStaticText* m_side_text = nullptr;
|
||||
|
||||
// current 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; }
|
||||
|
||||
/// 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.
|
||||
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; }
|
||||
|
||||
void enable() override { dynamic_cast<wxColourPickerCtrl*>(window)->Enable(); };
|
||||
void disable() override{ dynamic_cast<wxColourPickerCtrl*>(window)->Disable(); };
|
||||
void enable() override { dynamic_cast<wxStaticText*>(window)->Enable(); };
|
||||
void disable() override{ dynamic_cast<wxStaticText*>(window)->Disable(); };
|
||||
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
|
||||
} // Slic3r
|
||||
|
||||
|
@ -2952,6 +2952,12 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
#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())
|
||||
{
|
||||
// to remove hover on objects when the mouse goes out of this canvas
|
||||
m_mouse.position = Vec2d(-1.0, -1.0);
|
||||
@ -3184,6 +3190,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
}
|
||||
const Vec3d& size = bb.size();
|
||||
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))
|
||||
@ -3284,6 +3292,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
case Gizmos::Scale:
|
||||
{
|
||||
m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale());
|
||||
Slic3r::GUI::update_settings_value();
|
||||
break;
|
||||
}
|
||||
case Gizmos::Rotate:
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/display.h>
|
||||
#include <wx/collpane.h>
|
||||
#include <wx/wupdlock.h>
|
||||
|
||||
#include "wxExtensions.hpp"
|
||||
|
||||
@ -53,12 +55,15 @@
|
||||
#include "PresetBundle.hpp"
|
||||
#include "UpdateDialogs.hpp"
|
||||
#include "FirmwareDialog.hpp"
|
||||
#include "GUI_ObjectParts.hpp"
|
||||
|
||||
#include "../Utils/PresetUpdater.hpp"
|
||||
#include "../Config/Snapshot.hpp"
|
||||
|
||||
#include "3DScene.hpp"
|
||||
#include "libslic3r/I18N.hpp"
|
||||
#include "Model.hpp"
|
||||
#include "LambdaObjectDialog.hpp"
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
@ -123,10 +128,26 @@ wxLocale* g_wxLocale;
|
||||
wxFont g_small_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;
|
||||
size_t m_label_width = 100;
|
||||
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()
|
||||
{
|
||||
auto luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
@ -206,6 +227,39 @@ void set_3DScene(_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()
|
||||
{
|
||||
return g_tabs_list;
|
||||
@ -332,11 +386,22 @@ enum ConfigMenuIDs {
|
||||
ConfigMenuTakeSnapshot,
|
||||
ConfigMenuUpdate,
|
||||
ConfigMenuPreferences,
|
||||
ConfigMenuModeSimple,
|
||||
ConfigMenuModeExpert,
|
||||
ConfigMenuLanguage,
|
||||
ConfigMenuFlashFirmware,
|
||||
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);
|
||||
|
||||
void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_language_change)
|
||||
@ -353,6 +418,13 @@ 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->AppendSeparator();
|
||||
local_menu->Append(config_id_base + ConfigMenuPreferences, _(L("Preferences"))+dots+"\tCtrl+,", _(L("Application preferences")));
|
||||
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->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")));
|
||||
@ -421,6 +493,13 @@ void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_l
|
||||
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")));
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
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
|
||||
// to notify the user whether he is aware that some preset changes will be lost.
|
||||
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)
|
||||
{
|
||||
if (comboCtrl == nullptr)
|
||||
@ -825,14 +940,37 @@ wxString from_u8(const std::string &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)
|
||||
{
|
||||
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();
|
||||
m_optgroup->label_width = ar.IsEmpty() ? 100 : ar.front()-4; // doesn't work
|
||||
m_optgroup->m_on_change = [config](t_config_option_key opt_key, boost::any value){
|
||||
m_label_width = ar.IsEmpty() ? 100 : ar.front()-4;
|
||||
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;
|
||||
for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++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;
|
||||
|
||||
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->update();
|
||||
}
|
||||
@ -885,10 +1023,10 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
|
||||
tab_print->update_dirty();
|
||||
};
|
||||
|
||||
Option option = m_optgroup->get_option("fill_density");
|
||||
Option option = optgroup->get_option("fill_density");
|
||||
option.opt.sidetext = "";
|
||||
option.opt.full_width = true;
|
||||
m_optgroup->append_single_option_line(option);
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
ConfigOptionDef def;
|
||||
|
||||
@ -907,7 +1045,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
|
||||
def.default_value = new ConfigOptionStrings { selection };
|
||||
option = Option(def, "support");
|
||||
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");
|
||||
def.label = L("Brim");
|
||||
@ -916,7 +1054,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
|
||||
def.gui_type = "";
|
||||
def.default_value = new ConfigOptionBool{ m_brim_width > 0.0 ? true : false };
|
||||
option = Option(def, "brim");
|
||||
m_optgroup->append_single_option_line(option);
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
|
||||
Line line = { "", "" };
|
||||
@ -942,16 +1080,93 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
|
||||
}));
|
||||
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()
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <vector>
|
||||
#include "PrintConfig.hpp"
|
||||
#include "../../libslic3r/Utils.hpp"
|
||||
#include "GUI_ObjectParts.hpp"
|
||||
|
||||
#include <wx/intl.h>
|
||||
#include <wx/string.h>
|
||||
@ -12,7 +13,6 @@
|
||||
class wxApp;
|
||||
class wxWindow;
|
||||
class wxFrame;
|
||||
class wxFont;
|
||||
class wxMenuBar;
|
||||
class wxNotebook;
|
||||
class wxComboCtrl;
|
||||
@ -24,6 +24,8 @@ class wxBoxSizer;
|
||||
class wxFlexGridSizer;
|
||||
class wxButton;
|
||||
class wxFileDialog;
|
||||
class wxStaticBitmap;
|
||||
class wxFont;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@ -100,10 +102,25 @@ void set_app_config(AppConfig *app_config);
|
||||
void set_preset_bundle(PresetBundle *preset_bundle);
|
||||
void set_preset_updater(PresetUpdater *updater);
|
||||
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();
|
||||
wxApp* get_app();
|
||||
PresetBundle* get_preset_bundle();
|
||||
wxFrame* get_main_frame();
|
||||
wxNotebook * get_tab_panel();
|
||||
wxNotebook* get_tab_panel();
|
||||
|
||||
const wxColour& get_label_clr_modified();
|
||||
@ -116,6 +133,11 @@ void set_label_clr_sys(const wxColour& clr);
|
||||
const wxFont& small_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);
|
||||
const std::vector<PresetTab>& get_preset_tabs();
|
||||
|
||||
@ -161,6 +183,8 @@ void save_language();
|
||||
void get_installed_languages(wxArrayString & names, wxArrayLong & identifiers);
|
||||
// select language from the list of installed languages
|
||||
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();
|
||||
bool checked_tab(Tab* tab);
|
||||
@ -180,13 +204,22 @@ wxString L_str(const std::string &str);
|
||||
// Return wxString from std::string in UTF8
|
||||
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);
|
||||
// Update view mode according to selected menu
|
||||
void update_mode();
|
||||
bool is_expert_mode();
|
||||
|
||||
// Callback to trigger a configuration update timer on the Plater.
|
||||
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();
|
||||
|
||||
void add_export_option(wxFileDialog* dlg, const std::string& format);
|
||||
|
1639
xs/src/slic3r/GUI/GUI_ObjectParts.cpp
Normal file
126
xs/src/slic3r/GUI/GUI_ObjectParts.hpp
Normal 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_
|
176
xs/src/slic3r/GUI/LambdaObjectDialog.cpp
Normal 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
|
35
xs/src/slic3r/GUI/LambdaObjectDialog.hpp
Normal 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_
|
@ -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) {
|
||||
m_fields.emplace(id, STDMOVE(Choice::Create<Choice>(parent(), opt, id)));
|
||||
} 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("legend") == 0) { // StaticText
|
||||
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)
|
||||
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.
|
||||
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*/) {
|
||||
//! if (line.sizer != nullptr || (line.widget != nullptr && line.full_width > 0)){
|
||||
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);
|
||||
|
||||
auto btn_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
btn_sizer->Add(field->m_Undo_to_sys_btn);
|
||||
btn_sizer->Add(field->m_Undo_btn);
|
||||
add_undo_buttuns_to_sizer(btn_sizer, field);
|
||||
tmp_sizer->Add(btn_sizer, 0, wxEXPAND | wxALL, 0);
|
||||
if (is_window_field(field))
|
||||
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();
|
||||
#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
|
||||
wxStaticText* label=nullptr;
|
||||
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);
|
||||
label->SetFont(label_font);
|
||||
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)
|
||||
label->SetToolTip(line.label_tooltip);
|
||||
}
|
||||
@ -177,28 +196,35 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
|
||||
return;
|
||||
}
|
||||
|
||||
// if we have a single option with no sidetext just add it directly to the grid sizer
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM|wxTOP|wxLEFT), staticbox ? 0 : 1);
|
||||
// If we're here, we have more than one option or a single option with sidetext
|
||||
// so we need a horizontal sizer to arrange these things
|
||||
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 &&
|
||||
option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0) {
|
||||
const auto& option = option_set.front();
|
||||
const auto& field = build_field(option, label);
|
||||
|
||||
sizer->Add(field->m_Undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sizer->Add(field->m_Undo_btn, 0, wxALIGN_CENTER_VERTICAL);
|
||||
add_undo_buttuns_to_sizer(sizer, field);
|
||||
if (is_window_field(field))
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
// if we're here, we have more than one option or a single option with sidetext
|
||||
// so we need a horizontal sizer to arrange these things
|
||||
for (auto opt : option_set) {
|
||||
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
|
||||
if (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);
|
||||
label = new wxStaticText(parent(), wxID_ANY, str_label + ":", wxDefaultPosition, wxDefaultSize);
|
||||
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
|
||||
const Option& opt_ref = opt;
|
||||
auto& field = build_field(opt_ref, label);
|
||||
sizer->Add(field->m_Undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sizer->Add(field->m_Undo_btn, 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||
add_undo_buttuns_to_sizer(sizer_tmp, field);
|
||||
is_sizer_field(field) ?
|
||||
sizer->Add(field->getSizer(), 0, wxALIGN_CENTER_VERTICAL, 0) :
|
||||
sizer->Add(field->getWindow(), 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||
sizer_tmp->Add(field->getSizer(), 0, wxALIGN_CENTER_VERTICAL, 0) :
|
||||
sizer_tmp->Add(field->getWindow(), 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||
|
||||
// add sidetext if any
|
||||
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);
|
||||
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
|
||||
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
|
||||
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*/)
|
||||
{
|
||||
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);
|
||||
|
@ -26,9 +26,13 @@
|
||||
|
||||
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).
|
||||
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 modified_label_clr = *new wxColour(254, 189, 101);
|
||||
@ -71,10 +75,13 @@ private:
|
||||
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_opt_map = std::map< std::string, std::pair<std::string, int> >;
|
||||
|
||||
class OptionsGroup {
|
||||
wxStaticBox* stb;
|
||||
public:
|
||||
const bool staticbox {true};
|
||||
const wxString title {wxString("")};
|
||||
@ -88,8 +95,7 @@ public:
|
||||
|
||||
wxFont sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
|
||||
wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
|
||||
|
||||
// std::function<const wxBitmap&()> nonsys_btn_icon{ nullptr };
|
||||
int sidetext_width{ -1 };
|
||||
|
||||
/// Returns a copy of the pointer of the parent wxWindow.
|
||||
/// Accessor function is because users are not allowed to change the parent
|
||||
@ -101,6 +107,11 @@ public:
|
||||
return m_parent;
|
||||
#endif /* __WXGTK__ */
|
||||
}
|
||||
#ifdef __WXGTK__
|
||||
wxWindow* get_parent() const {
|
||||
return m_parent;
|
||||
}
|
||||
#endif /* __WXGTK__ */
|
||||
|
||||
void append_line(const Line& line, wxStaticText** colored_Label = nullptr);
|
||||
Line create_single_option_line(const Option& option) const;
|
||||
@ -124,23 +135,39 @@ public:
|
||||
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 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) {
|
||||
m_show_modified_btns = show;
|
||||
}
|
||||
|
||||
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!="") {
|
||||
auto stb = new wxStaticBox(_parent, wxID_ANY, title);
|
||||
OptionsGroup( wxWindow* _parent, const wxString& title, bool is_tab_opt = false,
|
||||
ogDrawFlag flag = ogDEFAULT, column_t extra_clmn = nullptr) :
|
||||
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());
|
||||
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;
|
||||
if (label_width != 0) num_columns++;
|
||||
if (extra_column != nullptr) num_columns++;
|
||||
m_grid_sizer = new wxFlexGridSizer(0, num_columns, 0,0);
|
||||
static_cast<wxFlexGridSizer*>(m_grid_sizer)->SetFlexibleDirection(wxHORIZONTAL);
|
||||
m_grid_sizer = new wxFlexGridSizer(0, num_columns, 1,0);
|
||||
static_cast<wxFlexGridSizer*>(m_grid_sizer)->SetFlexibleDirection(wxBOTH/*wxHORIZONTAL*/);
|
||||
static_cast<wxFlexGridSizer*>(m_grid_sizer)->AddGrowableCol(label_width != 0);
|
||||
#ifdef __WXGTK__
|
||||
m_panel = new wxPanel( _parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
|
||||
@ -164,6 +191,8 @@ protected:
|
||||
// "true" if option is created in preset tabs
|
||||
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
|
||||
// Tooltips on GTK doesn't work inside wxStaticBoxSizer unless you insert a panel
|
||||
// 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, 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_change_OG(const t_config_option_key& opt_id, const boost::any& value);
|
||||
@ -186,8 +216,9 @@ protected:
|
||||
|
||||
class ConfigOptionsGroup: public OptionsGroup {
|
||||
public:
|
||||
ConfigOptionsGroup(wxWindow* parent, const wxString& title, DynamicPrintConfig* _config = nullptr, bool is_tab_opt = false) :
|
||||
OptionsGroup(parent, title, is_tab_opt), m_config(_config) {}
|
||||
ConfigOptionsGroup( wxWindow* parent, const wxString& title, DynamicPrintConfig* _config = nullptr,
|
||||
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 (?).
|
||||
DynamicPrintConfig* m_config {nullptr};
|
||||
|
@ -687,8 +687,8 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
|
||||
}
|
||||
if (opt_key == "fill_density")
|
||||
{
|
||||
boost::any val = get_optgroup()->get_config_value(*m_config, opt_key);
|
||||
get_optgroup()->set_value(opt_key, val);
|
||||
boost::any val = get_optgroup(ogFrequentlyChangingParameters)->get_config_value(*m_config, opt_key);
|
||||
get_optgroup(ogFrequentlyChangingParameters)->set_value(opt_key, val);
|
||||
}
|
||||
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") ?
|
||||
_("Support on build plate only") :
|
||||
_("Everywhere");
|
||||
get_optgroup()->set_value("support", new_selection);
|
||||
get_optgroup(ogFrequentlyChangingParameters)->set_value("support", new_selection);
|
||||
}
|
||||
if (opt_key == "brim_width")
|
||||
{
|
||||
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" )
|
||||
@ -719,9 +719,7 @@ 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 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();
|
||||
else get_wiping_dialog_button()->Hide();
|
||||
get_wiping_dialog_button()->Show(wipe_tower_enabled && multiple_extruders && single_extruder_mm);
|
||||
|
||||
(get_wiping_dialog_button()->GetParent())->Layout();
|
||||
}
|
||||
@ -789,18 +787,18 @@ void Tab::update_preset_description_line()
|
||||
|
||||
void Tab::update_frequently_changed_parameters()
|
||||
{
|
||||
boost::any value = get_optgroup()->get_config_value(*m_config, "fill_density");
|
||||
get_optgroup()->set_value("fill_density", value);
|
||||
boost::any value = get_optgroup(ogFrequentlyChangingParameters)->get_config_value(*m_config, "fill_density");
|
||||
get_optgroup(ogFrequentlyChangingParameters)->set_value("fill_density", value);
|
||||
|
||||
wxString new_selection = !m_config->opt_bool("support_material") ?
|
||||
_("None") :
|
||||
m_config->opt_bool("support_material_buildplate_only") ?
|
||||
_("Support on build plate only") :
|
||||
_("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;
|
||||
get_optgroup()->set_value("brim", val);
|
||||
get_optgroup(ogFrequentlyChangingParameters)->set_value("brim", val);
|
||||
|
||||
update_wiping_button_visibility();
|
||||
}
|
||||
@ -1478,7 +1476,7 @@ void TabPrinter::build_fff()
|
||||
Line line{ _(L("Bed shape")), "" };
|
||||
line.widget = [this](wxWindow* parent){
|
||||
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));
|
||||
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
@ -1546,7 +1544,7 @@ void TabPrinter::build_fff()
|
||||
auto serial_test = [this](wxWindow* parent){
|
||||
auto btn = m_serial_test_btn = new wxButton(parent, wxID_ANY,
|
||||
_(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));
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(btn);
|
||||
@ -1832,6 +1830,7 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){
|
||||
build_extruder_pages();
|
||||
reload_config();
|
||||
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)
|
||||
|
@ -267,11 +267,11 @@ public:
|
||||
|
||||
void on_value_change(const std::string& opt_key, const boost::any& value);
|
||||
|
||||
void update_wiping_button_visibility();
|
||||
protected:
|
||||
void on_presets_changed();
|
||||
void update_preset_description_line();
|
||||
void update_frequently_changed_parameters();
|
||||
void update_wiping_button_visibility();
|
||||
void update_tab_presets(wxComboCtrl* ui, bool show_incompatible);
|
||||
void fill_icon_descriptions();
|
||||
void set_tooltips_text();
|
||||
|
@ -4,6 +4,14 @@
|
||||
#include <wx/checklst.h>
|
||||
#include <wx/combo.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
|
||||
{
|
||||
@ -65,4 +73,568 @@ public:
|
||||
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_
|
||||
|
@ -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"),
|
||||
(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)
|
||||
%code%{ RETVAL = Slic3r::fold_utf8_to_ascii(src); %};
|
||||
|
||||
|