2017-12-13 14:45:10 +01:00
#ifndef SLIC3R_GUI_FIELD_HPP
#define SLIC3R_GUI_FIELD_HPP
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <memory>
2019-05-20 13:32:36 +02:00
#include <cstdint>
2017-12-13 14:45:10 +01:00
#include <functional>
#include <boost/any.hpp>
2017-12-18 13:58:51 +01:00
#include <wx/spinctrl.h>
2019-03-07 16:21:56 +01:00
#include <wx/bmpcbox.h>
2017-12-22 11:50:28 +01:00
#include <wx/clrpicker.h>
2017-12-18 13:58:51 +01:00
2018-11-26 14:41:58 +01:00
#include "libslic3r/libslic3r.h"
#include "libslic3r/Config.hpp"
#include "libslic3r/Utils.hpp"
2017-12-13 14:45:10 +01:00
#include "GUI.hpp"
2019-04-13 23:46:52 +02:00
#include "wxExtensions.hpp"
2017-12-13 14:45:10 +01:00
2018-03-06 13:34:39 +01:00
#ifdef __WXMSW__
#define wxMSW true
#else
#define wxMSW false
#endif
2017-12-13 14:45:10 +01:00
namespace Slic3r { namespace GUI {
class Field ;
using t_field = std :: unique_ptr < Field > ;
2018-12-11 13:34:37 +01:00
using t_kill_focus = std :: function < void ( const std :: string & ) > ;
using t_change = std :: function < void ( const t_config_option_key & , const boost :: any & ) > ;
2018-04-13 12:35:04 +02:00
using t_back_to_init = std :: function < void ( const std :: string & ) > ;
2017-12-13 14:45:10 +01:00
2018-11-14 12:33:48 +01:00
wxString double_to_string ( double const value , const int max_precision = 4 );
2020-12-07 16:14:40 +01:00
wxString get_thumbnails_string ( const std :: vector < Vec2d >& values );
2018-02-19 09:15:15 +01:00
2017-12-26 23:04:54 +01:00
class Field {
2017-12-18 13:58:51 +01:00
protected :
2017-12-13 14:45:10 +01:00
// factory function to defer and enforce creation of derived type.
2018-03-06 12:34:20 +01:00
virtual void PostInitialize ();
2017-12-13 14:45:10 +01:00
/// Finish constructing the Field's wxWidget-related properties, including setting its own sizer, etc.
2018-01-31 16:46:17 +01:00
virtual void BUILD () = 0 ;
2017-12-13 14:45:10 +01:00
/// Call the attached on_kill_focus method.
2018-01-31 14:59:44 +01:00
//! It's important to use wxEvent instead of wxFocusEvent,
//! in another case we can't unfocused control at all
2019-01-08 16:05:49 +01:00
void on_kill_focus ();
2017-12-13 14:45:10 +01:00
/// Call the attached on_change method.
2018-12-11 13:57:50 +01:00
void on_set_focus ( wxEvent & event );
/// Call the attached on_change method.
2018-01-31 16:46:17 +01:00
void on_change_field ();
2020-10-26 19:38:09 +01:00
public :
2018-03-06 12:34:20 +01:00
/// Call the attached m_back_to_initial_value method.
void on_back_to_initial_value ();
2018-03-16 17:25:11 +01:00
/// Call the attached m_back_to_sys_value method.
void on_back_to_sys_value ();
2017-12-13 14:45:10 +01:00
2017-12-26 23:04:54 +01:00
public :
2017-12-13 14:45:10 +01:00
/// parent wx item, opportunity to refactor (probably not necessary - data duplication)
2018-01-05 15:11:33 +01:00
wxWindow * m_parent { nullptr };
2017-12-13 14:45:10 +01:00
/// Function object to store callback passed in from owning object.
2018-01-31 14:59:44 +01:00
t_kill_focus m_on_kill_focus { nullptr };
2017-12-13 14:45:10 +01:00
/// Function object to store callback passed in from owning object.
2018-12-11 13:57:50 +01:00
t_kill_focus m_on_set_focus { nullptr };
/// Function object to store callback passed in from owning object.
2018-01-05 15:11:33 +01:00
t_change m_on_change { nullptr };
2017-12-13 14:45:10 +01:00
2018-03-16 17:25:11 +01:00
/// Function object to store callback passed in from owning object.
2018-03-06 12:34:20 +01:00
t_back_to_init m_back_to_initial_value { nullptr };
2018-03-16 17:25:11 +01:00
t_back_to_init m_back_to_sys_value { nullptr };
2018-03-06 12:34:20 +01:00
2018-01-27 17:39:00 +01:00
// This is used to avoid recursive invocation of the field change/update by wxWidgets.
2018-01-05 15:11:33 +01:00
bool m_disable_change_event { false };
2018-03-07 15:05:41 +01:00
bool m_is_modified_value { false };
2018-03-16 17:25:11 +01:00
bool m_is_nonsys_value { true };
2017-12-13 14:45:10 +01:00
/// Copy of ConfigOption for deduction purposes
2018-01-05 15:11:33 +01:00
const ConfigOptionDef m_opt { ConfigOptionDef ()};
const t_config_option_key m_opt_id ; //! {""};
2018-06-22 16:13:34 +02:00
int m_opt_idx = 0 ;
2017-12-13 14:45:10 +01:00
2020-10-23 19:17:10 +02:00
double opt_height { 0.0 };
bool parent_is_custom_ctrl { false };
2017-12-13 14:45:10 +01:00
/// Sets a value for this control.
/// subclasses should overload with a specific version
/// Postcondition: Method does not fire the on_change event.
2018-04-13 12:35:04 +02:00
virtual void set_value ( const boost :: any & value , bool change_event ) = 0 ;
2019-07-28 22:00:39 +02:00
virtual void set_last_meaningful_value () {}
virtual void set_na_value () {}
2019-01-29 15:57:22 +01:00
2017-12-13 14:45:10 +01:00
/// Gets a boost::any representing this control.
/// subclasses should overload with a specific version
2018-04-24 10:33:11 +02:00
virtual boost :: any & get_value () = 0 ;
2017-12-13 14:45:10 +01:00
2018-01-05 15:11:33 +01:00
virtual void enable () = 0 ;
virtual void disable () = 0 ;
2017-12-13 14:45:10 +01:00
2018-04-17 10:15:48 +02:00
/// Fires the enable or disable function, based on the input.
2018-01-05 15:11:33 +01:00
inline void toggle ( bool en ) { en ? enable () : disable (); }
2017-12-13 14:45:10 +01:00
2018-01-27 14:21:16 +01:00
virtual wxString get_tooltip_text ( const wxString & default_string );
2017-12-13 14:45:10 +01:00
2019-01-29 15:57:22 +01:00
void field_changed () { on_change_field (); }
2018-01-05 15:11:33 +01:00
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 ) {};
2020-09-22 11:17:43 +02:00
virtual ~ Field ();
2017-12-13 14:45:10 +01:00
/// If you don't know what you are getting back, check both methods for nullptr.
2018-01-05 15:11:33 +01:00
virtual wxSizer * getSizer () { return nullptr ; }
virtual wxWindow * getWindow () { return nullptr ; }
2017-12-13 14:45:10 +01:00
2018-04-13 12:35:04 +02:00
bool is_matched ( const std :: string & string , const std :: string & pattern );
2019-09-02 14:02:26 +02:00
void get_value_by_opt_type ( wxString & str , const bool check_value = true );
2017-12-13 14:45:10 +01:00
/// Factory method for generating new derived classes.
template < class T >
2018-12-11 13:34:37 +01:00
static t_field Create ( wxWindow * parent , const ConfigOptionDef & opt , const t_config_option_key & id ) // interface for creating shared objects
2017-12-13 14:45:10 +01:00
{
2018-01-21 21:42:06 +01:00
auto p = Slic3r :: make_unique < T > ( parent , opt , id );
2017-12-13 14:45:10 +01:00
p -> PostInitialize ();
2017-12-18 13:58:51 +01:00
return std :: move ( p ); //!p;
2017-12-13 14:45:10 +01:00
}
2018-04-16 11:03:08 +02:00
2019-04-25 01:45:00 +02:00
bool set_undo_bitmap ( const ScalableBitmap * bmp ) {
2018-04-16 11:03:08 +02:00
if ( m_undo_bitmap != bmp ) {
m_undo_bitmap = bmp ;
return true ;
}
return false ;
}
2019-04-25 01:45:00 +02:00
bool set_undo_to_sys_bitmap ( const ScalableBitmap * bmp ) {
2018-04-16 11:03:08 +02:00
if ( m_undo_to_sys_bitmap != bmp ) {
m_undo_to_sys_bitmap = bmp ;
return true ;
}
return false ;
}
2018-04-17 10:15:48 +02:00
bool set_label_colour ( const wxColour * clr ) {
if ( m_label_color != clr ) {
m_label_color = clr ;
}
return false ;
}
2018-04-24 14:11:23 +02:00
bool set_undo_tooltip ( const wxString * tip ) {
if ( m_undo_tooltip != tip ) {
m_undo_tooltip = tip ;
return true ;
}
return false ;
}
bool set_undo_to_sys_tooltip ( const wxString * tip ) {
if ( m_undo_to_sys_tooltip != tip ) {
m_undo_to_sys_tooltip = tip ;
return true ;
}
return false ;
}
2020-10-27 22:19:12 +01:00
bool * get_blink_ptr () {
return & m_blink ;
}
2020-11-02 15:28:43 +01:00
virtual void msw_rescale ();
2020-05-22 15:23:05 +02:00
void sys_color_changed ();
2019-04-13 23:46:52 +02:00
2019-05-06 15:24:50 +02:00
bool get_enter_pressed () const { return bEnterPressed ; }
void set_enter_pressed ( bool pressed ) { bEnterPressed = pressed ; }
2020-02-18 11:09:28 +01:00
// Values of width to alignments of fields
static int def_width () ;
static int def_width_wider () ;
static int def_width_thinner () ;
2020-02-12 12:08:43 +01:00
2020-10-13 12:17:39 +02:00
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 ; }
2020-10-27 22:19:12 +01:00
const bool blink () { return m_blink ; }
2020-10-13 12:17:39 +02:00
2018-04-16 11:03:08 +02:00
protected :
2018-04-24 14:11:23 +02:00
// 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.
2019-04-25 01:45:00 +02:00
const ScalableBitmap * m_undo_bitmap = nullptr ;
const wxString * m_undo_tooltip = nullptr ;
2018-04-24 14:11:23 +02:00
// 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.
2019-04-25 01:45:00 +02:00
const ScalableBitmap * m_undo_to_sys_bitmap = nullptr ;
const wxString * m_undo_to_sys_tooltip = nullptr ;
2018-04-16 11:03:08 +02:00
2020-10-27 22:19:12 +01:00
bool m_blink { false };
2018-04-17 10:15:48 +02:00
// Color for Label. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one.
2018-04-30 14:20:33 +02:00
const wxColour * m_label_color = nullptr ;
2018-04-17 10:15:48 +02:00
2018-04-24 10:33:11 +02:00
// current value
boost :: any m_value ;
2019-07-28 22:00:39 +02:00
// last maeningful value
boost :: any m_last_meaningful_value ;
2019-01-08 16:05:49 +01:00
2019-04-17 21:35:53 +02:00
int m_em_unit ;
2019-01-08 16:05:49 +01:00
bool bEnterPressed = false ;
2018-11-14 12:33:48 +01:00
2018-04-16 11:03:08 +02:00
friend class OptionsGroup ;
2017-12-13 14:45:10 +01:00
};
/// Convenience function, accepts a const reference to t_field and checks to see whether
/// or not both wx pointers are null.
inline bool is_bad_field ( const t_field & obj ) { return obj -> getSizer () == nullptr && obj -> getWindow () == nullptr ; }
/// Covenience function to determine whether this field is a valid window field.
2018-06-16 03:04:59 +02:00
inline bool is_window_field ( const t_field & obj ) { return ! is_bad_field ( obj ) && obj -> getWindow () != nullptr && obj -> getSizer () == nullptr ; }
2017-12-13 14:45:10 +01:00
/// Covenience function to determine whether this field is a valid sizer field.
inline bool is_sizer_field ( const t_field & obj ) { return ! is_bad_field ( obj ) && obj -> getSizer () != nullptr ; }
class TextCtrl : public Field {
using Field :: Field ;
2018-06-11 16:23:10 +02:00
#ifdef __WXGTK__
2018-09-05 15:03:20 +02:00
bool bChangedValueEvent = true ;
2018-09-05 09:47:36 +02:00
void change_field_value ( wxEvent & event );
2018-06-11 16:23:10 +02:00
#endif //__WXGTK__
2020-02-18 11:09:28 +01:00
#ifdef __WXOSX__
bool bKilledFocus = false ;
#endif // __WXOSX__
2017-12-13 14:45:10 +01:00
public :
2017-12-18 13:58:51 +01:00
TextCtrl ( const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( opt , id ) {}
TextCtrl ( wxWindow * parent , const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( parent , opt , id ) {}
2018-04-13 12:35:04 +02:00
~ TextCtrl () {}
2017-12-18 13:58:51 +01:00
2020-03-04 12:48:04 +01:00
void BUILD () override ;
2019-07-30 14:16:07 +02:00
bool value_was_changed ();
2019-01-08 16:05:49 +01:00
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
void propagate_value ();
2017-12-13 14:45:10 +01:00
wxWindow * window { nullptr };
2020-11-26 13:45:30 +01:00
void set_value ( const std :: string & value , bool change_event = false ) {
2018-03-15 18:06:26 +01:00
m_disable_change_event = ! change_event ;
2017-12-13 14:45:10 +01:00
dynamic_cast < wxTextCtrl *> ( window ) -> SetValue ( wxString ( value ));
2018-01-27 17:39:00 +01:00
m_disable_change_event = false ;
2017-12-13 14:45:10 +01:00
}
2020-11-26 13:45:30 +01:00
void set_value ( const boost :: any & value , bool change_event = false ) override ;
void set_last_meaningful_value () override ;
void set_na_value () override ;
2019-07-28 22:00:39 +02:00
2018-04-24 10:33:11 +02:00
boost :: any & get_value () override ;
2019-04-13 23:46:52 +02:00
2020-11-02 15:28:43 +01:00
void msw_rescale () override ;
2018-11-21 15:02:22 +01:00
2020-03-04 12:48:04 +01:00
void enable () override ;
void disable () override ;
wxWindow * getWindow () override { return window ; }
2017-12-13 14:45:10 +01:00
};
2017-12-18 13:58:51 +01:00
class CheckBox : public Field {
using Field :: Field ;
2019-07-28 22:00:39 +02:00
bool m_is_na_val { false };
2017-12-18 13:58:51 +01:00
public :
CheckBox ( const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( opt , id ) {}
CheckBox ( wxWindow * parent , const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( parent , opt , id ) {}
2018-04-13 12:35:04 +02:00
~ CheckBox () {}
2017-12-18 13:58:51 +01:00
wxWindow * window { nullptr };
void BUILD () override ;
2018-03-15 18:06:26 +01:00
void set_value ( const bool value , bool change_event = false ) {
m_disable_change_event = ! change_event ;
2017-12-18 13:58:51 +01:00
dynamic_cast < wxCheckBox *> ( window ) -> SetValue ( value );
2018-01-27 17:39:00 +01:00
m_disable_change_event = false ;
2017-12-18 13:58:51 +01:00
}
2019-07-28 22:00:39 +02:00
void set_value ( const boost :: any & value , bool change_event = false ) override ;
void set_last_meaningful_value () override ;
void set_na_value () override ;
2018-04-24 10:33:11 +02:00
boost :: any & get_value () override ;
2017-12-18 13:58:51 +01:00
2020-11-02 15:28:43 +01:00
void msw_rescale () override ;
2019-04-25 15:06:44 +02:00
2017-12-18 13:58:51 +01:00
void enable () override { dynamic_cast < wxCheckBox *> ( window ) -> Enable (); }
void disable () override { dynamic_cast < wxCheckBox *> ( window ) -> Disable (); }
wxWindow * getWindow () override { return window ; }
};
class SpinCtrl : public Field {
using Field :: Field ;
2019-05-20 13:32:36 +02:00
private :
static const int UNDEF_VALUE = INT_MIN ;
2019-08-22 10:25:19 +02:00
bool suppress_propagation { false };
2017-12-18 13:58:51 +01:00
public :
2019-05-20 13:32:36 +02:00
SpinCtrl ( const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( opt , id ), tmp_value ( UNDEF_VALUE ) {}
SpinCtrl ( wxWindow * parent , const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( parent , opt , id ), tmp_value ( UNDEF_VALUE ) {}
2018-04-13 12:35:04 +02:00
~ SpinCtrl () {}
2017-12-18 13:58:51 +01:00
int tmp_value ;
wxWindow * window { nullptr };
void BUILD () override ;
2019-01-08 16:05:49 +01:00
/// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
void propagate_value () ;
2017-12-18 13:58:51 +01:00
2018-04-13 12:35:04 +02:00
void set_value ( const std :: string & value , bool change_event = false ) {
2018-03-15 18:06:26 +01:00
m_disable_change_event = ! change_event ;
2017-12-18 13:58:51 +01:00
dynamic_cast < wxSpinCtrl *> ( window ) -> SetValue ( value );
2018-01-27 17:39:00 +01:00
m_disable_change_event = false ;
2017-12-18 13:58:51 +01:00
}
2018-04-13 12:35:04 +02:00
void set_value ( const boost :: any & value , bool change_event = false ) {
2018-03-15 18:06:26 +01:00
m_disable_change_event = ! change_event ;
2018-04-05 12:12:35 +02:00
tmp_value = boost :: any_cast < int > ( value );
2019-01-14 15:38:54 +01:00
m_value = value ;
2018-04-13 12:35:04 +02:00
dynamic_cast < wxSpinCtrl *> ( window ) -> SetValue ( tmp_value );
2018-01-27 17:39:00 +01:00
m_disable_change_event = false ;
2017-12-18 13:58:51 +01:00
}
2019-05-20 13:32:36 +02:00
2018-04-24 10:33:11 +02:00
boost :: any & get_value () override {
2019-05-20 13:32:36 +02:00
int value = static_cast < wxSpinCtrl *> ( window ) -> GetValue ();
return m_value = value ;
2017-12-18 13:58:51 +01:00
}
2020-11-02 15:28:43 +01:00
void msw_rescale () override ;
2019-04-13 23:46:52 +02:00
2017-12-18 13:58:51 +01:00
void enable () override { dynamic_cast < wxSpinCtrl *> ( window ) -> Enable (); }
void disable () override { dynamic_cast < wxSpinCtrl *> ( window ) -> Disable (); }
wxWindow * getWindow () override { return window ; }
};
class Choice : public Field {
using Field :: Field ;
public :
Choice ( const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( opt , id ) {}
Choice ( wxWindow * parent , const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( parent , opt , id ) {}
2018-04-13 12:35:04 +02:00
~ Choice () {}
2017-12-18 13:58:51 +01:00
wxWindow * window { nullptr };
2017-12-26 23:04:54 +01:00
void BUILD () override ;
2017-12-18 13:58:51 +01:00
2019-03-07 16:36:39 +01:00
/* Under OSX: wxBitmapComboBox->GetWindowStyle() returns some weard value,
* so let use a flag, which has TRUE value for a control without wxCB_READONLY style
*/
2020-11-24 18:44:13 +01:00
bool m_is_editable { false };
bool m_is_dropped { false };
bool m_suppress_scroll { false };
int m_last_selected { wxNOT_FOUND };
2019-03-07 16:36:39 +01:00
2017-12-18 13:58:51 +01:00
void set_selection ();
2018-04-13 12:35:04 +02:00
void set_value ( const std :: string & value , bool change_event = false );
2020-11-26 13:45:30 +01:00
void set_value ( const boost :: any & value , bool change_event = false ) override ;
2018-04-13 12:35:04 +02:00
void set_values ( const std :: vector < std :: string > & values );
2020-10-28 09:51:05 +01:00
void set_values ( const wxArrayString & values );
2018-04-24 10:33:11 +02:00
boost :: any & get_value () override ;
2017-12-18 13:58:51 +01:00
2020-11-02 15:28:43 +01:00
void msw_rescale () override ;
2019-04-13 23:46:52 +02:00
2020-10-16 21:18:23 +02:00
void enable () override ; //{ dynamic_cast<wxBitmapComboBox*>(window)->Enable(); };
void disable () override ; //{ dynamic_cast<wxBitmapComboBox*>(window)->Disable(); };
2017-12-18 13:58:51 +01:00
wxWindow * getWindow () override { return window ; }
2020-11-24 18:44:13 +01:00
void suppress_scroll ();
2017-12-18 13:58:51 +01:00
};
2017-12-13 14:45:10 +01:00
2017-12-22 11:50:28 +01:00
class ColourPicker : public Field {
using Field :: Field ;
2019-08-13 09:37:44 +02:00
void set_undef_value ( wxColourPickerCtrl * field );
2017-12-22 11:50:28 +01:00
public :
ColourPicker ( const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( opt , id ) {}
ColourPicker ( wxWindow * parent , const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( parent , opt , id ) {}
2018-04-13 12:35:04 +02:00
~ ColourPicker () {}
2017-12-22 11:50:28 +01:00
wxWindow * window { nullptr };
void BUILD () override ;
2018-04-13 12:35:04 +02:00
void set_value ( const std :: string & value , bool change_event = false ) {
2018-03-15 18:06:26 +01:00
m_disable_change_event = ! change_event ;
2018-01-27 17:39:00 +01:00
dynamic_cast < wxColourPickerCtrl *> ( window ) -> SetColour ( value );
m_disable_change_event = false ;
2017-12-22 11:50:28 +01:00
}
2019-08-13 09:37:44 +02:00
void set_value ( const boost :: any & value , bool change_event = false ) override ;
2018-04-24 10:33:11 +02:00
boost :: any & get_value () override ;
2020-11-02 15:28:43 +01:00
void msw_rescale () override ;
2017-12-22 11:50:28 +01:00
void enable () override { dynamic_cast < wxColourPickerCtrl *> ( window ) -> Enable (); };
void disable () override { dynamic_cast < wxColourPickerCtrl *> ( window ) -> Disable (); };
wxWindow * getWindow () override { return window ; }
};
2018-01-25 13:46:04 +01:00
class PointCtrl : public Field {
2017-12-22 11:50:28 +01:00
using Field :: Field ;
public :
2018-01-25 13:46:04 +01:00
PointCtrl ( const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( opt , id ) {}
PointCtrl ( wxWindow * parent , const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( parent , opt , id ) {}
2018-04-13 12:35:04 +02:00
~ PointCtrl () {}
2017-12-22 11:50:28 +01:00
wxSizer * sizer { nullptr };
2018-04-13 12:35:04 +02:00
wxTextCtrl * x_textctrl { nullptr };
wxTextCtrl * y_textctrl { nullptr };
2017-12-22 11:50:28 +01:00
void BUILD () override ;
2020-04-01 19:01:00 +02:00
bool value_was_changed ( wxTextCtrl * win );
2019-01-08 16:05:49 +01:00
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
void propagate_value ( wxTextCtrl * win );
2018-08-21 21:05:24 +02:00
void set_value ( const Vec2d & value , bool change_event = false );
2020-11-26 13:45:30 +01:00
void set_value ( const boost :: any & value , bool change_event = false ) override ;
2018-04-24 10:33:11 +02:00
boost :: any & get_value () override ;
2017-12-22 11:50:28 +01:00
2020-11-02 15:28:43 +01:00
void msw_rescale () override ;
2019-04-17 21:35:53 +02:00
2017-12-26 23:04:54 +01:00
void enable () override {
x_textctrl -> Enable ();
2018-04-13 12:35:04 +02:00
y_textctrl -> Enable (); }
2017-12-26 23:04:54 +01:00
void disable () override {
x_textctrl -> Disable ();
2018-04-13 12:35:04 +02:00
y_textctrl -> Disable (); }
2017-12-22 11:50:28 +01:00
wxSizer * getSizer () override { return sizer ; }
2020-03-21 19:45:55 +01:00
wxWindow * getWindow () override { return dynamic_cast < wxWindow *> ( x_textctrl ); }
2017-12-22 11:50:28 +01:00
};
2018-06-21 16:15:56 +02:00
class StaticText : public Field {
using Field :: Field ;
public :
StaticText ( const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( opt , id ) {}
StaticText ( wxWindow * parent , const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( parent , opt , id ) {}
~ StaticText () {}
wxWindow * window { nullptr };
void BUILD () override ;
void set_value ( const std :: string & value , bool change_event = false ) {
m_disable_change_event = ! change_event ;
2019-05-09 15:13:14 +02:00
dynamic_cast < wxStaticText *> ( window ) -> SetLabel ( wxString :: FromUTF8 ( value . data ()));
2018-06-21 16:15:56 +02:00
m_disable_change_event = false ;
}
2020-11-26 13:45:30 +01:00
void set_value ( const boost :: any & value , bool change_event = false ) override {
2018-06-21 16:15:56 +02:00
m_disable_change_event = ! change_event ;
dynamic_cast < wxStaticText *> ( window ) -> SetLabel ( boost :: any_cast < wxString > ( value ));
m_disable_change_event = false ;
}
boost :: any & get_value () override { return m_value ; }
2020-11-02 15:28:43 +01:00
void msw_rescale () override ;
2019-04-13 23:46:52 +02:00
2018-07-29 12:19:08 +02:00
void enable () override { dynamic_cast < wxStaticText *> ( window ) -> Enable (); };
void disable () override { dynamic_cast < wxStaticText *> ( window ) -> Disable (); };
2018-06-21 16:15:56 +02:00
wxWindow * getWindow () override { return window ; }
};
2018-06-12 23:42:01 +02:00
class SliderCtrl : public Field {
using Field :: Field ;
public :
SliderCtrl ( const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( opt , id ) {}
SliderCtrl ( wxWindow * parent , const ConfigOptionDef & opt , const t_config_option_key & id ) : Field ( parent , opt , id ) {}
~ SliderCtrl () {}
wxSizer * m_sizer { nullptr };
wxTextCtrl * m_textctrl { nullptr };
wxSlider * m_slider { nullptr };
int m_scale = 10 ;
void BUILD () override ;
void set_value ( const int value , bool change_event = false );
2020-11-26 13:45:30 +01:00
void set_value ( const boost :: any & value , bool change_event = false ) override ;
2018-06-12 23:42:01 +02:00
boost :: any & get_value () override ;
void enable () override {
m_slider -> Enable ();
m_textctrl -> Enable ();
m_textctrl -> SetEditable ( true );
}
void disable () override {
m_slider -> Disable ();
m_textctrl -> Disable ();
m_textctrl -> SetEditable ( false );
}
wxSizer * getSizer () override { return m_sizer ; }
2018-06-16 03:04:59 +02:00
wxWindow * getWindow () override { return dynamic_cast < wxWindow *> ( m_slider ); }
2018-06-12 23:42:01 +02:00
};
2017-12-18 13:58:51 +01:00
} // GUI
} // Slic3r
2018-03-12 16:04:32 +01:00
#endif /* SLIC3R_GUI_FIELD_HPP */