2020-06-16 12:57:49 +02:00
#include "PresetComboBoxes.hpp"
#include <cstddef>
#include <vector>
#include <string>
#include <boost/algorithm/string.hpp>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>
#include <wx/button.h>
#include <wx/statbox.h>
#include <wx/colordlg.h>
#include <wx/wupdlock.h>
2020-06-24 12:28:00 +02:00
#include <wx/menu.h>
2020-06-16 12:57:49 +02:00
#include "libslic3r/libslic3r.h"
#include "libslic3r/PrintConfig.hpp"
2020-06-16 16:58:41 +02:00
#include "libslic3r/PresetBundle.hpp"
2020-06-16 12:57:49 +02:00
#include "GUI.hpp"
#include "GUI_App.hpp"
#include "Plater.hpp"
#include "MainFrame.hpp"
#include "format.hpp"
#include "Tab.hpp"
#include "ConfigWizard.hpp"
#include "../Utils/ASCIIFolding.hpp"
#include "../Utils/FixModelByWin10.hpp"
#include "../Utils/UndoRedo.hpp"
#include "BitmapCache.hpp"
2020-07-24 16:34:25 +02:00
#include "PhysicalPrinterDialog.hpp"
2020-06-16 12:57:49 +02:00
using Slic3r :: GUI :: format_wxstr ;
namespace Slic3r {
namespace GUI {
2020-07-14 15:34:08 +02:00
#define BORDER_W 10
2020-06-16 12:57:49 +02:00
// ---------------------------------
// *** PresetComboBox ***
// ---------------------------------
/* For PresetComboBox we use bitmaps that are created from images that are already scaled appropriately for Retina
* (Contrary to the intuition, the `scale` argument for Bitmap's constructor doesn't mean
* "please scale this to such and such" but rather
* "the wxImage is already sized for backing scale such and such". )
* Unfortunately, the constructor changes the size of wxBitmap too.
* Thus We need to use unscaled size value for bitmaps that we use
* to avoid scaled size of control items.
* For this purpose control drawing methods and
* control size calculation methods (virtual) are overridden.
**/
PresetComboBox :: PresetComboBox ( wxWindow * parent , Preset :: Type preset_type , const wxSize & size ) :
wxBitmapComboBox ( parent , wxID_ANY , wxEmptyString , wxDefaultPosition , size , 0 , nullptr , wxCB_READONLY ),
m_type ( preset_type ),
m_last_selected ( wxNOT_FOUND ),
2020-06-18 11:39:25 +02:00
m_em_unit ( em_unit ( this )),
2020-07-17 14:32:38 +02:00
m_preset_bundle ( wxGetApp (). preset_bundle )
2020-06-16 12:57:49 +02:00
{
SetFont ( wxGetApp (). normal_font ());
#ifdef _WIN32
// Workaround for ignoring CBN_EDITCHANGE events, which are processed after the content of the combo box changes, so that
// the index of the item inside CBN_EDITCHANGE may no more be valid.
EnableTextChangedEvents ( false );
#endif /* _WIN32 */
switch ( m_type )
{
case Preset :: TYPE_PRINT : {
m_collection = & m_preset_bundle -> prints ;
m_main_bitmap_name = "cog" ;
break ;
}
case Preset :: TYPE_FILAMENT : {
m_collection = & m_preset_bundle -> filaments ;
m_main_bitmap_name = "spool" ;
break ;
}
case Preset :: TYPE_SLA_PRINT : {
m_collection = & m_preset_bundle -> sla_prints ;
m_main_bitmap_name = "cog" ;
break ;
}
case Preset :: TYPE_SLA_MATERIAL : {
m_collection = & m_preset_bundle -> sla_materials ;
m_main_bitmap_name = "resin" ;
break ;
}
case Preset :: TYPE_PRINTER : {
m_collection = & m_preset_bundle -> printers ;
m_main_bitmap_name = "printer" ;
break ;
}
default : break ;
}
2020-06-18 11:39:25 +02:00
m_bitmapCompatible = ScalableBitmap ( this , "flag_green" );
m_bitmapIncompatible = ScalableBitmap ( this , "flag_red" );
2020-06-16 12:57:49 +02:00
// parameters for an icon's drawing
fill_width_height ();
2020-07-17 14:32:38 +02:00
Bind ( wxEVT_COMBOBOX , [ this ]( wxCommandEvent & evt ) {
// see https://github.com/prusa3d/PrusaSlicer/issues/3889
// Under OSX: in case of use of a same names written in different case (like "ENDER" and "Ender")
// m_presets_choice->GetSelection() will return first item, because search in PopupListCtrl is case-insensitive.
// So, use GetSelection() from event parameter
auto selected_item = evt . GetSelection ();
auto marker = reinterpret_cast < Marker > ( this -> GetClientData ( selected_item ));
if ( marker >= LABEL_ITEM_DISABLED && marker < LABEL_ITEM_MAX )
this -> SetSelection ( this -> m_last_selected );
else if ( on_selection_changed && ( m_last_selected != selected_item || m_collection -> current_is_dirty ())) {
m_last_selected = selected_item ;
on_selection_changed ( selected_item );
evt . StopPropagation ();
}
evt . Skip ();
});
2020-06-16 12:57:49 +02:00
}
PresetComboBox ::~ PresetComboBox ()
{
}
2020-07-20 16:27:39 +02:00
BitmapCache & PresetComboBox :: bitmap_cache ()
{
static BitmapCache bmps ;
return bmps ;
}
2020-06-16 12:57:49 +02:00
void PresetComboBox :: set_label_marker ( int item , LabelItemType label_item_type )
{
this -> SetClientData ( item , ( void * ) label_item_type );
}
2020-07-24 16:34:25 +02:00
bool PresetComboBox :: set_printer_technology ( PrinterTechnology pt )
{
if ( printer_technology != pt ) {
printer_technology = pt ;
return true ;
}
return false ;
}
2020-07-22 13:23:44 +02:00
void PresetComboBox :: invalidate_selection ()
{
m_last_selected = INT_MAX ; // this value means that no one item is selected
}
void PresetComboBox :: validate_selection ( bool predicate /*=false*/ )
{
if ( predicate ||
// just in case: mark m_last_selected as a first added element
m_last_selected == INT_MAX )
m_last_selected = GetCount () - 1 ;
}
void PresetComboBox :: update_selection ()
{
/* If selected_preset_item is still equal to INT_MAX, it means that
* there is no presets added to the list.
* So, select last combobox item ("Add/Remove preset")
*/
validate_selection ();
SetSelection ( m_last_selected );
SetToolTip ( GetString ( m_last_selected ));
}
2020-07-17 14:32:38 +02:00
void PresetComboBox :: update ( const std :: string & select_preset_name )
{
Freeze ();
Clear ();
2020-07-22 13:23:44 +02:00
invalidate_selection ();
2020-07-17 14:32:38 +02:00
const std :: deque < Preset >& presets = m_collection -> get_presets ();
std :: map < wxString , std :: pair < wxBitmap * , bool >> nonsys_presets ;
wxString selected = "" ;
if ( ! presets . front (). is_visible )
set_label_marker ( Append ( separator ( L ( "System presets" )), wxNullBitmap ));
for ( size_t i = presets . front (). is_visible ? 0 : m_collection -> num_default_presets (); i < presets . size (); ++ i )
{
const Preset & preset = presets [ i ];
if ( ! preset . is_visible || ! preset . is_compatible )
continue ;
// marker used for disable incompatible printer models for the selected physical printer
2020-07-24 16:34:25 +02:00
bool is_enabled = m_type == Preset :: TYPE_PRINTER && printer_technology != ptAny ? preset . printer_technology () == printer_technology : true ;
2020-07-17 14:32:38 +02:00
2020-07-22 13:23:44 +02:00
std :: string bitmap_key = "cb" ;
2020-07-17 14:32:38 +02:00
if ( m_type == Preset :: TYPE_PRINTER ) {
bitmap_key += "_printer" ;
if ( preset . printer_technology () == ptSLA )
bitmap_key += "_sla" ;
}
2020-07-22 13:23:44 +02:00
std :: string main_icon_name = m_type == Preset :: TYPE_PRINTER && preset . printer_technology () == ptSLA ? "sla_printer" : m_main_bitmap_name ;
2020-07-17 14:32:38 +02:00
wxBitmap * bmp = get_bmp ( bitmap_key , main_icon_name , "lock_closed" , is_enabled , preset . is_compatible , preset . is_system || preset . is_default );
assert ( bmp );
if ( preset . is_default || preset . is_system ) {
int item_id = Append ( wxString :: FromUTF8 (( preset . name + ( preset . is_dirty ? Preset :: suffix_modified () : "" )). c_str ()), * bmp );
if ( ! is_enabled )
set_label_marker ( item_id , LABEL_ITEM_DISABLED );
2020-07-24 16:34:25 +02:00
validate_selection ( preset . name == select_preset_name || ( select_preset_name . empty () && is_enabled ));
2020-07-17 14:32:38 +02:00
}
else
{
std :: pair < wxBitmap * , bool > pair ( bmp , is_enabled );
nonsys_presets . emplace ( wxString :: FromUTF8 (( preset . name + ( preset . is_dirty ? Preset :: suffix_modified () : "" )). c_str ()), std :: pair < wxBitmap * , bool > ( bmp , is_enabled ));
2020-07-24 16:34:25 +02:00
if ( preset . name == select_preset_name || ( select_preset_name . empty () && is_enabled ))
2020-07-17 14:32:38 +02:00
selected = wxString :: FromUTF8 (( preset . name + ( preset . is_dirty ? Preset :: suffix_modified () : "" )). c_str ());
}
if ( i + 1 == m_collection -> num_default_presets ())
set_label_marker ( Append ( separator ( L ( "System presets" )), wxNullBitmap ));
}
if ( ! nonsys_presets . empty ())
{
set_label_marker ( Append ( separator ( L ( "User presets" )), wxNullBitmap ));
for ( std :: map < wxString , std :: pair < wxBitmap * , bool >>:: iterator it = nonsys_presets . begin (); it != nonsys_presets . end (); ++ it ) {
int item_id = Append ( it -> first , * it -> second . first );
bool is_enabled = it -> second . second ;
if ( ! is_enabled )
set_label_marker ( item_id , LABEL_ITEM_DISABLED );
2020-07-22 13:23:44 +02:00
validate_selection ( it -> first == selected );
2020-07-17 14:32:38 +02:00
}
}
2020-07-22 13:23:44 +02:00
update_selection ();
2020-07-17 14:32:38 +02:00
Thaw ();
}
2020-07-24 16:34:25 +02:00
void PresetComboBox :: update ()
{
this -> update ( into_u8 ( this -> GetString ( this -> GetSelection ())));
}
2020-06-16 12:57:49 +02:00
void PresetComboBox :: msw_rescale ()
{
2020-06-18 11:39:25 +02:00
m_em_unit = em_unit ( this );
2020-06-16 12:57:49 +02:00
m_bitmapIncompatible . msw_rescale ();
m_bitmapCompatible . msw_rescale ();
// parameters for an icon's drawing
fill_width_height ();
// update the control to redraw the icons
update ();
}
void PresetComboBox :: fill_width_height ()
{
// To avoid asserts, each added bitmap to wxBitmapCombobox should be the same size, so
2020-07-17 14:32:38 +02:00
// set a bitmap's height to m_bitmapCompatible->GetHeight() and norm_icon_width to m_bitmapCompatible->GetWidth()
icon_height = m_bitmapCompatible . GetBmpHeight ();
norm_icon_width = m_bitmapCompatible . GetBmpWidth ();
2020-06-16 12:57:49 +02:00
/* It's supposed that standard size of an icon is 16px*16px for 100% scaled display.
* So set sizes for solid_colored icons used for filament preset
* and scale them in respect to em_unit value
*/
const float scale_f = ( float ) m_em_unit * 0.1f ;
thin_icon_width = lroundf ( 8 * scale_f ); // analogue to 8px;
wide_icon_width = norm_icon_width + thin_icon_width ;
space_icon_width = lroundf ( 2 * scale_f );
thin_space_icon_width = 2 * space_icon_width ;
wide_space_icon_width = 3 * space_icon_width ;
}
wxString PresetComboBox :: separator ( const std :: string & label )
{
return wxString :: FromUTF8 ( separator_head ()) + _ ( label ) + wxString :: FromUTF8 ( separator_tail ());
}
2020-07-17 14:32:38 +02:00
wxBitmap * PresetComboBox :: get_bmp ( std :: string bitmap_key , bool wide_icons , const std :: string & main_icon_name ,
bool is_compatible /* = true*/ , bool is_system /* = false*/ , bool is_single_bar /* = false*/ ,
std :: string filament_rgb /* = ""*/ , std :: string extruder_rgb /* = ""*/ )
{
2020-07-22 13:23:44 +02:00
// If the filament preset is not compatible and there is a "red flag" icon loaded, show it left
// to the filament color image.
if ( wide_icons )
bitmap_key += is_compatible ? ",cmpt" : ",ncmpt" ;
bitmap_key += is_system ? ",syst" : ",nsyst" ;
2020-07-17 14:32:38 +02:00
bitmap_key += ",h" + std :: to_string ( icon_height );
wxBitmap * bmp = bitmap_cache (). find ( bitmap_key );
if ( bmp == nullptr ) {
// Create the bitmap with color bars.
std :: vector < wxBitmap > bmps ;
if ( wide_icons )
// Paint a red flag for incompatible presets.
bmps . emplace_back ( is_compatible ? bitmap_cache (). mkclear ( norm_icon_width , icon_height ) : m_bitmapIncompatible . bmp ());
if ( m_type == Preset :: TYPE_FILAMENT )
{
unsigned char rgb [ 3 ];
// Paint the color bars.
bitmap_cache (). parse_color ( filament_rgb , rgb );
bmps . emplace_back ( bitmap_cache (). mksolid ( is_single_bar ? wide_icon_width : norm_icon_width , icon_height , rgb ));
if ( ! is_single_bar ) {
bitmap_cache (). parse_color ( extruder_rgb , rgb );
bmps . emplace_back ( bitmap_cache (). mksolid ( thin_icon_width , icon_height , rgb ));
}
// Paint a lock at the system presets.
bmps . emplace_back ( bitmap_cache (). mkclear ( space_icon_width , icon_height ));
}
else
{
// Paint the color bars.
bmps . emplace_back ( bitmap_cache (). mkclear ( thin_space_icon_width , icon_height ));
bmps . emplace_back ( create_scaled_bitmap ( main_icon_name ));
// Paint a lock at the system presets.
bmps . emplace_back ( bitmap_cache (). mkclear ( wide_space_icon_width , icon_height ));
}
bmps . emplace_back ( is_system ? create_scaled_bitmap ( "lock_closed" ) : bitmap_cache (). mkclear ( norm_icon_width , icon_height ));
bmp = bitmap_cache (). insert ( bitmap_key , bmps );
}
return bmp ;
}
wxBitmap * PresetComboBox :: get_bmp ( std :: string bitmap_key , const std :: string & main_icon_name , const std :: string & next_icon_name ,
bool is_enabled /* = true*/ , bool is_compatible /* = true*/ , bool is_system /* = false*/ )
{
2020-07-22 13:23:44 +02:00
bitmap_key += ! is_enabled ? "_disabled" : "" ;
bitmap_key += is_compatible ? ",cmpt" : ",ncmpt" ;
bitmap_key += is_system ? ",syst" : ",nsyst" ;
2020-07-17 14:32:38 +02:00
bitmap_key += ",h" + std :: to_string ( icon_height );
wxBitmap * bmp = bitmap_cache (). find ( bitmap_key );
if ( bmp == nullptr ) {
// Create the bitmap with color bars.
std :: vector < wxBitmap > bmps ;
bmps . emplace_back ( m_type == Preset :: TYPE_PRINTER ? create_scaled_bitmap ( main_icon_name , this , 16 , ! is_enabled ) :
is_compatible ? m_bitmapCompatible . bmp () : m_bitmapIncompatible . bmp ());
// Paint a lock at the system presets.
bmps . emplace_back ( is_system ? create_scaled_bitmap ( next_icon_name , this , 16 , ! is_enabled ) : bitmap_cache (). mkclear ( norm_icon_width , icon_height ));
bmp = bitmap_cache (). insert ( bitmap_key , bmps );
}
return bmp ;
}
bool PresetComboBox :: is_selected_physical_printer ()
{
auto selected_item = this -> GetSelection ();
auto marker = reinterpret_cast < Marker > ( this -> GetClientData ( selected_item ));
return marker == LABEL_ITEM_PHYSICAL_PRINTER ;
}
bool PresetComboBox :: selection_is_changed_according_to_physical_printers ()
{
if ( m_type != Preset :: TYPE_PRINTER || ! is_selected_physical_printer ())
return false ;
PhysicalPrinterCollection & physical_printers = m_preset_bundle -> physical_printers ;
std :: string selected_string = this -> GetString ( this -> GetSelection ()). ToUTF8 (). data ();
std :: string old_printer_full_name , old_printer_preset ;
if ( physical_printers . has_selection ()) {
old_printer_full_name = physical_printers . get_selected_full_printer_name ();
old_printer_preset = physical_printers . get_selected_printer_preset_name ();
}
else
old_printer_preset = m_collection -> get_edited_preset (). name ;
// Select related printer preset on the Printer Settings Tab
2020-07-23 12:17:18 +02:00
physical_printers . select_printer ( selected_string );
2020-07-17 14:32:38 +02:00
std :: string preset_name = physical_printers . get_selected_printer_preset_name ();
// if new preset wasn't selected, there is no need to call update preset selection
if ( old_printer_preset == preset_name ) {
// we need just to update according Plater<->Tab PresetComboBox
2020-07-21 16:21:18 +02:00
if ( dynamic_cast < PlaterPresetComboBox *> ( this ) != nullptr ) {
2020-07-17 14:32:38 +02:00
wxGetApp (). get_tab ( m_type ) -> update_preset_choice ();
2020-07-21 16:21:18 +02:00
// Synchronize config.ini with the current selections.
m_preset_bundle -> export_selections ( * wxGetApp (). app_config );
}
2020-07-17 14:32:38 +02:00
else if ( dynamic_cast < TabPresetComboBox *> ( this ) != nullptr )
wxGetApp (). sidebar (). update_presets ( m_type );
2020-07-20 14:56:09 +02:00
this -> update ();
2020-07-17 14:32:38 +02:00
return true ;
}
Tab * tab = wxGetApp (). get_tab ( Preset :: TYPE_PRINTER );
if ( tab )
tab -> select_preset ( preset_name , false , old_printer_full_name );
return true ;
}
2020-06-16 12:57:49 +02:00
#ifdef __APPLE__
bool PresetComboBox :: OnAddBitmap ( const wxBitmap & bitmap )
{
if ( bitmap . IsOk ())
{
// we should use scaled! size values of bitmap
int width = ( int ) bitmap . GetScaledWidth ();
int height = ( int ) bitmap . GetScaledHeight ();
if ( m_usedImgSize . x < 0 )
{
// If size not yet determined, get it from this image.
m_usedImgSize . x = width ;
m_usedImgSize . y = height ;
// Adjust control size to vertically fit the bitmap
wxWindow * ctrl = GetControl ();
ctrl -> InvalidateBestSize ();
wxSize newSz = ctrl -> GetBestSize ();
wxSize sz = ctrl -> GetSize ();
if ( newSz . y > sz . y )
ctrl -> SetSize ( sz . x , newSz . y );
else
DetermineIndent ();
}
wxCHECK_MSG ( width == m_usedImgSize . x && height == m_usedImgSize . y ,
false ,
"you can only add images of same size" );
return true ;
}
return false ;
}
void PresetComboBox :: OnDrawItem ( wxDC & dc ,
const wxRect & rect ,
int item ,
int flags ) const
{
const wxBitmap & bmp = * ( wxBitmap * ) m_bitmaps [ item ];
if ( bmp . IsOk ())
{
// we should use scaled! size values of bitmap
wxCoord w = bmp . GetScaledWidth ();
wxCoord h = bmp . GetScaledHeight ();
const int imgSpacingLeft = 4 ;
// Draw the image centered
dc . DrawBitmap ( bmp ,
rect . x + ( m_usedImgSize . x - w ) / 2 + imgSpacingLeft ,
rect . y + ( rect . height - h ) / 2 ,
true );
}
wxString text = GetString ( item );
if ( ! text . empty ())
dc . DrawText ( text ,
rect . x + m_imgAreaWidth + 1 ,
rect . y + ( rect . height - dc . GetCharHeight ()) / 2 );
}
#endif
// ---------------------------------
// *** PlaterPresetComboBox ***
// ---------------------------------
PlaterPresetComboBox :: PlaterPresetComboBox ( wxWindow * parent , Preset :: Type preset_type ) :
PresetComboBox ( parent , preset_type , wxSize ( 15 * wxGetApp (). em_unit (), - 1 ))
{
Bind ( wxEVT_COMBOBOX , [ this ]( wxCommandEvent & evt ) {
auto selected_item = evt . GetSelection ();
auto marker = reinterpret_cast < Marker > ( this -> GetClientData ( selected_item ));
if ( marker >= LABEL_ITEM_MARKER && marker < LABEL_ITEM_MAX ) {
this -> SetSelection ( this -> m_last_selected );
evt . StopPropagation ();
2020-06-26 09:58:39 +02:00
if ( marker == LABEL_ITEM_WIZARD_PRINTERS )
show_add_menu ();
else
{
ConfigWizard :: StartPage sp = ConfigWizard :: SP_WELCOME ;
switch ( marker ) {
case LABEL_ITEM_WIZARD_FILAMENTS : sp = ConfigWizard :: SP_FILAMENTS ; break ;
case LABEL_ITEM_WIZARD_MATERIALS : sp = ConfigWizard :: SP_MATERIALS ; break ;
default : break ;
}
wxTheApp -> CallAfter ([ sp ]() { wxGetApp (). run_wizard ( ConfigWizard :: RR_USER , sp ); });
}
2020-06-24 08:50:01 +02:00
} else if ( marker == LABEL_ITEM_PHYSICAL_PRINTER || this -> m_last_selected != selected_item || m_collection -> current_is_dirty () ) {
2020-06-16 12:57:49 +02:00
this -> m_last_selected = selected_item ;
evt . SetInt ( this -> m_type );
evt . Skip ();
} else {
evt . StopPropagation ();
}
});
if ( m_type == Preset :: TYPE_FILAMENT )
{
Bind ( wxEVT_LEFT_DOWN , [ this ]( wxMouseEvent & event ) {
const Preset * selected_preset = m_collection -> find_preset ( m_preset_bundle -> filament_presets [ m_extruder_idx ]);
// Wide icons are shown if the currently selected preset is not compatible with the current printer,
// and red flag is drown in front of the selected preset.
bool wide_icons = selected_preset != nullptr && ! selected_preset -> is_compatible ;
float scale = m_em_unit * 0.1f ;
int shifl_Left = wide_icons ? int ( scale * 16 + 0.5 ) : 0 ;
#if defined(wxBITMAPCOMBOBOX_OWNERDRAWN_BASED)
shifl_Left += int ( scale * 4 + 0.5f ); // IMAGE_SPACING_RIGHT = 4 for wxBitmapComboBox -> Space left of image
#endif
int icon_right_pos = shifl_Left + int ( scale * ( 24 + 4 ) + 0.5 );
int mouse_pos = event . GetLogicalPosition ( wxClientDC ( this )). x ;
if ( mouse_pos < shifl_Left || mouse_pos > icon_right_pos ) {
// Let the combo box process the mouse click.
event . Skip ();
return ;
}
// Swallow the mouse click and open the color picker.
// get current color
DynamicPrintConfig * cfg = wxGetApp (). get_tab ( Preset :: TYPE_PRINTER ) -> get_config ();
auto colors = static_cast < ConfigOptionStrings *> ( cfg -> option ( "extruder_colour" ) -> clone ());
wxColour clr ( colors -> values [ m_extruder_idx ]);
if ( ! clr . IsOk ())
clr = wxColour ( 0 , 0 , 0 ); // Don't set alfa to transparence
auto data = new wxColourData ();
data -> SetChooseFull ( 1 );
data -> SetColour ( clr );
wxColourDialog dialog ( this , data );
dialog . CenterOnParent ();
if ( dialog . ShowModal () == wxID_OK )
{
colors -> values [ m_extruder_idx ] = dialog . GetColourData (). GetColour (). GetAsString ( wxC2S_HTML_SYNTAX ). ToStdString ();
DynamicPrintConfig cfg_new = * cfg ;
cfg_new . set_key_value ( "extruder_colour" , colors );
wxGetApp (). get_tab ( Preset :: TYPE_PRINTER ) -> load_config ( cfg_new );
this -> update ();
wxGetApp (). plater () -> on_config_change ( cfg_new );
}
});
}
edit_btn = new ScalableButton ( parent , wxID_ANY , "cog" );
edit_btn -> SetToolTip ( _L ( "Click to edit preset" ));
edit_btn -> Bind ( wxEVT_BUTTON , [ this ]( wxCommandEvent )
{
2020-06-24 08:50:01 +02:00
// In a case of a physical printer, for its editing open PhysicalPrinterDialog
2020-07-24 16:34:25 +02:00
if ( m_type == Preset :: TYPE_PRINTER /* && this->is_selected_physical_printer()*/ ) {
2020-06-24 12:28:00 +02:00
this -> show_edit_menu ();
return ;
2020-06-24 08:50:01 +02:00
}
2020-06-24 12:28:00 +02:00
if ( ! switch_to_tab ())
2020-06-16 12:57:49 +02:00
return ;
/* In a case of a multi-material printing, for editing another Filament Preset
* it's needed to select this preset for the "Filament settings" Tab
*/
if ( m_type == Preset :: TYPE_FILAMENT && wxGetApp (). extruders_edited_cnt () > 1 )
{
const std :: string & selected_preset = GetString ( GetSelection ()). ToUTF8 (). data ();
// Call select_preset() only if there is new preset and not just modified
if ( ! boost :: algorithm :: ends_with ( selected_preset , Preset :: suffix_modified ()) )
{
const std :: string & preset_name = wxGetApp (). preset_bundle -> filaments . get_preset_name_by_alias ( selected_preset );
2020-06-24 12:28:00 +02:00
wxGetApp (). get_tab ( m_type ) -> select_preset ( preset_name );
2020-06-16 12:57:49 +02:00
}
}
});
}
PlaterPresetComboBox ::~ PlaterPresetComboBox ()
{
if ( edit_btn )
edit_btn -> Destroy ();
}
2020-06-24 12:28:00 +02:00
bool PlaterPresetComboBox :: switch_to_tab ()
{
Tab * tab = wxGetApp (). get_tab ( m_type );
if ( ! tab )
return false ;
int page_id = wxGetApp (). tab_panel () -> FindPage ( tab );
if ( page_id == wxNOT_FOUND )
return false ;
wxGetApp (). tab_panel () -> SetSelection ( page_id );
// Switch to Settings NotePad
wxGetApp (). mainframe -> select_tab ();
return true ;
}
2020-06-26 09:58:39 +02:00
void PlaterPresetComboBox :: show_add_menu ()
{
wxMenu * menu = new wxMenu ();
2020-07-24 16:34:25 +02:00
append_menu_item ( menu , wxID_ANY , _L ( "Add/Remove presets" ), "" ,
2020-06-26 09:58:39 +02:00
[ this ]( wxCommandEvent & ) {
wxTheApp -> CallAfter ([]() { wxGetApp (). run_wizard ( ConfigWizard :: RR_USER , ConfigWizard :: SP_PRINTERS ); });
}, "edit_uni" , menu , []() { return true ; }, wxGetApp (). plater ());
append_menu_item ( menu , wxID_ANY , _L ( "Add physical printer" ), "" ,
[ this ]( wxCommandEvent & ) {
PhysicalPrinterDialog dlg ( wxEmptyString );
if ( dlg . ShowModal () == wxID_OK )
update ();
}, "edit_uni" , menu , []() { return true ; }, wxGetApp (). plater ());
wxGetApp (). plater () -> PopupMenu ( menu );
}
2020-06-24 12:28:00 +02:00
void PlaterPresetComboBox :: show_edit_menu ()
{
wxMenu * menu = new wxMenu ();
2020-07-24 16:34:25 +02:00
append_menu_item ( menu , wxID_ANY , _L ( "Edit preset" ), "" ,
2020-06-24 12:28:00 +02:00
[ this ]( wxCommandEvent & ) { this -> switch_to_tab (); }, "cog" , menu , []() { return true ; }, wxGetApp (). plater ());
2020-07-24 16:34:25 +02:00
if ( this -> is_selected_physical_printer ()) {
2020-06-24 12:28:00 +02:00
append_menu_item ( menu , wxID_ANY , _L ( "Edit physical printer" ), "" ,
[ this ]( wxCommandEvent & ) {
PhysicalPrinterDialog dlg ( this -> GetString ( this -> GetSelection ()));
if ( dlg . ShowModal () == wxID_OK )
update ();
}, "cog" , menu , []() { return true ; }, wxGetApp (). plater ());
append_menu_item ( menu , wxID_ANY , _L ( "Delete physical printer" ), "" ,
[ this ]( wxCommandEvent & ) {
2020-06-26 09:58:39 +02:00
const std :: string & printer_name = m_preset_bundle -> physical_printers . get_selected_full_printer_name ();
2020-06-24 12:28:00 +02:00
if ( printer_name . empty ())
return ;
const wxString msg = from_u8 (( boost :: format ( _u8L ( "Are you sure you want to delete \" %1% \" printer?" )) % printer_name ). str ());
if ( wxMessageDialog ( this , msg , _L ( "Delete Physical Printer" ), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION ). ShowModal () != wxID_YES )
return ;
m_preset_bundle -> physical_printers . delete_selected_printer ();
2020-07-20 14:56:09 +02:00
wxGetApp (). get_tab ( m_type ) -> update_preset_choice ();
2020-06-24 12:28:00 +02:00
update ();
}, "cross" , menu , []() { return true ; }, wxGetApp (). plater ());
2020-07-24 16:34:25 +02:00
}
else
append_menu_item ( menu , wxID_ANY , _L ( "Add/Remove presets" ), "" ,
[ this ]( wxCommandEvent & ) {
wxTheApp -> CallAfter ([]() { wxGetApp (). run_wizard ( ConfigWizard :: RR_USER , ConfigWizard :: SP_PRINTERS ); });
}, "edit_uni" , menu , []() { return true ; }, wxGetApp (). plater ());
2020-06-24 12:28:00 +02:00
wxGetApp (). plater () -> PopupMenu ( menu );
}
2020-06-16 12:57:49 +02:00
// Only the compatible presets are shown.
// If an incompatible preset is selected, it is shown as well.
void PlaterPresetComboBox :: update ()
{
if ( m_type == Preset :: TYPE_FILAMENT &&
2020-06-18 11:39:25 +02:00
( m_preset_bundle -> printers . get_edited_preset (). printer_technology () == ptSLA ||
2020-06-16 12:57:49 +02:00
m_preset_bundle -> filament_presets . size () <= m_extruder_idx ) )
return ;
// Otherwise fill in the list from scratch.
this -> Freeze ();
this -> Clear ();
2020-07-22 13:23:44 +02:00
invalidate_selection ();
2020-06-16 12:57:49 +02:00
const Preset * selected_filament_preset ;
std :: string extruder_color ;
if ( m_type == Preset :: TYPE_FILAMENT )
{
unsigned char rgb [ 3 ];
extruder_color = m_preset_bundle -> printers . get_edited_preset (). config . opt_string ( "extruder_colour" , ( unsigned int ) m_extruder_idx );
2020-07-17 14:32:38 +02:00
if ( ! bitmap_cache (). parse_color ( extruder_color , rgb ))
2020-06-16 12:57:49 +02:00
// Extruder color is not defined.
extruder_color . clear ();
selected_filament_preset = m_collection -> find_preset ( m_preset_bundle -> filament_presets [ m_extruder_idx ]);
assert ( selected_filament_preset );
}
const Preset & selected_preset = m_type == Preset :: TYPE_FILAMENT ? * selected_filament_preset : m_collection -> get_selected_preset ();
// Show wide icons if the currently selected preset is not compatible with the current printer,
// and draw a red flag in front of the selected preset.
bool wide_icons = ! selected_preset . is_compatible ;
std :: map < wxString , wxBitmap *> nonsys_presets ;
wxString selected = "" ;
wxString tooltip = "" ;
const std :: deque < Preset >& presets = m_collection -> get_presets ();
if ( ! presets . front (). is_visible )
this -> set_label_marker ( this -> Append ( separator ( L ( "System presets" )), wxNullBitmap ));
for ( size_t i = presets . front (). is_visible ? 0 : m_collection -> num_default_presets (); i < presets . size (); ++ i )
{
const Preset & preset = presets [ i ];
2020-06-24 08:50:01 +02:00
bool is_selected = m_type == Preset :: TYPE_FILAMENT ?
m_preset_bundle -> filament_presets [ m_extruder_idx ] == preset . name :
// The case, when some physical printer is selected
m_type == Preset :: TYPE_PRINTER && m_preset_bundle -> physical_printers . has_selection () ? false :
i == m_collection -> get_selected_idx ();
2020-06-16 12:57:49 +02:00
if ( ! preset . is_visible || ( ! preset . is_compatible && ! is_selected ))
continue ;
std :: string bitmap_key , filament_rgb , extruder_rgb ;
2020-07-17 14:32:38 +02:00
std :: string bitmap_type_name = bitmap_key = m_type == Preset :: TYPE_PRINTER && preset . printer_technology () == ptSLA ? "sla_printer" : m_main_bitmap_name ;
2020-06-16 12:57:49 +02:00
bool single_bar = false ;
2020-07-17 14:32:38 +02:00
if ( m_type == Preset :: TYPE_FILAMENT )
2020-06-16 12:57:49 +02:00
{
// Assign an extruder color to the selected item if the extruder color is defined.
filament_rgb = preset . config . opt_string ( "filament_colour" , 0 );
extruder_rgb = ( selected && ! extruder_color . empty ()) ? extruder_color : filament_rgb ;
single_bar = filament_rgb == extruder_rgb ;
2020-07-17 14:32:38 +02:00
bitmap_key += single_bar ? filament_rgb : filament_rgb + extruder_rgb ;
2020-06-16 12:57:49 +02:00
}
2020-07-17 14:32:38 +02:00
wxBitmap * bmp = get_bmp ( bitmap_key , wide_icons , bitmap_type_name ,
preset . is_compatible , preset . is_system || preset . is_default ,
single_bar , filament_rgb , extruder_rgb );
assert ( bmp );
2020-06-16 12:57:49 +02:00
const std :: string name = preset . alias . empty () ? preset . name : preset . alias ;
if ( preset . is_default || preset . is_system ) {
2020-07-17 14:32:38 +02:00
Append ( wxString :: FromUTF8 (( name + ( preset . is_dirty ? Preset :: suffix_modified () : "" )). c_str ()), * bmp );
2020-07-22 13:23:44 +02:00
validate_selection ( is_selected );
if ( is_selected )
2020-06-16 12:57:49 +02:00
tooltip = wxString :: FromUTF8 ( preset . name . c_str ());
}
else
{
nonsys_presets . emplace ( wxString :: FromUTF8 (( name + ( preset . is_dirty ? Preset :: suffix_modified () : "" )). c_str ()), bmp );
if ( is_selected ) {
selected = wxString :: FromUTF8 (( name + ( preset . is_dirty ? Preset :: suffix_modified () : "" )). c_str ());
tooltip = wxString :: FromUTF8 ( preset . name . c_str ());
}
}
if ( i + 1 == m_collection -> num_default_presets ())
set_label_marker ( Append ( separator ( L ( "System presets" )), wxNullBitmap ));
}
if ( ! nonsys_presets . empty ())
{
set_label_marker ( Append ( separator ( L ( "User presets" )), wxNullBitmap ));
for ( std :: map < wxString , wxBitmap *>:: iterator it = nonsys_presets . begin (); it != nonsys_presets . end (); ++ it ) {
Append ( it -> first , * it -> second );
2020-07-22 13:23:44 +02:00
validate_selection ( it -> first == selected );
2020-06-16 12:57:49 +02:00
}
}
2020-06-24 08:50:01 +02:00
if ( m_type == Preset :: TYPE_PRINTER )
{
// add Physical printers, if any exists
if ( ! m_preset_bundle -> physical_printers . empty ()) {
set_label_marker ( Append ( separator ( L ( "Physical printers" )), wxNullBitmap ));
const PhysicalPrinterCollection & ph_printers = m_preset_bundle -> physical_printers ;
for ( PhysicalPrinterCollection :: ConstIterator it = ph_printers . begin (); it != ph_printers . end (); ++ it ) {
2020-07-17 14:32:38 +02:00
for ( const std :: string preset_name : it -> get_preset_names ()) {
Preset * preset = m_collection -> find_preset ( preset_name );
if ( ! preset )
continue ;
std :: string main_icon_name , bitmap_key = main_icon_name = preset -> printer_technology () == ptSLA ? "sla_printer" : m_main_bitmap_name ;
2020-07-22 13:23:44 +02:00
wxBitmap * bmp = get_bmp ( main_icon_name , wide_icons , main_icon_name );
2020-07-17 14:32:38 +02:00
assert ( bmp );
set_label_marker ( Append ( wxString :: FromUTF8 (( it -> get_full_name ( preset_name ) + ( preset -> is_dirty ? Preset :: suffix_modified () : "" )). c_str ()), * bmp ), LABEL_ITEM_PHYSICAL_PRINTER );
2020-07-22 13:23:44 +02:00
validate_selection ( ph_printers . is_selected ( it , preset_name ));
2020-07-17 14:32:38 +02:00
}
2020-06-24 08:50:01 +02:00
}
}
2020-06-26 09:58:39 +02:00
}
2020-07-24 16:34:25 +02:00
if ( /*m_type == Preset::TYPE_PRINTER || */ m_type == Preset :: TYPE_SLA_MATERIAL ) {
2020-07-22 13:23:44 +02:00
wxBitmap * bmp = get_bmp ( "edit_preset_list" , wide_icons , "edit_uni" );
2020-07-17 14:32:38 +02:00
assert ( bmp );
2020-06-26 09:58:39 +02:00
if ( m_type == Preset :: TYPE_SLA_MATERIAL )
set_label_marker ( Append ( separator ( L ( "Add/Remove materials" )), * bmp ), LABEL_ITEM_WIZARD_MATERIALS );
else
set_label_marker ( Append ( separator ( L ( "Add/Remove printers" )), * bmp ), LABEL_ITEM_WIZARD_PRINTERS );
2020-06-16 12:57:49 +02:00
}
2020-07-22 13:23:44 +02:00
update_selection ();
2020-06-16 12:57:49 +02:00
Thaw ();
2020-07-22 13:23:44 +02:00
if ( ! tooltip . IsEmpty ())
SetToolTip ( tooltip );
2020-06-16 12:57:49 +02:00
// Update control min size after rescale (changed Display DPI under MSW)
if ( GetMinWidth () != 20 * m_em_unit )
SetMinSize ( wxSize ( 20 * m_em_unit , GetSize (). GetHeight ()));
}
void PlaterPresetComboBox :: msw_rescale ()
{
PresetComboBox :: msw_rescale ();
edit_btn -> msw_rescale ();
}
// ---------------------------------
2020-06-18 11:39:25 +02:00
// *** TabPresetComboBox ***
2020-06-16 12:57:49 +02:00
// ---------------------------------
2020-06-24 08:50:01 +02:00
TabPresetComboBox :: TabPresetComboBox ( wxWindow * parent , Preset :: Type preset_type ) :
2020-06-16 12:57:49 +02:00
PresetComboBox ( parent , preset_type , wxSize ( 35 * wxGetApp (). em_unit (), - 1 ))
{
2020-06-24 08:50:01 +02:00
Bind ( wxEVT_COMBOBOX , [ this ]( wxCommandEvent & evt ) {
2020-06-16 12:57:49 +02:00
// see https://github.com/prusa3d/PrusaSlicer/issues/3889
// Under OSX: in case of use of a same names written in different case (like "ENDER" and "Ender")
// m_presets_choice->GetSelection() will return first item, because search in PopupListCtrl is case-insensitive.
// So, use GetSelection() from event parameter
auto selected_item = evt . GetSelection ();
auto marker = reinterpret_cast < Marker > ( this -> GetClientData ( selected_item ));
2020-06-26 09:58:39 +02:00
if ( marker >= LABEL_ITEM_DISABLED && marker < LABEL_ITEM_MAX ) {
2020-06-16 12:57:49 +02:00
this -> SetSelection ( this -> m_last_selected );
if ( marker == LABEL_ITEM_WIZARD_PRINTERS )
2020-06-24 08:50:01 +02:00
wxTheApp -> CallAfter ([ this ]() {
2020-06-18 11:39:25 +02:00
wxGetApp (). run_wizard ( ConfigWizard :: RR_USER , ConfigWizard :: SP_PRINTERS );
2020-06-24 08:50:01 +02:00
// update combobox if its parent is a PhysicalPrinterDialog
PhysicalPrinterDialog * parent = dynamic_cast < PhysicalPrinterDialog *> ( this -> GetParent ());
if ( parent != nullptr )
2020-06-18 11:39:25 +02:00
update ();
});
2020-06-16 12:57:49 +02:00
}
2020-07-17 14:32:38 +02:00
else if ( on_selection_changed && ( m_last_selected != selected_item || m_collection -> current_is_dirty ()) ) {
m_last_selected = selected_item ;
2020-06-24 08:50:01 +02:00
on_selection_changed ( selected_item );
2020-07-17 14:32:38 +02:00
}
2020-06-16 12:57:49 +02:00
evt . StopPropagation ();
});
}
// Update the choice UI from the list of presets.
// If show_incompatible, all presets are shown, otherwise only the compatible presets are shown.
// If an incompatible preset is selected, it is shown as well.
void TabPresetComboBox :: update ()
{
Freeze ();
Clear ();
2020-07-22 13:23:44 +02:00
invalidate_selection ();
2020-06-16 12:57:49 +02:00
const std :: deque < Preset >& presets = m_collection -> get_presets ();
2020-06-26 09:58:39 +02:00
std :: map < wxString , std :: pair < wxBitmap * , bool >> nonsys_presets ;
2020-06-16 12:57:49 +02:00
wxString selected = "" ;
if ( ! presets . front (). is_visible )
set_label_marker ( Append ( separator ( L ( "System presets" )), wxNullBitmap ));
int idx_selected = m_collection -> get_selected_idx ();
2020-07-17 14:32:38 +02:00
2020-07-20 14:56:09 +02:00
PrinterTechnology proper_pt = ptAny ;
if ( m_type == Preset :: TYPE_PRINTER && m_preset_bundle -> physical_printers . has_selection ()) {
std :: string sel_preset_name = m_preset_bundle -> physical_printers . get_selected_printer_preset_name ();
Preset * preset = m_collection -> find_preset ( sel_preset_name );
if ( preset )
proper_pt = preset -> printer_technology ();
else
m_preset_bundle -> physical_printers . unselect_printer ();
}
2020-07-17 14:32:38 +02:00
for ( size_t i = presets . front (). is_visible ? 0 : m_collection -> num_default_presets (); i < presets . size (); ++ i )
{
2020-06-16 12:57:49 +02:00
const Preset & preset = presets [ i ];
if ( ! preset . is_visible || ( ! show_incompatible && ! preset . is_compatible && i != idx_selected ))
continue ;
2020-06-26 09:58:39 +02:00
// marker used for disable incompatible printer models for the selected physical printer
bool is_enabled = true ;
2020-06-16 12:57:49 +02:00
2020-07-22 13:23:44 +02:00
std :: string bitmap_key = "tab" ;
2020-06-16 12:57:49 +02:00
if ( m_type == Preset :: TYPE_PRINTER ) {
bitmap_key += "_printer" ;
if ( preset . printer_technology () == ptSLA )
bitmap_key += "_sla" ;
}
2020-07-22 13:23:44 +02:00
std :: string main_icon_name = m_type == Preset :: TYPE_PRINTER && preset . printer_technology () == ptSLA ? "sla_printer" : m_main_bitmap_name ;
2020-06-16 12:57:49 +02:00
2020-07-17 14:32:38 +02:00
wxBitmap * bmp = get_bmp ( bitmap_key , main_icon_name , "lock_closed" , is_enabled , preset . is_compatible , preset . is_system || preset . is_default );
assert ( bmp );
2020-06-16 12:57:49 +02:00
if ( preset . is_default || preset . is_system ) {
2020-07-17 14:32:38 +02:00
int item_id = Append ( wxString :: FromUTF8 (( preset . name + ( preset . is_dirty ? Preset :: suffix_modified () : "" )). c_str ()), * bmp );
2020-06-26 09:58:39 +02:00
if ( ! is_enabled )
set_label_marker ( item_id , LABEL_ITEM_DISABLED );
2020-07-22 13:23:44 +02:00
validate_selection ( i == idx_selected );
2020-06-16 12:57:49 +02:00
}
else
{
2020-06-26 09:58:39 +02:00
std :: pair < wxBitmap * , bool > pair ( bmp , is_enabled );
nonsys_presets . emplace ( wxString :: FromUTF8 (( preset . name + ( preset . is_dirty ? Preset :: suffix_modified () : "" )). c_str ()), std :: pair < wxBitmap * , bool > ( bmp , is_enabled ));
2020-06-16 12:57:49 +02:00
if ( i == idx_selected )
selected = wxString :: FromUTF8 (( preset . name + ( preset . is_dirty ? Preset :: suffix_modified () : "" )). c_str ());
}
if ( i + 1 == m_collection -> num_default_presets ())
set_label_marker ( Append ( separator ( L ( "System presets" )), wxNullBitmap ));
}
if ( ! nonsys_presets . empty ())
{
set_label_marker ( Append ( separator ( L ( "User presets" )), wxNullBitmap ));
2020-06-26 09:58:39 +02:00
for ( std :: map < wxString , std :: pair < wxBitmap * , bool >>:: iterator it = nonsys_presets . begin (); it != nonsys_presets . end (); ++ it ) {
int item_id = Append ( it -> first , * it -> second . first );
bool is_enabled = it -> second . second ;
if ( ! is_enabled )
set_label_marker ( item_id , LABEL_ITEM_DISABLED );
2020-07-22 13:23:44 +02:00
validate_selection ( it -> first == selected );
2020-06-16 12:57:49 +02:00
}
}
2020-07-17 14:32:38 +02:00
if ( m_type == Preset :: TYPE_PRINTER )
{
// add Physical printers, if any exists
if ( ! m_preset_bundle -> physical_printers . empty ()) {
set_label_marker ( Append ( separator ( L ( "Physical printers" )), wxNullBitmap ));
const PhysicalPrinterCollection & ph_printers = m_preset_bundle -> physical_printers ;
for ( PhysicalPrinterCollection :: ConstIterator it = ph_printers . begin (); it != ph_printers . end (); ++ it ) {
for ( const std :: string preset_name : it -> get_preset_names ()) {
Preset * preset = m_collection -> find_preset ( preset_name );
if ( ! preset )
continue ;
std :: string main_icon_name = preset -> printer_technology () == ptSLA ? "sla_printer" : m_main_bitmap_name ;
2020-07-22 13:23:44 +02:00
wxBitmap * bmp = get_bmp ( main_icon_name , main_icon_name , "" , true , true , false );
2020-07-17 14:32:38 +02:00
assert ( bmp );
set_label_marker ( Append ( wxString :: FromUTF8 (( it -> get_full_name ( preset_name ) + ( preset -> is_dirty ? Preset :: suffix_modified () : "" )). c_str ()), * bmp ), LABEL_ITEM_PHYSICAL_PRINTER );
2020-07-22 13:23:44 +02:00
validate_selection ( ph_printers . is_selected ( it , preset_name ));
2020-07-17 14:32:38 +02:00
}
}
2020-06-16 12:57:49 +02:00
}
2020-07-17 14:32:38 +02:00
// add "Add/Remove printers" item
2020-07-22 13:23:44 +02:00
std :: string icon_name = "edit_uni" ;
wxBitmap * bmp = get_bmp ( "edit_preset_list, tab," , icon_name , "" );
2020-07-17 14:32:38 +02:00
assert ( bmp );
2020-06-16 12:57:49 +02:00
set_label_marker ( Append ( separator ( L ( "Add/Remove printers" )), * bmp ), LABEL_ITEM_WIZARD_PRINTERS );
}
2020-07-22 13:23:44 +02:00
update_selection ();
2020-06-16 12:57:49 +02:00
Thaw ();
}
void TabPresetComboBox :: msw_rescale ()
{
PresetComboBox :: msw_rescale ();
wxSize sz = wxSize ( 35 * m_em_unit , - 1 );
SetMinSize ( sz );
SetSize ( sz );
}
void TabPresetComboBox :: update_dirty ()
{
// 1) Update the dirty flag of the current preset.
m_collection -> update_dirty ();
// 2) Update the labels.
wxWindowUpdateLocker noUpdates ( this );
for ( unsigned int ui_id = 0 ; ui_id < GetCount (); ++ ui_id ) {
2020-07-17 14:32:38 +02:00
auto marker = reinterpret_cast < Marker > ( this -> GetClientData ( ui_id ));
if ( marker >= LABEL_ITEM_MARKER )
continue ;
2020-06-16 12:57:49 +02:00
std :: string old_label = GetString ( ui_id ). utf8_str (). data ();
std :: string preset_name = Preset :: remove_suffix_modified ( old_label );
2020-07-17 14:32:38 +02:00
std :: string ph_printer_name ;
if ( marker == LABEL_ITEM_PHYSICAL_PRINTER ) {
ph_printer_name = PhysicalPrinter :: get_short_name ( preset_name );
preset_name = PhysicalPrinter :: get_preset_name ( preset_name );
}
2020-06-16 12:57:49 +02:00
const Preset * preset = m_collection -> find_preset ( preset_name , false );
if ( preset ) {
std :: string new_label = preset -> is_dirty ? preset -> name + Preset :: suffix_modified () : preset -> name ;
2020-07-17 14:32:38 +02:00
if ( marker == LABEL_ITEM_PHYSICAL_PRINTER )
new_label = ph_printer_name + PhysicalPrinter :: separator () + new_label ;
2020-06-16 12:57:49 +02:00
if ( old_label != new_label )
SetString ( ui_id , wxString :: FromUTF8 ( new_label . c_str ()));
}
}
#ifdef __APPLE__
// wxWidgets on OSX do not upload the text of the combo box line automatically.
// Force it to update by re-selecting.
SetSelection ( GetSelection ());
#endif /* __APPLE __ */
}
2020-07-17 14:32:38 +02:00
void TabPresetComboBox :: update_physical_printers ( const std :: string & preset_name )
{
2020-07-20 14:56:09 +02:00
if ( m_type != Preset :: TYPE_PRINTER || ! m_allow_to_update_physical_printers )
return ;
m_allow_to_update_physical_printers = false ;
PhysicalPrinterCollection & physical_printers = m_preset_bundle -> physical_printers ;
if ( ! physical_printers . has_selection ())
return ;
std :: string printer_preset_name = physical_printers . get_selected_printer_preset_name ();
if ( Preset :: remove_suffix_modified ( preset_name ) == printer_preset_name ) {
if ( ! this -> is_selected_physical_printer ())
physical_printers . unselect_printer ();
}
else
{
ChangePresetForPhysicalPrinterDialog dlg ( Preset :: remove_suffix_modified ( preset_name ));
if ( dlg . ShowModal () == wxID_OK )
{
if ( dlg . m_selection == ChangePresetForPhysicalPrinterDialog :: Switch )
// unselect physical printer, if it was selected
m_preset_bundle -> physical_printers . unselect_printer ();
else
{
PhysicalPrinter printer = physical_printers . get_selected_printer ();
if ( dlg . m_selection == ChangePresetForPhysicalPrinterDialog :: ChangePreset )
printer . delete_preset ( printer_preset_name );
if ( printer . add_preset ( preset_name ))
physical_printers . save_printer ( printer );
else {
wxMessageDialog dialog ( nullptr , _L ( "This preset is already exist for this physical printer. Please, select another one." ), _L ( "Information" ), wxICON_INFORMATION | wxOK );
dialog . ShowModal ();
}
2020-07-23 12:17:18 +02:00
physical_printers . select_printer ( printer . get_full_name ( preset_name ));
2020-07-20 14:56:09 +02:00
}
}
else
wxGetApp (). get_tab ( Preset :: TYPE_PRINTER ) -> select_preset ( printer_preset_name );
}
2020-07-17 14:32:38 +02:00
}
2020-06-16 12:57:49 +02:00
2020-07-20 14:56:09 +02:00
//-----------------------------------------------
// ChangePresetForPhysicalPrinterDialog
//-----------------------------------------------
ChangePresetForPhysicalPrinterDialog :: ChangePresetForPhysicalPrinterDialog ( const std :: string & preset_name )
: DPIDialog ( nullptr , wxID_ANY , _L ( "Warning" ), wxDefaultPosition , wxSize ( 45 * wxGetApp (). em_unit (), - 1 ), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING /* | wxRESIZE_BORDER*/ )
{
SetFont ( wxGetApp (). normal_font ());
SetBackgroundColour ( wxSystemSettings :: GetColour ( wxSYS_COLOUR_WINDOW ));
PhysicalPrinterCollection & printers = wxGetApp (). preset_bundle -> physical_printers ;
std :: string printer_name = printers . get_selected_printer_name ();
std :: string old_preset_name = printers . get_selected_printer_preset_name ();
wxString msg_text = from_u8 (( boost :: format ( _u8L ( "You have selected physical printer \" %1% \"\n "
"with related printer preset \" %2% \" " )) %
printer_name % old_preset_name ). str ());
wxStaticText * label_top = new wxStaticText ( this , wxID_ANY , msg_text );
label_top -> SetFont ( wxGetApp (). bold_font ());
2020-07-24 16:34:25 +02:00
wxString choices [] = { from_u8 (( boost :: format ( _u8L ( "Change \" %1% \" to \" %2% \" for this physical printer" )) % old_preset_name % preset_name ). str ()),
from_u8 (( boost :: format ( _u8L ( "Add \" %1% \" as a next preset for the the physical printer" )) % preset_name ). str ()),
from_u8 (( boost :: format ( _u8L ( "Just switch to \" %1% \" " )) % preset_name ). str ()) };
2020-07-20 14:56:09 +02:00
wxRadioBox * selection_type_box = new wxRadioBox ( this , wxID_ANY , _L ( "What would you like to do?" ), wxDefaultPosition , wxDefaultSize , WXSIZEOF ( choices ), choices ,
3 , wxRA_SPECIFY_ROWS );
selection_type_box -> SetFont ( wxGetApp (). normal_font ());
selection_type_box -> SetSelection ( 0 );
selection_type_box -> Bind ( wxEVT_RADIOBOX , [ this ]( wxCommandEvent & e ) {
int selection = e . GetSelection ();
m_selection = ( SelectionType ) selection ;
});
auto radio_sizer = new wxBoxSizer ( wxHORIZONTAL );
radio_sizer -> Add ( selection_type_box , 1 , wxALIGN_CENTER_VERTICAL );
wxStdDialogButtonSizer * btns = this -> CreateStdDialogButtonSizer ( wxOK | wxCANCEL );
wxButton * btnOK = static_cast < wxButton *> ( this -> FindWindowById ( wxID_OK , this ));
btnOK -> Bind ( wxEVT_BUTTON , & ChangePresetForPhysicalPrinterDialog :: OnOK , this );
wxBoxSizer * topSizer = new wxBoxSizer ( wxVERTICAL );
topSizer -> Add ( label_top , 0 , wxEXPAND | wxLEFT | wxTOP | wxRIGHT , BORDER_W );
topSizer -> Add ( radio_sizer , 1 , wxEXPAND | wxLEFT | wxTOP | wxRIGHT , BORDER_W );
topSizer -> Add ( btns , 0 , wxEXPAND | wxALL , BORDER_W );
SetSizer ( topSizer );
topSizer -> SetSizeHints ( this );
}
void ChangePresetForPhysicalPrinterDialog :: on_dpi_changed ( const wxRect & suggested_rect )
{
const int & em = em_unit ();
msw_buttons_rescale ( this , em , { wxID_OK , wxID_CANCEL });
const wxSize & size = wxSize ( 45 * em , 35 * em );
SetMinSize ( size );
Fit ();
Refresh ();
}
void ChangePresetForPhysicalPrinterDialog :: OnOK ( wxEvent & event )
{
event . Skip ();
}
2020-06-16 12:57:49 +02:00
}} // namespace Slic3r::GUI