This commit is contained in:
enricoturri1966 2020-11-03 08:41:14 +01:00
commit 54d6834553
16 changed files with 1405 additions and 513 deletions

View File

@ -32,6 +32,15 @@ bed_model = ender3_bed.stl
bed_texture = ender3.svg
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:ENDER5]
name = Creality Ender-5
variants = 0.4
technology = FFF
family = ENDER
bed_model = ender3_bed.stl
bed_texture = ender3.svg
default_materials = Creality PLA @CREALITY; Generic PLA @CREALITY; Generic PETG @CREALITY; Generic ABS @CREALITY; Prusament PLA @CREALITY; Prusament PETG @CREALITY
[printer_model:ENDER5PLUS]
name = Creality Ender-5 Plus
variants = 0.4
@ -326,7 +335,7 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_CREALITY.*/
[filament:*PLA*]
inherits = *common*
bed_temperature = 40
bed_temperature = 60
fan_below_layer_time = 100
filament_colour = #FF3232
filament_max_volumetric_speed = 15
@ -450,6 +459,36 @@ first_layer_bed_temperature = 70
filament_cost = 24.99
filament_density = 1.27
[filament:Devil Design PLA @CREALITY]
inherits = *PLA*
filament_vendor = Devil Design
temperature = 215
bed_temperature = 60
first_layer_temperature = 215
first_layer_bed_temperature = 60
filament_cost = 19.00
filament_density = 1.24
[filament:Extrudr PLA NX2 @CREALITY]
inherits = *PLA*
filament_vendor = Extrudr
temperature = 200
bed_temperature = 60
first_layer_temperature = 205
first_layer_bed_temperature = 60
filament_cost = 23.63
filament_density = 1.3
[filament:Real Filament PLA @CREALITY]
inherits = *PLA*
filament_vendor = Real Filament
temperature = 195
bed_temperature = 60
first_layer_temperature = 200
first_layer_bed_temperature = 60
filament_cost = 24.99
filament_density = 1.24
# Common printer preset
[printer:*common*]
printer_technology = FFF
@ -542,20 +581,31 @@ retract_before_wipe = 70%
default_print_profile = 0.15mm OPTIMAL @CREALITY
default_filament_profile = Creality PLA @CREALITY
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 ; home all\nG1 Z2 F240\nG1 X2 Y10 F3000\nG1 Z0.28 F240\nG92 E0.0\nG1 Y190 E15.0 F1500.0 ; intro line\nG1 X2.3 F5000\nG1 Y10 E15.0 F1200.0 ; intro line\nG92 E0.0
end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+5, max_print_height)} F600{endif} ; Move print head up\nG1 X5 Y170 F3000 ; present print\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+70, max_print_height)} F600{endif} ; Move print head up\nM84 X Y E ; disable motors
end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+5, max_print_height)} F600{endif} ; Move print head up\nG1 X5 Y170 F3000 ; present print\n{if layer_z < max_print_height-10}G1 Z{z_offset+min(layer_z+70, max_print_height-10)} F600{endif} ; Move print head up\nM84 X Y E ; disable motors
[printer:*abl*]
start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S150 ; set extruder temp for auto bed leveling\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 ; home all\nG29 ; auto bed levelling\nG1 Z50 F240\nG1 X2 Y10 F3000\nM104 S[first_layer_temperature] ; set extruder temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG1 Z0.28 F240\nG92 E0.0\nG1 Y190 E15.0 F1500.0 ; intro line\nG1 X2.3 F5000\nG1 Y10 E15.0 F1200.0 ; intro line\nG92 E0.0
[printer:*invertedz*]
end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+5, max_print_height)} F600{endif} ; Move print bed down\nG1 X50 Y50 F3000 ; present print\n{if layer_z < max_print_height-10}G1 Z{z_offset+max_print_height-10} F600{endif} ; Move print bed down\nM84 X Y E ; disable motors
[printer:Creality Ender-3 BLTouch]
inherits = Creality Ender-3; *abl*
renamed_from = "Creality ENDER-3 BLTouch"
printer_model = ENDER3BLTOUCH
[printer:Creality Ender-5 Plus]
inherits = Creality Ender-3; *abl*
[printer:Creality Ender-5]
inherits = Creality Ender-3; *invertedz*
retract_length = 6
bed_shape = 10x10,360x10,360x360,10x360
bed_shape = 5x2.5,225x2.5,225x222.5,5x222.5
printer_model = ENDER5
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_CREALITY\nPRINTER_MODEL_ENDER5\nPRINTER_HAS_BOWDEN
max_print_height = 300
[printer:Creality Ender-5 Plus]
inherits = Creality Ender-3; *abl*; *invertedz*
retract_length = 6
bed_shape = 5x5,355x5,355x355,5x355
printer_model = ENDER5PLUS
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_CREALITY\nPRINTER_MODEL_ENDER5PLUS\nPRINTER_HAS_BOWDEN
max_print_height = 400

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

View File

@ -1,2 +1,3 @@
min_slic3r_version = 2.3.0-alpha0
0.0.2 Added 0.15mm print profile
0.0.1 Initial TriLAB bundle

View File

@ -4,13 +4,13 @@
[vendor]
# Vendor name will be shown by the Config Wizard.
name = TRILAB
name = TriLAB
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the PrusaSlicer configuration to be downgraded.
config_version = 0.0.1
config_version = 0.0.2
# Where to get the updates from?
config_update_url = http://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/TriLAB/
# changelog_url = http://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/TriLAB/
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
# The printer models will be shown by the Configuration Wizard in this order,
# also the first model installed & the first nozzle installed will be activated after install.
@ -43,10 +43,15 @@ default_materials = DeltiQ PLA; DeltiQ ASA; DeltiQ PET; DeltiQ ABS; DeltiQ CPE
# All presets starting with asterisk, for example *common*, are intermediate and they will
# not make it into the user interface.
[print:DeltiQ 0.15mm]
inherits = DeltiQ 0.2mm
layer_height = 0.15
bottom_solid_layers = 5
top_solid_layers = 6
[print:DeltiQ 0.2mm]
avoid_crossing_perimeters = 0
bottom_solid_layers = 3
bottom_solid_layers = 4
bridge_acceleration = 1000
bridge_angle = 0
bridge_flow_ratio = 0.95
@ -143,7 +148,7 @@ thin_walls = 0
threads = 4
top_infill_extrusion_width = 0.4
top_solid_infill_speed = 30
top_solid_layers = 4
top_solid_layers = 5
travel_speed = 150
wipe_tower = 0
wipe_tower_bridging = 10
@ -254,7 +259,6 @@ extra_loading_move = -2
extruder_colour = ""
extruder_offset = 0x0
gcode_flavor = repetier
host_type = octoprint
layer_gcode = ;AFTER_LAYER_CHANGE\nM117 layer [layer_num] at [layer_z]mm\n;[layer_z]\n
machine_max_acceleration_e = 10000,5000
machine_max_acceleration_extruding = 1500,1250
@ -277,14 +281,11 @@ max_print_height = 320
min_layer_height = 0.15
nozzle_diameter = 0.4
parking_pos_retraction = 92
print_host =
printer_model =
printer_notes = TRILAB
printer_settings_id =
printer_variant =
printer_vendor =
printhost_apikey =
printhost_cafile =
remaining_times = 0
retract_before_travel = 2
retract_before_wipe = 100%
@ -297,8 +298,6 @@ retract_lift_below = 0
retract_restart_extra = 0
retract_restart_extra_toolchange = 0
retract_speed = 33
serial_port =
serial_speed = 250000
silent_mode = 1
single_extruder_multi_material = 0
start_gcode = ;START\nM220 S100 ; Set feedmultiply back to 100percent\nG90 ; Absolute positioning\nM83 ; Relative extruder\nM107 ; Layer fan OFF\nM190 S[first_layer_bed_temperature] ; Set bed temperature and wait\nM104 S[first_layer_temperature] ; Set extruder temperature\nG28 ; Home all axes\nG33 ; auto leveling rutine\nG1 X-62 Y-108 Z0.3 F6000 ; Go to purge position start\nG92 E0 ; Zero extruder\nM109 S[first_layer_temperature] ; Set and wait - hotend temperature\nG3 X62 Y-108 I62 J108 E10 F200 ; Go ARC to purge end\nG92 E0 ; Zero extruder

View File

@ -111,6 +111,8 @@ set(SLIC3R_GUI_SOURCES
GUI/Field.hpp
GUI/OptionsGroup.cpp
GUI/OptionsGroup.hpp
GUI/OG_CustomCtrl.cpp
GUI/OG_CustomCtrl.hpp
GUI/BedShapeDialog.cpp
GUI/BedShapeDialog.hpp
GUI/2DBed.cpp

View File

@ -13,6 +13,7 @@
#include <wx/tooltip.h>
#include <wx/notebook.h>
#include <boost/algorithm/string/predicate.hpp>
#include "OG_CustomCtrl.hpp"
#ifdef __WXOSX__
#define wxOSX true
@ -63,18 +64,16 @@ Field::~Field()
m_back_to_initial_value = nullptr;
if (m_back_to_sys_value)
m_back_to_sys_value = nullptr;
if (getWindow()) {
wxWindow* win = getWindow();
win->Destroy();
win = nullptr;
}
}
void Field::PostInitialize()
{
auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
m_Undo_btn = new RevertButton(m_parent, "bullet_white.png");
m_Undo_to_sys_btn = new RevertButton(m_parent, "bullet_white.png");
m_Undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_back_to_initial_value(); }));
m_Undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_back_to_sys_value(); }));
m_blinking_bmp = new BlinkingBitmap(m_parent);
switch (m_opt.type)
{
@ -94,6 +93,7 @@ void Field::PostInitialize()
// initialize m_unit_value
m_em_unit = em_unit(m_parent);
parent_is_custom_ctrl = dynamic_cast<OG_CustomCtrl*>(m_parent) != nullptr;
BUILD();
@ -216,10 +216,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
break;
}
wxString label = m_Label->GetLabel();
if (label.Last() == '\n') label.RemoveLast();
while (label.Last() == ' ') label.RemoveLast();
if (label.Last() == ':') label.RemoveLast();
wxString label = m_opt.full_label.empty() ? _(m_opt.label) : _(m_opt.full_label);
show_error(m_parent, from_u8((boost::format(_utf8(L("%s doesn't support percentage"))) % label).str()));
set_value(double_to_string(m_opt.min), true);
m_value = double(m_opt.min);
@ -305,28 +302,14 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
}
}
void Field::msw_rescale(bool rescale_sidetext)
void Field::msw_rescale()
{
m_Undo_to_sys_btn->msw_rescale();
m_Undo_btn->msw_rescale();
m_blinking_bmp->msw_rescale();
// update em_unit value
m_em_unit = em_unit(m_parent);
// update sidetext if it is needed
if (m_side_text && rescale_sidetext)
{
auto size = wxSize(def_width_thinner() * m_em_unit, -1);
m_side_text->SetSize(size);
m_side_text->SetMinSize(size);
}
}
void Field::sys_color_changed()
{
m_Undo_to_sys_btn->msw_rescale();
m_Undo_btn->msw_rescale();
}
template<class T>
@ -387,6 +370,8 @@ void TextCtrl::BUILD() {
const long style = m_opt.multiline ? wxTE_MULTILINE : wxTE_PROCESS_ENTER/*0*/;
auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, style);
if (parent_is_custom_ctrl && m_opt.height < 0)
opt_height = (double)temp->GetSize().GetHeight()/m_em_unit;
temp->SetFont(m_opt.is_code ?
Slic3r::GUI::wxGetApp().code_font():
Slic3r::GUI::wxGetApp().normal_font());
@ -550,16 +535,23 @@ boost::any& TextCtrl::get_value()
return m_value;
}
void TextCtrl::msw_rescale(bool rescale_sidetext/* = false*/)
void TextCtrl::msw_rescale()
{
Field::msw_rescale(rescale_sidetext);
Field::msw_rescale();
auto size = wxSize(def_width() * m_em_unit, wxDefaultCoord);
if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit);
if (m_opt.height >= 0)
size.SetHeight(m_opt.height*m_em_unit);
else if (parent_is_custom_ctrl && opt_height > 0)
size.SetHeight(lround(opt_height*m_em_unit));
if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit);
if (size != wxDefaultSize)
{
wxTextCtrl* field = dynamic_cast<wxTextCtrl*>(window);
if (parent_is_custom_ctrl)
field->SetSize(size);
else
field->SetMinSize(size);
}
@ -650,7 +642,7 @@ boost::any& CheckBox::get_value()
return m_value;
}
void CheckBox::msw_rescale(bool rescale_sidetext/* = false*/)
void CheckBox::msw_rescale()
{
Field::msw_rescale();
@ -704,6 +696,9 @@ void SpinCtrl::BUILD() {
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font());
if (!wxOSX) temp->SetBackgroundStyle(wxBG_STYLE_PAINT);
if (m_opt.height < 0 && parent_is_custom_ctrl)
opt_height = (double)temp->GetSize().GetHeight() / m_em_unit;
// XXX: On OS X the wxSpinCtrl widget is made up of two subwidgets, unfortunatelly
// the kill focus event is not propagated to the encompassing widget,
// so we need to bind it on the inner text widget instead. (Ugh.)
@ -785,23 +780,32 @@ void SpinCtrl::propagate_value()
suppress_propagation = false;
}
void SpinCtrl::msw_rescale(bool rescale_sidetext/* = false*/)
void SpinCtrl::msw_rescale()
{
Field::msw_rescale(rescale_sidetext);
Field::msw_rescale();
wxSpinCtrl* field = dynamic_cast<wxSpinCtrl*>(window);
if (parent_is_custom_ctrl)
field->SetSize(wxSize(def_width() * m_em_unit, lround(opt_height * m_em_unit)));
else
field->SetMinSize(wxSize(def_width() * m_em_unit, int(1.9f*field->GetFont().GetPixelSize().y)));
}
#ifdef __WXOSX__
using choice_ctrl = wxBitmapComboBox;
#else
using choice_ctrl = wxComboBox;
#endif // __WXOSX__
void Choice::BUILD() {
wxSize size(def_width_wider() * m_em_unit, wxDefaultCoord);
if (m_opt.height >= 0) size.SetHeight(m_opt.height*m_em_unit);
if (m_opt.width >= 0) size.SetWidth(m_opt.width*m_em_unit);
wxBitmapComboBox* temp;
choice_ctrl* temp;
if (!m_opt.gui_type.empty() && m_opt.gui_type.compare("select_open") != 0) {
m_is_editable = true;
temp = new wxBitmapComboBox(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size);
temp = new choice_ctrl(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size);
}
else {
#ifdef __WXOSX__
@ -809,11 +813,11 @@ void Choice::BUILD() {
* so ToolTip doesn't shown.
* Next workaround helps to solve this problem
*/
temp = new wxBitmapComboBox();
temp = new choice_ctrl();
temp->SetTextCtrlStyle(wxTE_READONLY);
temp->Create(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr);
#else
temp = new wxBitmapComboBox(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr, wxCB_READONLY);
temp = new choice_ctrl(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size, 0, nullptr, wxCB_READONLY);
#endif //__WXOSX__
}
@ -836,7 +840,8 @@ void Choice::BUILD() {
set_selection();
}
#ifndef __WXGTK__
#ifdef __WXOSX__
//#ifndef __WXGTK__
/* Workaround for a correct rendering of the control without Bitmap (under MSW and OSX):
*
* 1. We should create small Bitmap to fill Bitmaps RefData,
@ -863,7 +868,7 @@ void Choice::BUILD() {
}
double old_val = !m_value.empty() ? boost::any_cast<double>(m_value) : -99999;
if (is_defined_input_value<wxBitmapComboBox>(window, m_opt.type)) {
if (is_defined_input_value<choice_ctrl>(window, m_opt.type)) {
if (fabs(old_val - boost::any_cast<double>(get_value())) <= 0.0001)
return;
else
@ -886,7 +891,7 @@ void Choice::set_selection()
wxString text_value = wxString("");
wxBitmapComboBox* field = dynamic_cast<wxBitmapComboBox*>(window);
choice_ctrl* field = dynamic_cast<choice_ctrl*>(window);
switch (m_opt.type) {
case coFloat:
case coPercent: {
@ -956,7 +961,7 @@ void Choice::set_value(const std::string& value, bool change_event) //! Redunda
++idx;
}
wxBitmapComboBox* field = dynamic_cast<wxBitmapComboBox*>(window);
choice_ctrl* field = dynamic_cast<choice_ctrl*>(window);
idx == m_opt.enum_values.size() ?
field->SetValue(value) :
field->SetSelection(idx);
@ -968,7 +973,7 @@ void Choice::set_value(const boost::any& value, bool change_event)
{
m_disable_change_event = !change_event;
wxBitmapComboBox* field = dynamic_cast<wxBitmapComboBox*>(window);
choice_ctrl* field = dynamic_cast<choice_ctrl*>(window);
switch (m_opt.type) {
case coInt:
@ -1044,7 +1049,7 @@ void Choice::set_values(const std::vector<std::string>& values)
// # it looks that Clear() also clears the text field in recent wxWidgets versions,
// # but we want to preserve it
auto ww = dynamic_cast<wxBitmapComboBox*>(window);
auto ww = dynamic_cast<choice_ctrl*>(window);
auto value = ww->GetValue();
ww->Clear();
ww->Append("");
@ -1077,7 +1082,7 @@ void Choice::set_values(const wxArrayString &values)
boost::any& Choice::get_value()
{
wxBitmapComboBox* field = dynamic_cast<wxBitmapComboBox*>(window);
choice_ctrl* field = dynamic_cast<choice_ctrl*>(window);
wxString ret_str = field->GetValue();
@ -1137,16 +1142,20 @@ boost::any& Choice::get_value()
return m_value;
}
void Choice::msw_rescale(bool rescale_sidetext/* = false*/)
void Choice::enable() { dynamic_cast<choice_ctrl*>(window)->Enable(); };
void Choice::disable() { dynamic_cast<choice_ctrl*>(window)->Disable(); };
void Choice::msw_rescale()
{
Field::msw_rescale();
wxBitmapComboBox* field = dynamic_cast<wxBitmapComboBox*>(window);
choice_ctrl* field = dynamic_cast<choice_ctrl*>(window);
#ifdef __WXOSX__
const wxString selection = field->GetValue();// field->GetString(index);
/* To correct scaling (set new controll size) of a wxBitmapCombobox
* we need to refill control with new bitmaps. So, in our case :
* 1. clear conrol
* 1. clear control
* 2. add content
* 3. add scaled "empty" bitmap to the at least one item
*/
@ -1179,6 +1188,16 @@ void Choice::msw_rescale(bool rescale_sidetext/* = false*/)
idx == m_opt.enum_values.size() ?
field->SetValue(selection) :
field->SetSelection(idx);
#else
auto size = wxSize(def_width_wider() * m_em_unit, wxDefaultCoord);
if (m_opt.height >= 0) size.SetHeight(m_opt.height * m_em_unit);
if (m_opt.width >= 0) size.SetWidth(m_opt.width * m_em_unit);
if (parent_is_custom_ctrl)
field->SetSize(size);
else
field->SetMinSize(size);
#endif
}
void ColourPicker::BUILD()
@ -1195,6 +1214,8 @@ void ColourPicker::BUILD()
}
auto temp = new wxColourPickerCtrl(m_parent, wxID_ANY, clr, wxDefaultPosition, size);
if (parent_is_custom_ctrl && m_opt.height < 0)
opt_height = (double)temp->GetSize().GetHeight() / m_em_unit;
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font());
if (!wxOSX) temp->SetBackgroundStyle(wxBG_STYLE_PAINT);
@ -1251,14 +1272,20 @@ boost::any& ColourPicker::get_value()
return m_value;
}
void ColourPicker::msw_rescale(bool rescale_sidetext/* = false*/)
void ColourPicker::msw_rescale()
{
Field::msw_rescale();
wxColourPickerCtrl* field = dynamic_cast<wxColourPickerCtrl*>(window);
auto size = wxSize(def_width() * m_em_unit, wxDefaultCoord);
if (m_opt.height >= 0) size.SetHeight(m_opt.height * m_em_unit);
if (m_opt.height >= 0)
size.SetHeight(m_opt.height * m_em_unit);
else if (parent_is_custom_ctrl && opt_height > 0)
size.SetHeight(lround(opt_height * m_em_unit));
if (m_opt.width >= 0) size.SetWidth(m_opt.width * m_em_unit);
if (parent_is_custom_ctrl)
field->SetSize(size);
else
field->SetMinSize(size);
if (field->GetColour() == wxTransparentColour)
@ -1279,6 +1306,9 @@ void PointCtrl::BUILD()
x_textctrl = new wxTextCtrl(m_parent, wxID_ANY, X, wxDefaultPosition, field_size, wxTE_PROCESS_ENTER);
y_textctrl = new wxTextCtrl(m_parent, wxID_ANY, Y, wxDefaultPosition, field_size, wxTE_PROCESS_ENTER);
if (parent_is_custom_ctrl && m_opt.height < 0)
opt_height = (double)x_textctrl->GetSize().GetHeight() / m_em_unit;
x_textctrl->SetFont(Slic3r::GUI::wxGetApp().normal_font());
x_textctrl->SetBackgroundStyle(wxBG_STYLE_PAINT);
y_textctrl->SetFont(Slic3r::GUI::wxGetApp().normal_font());
@ -1296,9 +1326,6 @@ void PointCtrl::BUILD()
temp->Add(static_text_y, 0, wxALIGN_CENTER_VERTICAL, 0);
temp->Add(y_textctrl);
// x_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), x_textctrl->GetId());
// y_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), y_textctrl->GetId());
x_textctrl->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { propagate_value(x_textctrl); }), x_textctrl->GetId());
y_textctrl->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { propagate_value(y_textctrl); }), y_textctrl->GetId());
@ -1312,15 +1339,22 @@ void PointCtrl::BUILD()
y_textctrl->SetToolTip(get_tooltip_text(X+", "+Y));
}
void PointCtrl::msw_rescale(bool rescale_sidetext/* = false*/)
void PointCtrl::msw_rescale()
{
Field::msw_rescale();
const wxSize field_size(4 * m_em_unit, -1);
wxSize field_size(4 * m_em_unit, -1);
if (parent_is_custom_ctrl) {
field_size.SetHeight(lround(opt_height * m_em_unit));
x_textctrl->SetSize(field_size);
y_textctrl->SetSize(field_size);
}
else {
x_textctrl->SetMinSize(field_size);
y_textctrl->SetMinSize(field_size);
}
}
bool PointCtrl::value_was_changed(wxTextCtrl* win)
{
@ -1411,7 +1445,7 @@ void StaticText::BUILD()
temp->SetToolTip(get_tooltip_text(legend));
}
void StaticText::msw_rescale(bool rescale_sidetext/* = false*/)
void StaticText::msw_rescale()
{
Field::msw_rescale();

View File

@ -87,6 +87,8 @@ protected:
void on_set_focus(wxEvent& event);
/// Call the attached on_change method.
void on_change_field();
public:
/// Call the attached m_back_to_initial_value method.
void on_back_to_initial_value();
/// Call the attached m_back_to_sys_value method.
@ -119,6 +121,9 @@ public:
const t_config_option_key m_opt_id;//! {""};
int m_opt_idx = 0;
double opt_height{ 0.0 };
bool parent_is_custom_ctrl{ false };
/// Sets a value for this control.
/// subclasses should overload with a specific version
/// Postcondition: Method does not fire the on_change event.
@ -140,9 +145,6 @@ public:
void field_changed() { on_change_field(); }
// set icon to "UndoToSystemValue" button according to an inheritance of preset
// void set_nonsys_btn_icon(const wxBitmap& icon);
Field(const ConfigOptionDef& opt, const t_config_option_key& id) : m_opt(opt), m_opt_id(id) {};
Field(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : m_parent(parent), m_opt(opt), m_opt_id(id) {};
virtual ~Field();
@ -151,8 +153,6 @@ public:
virtual wxSizer* getSizer() { return nullptr; }
virtual wxWindow* getWindow() { return nullptr; }
wxStaticText* getLabel() { return m_Label; }
bool is_matched(const std::string& string, const std::string& pattern);
void get_value_by_opt_type(wxString& str, const bool check_value = true);
@ -168,7 +168,6 @@ public:
bool set_undo_bitmap(const ScalableBitmap *bmp) {
if (m_undo_bitmap != bmp) {
m_undo_bitmap = bmp;
m_Undo_btn->SetBitmap_(*bmp);
return true;
}
return false;
@ -177,33 +176,21 @@ public:
bool set_undo_to_sys_bitmap(const ScalableBitmap *bmp) {
if (m_undo_to_sys_bitmap != bmp) {
m_undo_to_sys_bitmap = bmp;
m_Undo_to_sys_btn->SetBitmap_(*bmp);
return true;
}
return false;
}
bool set_label_colour(const wxColour *clr) {
if (m_Label == nullptr) return false;
if (m_label_color != clr) {
m_label_color = clr;
m_Label->SetForegroundColour(*clr);
m_Label->Refresh(true);
}
return false;
}
bool set_label_colour_force(const wxColour *clr) {
if (m_Label == nullptr) return false;
m_Label->SetForegroundColour(*clr);
m_Label->Refresh(true);
return false;
}
bool set_undo_tooltip(const wxString *tip) {
if (m_undo_tooltip != tip) {
m_undo_tooltip = tip;
m_Undo_btn->SetToolTip(*tip);
return true;
}
return false;
@ -212,17 +199,16 @@ public:
bool set_undo_to_sys_tooltip(const wxString *tip) {
if (m_undo_to_sys_tooltip != tip) {
m_undo_to_sys_tooltip = tip;
m_Undo_to_sys_btn->SetToolTip(*tip);
return true;
}
return false;
}
void set_side_text_ptr(wxStaticText* side_text) {
m_side_text = side_text;
bool* get_blink_ptr() {
return &m_blink;
}
virtual void msw_rescale(bool rescale_sidetext = false);
virtual void msw_rescale();
void sys_color_changed();
bool get_enter_pressed() const { return bEnterPressed; }
@ -233,26 +219,26 @@ public:
static int def_width_wider() ;
static int def_width_thinner() ;
BlinkingBitmap* blinking_bitmap() const { return m_blinking_bmp;}
const ScalableBitmap* undo_bitmap() { return m_undo_bitmap; }
const wxString* undo_tooltip() { return m_undo_tooltip; }
const ScalableBitmap* undo_to_sys_bitmap() { return m_undo_to_sys_bitmap; }
const wxString* undo_to_sys_tooltip() { return m_undo_to_sys_tooltip; }
const wxColour* label_color() { return m_label_color; }
const bool blink() { return m_blink; }
protected:
RevertButton* 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.
const ScalableBitmap* m_undo_bitmap = nullptr;
const wxString* m_undo_tooltip = nullptr;
RevertButton* m_Undo_to_sys_btn = nullptr;
// Bitmap and Tooltip text for m_Undo_to_sys_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
const ScalableBitmap* m_undo_to_sys_bitmap = nullptr;
const wxString* m_undo_to_sys_tooltip = nullptr;
BlinkingBitmap* m_blinking_bmp{ nullptr };
bool m_blink{ false };
wxStaticText* m_Label = nullptr;
// 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;
// last maeningful value
@ -308,7 +294,7 @@ public:
boost::any& get_value() override;
void msw_rescale(bool rescale_sidetext = false) override;
void msw_rescale() override;
void enable() override;
void disable() override;
@ -336,7 +322,7 @@ public:
void set_na_value() override;
boost::any& get_value() override;
void msw_rescale(bool rescale_sidetext = false) override;
void msw_rescale() override;
void enable() override { dynamic_cast<wxCheckBox*>(window)->Enable(); }
void disable() override { dynamic_cast<wxCheckBox*>(window)->Disable(); }
@ -379,7 +365,7 @@ public:
return m_value = value;
}
void msw_rescale(bool rescale_sidetext = false) override;
void msw_rescale() override;
void enable() override { dynamic_cast<wxSpinCtrl*>(window)->Enable(); }
void disable() override { dynamic_cast<wxSpinCtrl*>(window)->Disable(); }
@ -408,10 +394,10 @@ public:
void set_values(const wxArrayString &values);
boost::any& get_value() override;
void msw_rescale(bool rescale_sidetext = false) override;
void msw_rescale() override;
void enable() override { dynamic_cast<wxBitmapComboBox*>(window)->Enable(); };
void disable() override{ dynamic_cast<wxBitmapComboBox*>(window)->Disable(); };
void enable() override ;//{ dynamic_cast<wxBitmapComboBox*>(window)->Enable(); };
void disable() override;//{ dynamic_cast<wxBitmapComboBox*>(window)->Disable(); };
wxWindow* getWindow() override { return window; }
};
@ -434,7 +420,7 @@ public:
}
void set_value(const boost::any& value, bool change_event = false) override;
boost::any& get_value() override;
void msw_rescale(bool rescale_sidetext = false) override;
void msw_rescale() override;
void enable() override { dynamic_cast<wxColourPickerCtrl*>(window)->Enable(); };
void disable() override{ dynamic_cast<wxColourPickerCtrl*>(window)->Disable(); };
@ -460,7 +446,7 @@ public:
void set_value(const boost::any& value, bool change_event = false);
boost::any& get_value() override;
void msw_rescale(bool rescale_sidetext = false) override;
void msw_rescale() override;
void enable() override {
x_textctrl->Enable();
@ -495,7 +481,7 @@ public:
boost::any& get_value()override { return m_value; }
void msw_rescale(bool rescale_sidetext = false) override;
void msw_rescale() override;
void enable() override { dynamic_cast<wxStaticText*>(window)->Enable(); };
void disable() override{ dynamic_cast<wxStaticText*>(window)->Disable(); };

View File

@ -0,0 +1,646 @@
#include "OG_CustomCtrl.hpp"
#include "OptionsGroup.hpp"
#include "Plater.hpp"
#include "GUI_App.hpp"
#include "libslic3r/AppConfig.hpp"
#include <wx/utils.h>
#include <boost/algorithm/string/split.hpp>
#include "libslic3r/Utils.hpp"
#include "I18N.hpp"
namespace Slic3r { namespace GUI {
static bool is_point_in_rect(const wxPoint& pt, const wxRect& rect)
{
return rect.GetLeft() <= pt.x && pt.x <= rect.GetRight() &&
rect.GetTop() <= pt.y && pt.y <= rect.GetBottom();
}
static wxSize get_bitmap_size(const wxBitmap& bmp)
{
#ifdef __APPLE__
return bmp.GetScaledSize();
#else
return bmp.GetSize();
#endif
}
static wxString get_url(const wxString& path_end, bool get_default = false)
{
if (path_end.IsEmpty())
return wxEmptyString;
wxString language = wxGetApp().app_config->get("translation_language");
wxString lang_marker = language.IsEmpty() ? "en" : language.BeforeFirst('_');
return wxString("https://help.prusa3d.com/") + lang_marker + "/article/" + path_end;
}
OG_CustomCtrl::OG_CustomCtrl( wxWindow* parent,
OptionsGroup* og,
const wxPoint& pos /* = wxDefaultPosition*/,
const wxSize& size/* = wxDefaultSize*/,
const wxValidator& val /* = wxDefaultValidator*/,
const wxString& name/* = wxEmptyString*/) :
wxPanel(parent, wxID_ANY, pos, size, /*wxWANTS_CHARS |*/ wxBORDER_NONE | wxTAB_TRAVERSAL),
opt_group(og)
{
if (!wxOSX)
SetDoubleBuffered(true);// SetDoubleBuffered exists on Win and Linux/GTK, but is missing on OSX
m_font = wxGetApp().normal_font();
m_em_unit = em_unit(m_parent);
m_v_gap = lround(1.0 * m_em_unit);
m_h_gap = lround(0.2 * m_em_unit);
m_bmp_mode_sz = get_bitmap_size(create_scaled_bitmap("mode_simple", this, wxOSX ? 10 : 12));
m_bmp_blinking_sz = get_bitmap_size(create_scaled_bitmap("search_blink", this));
init_ctrl_lines();// from og.lines()
this->Bind(wxEVT_PAINT, &OG_CustomCtrl::OnPaint, this);
this->Bind(wxEVT_MOTION, &OG_CustomCtrl::OnMotion, this);
this->Bind(wxEVT_LEFT_DOWN, &OG_CustomCtrl::OnLeftDown, this);
}
void OG_CustomCtrl::init_ctrl_lines()
{
const std::vector<Line>& og_lines = opt_group->get_lines();
for (const Line& line : og_lines)
{
if (line.full_width && (
// description line
line.widget != nullptr ||
// description line with widget (button)
!line.get_extra_widgets().empty())
)
continue;
const std::vector<Option>& option_set = line.get_options();
wxCoord height;
// if we have a single option with no label, no sidetext just add it directly to sizer
if (option_set.size() == 1 && opt_group->label_width == 0 && option_set.front().opt.full_width &&
option_set.front().opt.label.empty() &&
option_set.front().opt.sidetext.size() == 0 && option_set.front().side_widget == nullptr &&
line.get_extra_widgets().size() == 0)
{
height = m_bmp_blinking_sz.GetHeight() + m_v_gap;
ctrl_lines.emplace_back(CtrlLine(height, this, line, true));
}
else if (opt_group->label_width != 0 && !line.label.IsEmpty())
{
wxSize label_sz = GetTextExtent(line.label);
height = label_sz.y * (label_sz.GetWidth() > int(opt_group->label_width * m_em_unit) ? 2 : 1) + m_v_gap;
ctrl_lines.emplace_back(CtrlLine(height, this, line));
}
else
int i = 0;
}
}
int OG_CustomCtrl::get_height(const Line& line)
{
for (auto ctrl_line : ctrl_lines)
if (&ctrl_line.og_line == &line)
return ctrl_line.height;
return 0;
}
wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/)
{
wxCoord v_pos = 0;
wxCoord h_pos = 0;
for (auto ctrl_line : ctrl_lines) {
if (&ctrl_line.og_line == &line)
{
h_pos = m_bmp_mode_sz.GetWidth() + m_h_gap;
if (line.near_label_widget_win) {
wxSize near_label_widget_sz = line.near_label_widget_win->GetSize();
if (field_in)
h_pos += near_label_widget_sz.GetWidth() + m_h_gap;
else
break;
}
wxString label = line.label;
if (opt_group->label_width != 0 && !label.IsEmpty())
h_pos += opt_group->label_width * m_em_unit + m_h_gap;
int blinking_button_width = m_bmp_blinking_sz.GetWidth() + m_h_gap;
if (line.widget) {
h_pos += blinking_button_width;
break;
}
// If we have a single option with no sidetext
const std::vector<Option>& option_set = line.get_options();
if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 &&
option_set.front().opt.label.empty() &&
option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0)
{
h_pos += 3 * blinking_button_width;
break;
}
for (auto opt : option_set) {
Field* field = opt_group->get_field(opt.opt_id);
ConfigOptionDef option = opt.opt;
// add label if any
if (!option.label.empty()) {
//! To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1
label = (option.label == L_CONTEXT("Top", "Layers") || option.label == L_CONTEXT("Bottom", "Layers")) ?
_CTX(option.label, "Layers") : _(option.label);
label += ":";
wxPaintDC dc(this);
dc.SetFont(m_font);
h_pos += dc.GetMultiLineTextExtent(label).x + m_h_gap;
}
h_pos += 3 * blinking_button_width;
if (field == field_in)
break;
h_pos += field->getWindow()->GetSize().x;
if (option_set.size() == 1 && option_set.front().opt.full_width)
break;
// add sidetext if any
if (!option.sidetext.empty() || opt_group->sidetext_width > 0)
h_pos += opt_group->sidetext_width * m_em_unit + m_h_gap;
if (opt.opt_id != option_set.back().opt_id) //! istead of (opt != option_set.back())
h_pos += lround(0.6 * m_em_unit);
}
break;
}
if (ctrl_line.is_visible)
v_pos += ctrl_line.height;
}
return wxPoint(h_pos, v_pos);
}
void OG_CustomCtrl::OnPaint(wxPaintEvent&)
{
#ifdef _WIN32
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
#else
SetBackgroundColour(GetParent()->GetBackgroundColour());
#endif // _WIN32
// case, when custom controll is destroyed but doesn't deleted from the evet loop
if(!this->opt_group->custom_ctrl)
return;
wxPaintDC dc(this);
dc.SetFont(m_font);
wxCoord v_pos = 0;
for (CtrlLine& line : ctrl_lines) {
if (!line.is_visible)
continue;
line.render(dc, v_pos);
v_pos += line.height;
}
}
void OG_CustomCtrl::OnMotion(wxMouseEvent& event)
{
const wxPoint pos = event.GetLogicalPosition(wxClientDC(this));
wxString tooltip;
wxString language = wxGetApp().app_config->get("translation_language");
for (CtrlLine& line : ctrl_lines) {
line.is_focused = is_point_in_rect(pos, line.rect_label);
if (line.is_focused) {
tooltip = get_url(line.og_line.label_path);
break;
}
for (size_t opt_idx = 0; opt_idx < line.rects_undo_icon.size(); opt_idx++)
if (is_point_in_rect(pos, line.rects_undo_icon[opt_idx])) {
const std::vector<Option>& option_set = line.og_line.get_options();
Field* field = opt_group->get_field(option_set[opt_idx].opt_id);
if (field)
tooltip = *field->undo_tooltip();
break;
}
for (size_t opt_idx = 0; opt_idx < line.rects_undo_to_sys_icon.size(); opt_idx++)
if (is_point_in_rect(pos, line.rects_undo_to_sys_icon[opt_idx])) {
const std::vector<Option>& option_set = line.og_line.get_options();
Field* field = opt_group->get_field(option_set[opt_idx].opt_id);
if (field)
tooltip = *field->undo_to_sys_tooltip();
break;
}
if (!tooltip.IsEmpty())
break;
}
// Set tooltips with information for each icon
this->SetToolTip(tooltip);
Refresh();
Update();
event.Skip();
}
void OG_CustomCtrl::OnLeftDown(wxMouseEvent& event)
{
const wxPoint pos = event.GetLogicalPosition(wxClientDC(this));
for (const CtrlLine& line : ctrl_lines) {
if (line.launch_browser())
return;
for (size_t opt_idx = 0; opt_idx < line.rects_undo_icon.size(); opt_idx++)
if (is_point_in_rect(pos, line.rects_undo_icon[opt_idx])) {
const std::vector<Option>& option_set = line.og_line.get_options();
Field* field = opt_group->get_field(option_set[opt_idx].opt_id);
if (field)
field->on_back_to_initial_value();
event.Skip();
return;
}
for (size_t opt_idx = 0; opt_idx < line.rects_undo_to_sys_icon.size(); opt_idx++)
if (is_point_in_rect(pos, line.rects_undo_to_sys_icon[opt_idx])) {
const std::vector<Option>& option_set = line.og_line.get_options();
Field* field = opt_group->get_field(option_set[opt_idx].opt_id);
if (field)
field->on_back_to_sys_value();
event.Skip();
return;
}
}
}
bool OG_CustomCtrl::update_visibility(ConfigOptionMode mode)
{
wxCoord v_pos = 0;
size_t invisible_lines = 0;
for (CtrlLine& line : ctrl_lines) {
line.update_visibility(mode);
if (line.is_visible)
v_pos += (wxCoord)line.height;
else
invisible_lines++;
}
this->SetMinSize(wxSize(wxDefaultCoord, v_pos));
return invisible_lines != ctrl_lines.size();
}
void OG_CustomCtrl::correct_window_position(wxWindow* win, const Line& line, Field* field/* = nullptr*/)
{
wxPoint pos = get_pos(line, field);
int line_height = get_height(line);
pos.y += std::max(0, int(0.5 * (line_height - win->GetSize().y)));
win->SetPosition(pos);
};
void OG_CustomCtrl::correct_widgets_position(wxSizer* widget, const Line& line, Field* field/* = nullptr*/) {
auto children = widget->GetChildren();
wxPoint line_pos = get_pos(line, field);
int line_height = get_height(line);
for (auto child : children)
if (child->IsWindow()) {
wxPoint pos = line_pos;
wxSize sz = child->GetWindow()->GetSize();
pos.y += std::max(0, int(0.5 * (line_height - sz.y)));
child->GetWindow()->SetPosition(pos);
line_pos.x += sz.x + m_h_gap;
}
};
void OG_CustomCtrl::msw_rescale()
{
m_font = wxGetApp().normal_font();
m_em_unit = em_unit(m_parent);
m_v_gap = lround(1.0 * m_em_unit);
m_h_gap = lround(0.2 * m_em_unit);
m_bmp_mode_sz = create_scaled_bitmap("mode_simple", this, wxOSX ? 10 : 12).GetSize();
m_bmp_blinking_sz = create_scaled_bitmap("search_blink", this).GetSize();
wxCoord v_pos = 0;
for (CtrlLine& line : ctrl_lines) {
line.msw_rescale();
if (line.is_visible)
v_pos += (wxCoord)line.height;
}
this->SetMinSize(wxSize(wxDefaultCoord, v_pos));
GetParent()->Layout();
}
void OG_CustomCtrl::sys_color_changed()
{
msw_rescale();
}
OG_CustomCtrl::CtrlLine::CtrlLine( wxCoord height,
OG_CustomCtrl* ctrl,
const Line& og_line,
bool draw_just_act_buttons /* = false*/):
height(height),
ctrl(ctrl),
og_line(og_line),
draw_just_act_buttons(draw_just_act_buttons)
{
for (size_t i = 0; i < og_line.get_options().size(); i++) {
rects_undo_icon.emplace_back(wxRect());
rects_undo_to_sys_icon.emplace_back(wxRect());
}
}
void OG_CustomCtrl::CtrlLine::correct_items_positions()
{
if (draw_just_act_buttons || !is_visible)
return;
if (og_line.near_label_widget_win)
ctrl->correct_window_position(og_line.near_label_widget_win, og_line);
if (og_line.widget_sizer)
ctrl->correct_widgets_position(og_line.widget_sizer, og_line);
if (og_line.extra_widget_sizer)
ctrl->correct_widgets_position(og_line.extra_widget_sizer, og_line);
const std::vector<Option>& option_set = og_line.get_options();
for (auto opt : option_set) {
Field* field = ctrl->opt_group->get_field(opt.opt_id);
if (!field)
continue;
if (field->getSizer())
ctrl->correct_widgets_position(field->getSizer(), og_line, field);
else if (field->getWindow())
ctrl->correct_window_position(field->getWindow(), og_line, field);
}
}
void OG_CustomCtrl::CtrlLine::msw_rescale()
{
// if we have a single option with no label, no sidetext
if (draw_just_act_buttons)
height = get_bitmap_size(create_scaled_bitmap("empty")).GetHeight();
if (ctrl->opt_group->label_width != 0 && !og_line.label.IsEmpty()) {
wxSize label_sz = ctrl->GetTextExtent(og_line.label);
height = label_sz.y * (label_sz.GetWidth() > int(ctrl->opt_group->label_width * ctrl->m_em_unit) ? 2 : 1) + ctrl->m_v_gap;
}
if (og_line.get_options().front().opt.full_width) {
Field* field = ctrl->opt_group->get_field(og_line.get_options().front().opt_id);
if (field->getWindow())
field->getWindow()->SetSize(wxSize(3 * Field::def_width_wider() * ctrl->m_em_unit, -1));
}
correct_items_positions();
}
void OG_CustomCtrl::CtrlLine::update_visibility(ConfigOptionMode mode)
{
const std::vector<Option>& option_set = og_line.get_options();
const ConfigOptionMode& line_mode = option_set.front().opt.mode;
is_visible = line_mode <= mode;
if (draw_just_act_buttons)
return;
if (og_line.near_label_widget_win)
og_line.near_label_widget_win->Show(is_visible);
if (og_line.widget_sizer)
og_line.widget_sizer->ShowItems(is_visible);
if (og_line.extra_widget_sizer)
og_line.extra_widget_sizer->ShowItems(is_visible);
for (auto opt : option_set) {
Field* field = ctrl->opt_group->get_field(opt.opt_id);
if (!field)
continue;
if (field->getSizer()) {
auto children = field->getSizer()->GetChildren();
for (auto child : children)
if (child->IsWindow())
child->GetWindow()->Show(is_visible);
}
else if (field->getWindow())
field->getWindow()->Show(is_visible);
}
correct_items_positions();
}
void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos)
{
Field* field = ctrl->opt_group->get_field(og_line.get_options().front().opt_id);
if (draw_just_act_buttons) {
if (field)
draw_act_bmps(dc, wxPoint(0, v_pos), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp(), field->blink());
return;
}
wxCoord h_pos = draw_mode_bmp(dc, v_pos);
if (og_line.near_label_widget_win)
h_pos += og_line.near_label_widget_win->GetSize().x + ctrl->m_h_gap;
const std::vector<Option>& option_set = og_line.get_options();
wxString label = og_line.label;
bool is_url_string = false;
if (ctrl->opt_group->label_width != 0 && !label.IsEmpty()) {
const wxColour* text_clr = (option_set.size() == 1 && field ? field->label_color() : og_line.full_Label_color);
is_url_string = !og_line.label_path.IsEmpty();
h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label + ":", text_clr, ctrl->opt_group->label_width * ctrl->m_em_unit, is_url_string);
}
// If there's a widget, build it and set result to the correct position.
if (og_line.widget != nullptr) {
draw_blinking_bmp(dc, wxPoint(h_pos, v_pos), og_line.blink);
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
// 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().opt.label.empty() &&
option_set.front().side_widget == nullptr && og_line.get_extra_widgets().size() == 0)
{
if (field && field->undo_to_sys_bitmap())
draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp(), field->blink());
return;
}
size_t bmp_rect_id = 0;
for (const Option& opt : option_set) {
field = ctrl->opt_group->get_field(opt.opt_id);
ConfigOptionDef option = opt.opt;
// add label if any
if (!option.label.empty()) {
//! To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1
label = (option.label == L_CONTEXT("Top", "Layers") || option.label == L_CONTEXT("Bottom", "Layers")) ?
_CTX(option.label, "Layers") : _(option.label);
label += ":";
if (is_url_string)
is_url_string = false;
else if(opt == option_set.front())
is_url_string = !og_line.label_path.IsEmpty();
h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label, field ? field->label_color() : nullptr, ctrl->opt_group->sublabel_width * ctrl->m_em_unit, is_url_string);
}
if (field && field->undo_to_sys_bitmap()) {
h_pos = draw_act_bmps(dc, wxPoint(h_pos, v_pos), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp(), field->blink(), bmp_rect_id++);
if (field->getSizer())
{
auto children = field->getSizer()->GetChildren();
for (auto child : children)
if (child->IsWindow())
h_pos += child->GetWindow()->GetSize().x + ctrl->m_h_gap;
}
else if (field->getWindow())
h_pos += field->getWindow()->GetSize().x + ctrl->m_h_gap;
}
// add field
if (option_set.size() == 1 && option_set.front().opt.full_width)
break;
// add sidetext if any
if (!option.sidetext.empty() || ctrl->opt_group->sidetext_width > 0)
h_pos = draw_text(dc, wxPoint(h_pos, v_pos), _(option.sidetext), nullptr, ctrl->opt_group->sidetext_width * ctrl->m_em_unit);
if (opt.opt_id != option_set.back().opt_id) //! istead of (opt != option_set.back())
h_pos += lround(0.6 * ctrl->m_em_unit);
}
}
wxCoord OG_CustomCtrl::CtrlLine::draw_mode_bmp(wxDC& dc, wxCoord v_pos)
{
ConfigOptionMode mode = og_line.get_options()[0].opt.mode;
const std::string& bmp_name = mode == ConfigOptionMode::comSimple ? "mode_simple" :
mode == ConfigOptionMode::comAdvanced ? "mode_advanced" : "mode_expert";
wxBitmap bmp = create_scaled_bitmap(bmp_name, ctrl, wxOSX ? 10 : 12);
wxCoord y_draw = v_pos + lround((height - get_bitmap_size(bmp).GetHeight()) / 2);
dc.DrawBitmap(bmp, 0, y_draw);
return get_bitmap_size(bmp).GetWidth() + ctrl->m_h_gap;
}
wxCoord OG_CustomCtrl::CtrlLine::draw_text(wxDC& dc, wxPoint pos, const wxString& text, const wxColour* color, int width, bool is_url/* = false*/)
{
wxString multiline_text;
if (width > 0 && dc.GetTextExtent(text).x > width) {
multiline_text = text;
size_t idx = size_t(-1);
for (size_t i = 0; i < multiline_text.Len(); i++)
{
if (multiline_text[i] == ' ')
{
if (dc.GetTextExtent(multiline_text.SubString(0, i)).x < width)
idx = i;
else {
if (idx != size_t(-1))
multiline_text[idx] = '\n';
else
multiline_text[i] = '\n';
break;
}
}
}
if (idx != size_t(-1))
multiline_text[idx] = '\n';
}
if (!text.IsEmpty()) {
const wxString& out_text = multiline_text.IsEmpty() ? text : multiline_text;
wxCoord text_width, text_height;
dc.GetMultiLineTextExtent(out_text, &text_width, &text_height);
pos.y = pos.y + lround((height - text_height) / 2);
if (width > 0 && is_url)
rect_label = wxRect(pos, wxSize(text_width, text_height));
wxColour old_clr = dc.GetTextForeground();
wxFont old_font = dc.GetFont();
if (is_focused && is_url)
// temporary workaround for the OSX because of strange Bold font behavior on BigSerf
#ifdef __APPLE__
dc.SetFont(old_font.Underlined());
#else
dc.SetFont(old_font.Bold().Underlined());
#endif
dc.SetTextForeground(color ? *color : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
dc.DrawText(out_text, pos);
dc.SetTextForeground(old_clr);
dc.SetFont(old_font);
if (width < 1)
width = text_width;
}
return pos.x + width + ctrl->m_h_gap;
}
wxPoint OG_CustomCtrl::CtrlLine::draw_blinking_bmp(wxDC& dc, wxPoint pos, bool is_blinking, size_t rect_id)
{
wxBitmap bmp_blinking = create_scaled_bitmap(is_blinking ? "search_blink" : "empty", ctrl);
wxCoord h_pos = pos.x;
wxCoord v_pos = pos.y + lround((height - get_bitmap_size(bmp_blinking).GetHeight()) / 2);
dc.DrawBitmap(bmp_blinking, h_pos, v_pos);
int bmp_dim = get_bitmap_size(bmp_blinking).GetWidth();
h_pos += bmp_dim + ctrl->m_h_gap;
return wxPoint(h_pos, v_pos);
}
wxCoord OG_CustomCtrl::CtrlLine::draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo, bool is_blinking, size_t rect_id)
{
pos = draw_blinking_bmp(dc, pos, is_blinking, rect_id);
wxCoord h_pos = pos.x;
wxCoord v_pos = pos.y;
dc.DrawBitmap(bmp_undo_to_sys, h_pos, v_pos);
int bmp_dim = get_bitmap_size(bmp_undo_to_sys).GetWidth();
rects_undo_to_sys_icon[rect_id] = wxRect(h_pos, v_pos, bmp_dim, bmp_dim);
h_pos += bmp_dim + ctrl->m_h_gap;
dc.DrawBitmap(bmp_undo, h_pos, v_pos);
bmp_dim = get_bitmap_size(bmp_undo).GetWidth();
rects_undo_icon[rect_id] = wxRect(h_pos, v_pos, bmp_dim, bmp_dim);
h_pos += bmp_dim + ctrl->m_h_gap;
return h_pos;
}
bool OG_CustomCtrl::CtrlLine::launch_browser() const
{
return is_focused && !og_line.label_path.IsEmpty() && wxLaunchDefaultBrowser(get_url(og_line.label_path));
}
} // GUI
} // Slic3r

View File

@ -0,0 +1,99 @@
#ifndef slic3r_OG_CustomCtrl_hpp_
#define slic3r_OG_CustomCtrl_hpp_
#include <wx/stattext.h>
#include <wx/settings.h>
#include <map>
#include <functional>
#include "libslic3r/Config.hpp"
#include "libslic3r/PrintConfig.hpp"
#include "OptionsGroup.hpp"
#include "I18N.hpp"
// Translate the ifdef
#ifdef __WXOSX__
#define wxOSX true
#else
#define wxOSX false
#endif
namespace Slic3r { namespace GUI {
// Static text shown among the options.
class OG_CustomCtrl :public wxPanel
{
wxFont m_font;
int m_v_gap;
int m_h_gap;
int m_em_unit;
wxSize m_bmp_mode_sz;
wxSize m_bmp_blinking_sz;
struct CtrlLine {
wxCoord height { wxDefaultCoord };
OG_CustomCtrl* ctrl { nullptr };
const Line& og_line;
bool draw_just_act_buttons { false };
bool is_visible { true };
bool is_focused { false };
CtrlLine( wxCoord height,
OG_CustomCtrl* ctrl,
const Line& og_line,
bool draw_just_act_buttons = false);
~CtrlLine() { ctrl = nullptr; }
void correct_items_positions();
void msw_rescale();
void update_visibility(ConfigOptionMode mode);
void render(wxDC& dc, wxCoord v_pos);
wxCoord draw_mode_bmp(wxDC& dc, wxCoord v_pos);
wxCoord draw_text (wxDC& dc, wxPoint pos, const wxString& text, const wxColour* color, int width, bool is_url = false);
wxPoint draw_blinking_bmp(wxDC& dc, wxPoint pos, bool is_blinking, size_t rect_id = 0);
wxCoord draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo, bool is_blinking, size_t rect_id = 0);
bool launch_browser() const;
std::vector<wxRect> rects_undo_icon;
std::vector<wxRect> rects_undo_to_sys_icon;
wxRect rect_label;
};
std::vector<CtrlLine> ctrl_lines;
public:
OG_CustomCtrl( wxWindow* parent,
OptionsGroup* og,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
const wxValidator& val = wxDefaultValidator,
const wxString& name = wxEmptyString);
~OG_CustomCtrl() {}
void OnPaint(wxPaintEvent&);
void OnMotion(wxMouseEvent& event);
void OnLeftDown(wxMouseEvent& event);
void init_ctrl_lines();
bool update_visibility(ConfigOptionMode mode);
void correct_window_position(wxWindow* win, const Line& line, Field* field = nullptr);
void correct_widgets_position(wxSizer* widget, const Line& line, Field* field = nullptr);
void msw_rescale();
void sys_color_changed();
wxPoint get_pos(const Line& line, Field* field = nullptr);
int get_height(const Line& line);
OptionsGroup* opt_group;
};
}}
#endif /* slic3r_OG_CustomCtrl_hpp_ */

View File

@ -2,6 +2,7 @@
#include "ConfigExceptions.hpp"
#include "Plater.hpp"
#include "GUI_App.hpp"
#include "OG_CustomCtrl.hpp"
#include <utility>
#include <wx/numformatter.h>
@ -13,15 +14,15 @@
namespace Slic3r { namespace GUI {
const t_field& OptionsGroup::build_field(const Option& opt, wxStaticText* label/* = nullptr*/) {
return build_field(opt.opt_id, opt.opt, label);
const t_field& OptionsGroup::build_field(const Option& opt) {
return build_field(opt.opt_id, opt.opt);
}
const t_field& OptionsGroup::build_field(const t_config_option_key& id, wxStaticText* label/* = nullptr*/) {
const t_field& OptionsGroup::build_field(const t_config_option_key& id) {
const ConfigOptionDef& opt = m_options.at(id).opt;
return build_field(id, opt, label);
return build_field(id, opt);
}
const t_field& OptionsGroup::build_field(const t_config_option_key& id, const ConfigOptionDef& opt, wxStaticText* label/* = nullptr*/) {
const t_field& OptionsGroup::build_field(const t_config_option_key& id, const ConfigOptionDef& opt) {
// Check the gui_type field first, fall through
// is the normal type.
if (opt.gui_type.compare("select") == 0) {
@ -88,8 +89,6 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
};
field->m_parent = parent();
//! Label to change background color, when option is modified
field->m_Label = label;
field->m_back_to_initial_value = [this](std::string opt_id) {
if (!m_disabled)
this->back_to_initial_value(opt_id);
@ -112,18 +111,44 @@ OptionsGroup::OptionsGroup( wxWindow* _parent, const wxString& title,
{
}
void OptionsGroup::add_undo_buttons_to_sizer(wxSizer* sizer, const t_field& field)
void OptionsGroup::show_field(const t_config_option_key& opt_key, bool show/* = true*/)
{
if (!m_show_modified_btns) {
field->m_Undo_btn->set_as_hidden();
field->m_Undo_to_sys_btn->set_as_hidden();
field->m_blinking_bmp->Hide();
Field* field = get_field(opt_key);
if (!field) return;
wxWindow* win = field->getWindow();
if (!win) return;
wxSizerItem* win_item = m_grid_sizer->GetItem(win, true);
if (!win_item) return;
const size_t cols = (size_t)m_grid_sizer->GetCols();
const size_t rows = (size_t)m_grid_sizer->GetEffectiveRowsCount();
auto show_row = [this, show, cols, win_item](wxSizerItem* item, size_t row_shift) {
// check if item contanes required win
if (!item->IsWindow() || item != win_item)
return false;
// show/hide hole line contanes this window
for (size_t i = 0; i < cols; ++i)
m_grid_sizer->Show(row_shift + i, show);
return true;
};
size_t row_shift = 0;
for (size_t j = 0; j < rows; ++j) {
for (size_t i = 0; i < cols; ++i) {
wxSizerItem* item = m_grid_sizer->GetItem(row_shift + i);
if (!item)
continue;
if (item->IsSizer()) {
for (wxSizerItem* child_item : item->GetSizer()->GetChildren())
if (show_row(child_item, row_shift))
return;
}
sizer->Add(field->m_blinking_bmp, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 2);
sizer->Add(field->m_Undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL);
sizer->Add(field->m_Undo_btn, 0, wxALIGN_CENTER_VERTICAL);
else if (show_row(item, row_shift))
return;
}
row_shift += cols;
}
}
void OptionsGroup::append_line(const Line& line)
@ -147,11 +172,14 @@ void OptionsGroup::append_line(const Line& line)
void OptionsGroup::activate_line(Line& line)
{
m_use_custom_ctrl_as_parent = false;
if (line.full_width && (
line.widget != nullptr ||
!line.get_extra_widgets().empty())
) {
if (line.widget != nullptr) {
// description lines
sizer->Add(line.widget(this->ctrl_parent()), 0, wxEXPAND | wxALL, wxOSX ? 0 : 15);
return;
}
@ -168,6 +196,11 @@ void OptionsGroup::activate_line(Line& line)
}
}
if (!custom_ctrl && m_show_modified_btns) {
custom_ctrl = new OG_CustomCtrl((wxWindow*)this->stb, this);
sizer->Add(custom_ctrl, 0, wxEXPAND | wxALL, wxOSX || !staticbox ? 0 : 5);
}
auto option_set = line.get_options();
// Set sidetext width for a better alignment of options in line
@ -181,36 +214,24 @@ void OptionsGroup::activate_line(Line& line)
option_set.front().opt.label.empty() &&
option_set.front().opt.sidetext.size() == 0 && option_set.front().side_widget == nullptr &&
line.get_extra_widgets().size() == 0) {
wxSizer* tmp_sizer;
#if 0//#ifdef __WXGTK__
tmp_sizer = new wxBoxSizer(wxVERTICAL);
m_panel->SetSizer(tmp_sizer);
m_panel->Layout();
#else
tmp_sizer = sizer;
#endif /* __WXGTK__ */
const auto& option = option_set.front();
const auto& field = build_field(option);
auto btn_sizer = new wxBoxSizer(wxHORIZONTAL);
add_undo_buttons_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);
sizer->Add(field->getWindow(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5);
if (is_sizer_field(field))
tmp_sizer->Add(field->getSizer(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5);
sizer->Add(field->getSizer(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5);
return;
}
auto grid_sizer = m_grid_sizer;
#if 0//#ifdef __WXGTK__
m_panel->SetSizer(m_grid_sizer);
m_panel->Layout();
#endif /* __WXGTK__ */
if (custom_ctrl)
m_use_custom_ctrl_as_parent = true;
// if we have an extra column, build it
if (extra_column)
if (extra_column && !m_show_modified_btns)
{
m_extra_column_item_ptrs.push_back(extra_column(this->ctrl_parent(), line));
grid_sizer->Add(m_extra_column_item_ptrs.back(), 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 3);
@ -219,6 +240,11 @@ void OptionsGroup::activate_line(Line& line)
// Build a label if we have it
wxStaticText* label=nullptr;
if (label_width != 0) {
if (custom_ctrl) {
if (line.near_label_widget)
line.near_label_widget_win = line.near_label_widget(this->ctrl_parent());
}
else {
if (!line.near_label_widget || !line.label.IsEmpty()) {
// Only create the label if it is going to be displayed.
long label_style = staticbox ? 0 : wxALIGN_RIGHT;
@ -236,30 +262,24 @@ void OptionsGroup::activate_line(Line& line)
}
if (!line.near_label_widget)
grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, line.label.IsEmpty() ? 0 : 5);
else {
m_near_label_widget_ptrs.push_back(line.near_label_widget(this->ctrl_parent()));
if (line.label.IsEmpty())
grid_sizer->Add(m_near_label_widget_ptrs.back(), 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 7);
else {
else if (!line.label.IsEmpty()) {
// If we're here, we have some widget near the label
// so we need a horizontal sizer to arrange these things
auto sizer = new wxBoxSizer(wxHORIZONTAL);
grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1);
sizer->Add(m_near_label_widget_ptrs.back(), 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 7);
sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5);
}
}
if (label != nullptr && line.label_tooltip != "")
label->SetToolTip(line.label_tooltip);
}
}
if (line.full_Label != nullptr)
*line.full_Label = label; // Initiate the pointer to the control of the full label, if we need this one.
// If there's a widget, build it and add the result to the sizer.
if (line.widget != nullptr) {
auto wgt = line.widget(this->ctrl_parent());
// If widget doesn't have label, don't use border
if (custom_ctrl)
line.widget_sizer = wgt;
else
grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, (wxOSX || line.label.IsEmpty()) ? 0 : 5);
return;
}
@ -267,20 +287,26 @@ void OptionsGroup::activate_line(Line& line)
// 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(wxHORIZONTAL);
if (!custom_ctrl)
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().opt.label.empty() &&
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);
const auto& field = build_field(option);
add_undo_buttons_to_sizer(sizer, field);
if (custom_ctrl) {
if (is_window_field(field) && option.opt.full_width)
field->getWindow()->SetSize(wxSize(3 * Field::def_width_wider() * wxGetApp().em_unit(), -1));
}
else {
if (is_window_field(field))
sizer->Add(field->getWindow(), option.opt.full_width ? 1 : 0, //(option.opt.full_width ? wxEXPAND : 0) |
sizer->Add(field->getWindow(), option.opt.full_width ? 1 : 0,
wxBOTTOM | wxTOP | (option.opt.full_width ? wxEXPAND : wxALIGN_CENTER_VERTICAL), (wxOSX || !staticbox) ? 0 : 2);
if (is_sizer_field(field))
sizer->Add(field->getSizer(), 1, /*(*/option.opt.full_width ? wxEXPAND : /*0) |*/ wxALIGN_CENTER_VERTICAL, 0);
sizer->Add(field->getSizer(), 1, option.opt.full_width ? wxEXPAND : wxALIGN_CENTER_VERTICAL, 0);
}
return;
}
@ -288,7 +314,7 @@ void OptionsGroup::activate_line(Line& line)
ConfigOptionDef option = opt.opt;
wxSizer* sizer_tmp = sizer;
// add label if any
if (!option.label.empty()) {
if (!option.label.empty() && !custom_ctrl) {
//! To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1
wxString str_label = (option.label == L_CONTEXT("Top", "Layers") || option.label == L_CONTEXT("Bottom", "Layers")) ?
_CTX(option.label, "Layers") :
@ -302,8 +328,8 @@ void OptionsGroup::activate_line(Line& line)
// add field
const Option& opt_ref = opt;
auto& field = build_field(opt_ref, label);
add_undo_buttons_to_sizer(sizer_tmp, field);
auto& field = build_field(opt_ref);
if (!custom_ctrl) {
if (option_set.size() == 1 && option_set.front().opt.full_width)
{
const auto v_sizer = new wxBoxSizer(wxVERTICAL);
@ -311,7 +337,7 @@ void OptionsGroup::activate_line(Line& line)
is_sizer_field(field) ?
v_sizer->Add(field->getSizer(), 0, wxEXPAND) :
v_sizer->Add(field->getWindow(), 0, wxEXPAND);
break;//return;
break;
}
is_sizer_field(field) ?
@ -325,7 +351,6 @@ void OptionsGroup::activate_line(Line& line)
sidetext->SetBackgroundStyle(wxBG_STYLE_PAINT);
sidetext->SetFont(wxGetApp().normal_font());
sizer_tmp->Add(sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4);
field->set_side_text_ptr(sidetext);
}
// add side widget if any
@ -334,10 +359,10 @@ void OptionsGroup::activate_line(Line& line)
}
if (opt.opt_id != option_set.back().opt_id) //! istead of (opt != option_set.back())
{
sizer_tmp->AddSpacer(6);
}
}
// add extra sizers if any
for (auto extra_widget : line.get_extra_widgets())
{
@ -350,7 +375,9 @@ void OptionsGroup::activate_line(Line& line)
return;
}
sizer->Add(extra_widget(this->ctrl_parent())/*!.target<wxWindow>()*/, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4); //! requires verification
line.extra_widget_sizer = extra_widget(this->ctrl_parent());
if (!custom_ctrl)
sizer->Add(line.extra_widget_sizer, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4); //! requires verification
}
}
@ -405,7 +432,7 @@ bool OptionsGroup::activate(std::function<void()> throw_if_canceled)
return true;
}
// delete all controls from the option group
void OptionsGroup::clear()
void OptionsGroup::clear(bool destroy_custom_ctrl)
{
if (!sizer)
return;
@ -413,20 +440,43 @@ void OptionsGroup::clear()
m_grid_sizer = nullptr;
sizer = nullptr;
for (Line& line : m_lines)
if(line.full_Label)
*line.full_Label = nullptr;
for (Line& line : m_lines) {
if (line.near_label_widget_win)
line.near_label_widget_win = nullptr;
if (line.widget_sizer) {
line.widget_sizer->Clear(true);
line.widget_sizer = nullptr;
}
if (line.extra_widget_sizer) {
line.extra_widget_sizer->Clear(true);
line.extra_widget_sizer = nullptr;
}
}
if (custom_ctrl) {
for (auto const &item : m_fields) {
wxWindow* win = item.second.get()->getWindow();
if (win)
win = nullptr;
}
if (destroy_custom_ctrl)
custom_ctrl->Destroy();
else
custom_ctrl = nullptr;
}
m_extra_column_item_ptrs.clear();
m_near_label_widget_ptrs.clear();
m_fields.clear();
}
Line OptionsGroup::create_single_option_line(const Option& option) const {
Line OptionsGroup::create_single_option_line(const Option& option, const wxString& path/* = wxEmptyString*/) const {
// Line retval{ _(option.opt.label), _(option.opt.tooltip) };
wxString tooltip = _(option.opt.tooltip);
edit_tooltip(tooltip);
Line retval{ _(option.opt.label), tooltip };
retval.label_path = path;
Option tmp(option);
tmp.opt.label = std::string("");
retval.append_option(tmp);
@ -590,6 +640,13 @@ bool ConfigOptionsGroup::update_visibility(ConfigOptionMode mode)
{
if (m_options_mode.empty() || !m_grid_sizer)
return true;
if (custom_ctrl) {
bool show = custom_ctrl->update_visibility(mode);
this->Show(show);
return show;
}
int opt_mode_size = m_options_mode.size();
if (m_grid_sizer->GetEffectiveRowsCount() != opt_mode_size &&
opt_mode_size == 1)
@ -624,62 +681,55 @@ void ConfigOptionsGroup::msw_rescale()
for (auto extra_col : m_extra_column_item_ptrs)
rescale_extra_column_item(extra_col);
// update bitmaps for near label widgets (like "Set uniform scale" button on settings panel)
if (rescale_near_label_widget)
for (auto near_label_widget : m_near_label_widget_ptrs)
rescale_near_label_widget(near_label_widget);
// update undo buttons : rescale bitmaps
for (const auto& field : m_fields)
field.second->msw_rescale(sidetext_width>0);
field.second->msw_rescale();
const int em = em_unit(parent());
auto rescale = [](wxSizer* sizer) {
for (wxSizerItem* item : sizer->GetChildren())
if (item->IsWindow()) {
wxWindow* win = item->GetWindow();
// check if window is ScalableButton
ScalableButton* sc_btn = dynamic_cast<ScalableButton*>(win);
if (sc_btn) {
sc_btn->msw_rescale();
sc_btn->SetSize(sc_btn->GetBestSize());
return;
}
// check if window is wxButton
wxButton* btn = dynamic_cast<wxButton*>(win);
if (btn) {
btn->SetSize(btn->GetBestSize());
return;
}
}
};
// rescale width of label column
if (m_grid_sizer && !m_options_mode.empty() && label_width > 1)
{
const int cols = m_grid_sizer->GetCols();
const int rows = m_grid_sizer->GetEffectiveRowsCount();
const int label_col = extra_column == nullptr ? 0 : 1;
// scale widgets and extra widgets if any exists
for (const Line& line : m_lines) {
if (line.widget_sizer)
rescale(line.widget_sizer);
if (line.extra_widget_sizer)
rescale(line.extra_widget_sizer);
}
for (int i = 0; i < rows; i++)
{
const wxSizerItem* label_item = m_grid_sizer->GetItem(i*cols+label_col);
if (label_item->IsWindow())
{
auto label = dynamic_cast<wxStaticText*>(label_item->GetWindow());
if (label != nullptr) {
label->SetMinSize(wxSize(label_width*em, -1));
}
}
else if (label_item->IsSizer()) // case when we have near_label_widget
{
const wxSizerItem* l_item = label_item->GetSizer()->GetItem(1);
if (l_item->IsWindow())
{
auto label = dynamic_cast<wxStaticText*>(l_item->GetWindow());
if (label != nullptr) {
label->SetMinSize(wxSize(label_width*em, -1));
}
}
}
}
m_grid_sizer->Layout();
}
if (custom_ctrl)
custom_ctrl->msw_rescale();
}
void ConfigOptionsGroup::sys_color_changed()
{
// update bitmaps for near label widgets (like "Set uniform scale" button on settings panel)
if (rescale_near_label_widget)
for (auto near_label_widget : m_near_label_widget_ptrs)
rescale_near_label_widget(near_label_widget);
// update undo buttons : rescale bitmaps
for (const auto& field : m_fields)
field.second->sys_color_changed();
}
void ConfigOptionsGroup::refresh()
{
if (custom_ctrl)
custom_ctrl->Refresh();
}
boost::any ConfigOptionsGroup::config_value(const std::string& opt_key, int opt_index, bool deserialize) {
if (deserialize) {
@ -858,6 +908,21 @@ Field* ConfigOptionsGroup::get_fieldc(const t_config_option_key& opt_key, int op
return opt_id.empty() ? nullptr : get_field(opt_id);
}
std::pair<OG_CustomCtrl*, bool*> ConfigOptionsGroup::get_custom_ctrl_with_blinking_ptr(const t_config_option_key& opt_key, int opt_index/* = -1*/)
{
Field* field = get_fieldc(opt_key, opt_index);
if (field)
return {custom_ctrl, field->get_blink_ptr()};
for (Line& line : m_lines)
for (const Option& opt : line.get_options())
if (opt.opt_id == opt_key && line.widget)
return { custom_ctrl, line.get_blink_ptr() };
return { nullptr, nullptr };
}
// Change an option on m_config, possibly call ModelConfig::touch().
void ConfigOptionsGroup::change_opt_value(const t_config_option_key& opt_key, const boost::any& value, int opt_index /*= 0*/)

View File

@ -26,13 +26,11 @@ namespace Slic3r { namespace GUI {
// Thrown if the building of a parameter page is canceled.
class UIBuildCanceled : public std::exception {};
class OG_CustomCtrl;
/// 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*)>;
//auto default_label_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT); //GetSystemColour
//auto modified_label_clr = *new wxColour(254, 189, 101);
/// Wraps a ConfigOptionDef and adds function object for creating a side_widget.
struct Option {
ConfigOptionDef opt { ConfigOptionDef() };
@ -40,6 +38,10 @@ struct Option {
widget_t side_widget {nullptr};
bool readonly {false};
bool operator==(const Option& rhs) const {
return (rhs.opt_id == this->opt_id);
}
Option(const ConfigOptionDef& _opt, t_config_option_key id) :
opt(_opt), opt_id(id) {}
};
@ -48,12 +50,18 @@ using t_option = std::unique_ptr<Option>; //!
/// Represents option lines
class Line {
public:
wxString label {wxString("")};
wxString label_tooltip {wxString("")};
wxString label;
wxString label_tooltip;
wxString label_path;
size_t full_width {0};
wxStaticText** full_Label {nullptr};
wxColour* full_Label_color {nullptr};
bool blink {false};
widget_t widget {nullptr};
std::function<wxWindow*(wxWindow*)> near_label_widget{ nullptr };
wxWindow* near_label_widget_win {nullptr};
wxSizer* widget_sizer {nullptr};
wxSizer* extra_widget_sizer {nullptr};
void append_option(const Option& option) {
m_options.push_back(option);
@ -66,6 +74,7 @@ public:
const std::vector<widget_t>& get_extra_widgets() const {return m_extra_widgets;}
const std::vector<Option>& get_options() const { return m_options; }
bool* get_blink_ptr() { return &blink; }
private:
std::vector<Option> m_options;//! {std::vector<Option>()};
@ -84,6 +93,7 @@ public:
const wxString title;
size_t label_width = 20 ;// {200};
wxSizer* sizer {nullptr};
OG_CustomCtrl* custom_ctrl{ nullptr };
column_t extra_column {nullptr};
t_change m_on_change { nullptr };
// To be called when the field loses focus, to assign a new initial value to the field.
@ -119,7 +129,7 @@ public:
#endif /* __WXGTK__ */
wxWindow* ctrl_parent() const {
return this->stb ? (wxWindow*)this->stb : this->parent();
return this->stb ? (this->custom_ctrl && m_use_custom_ctrl_as_parent ? (wxWindow*)this->custom_ctrl : (wxWindow*)this->stb) : this->parent();
}
void append_line(const Line& line);
@ -129,10 +139,10 @@ public:
// create all controls for the option group from the m_lines
bool activate(std::function<void()> throw_if_canceled = [](){});
// delete all controls from the option group
void clear();
void clear(bool destroy_custom_ctrl = false);
Line create_single_option_line(const Option& option) const;
void append_single_option_line(const Option& option) { append_line(create_single_option_line(option)); }
Line create_single_option_line(const Option& option, const wxString& path = wxEmptyString) const;
void append_single_option_line(const Option& option, const wxString& path = wxEmptyString) { append_line(create_single_option_line(option, path)); }
// return a non-owning pointer reference
inline Field* get_field(const t_config_option_key& id) const{
@ -152,19 +162,7 @@ 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 show_field(const t_config_option_key& opt_key, bool show = true) {
Field* field = get_field(opt_key);
field->getWindow()->Show(show);
field->getLabel()->Show(show);
}
void show_field(const t_config_option_key& opt_key, bool show = true);
void hide_field(const t_config_option_key& opt_key) { show_field(opt_key, false); }
void set_name(const wxString& new_name) {
@ -185,15 +183,16 @@ public:
OptionsGroup( wxWindow* _parent, const wxString& title, bool is_tab_opt = false,
column_t extra_clmn = nullptr);
~OptionsGroup() { clear(true); }
wxGridSizer* get_grid_sizer() { return m_grid_sizer; }
const std::vector<Line>& get_lines() { return m_lines; }
protected:
std::map<t_config_option_key, Option> m_options;
wxWindow* m_parent {nullptr};
std::vector<ConfigOptionMode> m_options_mode;
std::vector<wxWindow*> m_extra_column_item_ptrs;
std::vector<wxWindow*> m_near_label_widget_ptrs;
std::vector<Line> m_lines;
@ -206,6 +205,9 @@ protected:
// "true" if option is created in preset tabs
bool m_show_modified_btns{ false };
// "true" if control should be created on custom_ctrl
bool m_use_custom_ctrl_as_parent { false };
// 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.
@ -216,10 +218,9 @@ protected:
/// Generate a wxSizer or wxWindow from a configuration option
/// Precondition: opt resolves to a known ConfigOption
/// Postcondition: fields contains a wx gui object.
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_buttons_to_sizer(wxSizer* sizer, const t_field& field);
const t_field& build_field(const t_config_option_key& id, const ConfigOptionDef& opt);
const t_field& build_field(const t_config_option_key& id);
const t_field& build_field(const Option& opt);
virtual void on_kill_focus(const std::string& opt_key) {};
virtual void on_set_focus(const std::string& opt_key);
@ -243,20 +244,20 @@ public:
void set_config_category(const std::string &category) { this->m_config_category = category; }
void set_config(DynamicPrintConfig* config) { m_config = config; m_modelconfig = nullptr; }
Option get_option(const std::string& opt_key, int opt_index = -1);
Line create_single_option_line(const std::string& title, int idx = -1) /*const*/{
Line create_single_option_line(const std::string& title, const wxString& path = wxEmptyString, int idx = -1) /*const*/{
Option option = get_option(title, idx);
return OptionsGroup::create_single_option_line(option);
return OptionsGroup::create_single_option_line(option, path);
}
Line create_single_option_line(const Option& option) const {
return OptionsGroup::create_single_option_line(option);
Line create_single_option_line(const Option& option, const wxString& path = wxEmptyString) const {
return OptionsGroup::create_single_option_line(option, path);
}
void append_single_option_line(const Option& option) {
OptionsGroup::append_single_option_line(option);
void append_single_option_line(const Option& option, const wxString& path = wxEmptyString) {
OptionsGroup::append_single_option_line(option, path);
}
void append_single_option_line(const std::string title, int idx = -1)
void append_single_option_line(const std::string title, const wxString& path = wxEmptyString, int idx = -1)
{
Option option = get_option(title, idx);
append_single_option_line(option);
append_single_option_line(option, path);
}
void on_change_OG(const t_config_option_key& opt_id, const boost::any& value) override;
@ -272,10 +273,12 @@ public:
bool update_visibility(ConfigOptionMode mode);
void msw_rescale();
void sys_color_changed();
void refresh();
boost::any config_value(const std::string& opt_key, int opt_index, bool deserialize);
// return option value from config
boost::any get_config_value(const DynamicPrintConfig& config, const std::string& opt_key, int opt_index = -1);
Field* get_fieldc(const t_config_option_key& opt_key, int opt_index);
std::pair<OG_CustomCtrl*, bool*> get_custom_ctrl_with_blinking_ptr(const t_config_option_key& opt_key, int opt_index/* = -1*/);
private:
// Reference to libslic3r config or ModelConfig::get(), non-owning pointer.
@ -296,7 +299,6 @@ private:
class ogStaticText :public wxStaticText{
public:
ogStaticText() {}
// ogStaticText(wxWindow* parent, const char *text) : wxStaticText(parent, wxID_ANY, text, wxDefaultPosition, wxDefaultSize) {}
ogStaticText(wxWindow* parent, const wxString& text);
~ogStaticText() {}

View File

@ -433,6 +433,7 @@ void PhysicalPrinterDialog::update()
if (tech == ptFFF) {
m_optgroup->show_field("host_type");
m_optgroup->hide_field("printhost_authorization_type");
m_optgroup->show_field("printhost_apikey", true);
for (const std::string& opt_key : std::vector<std::string>{ "printhost_user", "printhost_password" })
m_optgroup->hide_field(opt_key);
const auto opt = m_config->option<ConfigOptionEnum<PrintHostType>>("host_type");
@ -453,6 +454,12 @@ void PhysicalPrinterDialog::update()
m_optgroup->show_field("printhost_port", supports_multiple_printers);
m_printhost_port_browse_btn->Show(supports_multiple_printers);
std::unique_ptr<PrintHost> host(PrintHost::get_print_host(m_config));
m_printhost_test_btn->Enable(!m_config->opt_string("print_host").empty() && host->can_test());
m_printhost_browse_btn->Enable(host->has_auto_discovery());
this->SetSize(this->GetBestSize());
this->Layout();
}

View File

@ -349,6 +349,8 @@ wxBitmap* PresetComboBox::get_bmp( std::string bitmap_key, bool wide_icons, con
bitmap_key += is_system ? ",syst" : ",nsyst";
bitmap_key += ",h" + std::to_string(icon_height);
if (wxGetApp().dark_mode())
bitmap_key += ",dark";
wxBitmap* bmp = bitmap_cache().find(bitmap_key);
if (bmp == nullptr) {
@ -393,6 +395,8 @@ wxBitmap* PresetComboBox::get_bmp( std::string bitmap_key, const std::string& m
bitmap_key += is_compatible ? ",cmpt" : ",ncmpt";
bitmap_key += is_system ? ",syst" : ",nsyst";
bitmap_key += ",h" + std::to_string(icon_height);
if (wxGetApp().dark_mode())
bitmap_key += ",dark";
wxBitmap* bmp = bitmap_cache().find(bitmap_key);
if (bmp == nullptr) {

View File

@ -12,6 +12,7 @@
#include "WipeTowerDialog.hpp"
#include "ButtonsDescription.hpp"
#include "Search.hpp"
#include "OG_CustomCtrl.hpp"
#include <wx/app.h>
#include <wx/button.h>
@ -52,40 +53,49 @@ wxDEFINE_EVENT(EVT_TAB_PRESETS_CHANGED, SimpleEvent);
void Tab::Highlighter::set_timer_owner(wxEvtHandler* owner, int timerid/* = wxID_ANY*/)
{
timer.SetOwner(owner, timerid);
m_timer.SetOwner(owner, timerid);
}
void Tab::Highlighter::init(BlinkingBitmap* bmp)
void Tab::Highlighter::init(std::pair<OG_CustomCtrl*, bool*> params)
{
if (timer.IsRunning())
if (m_timer.IsRunning())
invalidate();
if (!bmp)
if (!params.first || !params.second)
return;
timer.Start(300, false);
m_timer.Start(300, false);
bbmp = bmp;
bbmp->activate();
m_custom_ctrl = params.first;
m_show_blink_ptr = params.second;
*m_show_blink_ptr = true;
m_custom_ctrl->Refresh();
}
void Tab::Highlighter::invalidate()
{
timer.Stop();
m_timer.Stop();
if (bbmp) {
bbmp->invalidate();
bbmp = nullptr;
if (m_custom_ctrl && m_show_blink_ptr) {
*m_show_blink_ptr = false;
m_custom_ctrl->Refresh();
m_show_blink_ptr = nullptr;
m_custom_ctrl = nullptr;
}
blink_counter = 0;
m_blink_counter = 0;
}
void Tab::Highlighter::blink()
{
if (!bbmp)
if (m_custom_ctrl && m_show_blink_ptr) {
*m_show_blink_ptr = !*m_show_blink_ptr;
m_custom_ctrl->Refresh();
}
else
return;
bbmp->blink();
if ((++blink_counter) == 11)
if ((++m_blink_counter) == 11)
invalidate();
}
@ -344,12 +354,6 @@ void Tab::create_preset_tab()
m_presets_choice->add_physical_printer();
});
// Fill cache for mode bitmaps
m_mode_bitmap_cache.reserve(3);
m_mode_bitmap_cache.push_back(ScalableBitmap(this, "mode_simple" , mode_icon_px_size()));
m_mode_bitmap_cache.push_back(ScalableBitmap(this, "mode_advanced", mode_icon_px_size()));
m_mode_bitmap_cache.push_back(ScalableBitmap(this, "mode_expert" , mode_icon_px_size()));
// Initialize the DynamicPrintConfig by default keys/values.
build();
@ -414,7 +418,7 @@ Slic3r::GUI::PageShp Tab::add_options_page(const wxString& title, const std::str
#else
auto panel = this;
#endif
PageShp page(new Page(/*panel*/m_page_view, title, icon_idx, m_mode_bitmap_cache));
PageShp page(new Page(m_page_view, title, icon_idx));
// page->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
#ifdef __WINDOWS__
// page->SetDoubleBuffered(true);
@ -487,17 +491,14 @@ void Tab::update_labels_colour()
}
if (opt.first == "bed_shape" || opt.first == "filament_ramming_parameters" ||
opt.first == "compatible_prints" || opt.first == "compatible_printers" ) {
wxStaticText* label = m_colored_Labels.find(opt.first) == m_colored_Labels.end() ? nullptr : m_colored_Labels.at(opt.first);
if (label) {
label->SetForegroundColour(*color);
label->Refresh(true);
}
if (m_colored_Label_colors.find(opt.first) != m_colored_Label_colors.end())
*m_colored_Label_colors.at(opt.first) = *color;
continue;
}
Field* field = get_field(opt.first);
if (field == nullptr) continue;
field->set_label_colour_force(color);
field->set_label_colour(color);
}
auto cur_item = m_treectrl->GetFirstVisibleItem();
@ -525,17 +526,18 @@ void Tab::decorate()
{
for (const auto opt : m_options_list)
{
wxStaticText* label = nullptr;
Field* field = nullptr;
wxColour* colored_label_clr = nullptr;
if (opt.first == "bed_shape" || opt.first == "filament_ramming_parameters" ||
opt.first == "compatible_prints" || opt.first == "compatible_printers")
label = (m_colored_Labels.find(opt.first) == m_colored_Labels.end()) ? nullptr : m_colored_Labels.at(opt.first);
colored_label_clr = (m_colored_Label_colors.find(opt.first) == m_colored_Label_colors.end()) ? nullptr : m_colored_Label_colors.at(opt.first);
if (!label)
if (!colored_label_clr) {
field = get_field(opt.first);
if (!label && !field)
if (!field)
continue;
}
bool is_nonsys_value = false;
bool is_modified_value = true;
@ -566,9 +568,8 @@ void Tab::decorate()
tt = &m_tt_white_bullet;
}
if (label) {
label->SetForegroundColour(*color);
label->Refresh(true);
if (colored_label_clr) {
*colored_label_clr = *color;
continue;
}
@ -580,6 +581,9 @@ void Tab::decorate()
field->set_undo_to_sys_tooltip(sys_tt);
field->set_label_colour(color);
}
if (m_active_page)
m_active_page->refresh();
}
// Update UI according to changes
@ -664,6 +668,9 @@ void TabPrinter::msw_rescale()
for (auto page : pages)
page->msw_rescale();
if (m_reset_to_filament_color)
m_reset_to_filament_color->msw_rescale();
Layout();
}
@ -933,10 +940,9 @@ void Tab::msw_rescale()
btn->msw_rescale();
for (const auto bmp : m_scaled_bitmaps)
bmp->msw_rescale();
for (const auto ikon : m_blinking_ikons)
ikon.second->msw_rescale();
for (ScalableBitmap& bmp : m_mode_bitmap_cache)
bmp.msw_rescale();
if (m_detach_preset_btn)
m_detach_preset_btn->msw_rescale();
// rescale icons for tree_ctrl
for (ScalableBitmap& bmp : m_scaled_icons_list)
@ -958,14 +964,13 @@ void Tab::msw_rescale()
void Tab::sys_color_changed()
{
update_tab_ui();
m_presets_choice->msw_rescale();
// update buttons and cached bitmaps
for (const auto btn : m_scaled_buttons)
btn->msw_rescale();
for (const auto bmp : m_scaled_bitmaps)
bmp->msw_rescale();
// for (ScalableBitmap& bmp : m_mode_bitmap_cache)
// bmp.msw_rescale();
// update icons for tree_ctrl
for (ScalableBitmap& bmp : m_scaled_icons_list)
@ -992,14 +997,21 @@ void Tab::sys_color_changed()
Field* Tab::get_field(const t_config_option_key& opt_key, int opt_index/* = -1*/) const
{
return m_active_page ? m_active_page->get_field(opt_key, opt_index) : nullptr;
Field* field = nullptr;
for (auto page : m_pages) {
field = page->get_field(opt_key, opt_index);
if (field != nullptr)
return field;
}
return field;
std::pair<OG_CustomCtrl*, bool*> Tab::get_custom_ctrl_with_blinking_ptr(const t_config_option_key& opt_key, int opt_index/* = -1*/)
{
if (!m_active_page)
return {nullptr, nullptr};
std::pair<OG_CustomCtrl*, bool*> ret = {nullptr, nullptr};
for (auto opt_group : m_active_page->m_optgroups) {
ret = opt_group->get_custom_ctrl_with_blinking_ptr(opt_key, opt_index);
if (ret.first && ret.second)
break;
}
return ret;
}
Field* Tab::get_field(const t_config_option_key& opt_key, Page** selected_page, int opt_index/* = -1*/)
@ -1141,25 +1153,19 @@ void Tab::activate_option(const std::string& opt_key, const wxString& category)
Field* field = get_field(opt_key);
// focused selected field
if (field) {
if (field)
field->getWindow()->SetFocus();
m_highlighter.init(field->blinking_bitmap());
}
else if (category == "Single extruder MM setup")
{
else if (category == "Single extruder MM setup") {
// When we show and hide "Single extruder MM setup" page,
// related options are still in the search list
// So, let's hightlighte a "single_extruder_multi_material" option,
// as a "way" to show hidden page again
field = get_field("single_extruder_multi_material");
if (field) {
if (field)
field->getWindow()->SetFocus();
m_highlighter.init(field->blinking_bitmap());
}
}
else
m_highlighter.init(m_blinking_ikons[opt_key]);
m_highlighter.init(get_custom_ctrl_with_blinking_ptr(opt_key));
}
void Tab::apply_searcher()
@ -1219,7 +1225,6 @@ void Tab::build_preset_description_line(ConfigOptionsGroup* optgroup)
};
auto detach_preset_btn = [this](wxWindow* parent) {
//add_scaled_button(parent, &m_detach_preset_btn, "lock_open_sys", _(L("Detach from system preset")), wxBU_LEFT | wxBU_EXACTFIT);
m_detach_preset_btn = new ScalableButton(parent, wxID_ANY, "lock_open_sys", _L("Detach from system preset"),
wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT, true);
ScalableButton* btn = m_detach_preset_btn;
@ -1367,16 +1372,18 @@ void TabPrint::build()
load_initial_data();
auto page = add_options_page(L("Layers and perimeters"), "layers");
wxString category_path = "layers-and-perimeters_1748#";
auto optgroup = page->new_optgroup(L("Layer height"));
optgroup->append_single_option_line("layer_height");
optgroup->append_single_option_line("first_layer_height");
optgroup->append_single_option_line("layer_height", category_path + "layer-height");
optgroup->append_single_option_line("first_layer_height", category_path + "first-layer-height");
optgroup = page->new_optgroup(L("Vertical shells"));
optgroup->append_single_option_line("perimeters");
optgroup->append_single_option_line("spiral_vase");
optgroup->append_single_option_line("perimeters", category_path + "perimeters");
optgroup->append_single_option_line("spiral_vase", category_path + "spiral-vase");
Line line { "", "" };
line.full_width = 1;
line.label_path = category_path + "recommended-thin-wall-thickness";
line.widget = [this](wxWindow* parent) {
return description_line_widget(parent, &m_recommended_thin_wall_thickness_description_line);
};
@ -1384,6 +1391,7 @@ void TabPrint::build()
optgroup = page->new_optgroup(L("Horizontal shells"));
line = { L("Solid layers"), "" };
line.label_path = category_path + "solid-layers-top-bottom";
line.append_option(optgroup->get_option("top_solid_layers"));
line.append_option(optgroup->get_option("bottom_solid_layers"));
optgroup->append_line(line);
@ -1399,22 +1407,23 @@ void TabPrint::build()
optgroup->append_line(line);
optgroup = page->new_optgroup(L("Quality (slower slicing)"));
optgroup->append_single_option_line("extra_perimeters");
optgroup->append_single_option_line("ensure_vertical_shell_thickness");
optgroup->append_single_option_line("avoid_crossing_perimeters");
optgroup->append_single_option_line("thin_walls");
optgroup->append_single_option_line("overhangs");
optgroup->append_single_option_line("extra_perimeters", category_path + "extra-perimeters-if-needed");
optgroup->append_single_option_line("ensure_vertical_shell_thickness", category_path + "ensure-vertical-shell-thickness");
optgroup->append_single_option_line("avoid_crossing_perimeters", category_path + "avoid-crossing-perimeters");
optgroup->append_single_option_line("thin_walls", category_path + "detect-thin-walls");
optgroup->append_single_option_line("overhangs", category_path + "detect-bridging-perimeters");
optgroup = page->new_optgroup(L("Advanced"));
optgroup->append_single_option_line("seam_position");
optgroup->append_single_option_line("external_perimeters_first");
optgroup->append_single_option_line("seam_position", category_path + "seam-position");
optgroup->append_single_option_line("external_perimeters_first", category_path + "external-perimeters-first");
page = add_options_page(L("Infill"), "infill");
category_path = "infill_42#";
optgroup = page->new_optgroup(L("Infill"));
optgroup->append_single_option_line("fill_density");
optgroup->append_single_option_line("fill_pattern");
optgroup->append_single_option_line("top_fill_pattern");
optgroup->append_single_option_line("bottom_fill_pattern");
optgroup->append_single_option_line("fill_density", category_path + "fill-density");
optgroup->append_single_option_line("fill_pattern", category_path + "fill-pattern");
optgroup->append_single_option_line("top_fill_pattern", category_path + "top-fill-pattern");
optgroup->append_single_option_line("bottom_fill_pattern", category_path + "bottom-fill-pattern");
optgroup = page->new_optgroup(L("Ironing"));
optgroup->append_single_option_line("ironing");
@ -1423,52 +1432,54 @@ void TabPrint::build()
optgroup->append_single_option_line("ironing_spacing");
optgroup = page->new_optgroup(L("Reducing printing time"));
optgroup->append_single_option_line("infill_every_layers");
optgroup->append_single_option_line("infill_only_where_needed");
optgroup->append_single_option_line("infill_every_layers", category_path + "combine-infill-every-x-layers");
optgroup->append_single_option_line("infill_only_where_needed", category_path + "only-infill-where-needed");
optgroup = page->new_optgroup(L("Advanced"));
optgroup->append_single_option_line("solid_infill_every_layers");
optgroup->append_single_option_line("fill_angle");
optgroup->append_single_option_line("solid_infill_below_area");
optgroup->append_single_option_line("solid_infill_every_layers", category_path + "solid-infill-every-x-layers");
optgroup->append_single_option_line("fill_angle", category_path + "fill-angle");
optgroup->append_single_option_line("solid_infill_below_area", category_path + "solid-infill-threshold-area");
optgroup->append_single_option_line("bridge_angle");
optgroup->append_single_option_line("only_retract_when_crossing_perimeters");
optgroup->append_single_option_line("infill_first");
page = add_options_page(L("Skirt and brim"), "skirt+brim");
category_path = "skirt-and-brim_133969#";
optgroup = page->new_optgroup(L("Skirt"));
optgroup->append_single_option_line("skirts");
optgroup->append_single_option_line("skirt_distance");
optgroup->append_single_option_line("skirt_height");
optgroup->append_single_option_line("draft_shield");
optgroup->append_single_option_line("min_skirt_length");
optgroup->append_single_option_line("skirts", category_path + "skirt");
optgroup->append_single_option_line("skirt_distance", category_path + "skirt");
optgroup->append_single_option_line("skirt_height", category_path + "skirt");
optgroup->append_single_option_line("draft_shield", category_path + "skirt");
optgroup->append_single_option_line("min_skirt_length", category_path + "skirt");
optgroup = page->new_optgroup(L("Brim"));
optgroup->append_single_option_line("brim_width");
optgroup->append_single_option_line("brim_width", category_path + "brim");
page = add_options_page(L("Support material"), "support");
category_path = "support-material_1698#";
optgroup = page->new_optgroup(L("Support material"));
optgroup->append_single_option_line("support_material");
optgroup->append_single_option_line("support_material_auto");
optgroup->append_single_option_line("support_material_threshold");
optgroup->append_single_option_line("support_material_enforce_layers");
optgroup->append_single_option_line("support_material", category_path + "generate-support-material");
optgroup->append_single_option_line("support_material_auto", category_path + "auto-generated-supports");
optgroup->append_single_option_line("support_material_threshold", category_path + "overhang-threshold");
optgroup->append_single_option_line("support_material_enforce_layers", category_path + "enforce-support-for-the-first");
optgroup = page->new_optgroup(L("Raft"));
optgroup->append_single_option_line("raft_layers");
optgroup->append_single_option_line("raft_layers", category_path + "raft-layers");
// # optgroup->append_single_option_line(get_option_("raft_contact_distance");
optgroup = page->new_optgroup(L("Options for support material and raft"));
optgroup->append_single_option_line("support_material_contact_distance");
optgroup->append_single_option_line("support_material_pattern");
optgroup->append_single_option_line("support_material_with_sheath");
optgroup->append_single_option_line("support_material_spacing");
optgroup->append_single_option_line("support_material_angle");
optgroup->append_single_option_line("support_material_interface_layers");
optgroup->append_single_option_line("support_material_interface_spacing");
optgroup->append_single_option_line("support_material_interface_contact_loops");
optgroup->append_single_option_line("support_material_buildplate_only");
optgroup->append_single_option_line("support_material_xy_spacing");
optgroup->append_single_option_line("dont_support_bridges");
optgroup->append_single_option_line("support_material_synchronize_layers");
optgroup->append_single_option_line("support_material_contact_distance", category_path + "contact-z-distance");
optgroup->append_single_option_line("support_material_pattern", category_path + "pattern");
optgroup->append_single_option_line("support_material_with_sheath", category_path + "with-sheath-around-the-support");
optgroup->append_single_option_line("support_material_spacing", category_path + "pattern-spacing-0-inf");
optgroup->append_single_option_line("support_material_angle", category_path + "pattern-angle");
optgroup->append_single_option_line("support_material_interface_layers", category_path + "interface-layers");
optgroup->append_single_option_line("support_material_interface_spacing", category_path + "interface-pattern-spacing");
optgroup->append_single_option_line("support_material_interface_contact_loops", category_path + "interface-loops");
optgroup->append_single_option_line("support_material_buildplate_only", category_path + "support-on-build-plate-only");
optgroup->append_single_option_line("support_material_xy_spacing", category_path + "xy-separation-between-an-object-and-its-support");
optgroup->append_single_option_line("dont_support_bridges", category_path + "dont-support-bridges");
optgroup->append_single_option_line("support_material_synchronize_layers", category_path + "synchronize-with-object-layers");
page = add_options_page(L("Speed"), "time");
optgroup = page->new_optgroup(L("Speed for print moves"));
@ -1498,8 +1509,8 @@ void TabPrint::build()
optgroup->append_single_option_line("default_acceleration");
optgroup = page->new_optgroup(L("Autospeed (advanced)"));
optgroup->append_single_option_line("max_print_speed");
optgroup->append_single_option_line("max_volumetric_speed");
optgroup->append_single_option_line("max_print_speed", "max-volumetric-speed_127176");
optgroup->append_single_option_line("max_volumetric_speed", "max-volumetric-speed_127176");
#ifdef HAS_PRESSURE_EQUALIZER
optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_positive");
optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_negative");
@ -1551,14 +1562,14 @@ void TabPrint::build()
optgroup->append_single_option_line("slice_closing_radius");
optgroup->append_single_option_line("resolution");
optgroup->append_single_option_line("xy_size_compensation");
optgroup->append_single_option_line("elefant_foot_compensation");
optgroup->append_single_option_line("elefant_foot_compensation", "elephant-foot-compensation_114487");
optgroup = page->new_optgroup(L("Other"));
optgroup->append_single_option_line("clip_multipart_objects");
page = add_options_page(L("Output options"), "output+page_white");
optgroup = page->new_optgroup(L("Sequential printing"));
optgroup->append_single_option_line("complete_objects");
optgroup->append_single_option_line("complete_objects", "sequential-printing_124589");
line = { L("Extruder clearance (mm)"), "" };
line.append_option(optgroup->get_option("extruder_clearance_radius"));
line.append_option(optgroup->get_option("extruder_clearance_height"));
@ -1587,7 +1598,7 @@ void TabPrint::build()
page = add_options_page(L("Dependencies"), "wrench.png");
optgroup = page->new_optgroup(L("Profile dependencies"));
create_line_with_widget(optgroup.get(), "compatible_printers", [this](wxWindow* parent) {
create_line_with_widget(optgroup.get(), "compatible_printers", wxEmptyString, [this](wxWindow* parent) {
return compatible_widget_create(parent, m_compatible_printers);
});
@ -1787,6 +1798,7 @@ void TabFilament::build()
optgroup->append_line(line);
page = add_options_page(L("Cooling"), "cooling");
wxString category_path = "cooling_127569#";
optgroup = page->new_optgroup(L("Enable"));
optgroup->append_single_option_line("fan_always_on");
optgroup->append_single_option_line("cooling");
@ -1800,17 +1812,18 @@ void TabFilament::build()
optgroup = page->new_optgroup(L("Fan settings"));
line = { L("Fan speed"), "" };
line.label_path = category_path + "fan-settings";
line.append_option(optgroup->get_option("min_fan_speed"));
line.append_option(optgroup->get_option("max_fan_speed"));
optgroup->append_line(line);
optgroup->append_single_option_line("bridge_fan_speed");
optgroup->append_single_option_line("disable_fan_first_layers");
optgroup->append_single_option_line("bridge_fan_speed", category_path + "fan-settings");
optgroup->append_single_option_line("disable_fan_first_layers", category_path + "fan-settings");
optgroup = page->new_optgroup(L("Cooling thresholds"), 25);
optgroup->append_single_option_line("fan_below_layer_time");
optgroup->append_single_option_line("slowdown_below_layer_time");
optgroup->append_single_option_line("min_print_speed");
optgroup->append_single_option_line("fan_below_layer_time", category_path + "cooling-thresholds");
optgroup->append_single_option_line("slowdown_below_layer_time", category_path + "cooling-thresholds");
optgroup->append_single_option_line("min_print_speed", category_path + "cooling-thresholds");
page = add_options_page(L("Advanced"), "wrench");
optgroup = page->new_optgroup(L("Filament properties"));
@ -1821,7 +1834,7 @@ void TabFilament::build()
optgroup->append_single_option_line("filament_soluble");
optgroup = page->new_optgroup(L("Print speed override"));
optgroup->append_single_option_line("filament_max_volumetric_speed");
optgroup->append_single_option_line("filament_max_volumetric_speed", "max-volumetric-speed_127176");
line = { "", "" };
line.full_width = 1;
@ -1845,9 +1858,10 @@ void TabFilament::build()
optgroup->append_single_option_line("filament_cooling_initial_speed");
optgroup->append_single_option_line("filament_cooling_final_speed");
create_line_with_widget(optgroup.get(), "filament_ramming_parameters", [this](wxWindow* parent) {
create_line_with_widget(optgroup.get(), "filament_ramming_parameters", wxEmptyString, [this](wxWindow* parent) {
auto ramming_dialog_btn = new wxButton(parent, wxID_ANY, _(L("Ramming settings"))+dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
ramming_dialog_btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
ramming_dialog_btn->SetSize(ramming_dialog_btn->GetBestSize());
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(ramming_dialog_btn);
@ -1893,7 +1907,7 @@ void TabFilament::build()
page = add_options_page(L("Dependencies"), "wrench.png");
optgroup = page->new_optgroup(L("Profile dependencies"));
create_line_with_widget(optgroup.get(), "compatible_printers", [this](wxWindow* parent) {
create_line_with_widget(optgroup.get(), "compatible_printers", wxEmptyString, [this](wxWindow* parent) {
return compatible_widget_create(parent, m_compatible_printers);
});
@ -1901,7 +1915,7 @@ void TabFilament::build()
option.opt.full_width = true;
optgroup->append_single_option_line(option);
create_line_with_widget(optgroup.get(), "compatible_prints", [this](wxWindow* parent) {
create_line_with_widget(optgroup.get(), "compatible_prints", wxEmptyString, [this](wxWindow* parent) {
return compatible_widget_create(parent, m_compatible_prints);
});
@ -2057,7 +2071,7 @@ void TabPrinter::build_fff()
auto page = add_options_page(L("General"), "printer");
auto optgroup = page->new_optgroup(L("Size and coordinates"));
create_line_with_widget(optgroup.get(), "bed_shape", [this](wxWindow* parent) {
create_line_with_widget(optgroup.get(), "bed_shape", "custom-svg-and-png-bed-textures_124612", [this](wxWindow* parent) {
return create_bed_shape_widget(parent);
});
@ -2239,7 +2253,7 @@ void TabPrinter::build_sla()
auto page = add_options_page(L("General"), "printer");
auto optgroup = page->new_optgroup(L("Size and coordinates"));
create_line_with_widget(optgroup.get(), "bed_shape", [this](wxWindow* parent) {
create_line_with_widget(optgroup.get(), "bed_shape", "custom-svg-and-png-bed-textures_124612", [this](wxWindow* parent) {
return create_bed_shape_widget(parent);
});
optgroup->append_single_option_line("max_print_height");
@ -2490,7 +2504,7 @@ void TabPrinter::build_unregular_pages()
m_pages.insert(m_pages.begin() + n_before_extruders + extruder_idx, page);
auto optgroup = page->new_optgroup(L("Size"));
optgroup->append_single_option_line("nozzle_diameter", extruder_idx);
optgroup->append_single_option_line("nozzle_diameter", wxEmptyString, extruder_idx);
optgroup->m_on_change = [this, extruder_idx](const t_config_option_key& opt_key, boost::any value)
{
@ -2528,42 +2542,41 @@ void TabPrinter::build_unregular_pages()
};
optgroup = page->new_optgroup(L("Layer height limits"));
optgroup->append_single_option_line("min_layer_height", extruder_idx);
optgroup->append_single_option_line("max_layer_height", extruder_idx);
optgroup->append_single_option_line("min_layer_height", wxEmptyString, extruder_idx);
optgroup->append_single_option_line("max_layer_height", wxEmptyString, extruder_idx);
optgroup = page->new_optgroup(L("Position (for multi-extruder printers)"));
optgroup->append_single_option_line("extruder_offset", extruder_idx);
optgroup->append_single_option_line("extruder_offset", wxEmptyString, extruder_idx);
optgroup = page->new_optgroup(L("Retraction"));
optgroup->append_single_option_line("retract_length", extruder_idx);
optgroup->append_single_option_line("retract_lift", extruder_idx);
optgroup->append_single_option_line("retract_length", wxEmptyString, extruder_idx);
optgroup->append_single_option_line("retract_lift", wxEmptyString, extruder_idx);
Line line = { L("Only lift Z"), "" };
line.append_option(optgroup->get_option("retract_lift_above", extruder_idx));
line.append_option(optgroup->get_option("retract_lift_below", extruder_idx));
optgroup->append_line(line);
optgroup->append_single_option_line("retract_speed", extruder_idx);
optgroup->append_single_option_line("deretract_speed", extruder_idx);
optgroup->append_single_option_line("retract_restart_extra", extruder_idx);
optgroup->append_single_option_line("retract_before_travel", extruder_idx);
optgroup->append_single_option_line("retract_layer_change", extruder_idx);
optgroup->append_single_option_line("wipe", extruder_idx);
optgroup->append_single_option_line("retract_before_wipe", extruder_idx);
optgroup->append_single_option_line("retract_speed", wxEmptyString, extruder_idx);
optgroup->append_single_option_line("deretract_speed", wxEmptyString, extruder_idx);
optgroup->append_single_option_line("retract_restart_extra", wxEmptyString, extruder_idx);
optgroup->append_single_option_line("retract_before_travel", wxEmptyString, extruder_idx);
optgroup->append_single_option_line("retract_layer_change", wxEmptyString, extruder_idx);
optgroup->append_single_option_line("wipe", wxEmptyString, extruder_idx);
optgroup->append_single_option_line("retract_before_wipe", wxEmptyString, extruder_idx);
optgroup = page->new_optgroup(L("Retraction when tool is disabled (advanced settings for multi-extruder setups)"));
optgroup->append_single_option_line("retract_length_toolchange", extruder_idx);
optgroup->append_single_option_line("retract_restart_extra_toolchange", extruder_idx);
optgroup->append_single_option_line("retract_length_toolchange", wxEmptyString, extruder_idx);
optgroup->append_single_option_line("retract_restart_extra_toolchange", wxEmptyString, extruder_idx);
optgroup = page->new_optgroup(L("Preview"));
auto reset_to_filament_color = [this, extruder_idx](wxWindow* parent) {
//add_scaled_button(parent, &m_reset_to_filament_color, "undo",
// _(L("Reset to Filament Color")), wxBU_LEFT | wxBU_EXACTFIT);
m_reset_to_filament_color = new ScalableButton(parent, wxID_ANY, "undo", _L("Reset to Filament Color"),
wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT, true);
ScalableButton* btn = m_reset_to_filament_color;
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
btn->SetSize(btn->GetBestSize());
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn);
@ -2582,7 +2595,7 @@ void TabPrinter::build_unregular_pages()
return sizer;
};
line = optgroup->create_single_option_line("extruder_colour", extruder_idx);
line = optgroup->create_single_option_line("extruder_colour", wxEmptyString, extruder_idx);
line.append_widget(reset_to_filament_color);
optgroup->append_line(line);
@ -2656,6 +2669,16 @@ void TabPrinter::update_pages()
rebuild_page_tree();
}
void TabPrinter::reload_config()
{
Tab::reload_config();
// "extruders_count" doesn't update from the update_config(),
// so update it implicitly
if (m_active_page && m_active_page->title() == "General")
m_active_page->set_value("extruders_count", int(m_extruders_count));
}
void TabPrinter::activate_selected_page(std::function<void()> throw_if_canceled)
{
Tab::activate_selected_page(throw_if_canceled);
@ -3207,8 +3230,6 @@ void Tab::clear_pages()
m_compatible_prints.checkbox = nullptr;
m_compatible_prints.btn = nullptr;
m_blinking_ikons.clear();
}
void Tab::update_description_lines()
@ -3491,13 +3512,15 @@ void Tab::update_ui_from_settings()
}
}
void Tab::create_line_with_widget(ConfigOptionsGroup* optgroup, const std::string& opt_key, widget_t widget)
void Tab::create_line_with_widget(ConfigOptionsGroup* optgroup, const std::string& opt_key, const wxString& path, widget_t widget)
{
Line line = optgroup->create_single_option_line(opt_key);
line.widget = widget;
line.label_path = path;
m_colored_Label_colors[opt_key] = &m_default_text_clr;
line.full_Label_color = m_colored_Label_colors[opt_key];
m_colored_Labels[opt_key] = nullptr;
line.full_Label = &m_colored_Labels[opt_key];
optgroup->append_line(line);
}
@ -3506,14 +3529,12 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep
{
deps.checkbox = new wxCheckBox(parent, wxID_ANY, _(L("All")));
deps.checkbox->SetFont(Slic3r::GUI::wxGetApp().normal_font());
deps.btn = new ScalableButton(parent, wxID_ANY, "printer_white", from_u8((boost::format(" %s %s") % _utf8(L("Set")) % std::string(dots.ToUTF8())).str()),
deps.btn = new ScalableButton(parent, wxID_ANY, "printer", from_u8((boost::format(" %s %s") % _utf8(L("Set")) % std::string(dots.ToUTF8())).str()),
wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT, true);
deps.btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
BlinkingBitmap* bbmp = new BlinkingBitmap(parent);
deps.btn->SetSize(deps.btn->GetBestSize());
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(bbmp, 0, wxALIGN_CENTER_VERTICAL);
sizer->Add((deps.checkbox), 0, wxALIGN_CENTER_VERTICAL);
sizer->Add((deps.btn), 0, wxALIGN_CENTER_VERTICAL);
@ -3574,25 +3595,18 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep
}
}));
// fill m_blinking_ikons map with options
{
m_blinking_ikons[deps.key_list] = bbmp;
}
return sizer;
}
// Return a callback to create a TabPrinter widget to edit bed shape
wxSizer* TabPrinter::create_bed_shape_widget(wxWindow* parent)
{
ScalableButton* btn = new ScalableButton(parent, wxID_ANY, "printer_white", " " + _(L("Set")) + " " + dots,
ScalableButton* btn = new ScalableButton(parent, wxID_ANY, "printer", " " + _(L("Set")) + " " + dots,
wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT, true);
btn->SetFont(wxGetApp().normal_font());
BlinkingBitmap* bbmp = new BlinkingBitmap(parent);
btn->SetSize(btn->GetBestSize());
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(bbmp, 0, wxALIGN_CENTER_VERTICAL);
sizer->Add(btn, 0, wxALIGN_CENTER_VERTICAL);
btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e)
@ -3624,12 +3638,6 @@ wxSizer* TabPrinter::create_bed_shape_widget(wxWindow* parent)
searcher.add_key("bed_custom_model", gc.group, gc.category);
}
// fill m_blinking_ikons map with options
{
for (const std::string opt : {"bed_shape", "bed_custom_texture", "bed_custom_model"})
m_blinking_ikons[opt] = bbmp;
}
return sizer;
}
@ -3742,11 +3750,10 @@ void Tab::set_tooltips_text()
"Click to reset current value to the last saved preset."));
}
Page::Page(wxWindow* parent, const wxString& title, const int iconID, const std::vector<ScalableBitmap>& mode_bmp_cache) :
Page::Page(wxWindow* parent, const wxString& title, int iconID) :
m_parent(parent),
m_title(title),
m_iconID(iconID),
m_mode_bitmap_cache(mode_bmp_cache)
m_iconID(iconID)
{
m_vsizer = (wxBoxSizer*)parent->GetSizer();
m_item_color = &wxGetApp().get_label_clr_default();
@ -3801,6 +3808,12 @@ void Page::sys_color_changed()
group->sys_color_changed();
}
void Page::refresh()
{
for (auto group : m_optgroups)
group->refresh();
}
Field* Page::get_field(const t_config_option_key& opt_key, int opt_index /*= -1*/) const
{
Field* field = nullptr;
@ -3824,22 +3837,8 @@ bool Page::set_value(const t_config_option_key& opt_key, const boost::any& value
// package Slic3r::GUI::Tab::Page;
ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_label_width /*= -1*/)
{
auto extra_column = [this](wxWindow* parent, const Line& line)
{
std::string bmp_name;
const std::vector<Option>& options = line.get_options();
int mode_id = int(options[0].opt.mode);
const wxBitmap& bitmap = options.size() == 0 || options[0].opt.gui_type == "legend" ? wxNullBitmap :
m_mode_bitmap_cache[mode_id].bmp();
auto bmp = new wxStaticBitmap(parent, wxID_ANY, bitmap);
bmp->SetClientData((void*)&m_mode_bitmap_cache[mode_id]);
bmp->SetBackgroundStyle(wxBG_STYLE_PAINT);
return bmp;
};
//! config_ have to be "right"
ConfigOptionsGroupShp optgroup = std::make_shared<ConfigOptionsGroup>(/*this*/m_parent, title, m_config, true, extra_column);
ConfigOptionsGroupShp optgroup = std::make_shared<ConfigOptionsGroup>(m_parent, title, m_config, true);
optgroup->set_config_category(m_title.ToStdString());
if (noncommon_label_width >= 0)
optgroup->label_width = noncommon_label_width;
@ -3959,7 +3958,7 @@ void TabSLAMaterial::build()
page = add_options_page(L("Dependencies"), "wrench.png");
optgroup = page->new_optgroup(L("Profile dependencies"));
create_line_with_widget(optgroup.get(), "compatible_printers", [this](wxWindow* parent) {
create_line_with_widget(optgroup.get(), "compatible_printers", wxEmptyString, [this](wxWindow* parent) {
return compatible_widget_create(parent, m_compatible_printers);
});
@ -3967,7 +3966,7 @@ void TabSLAMaterial::build()
option.opt.full_width = true;
optgroup->append_single_option_line(option);
create_line_with_widget(optgroup.get(), "compatible_prints", [this](wxWindow* parent) {
create_line_with_widget(optgroup.get(), "compatible_prints", wxEmptyString, [this](wxWindow* parent) {
return compatible_widget_create(parent, m_compatible_prints);
});
@ -4090,7 +4089,7 @@ void TabSLAPrint::build()
page = add_options_page(L("Dependencies"), "wrench");
optgroup = page->new_optgroup(L("Profile dependencies"));
create_line_with_widget(optgroup.get(), "compatible_printers", [this](wxWindow* parent) {
create_line_with_widget(optgroup.get(), "compatible_printers", wxEmptyString, [this](wxWindow* parent) {
return compatible_widget_create(parent, m_compatible_printers);
});

View File

@ -40,6 +40,7 @@ namespace Slic3r {
namespace GUI {
class TabPresetComboBox;
class OG_CustomCtrl;
// Single Tab page containing a{ vsizer } of{ optgroups }
// package Slic3r::GUI::Tab::Page;
@ -52,16 +53,12 @@ class Page// : public wxScrolledWindow
wxBoxSizer* m_vsizer;
bool m_show = true;
public:
Page(wxWindow* parent, const wxString& title, const int iconID,
const std::vector<ScalableBitmap>& mode_bmp_cache);
Page(wxWindow* parent, const wxString& title, int iconID);
~Page() {}
bool m_is_modified_values{ false };
bool m_is_nonsys_values{ true };
// Delayed layout after resizing the main window.
const std::vector<ScalableBitmap>& m_mode_bitmap_cache;
public:
std::vector <ConfigOptionsGroupShp> m_optgroups;
DynamicPrintConfig* m_config;
@ -77,6 +74,7 @@ public:
void clear();
void msw_rescale();
void sys_color_changed();
void refresh();
Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const;
bool set_value(const t_config_option_key& opt_key, const boost::any& value);
ConfigOptionsGroupShp new_optgroup(const wxString& title, int noncommon_label_width = -1);
@ -170,7 +168,6 @@ protected:
std::vector<ScalableButton*> m_scaled_buttons = {};
std::vector<ScalableBitmap*> m_scaled_bitmaps = {};
std::vector<ScalableBitmap> m_scaled_icons_list = {};
std::vector<ScalableBitmap> m_mode_bitmap_cache = {};
// Colors for ui "decoration"
wxColour m_sys_label_clr;
@ -225,15 +222,15 @@ protected:
struct Highlighter
{
void set_timer_owner(wxEvtHandler* owner, int timerid = wxID_ANY);
void init(BlinkingBitmap* bmp);
void init(std::pair<OG_CustomCtrl*, bool*>);
void blink();
void invalidate();
private:
BlinkingBitmap* bbmp {nullptr};
int blink_counter {0};
wxTimer timer;
OG_CustomCtrl* m_custom_ctrl {nullptr};
bool* m_show_blink_ptr{nullptr};
int m_blink_counter {0};
wxTimer m_timer;
}
m_highlighter;
@ -251,13 +248,9 @@ public:
ogStaticText* m_parent_preset_description_line = nullptr;
ScalableButton* m_detach_preset_btn = nullptr;
// map of option name -> wxStaticText (colored label, associated with option)
// map of option name -> wxColour (color of the colored label, associated with option)
// Used for options which don't have corresponded field
std::map<std::string, wxStaticText*> m_colored_Labels;
// map of option name -> BlinkingBitmap (blinking ikon, associated with option)
// Used for options which don't have corresponded field
std::map<std::string, BlinkingBitmap*> m_blinking_ikons;
std::map<std::string, wxColour*> m_colored_Label_colors;
// Counter for the updating (because of an update() function can have a recursive behavior):
// 1. increase value from the very beginning of an update() function
@ -333,6 +326,8 @@ public:
virtual void msw_rescale();
virtual void sys_color_changed();
Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const;
std::pair<OG_CustomCtrl*, bool*> get_custom_ctrl_with_blinking_ptr(const t_config_option_key& opt_key, int opt_index = -1);
Field* get_field(const t_config_option_key &opt_key, Page** selected_page, int opt_index = -1);
void toggle_option(const std::string& opt_key, bool toggle, int opt_index = -1);
wxSizer* description_line_widget(wxWindow* parent, ogStaticText** StaticText, wxString text = wxEmptyString);
@ -352,7 +347,7 @@ public:
const std::map<wxString, std::string>& get_category_icon_map() { return m_category_icon; }
protected:
void create_line_with_widget(ConfigOptionsGroup* optgroup, const std::string& opt_key, widget_t widget);
void create_line_with_widget(ConfigOptionsGroup* optgroup, const std::string& opt_key, const wxString& path, widget_t widget);
wxSizer* compatible_widget_create(wxWindow* parent, PresetDependencies &deps);
void compatible_widget_reload(PresetDependencies &deps);
void load_key_value(const std::string& opt_key, const boost::any& value, bool saved_value = false);
@ -454,6 +449,7 @@ public:
void build_print_host_upload_group(Page* page);
void build_fff();
void build_sla();
void reload_config() override;
void activate_selected_page(std::function<void()> throw_if_canceled) override;
void clear_pages() override;
void toggle_options() override;

View File

@ -348,6 +348,8 @@ public:
void activate();
void blink();
const wxBitmap& get_bmp() const { return bmp.bmp(); }
private:
ScalableBitmap bmp;
bool show {false};