2018-02-02 11:38:35 +00:00
# include "wxExtensions.hpp"
2019-04-05 16:53:02 +00:00
# include <stdexcept>
2018-11-26 13:41:58 +00:00
# include "libslic3r/Utils.hpp"
# include "libslic3r/Model.hpp"
2018-05-10 14:36:12 +00:00
# include <wx/sizer.h>
# include <wx/statline.h>
2018-08-21 00:03:10 +00:00
# include <wx/dcclient.h>
2018-08-21 15:47:05 +00:00
# include <wx/numformatter.h>
2018-11-26 13:41:58 +00:00
2019-04-04 07:20:11 +00:00
# include <boost/algorithm/string/replace.hpp>
2018-11-26 13:41:58 +00:00
# include "BitmapCache.hpp"
2019-01-07 18:17:10 +00:00
# include "GUI.hpp"
2018-10-05 21:29:15 +00:00
# include "GUI_App.hpp"
# include "GUI_ObjectList.hpp"
2019-01-10 16:24:23 +00:00
# include "libslic3r/GCode/PreviewData.hpp"
2019-02-11 13:14:35 +00:00
# include "I18N.hpp"
2019-04-17 19:35:53 +00:00
# include "GUI_Utils.hpp"
2018-05-10 14:36:12 +00:00
2019-01-07 18:17:10 +00:00
using Slic3r : : GUI : : from_u8 ;
2018-11-07 13:44:47 +00:00
wxDEFINE_EVENT ( wxCUSTOMEVT_TICKSCHANGED , wxEvent ) ;
2018-11-12 12:47:24 +00:00
wxDEFINE_EVENT ( wxCUSTOMEVT_LAST_VOLUME_IS_DELETED , wxCommandEvent ) ;
2018-11-07 13:44:47 +00:00
2018-10-17 10:17:25 +00:00
wxMenuItem * append_menu_item ( wxMenu * menu , int id , const wxString & string , const wxString & description ,
2018-12-06 13:49:14 +00:00
std : : function < void ( wxCommandEvent & event ) > cb , const wxBitmap & icon , wxEvtHandler * event_handler )
2018-10-17 10:17:25 +00:00
{
if ( id = = wxID_ANY )
id = wxNewId ( ) ;
wxMenuItem * item = menu - > Append ( id , string , description ) ;
2018-12-06 13:49:14 +00:00
item - > SetBitmap ( icon ) ;
2018-10-17 10:17:25 +00:00
2018-12-06 13:49:14 +00:00
# ifdef __WXMSW__
2018-12-07 16:50:48 +00:00
if ( event_handler ! = nullptr & & event_handler ! = menu )
2018-10-18 12:42:21 +00:00
event_handler - > Bind ( wxEVT_MENU , cb , id ) ;
else
2018-12-07 16:50:48 +00:00
# endif // __WXMSW__
2018-10-18 12:42:21 +00:00
menu - > Bind ( wxEVT_MENU , cb , id ) ;
return item ;
}
2018-12-06 13:49:14 +00:00
wxMenuItem * append_menu_item ( wxMenu * menu , int id , const wxString & string , const wxString & description ,
std : : function < void ( wxCommandEvent & event ) > cb , const std : : string & icon , wxEvtHandler * event_handler )
{
2019-04-05 16:53:02 +00:00
const wxBitmap & bmp = ! icon . empty ( ) ? create_scaled_bitmap ( nullptr , icon ) : wxNullBitmap ; // FIXME: pass window ptr
2018-12-06 13:49:14 +00:00
return append_menu_item ( menu , id , string , description , cb , bmp , event_handler ) ;
}
2018-10-18 12:42:21 +00:00
wxMenuItem * append_submenu ( wxMenu * menu , wxMenu * sub_menu , int id , const wxString & string , const wxString & description , const std : : string & icon )
{
if ( id = = wxID_ANY )
id = wxNewId ( ) ;
wxMenuItem * item = new wxMenuItem ( menu , id , string , description ) ;
if ( ! icon . empty ( ) )
2019-04-05 16:53:02 +00:00
item - > SetBitmap ( create_scaled_bitmap ( nullptr , icon ) ) ; // FIXME: pass window ptr
2018-10-18 12:42:21 +00:00
item - > SetSubMenu ( sub_menu ) ;
menu - > Append ( item ) ;
2018-10-17 10:17:25 +00:00
return item ;
}
2019-03-28 15:28:34 +00:00
wxMenuItem * append_menu_radio_item ( wxMenu * menu , int id , const wxString & string , const wxString & description ,
std : : function < void ( wxCommandEvent & event ) > cb , wxEvtHandler * event_handler )
{
if ( id = = wxID_ANY )
id = wxNewId ( ) ;
wxMenuItem * item = menu - > AppendRadioItem ( id , string , description ) ;
# ifdef __WXMSW__
if ( event_handler ! = nullptr & & event_handler ! = menu )
event_handler - > Bind ( wxEVT_MENU , cb , id ) ;
else
# endif // __WXMSW__
menu - > Bind ( wxEVT_MENU , cb , id ) ;
return item ;
}
2018-02-20 13:25:40 +00:00
const unsigned int wxCheckListBoxComboPopup : : DefaultWidth = 200 ;
const unsigned int wxCheckListBoxComboPopup : : DefaultHeight = 200 ;
2018-02-20 13:44:00 +00:00
const unsigned int wxCheckListBoxComboPopup : : DefaultItemHeight = 18 ;
2018-02-02 11:38:35 +00:00
bool wxCheckListBoxComboPopup : : Create ( wxWindow * parent )
{
2018-02-06 11:43:25 +00:00
return wxCheckListBox : : Create ( parent , wxID_HIGHEST + 1 , wxPoint ( 0 , 0 ) ) ;
2018-02-02 11:38:35 +00:00
}
wxWindow * wxCheckListBoxComboPopup : : GetControl ( )
{
return this ;
}
void wxCheckListBoxComboPopup : : SetStringValue ( const wxString & value )
{
m_text = value ;
}
wxString wxCheckListBoxComboPopup : : GetStringValue ( ) const
{
return m_text ;
}
wxSize wxCheckListBoxComboPopup : : GetAdjustedSize ( int minWidth , int prefHeight , int maxHeight )
{
// matches owner wxComboCtrl's width
2018-02-20 13:25:40 +00:00
// and sets height dinamically in dependence of contained items count
2018-02-02 11:38:35 +00:00
wxComboCtrl * cmb = GetComboCtrl ( ) ;
if ( cmb ! = nullptr )
{
wxSize size = GetComboCtrl ( ) - > GetSize ( ) ;
2018-02-20 13:25:40 +00:00
unsigned int count = GetCount ( ) ;
if ( count > 0 )
2018-02-20 13:44:00 +00:00
size . SetHeight ( count * DefaultItemHeight ) ;
2018-02-20 13:25:40 +00:00
else
size . SetHeight ( DefaultHeight ) ;
2018-02-02 11:38:35 +00:00
return size ;
}
else
2018-02-20 13:25:40 +00:00
return wxSize ( DefaultWidth , DefaultHeight ) ;
}
void wxCheckListBoxComboPopup : : OnKeyEvent ( wxKeyEvent & evt )
{
2018-02-22 07:59:47 +00:00
// filters out all the keys which are not working properly
switch ( evt . GetKeyCode ( ) )
{
case WXK_LEFT :
case WXK_UP :
case WXK_RIGHT :
case WXK_DOWN :
case WXK_PAGEUP :
case WXK_PAGEDOWN :
case WXK_END :
case WXK_HOME :
case WXK_NUMPAD_LEFT :
case WXK_NUMPAD_UP :
case WXK_NUMPAD_RIGHT :
case WXK_NUMPAD_DOWN :
case WXK_NUMPAD_PAGEUP :
case WXK_NUMPAD_PAGEDOWN :
case WXK_NUMPAD_END :
case WXK_NUMPAD_HOME :
{
break ;
}
default :
{
evt . Skip ( ) ;
break ;
}
}
2018-02-02 11:38:35 +00:00
}
void wxCheckListBoxComboPopup : : OnCheckListBox ( wxCommandEvent & evt )
{
// forwards the checklistbox event to the owner wxComboCtrl
2018-05-17 08:23:02 +00:00
if ( m_check_box_events_status = = OnCheckListBoxFunction : : FreeToProceed )
2018-02-02 11:38:35 +00:00
{
2018-05-17 08:23:02 +00:00
wxComboCtrl * cmb = GetComboCtrl ( ) ;
if ( cmb ! = nullptr ) {
wxCommandEvent event ( wxEVT_CHECKLISTBOX , cmb - > GetId ( ) ) ;
event . SetEventObject ( cmb ) ;
cmb - > ProcessWindowEvent ( event ) ;
}
2018-02-02 11:38:35 +00:00
}
2018-02-20 14:22:30 +00:00
evt . Skip ( ) ;
2018-05-17 08:23:02 +00:00
# ifndef _WIN32 // events are sent differently on OSX+Linux vs Win (more description in header file)
if ( m_check_box_events_status = = OnCheckListBoxFunction : : RefuseToProceed )
// this happens if the event was resent by OnListBoxSelection - next call to OnListBoxSelection is due to user clicking the text, so the function should
// explicitly change the state on the checkbox
m_check_box_events_status = OnCheckListBoxFunction : : WasRefusedLastTime ;
else
// if the user clicked the checkbox square, this event was sent before OnListBoxSelection was called, so we don't want it to resend it
m_check_box_events_status = OnCheckListBoxFunction : : RefuseToProceed ;
# endif
2018-02-02 11:38:35 +00:00
}
void wxCheckListBoxComboPopup : : OnListBoxSelection ( wxCommandEvent & evt )
{
// transforms list box item selection event into checklistbox item toggle event
int selId = GetSelection ( ) ;
if ( selId ! = wxNOT_FOUND )
{
2018-05-17 08:23:02 +00:00
# ifndef _WIN32
if ( m_check_box_events_status = = OnCheckListBoxFunction : : RefuseToProceed )
# endif
Check ( ( unsigned int ) selId , ! IsChecked ( ( unsigned int ) selId ) ) ;
m_check_box_events_status = OnCheckListBoxFunction : : FreeToProceed ; // so the checkbox reacts to square-click the next time
2018-02-02 11:38:35 +00:00
2018-05-17 08:23:02 +00:00
SetSelection ( wxNOT_FOUND ) ;
2018-02-02 11:38:35 +00:00
wxCommandEvent event ( wxEVT_CHECKLISTBOX , GetId ( ) ) ;
event . SetInt ( selId ) ;
event . SetEventObject ( this ) ;
ProcessEvent ( event ) ;
}
}
2018-04-06 11:37:00 +00:00
// *** wxDataViewTreeCtrlComboPopup ***
const unsigned int wxDataViewTreeCtrlComboPopup : : DefaultWidth = 270 ;
const unsigned int wxDataViewTreeCtrlComboPopup : : DefaultHeight = 200 ;
const unsigned int wxDataViewTreeCtrlComboPopup : : DefaultItemHeight = 22 ;
bool wxDataViewTreeCtrlComboPopup : : Create ( wxWindow * parent )
{
2018-04-09 14:50:17 +00:00
return wxDataViewTreeCtrl : : Create ( parent , wxID_ANY /*HIGHEST + 1*/ , wxPoint ( 0 , 0 ) , wxDefaultSize /*wxSize(270, -1)*/ , wxDV_NO_HEADER ) ;
2018-04-06 11:37:00 +00:00
}
2018-04-09 10:41:25 +00:00
/*
2018-04-06 11:37:00 +00:00
wxSize wxDataViewTreeCtrlComboPopup : : GetAdjustedSize ( int minWidth , int prefHeight , int maxHeight )
{
// matches owner wxComboCtrl's width
// and sets height dinamically in dependence of contained items count
2018-04-06 13:42:52 +00:00
wxComboCtrl * cmb = GetComboCtrl ( ) ;
if ( cmb ! = nullptr )
{
wxSize size = GetComboCtrl ( ) - > GetSize ( ) ;
if ( m_cnt_open_items > 0 )
size . SetHeight ( m_cnt_open_items * DefaultItemHeight ) ;
else
size . SetHeight ( DefaultHeight ) ;
return size ;
}
else
return wxSize ( DefaultWidth , DefaultHeight ) ;
2018-04-06 11:37:00 +00:00
}
2018-04-09 10:41:25 +00:00
*/
2018-04-06 11:37:00 +00:00
void wxDataViewTreeCtrlComboPopup : : OnKeyEvent ( wxKeyEvent & evt )
{
// filters out all the keys which are not working properly
if ( evt . GetKeyCode ( ) = = WXK_UP )
{
return ;
}
else if ( evt . GetKeyCode ( ) = = WXK_DOWN )
{
return ;
}
else
{
evt . Skip ( ) ;
return ;
}
}
void wxDataViewTreeCtrlComboPopup : : OnDataViewTreeCtrlSelection ( wxCommandEvent & evt )
{
wxComboCtrl * cmb = GetComboCtrl ( ) ;
auto selected = GetItemText ( GetSelection ( ) ) ;
cmb - > SetText ( selected ) ;
}
2018-05-04 16:32:20 +00:00
2019-04-26 08:52:38 +00:00
// edit tooltip : change Slic3r to SLIC3R_APP_KEY
// Temporary workaround for localization
void edit_tooltip ( wxString & tooltip )
{
tooltip . Replace ( " Slic3r " , SLIC3R_APP_KEY , true ) ;
}
2019-04-25 13:06:44 +00:00
/* Function for rescale of buttons in Dialog under MSW if dpi is changed.
* btn_ids - vector of buttons identifiers
*/
void msw_buttons_rescale ( wxDialog * dlg , const int em_unit , const std : : vector < int > & btn_ids )
{
const wxSize & btn_size = wxSize ( - 1 , int ( 2.5f * em_unit + 0.5f ) ) ;
for ( int btn_id : btn_ids ) {
// There is a case [FirmwareDialog], when we have wxControl instead of wxButton
// so let casting everything to the wxControl
wxControl * btn = static_cast < wxControl * > ( dlg - > FindWindowById ( btn_id , dlg ) ) ;
if ( btn )
btn - > SetMinSize ( btn_size ) ;
}
}
2019-04-17 19:35:53 +00:00
/* Function for getting of em_unit value from correct parent.
* In most of cases it is m_em_unit value from GUI_App ,
* but for DPIDialogs it ' s its own value .
* This value will be used to correct rescale after moving between
* Displays with different HDPI */
int em_unit ( wxWindow * win )
{
2019-04-18 13:05:17 +00:00
if ( win )
{
Slic3r : : GUI : : DPIDialog * dlg = dynamic_cast < Slic3r : : GUI : : DPIDialog * > ( Slic3r : : GUI : : find_toplevel_parent ( win ) ) ;
2019-04-17 19:35:53 +00:00
if ( dlg )
2019-04-18 13:05:17 +00:00
return dlg - > em_unit ( ) ;
2019-04-17 19:35:53 +00:00
}
return Slic3r : : GUI : : wxGetApp ( ) . em_unit ( ) ;
}
2018-07-04 06:54:30 +00:00
2019-04-05 09:18:13 +00:00
// If an icon has horizontal orientation (width > height) call this function with is_horizontal = true
2019-04-09 12:18:03 +00:00
wxBitmap create_scaled_bitmap ( wxWindow * win , const std : : string & bmp_name_in , const int px_cnt /* = 16*/ , const bool is_horizontal /* = false*/ )
2019-02-06 14:29:13 +00:00
{
2019-04-08 07:37:23 +00:00
static Slic3r : : GUI : : BitmapCache cache ;
2019-04-05 09:18:13 +00:00
2019-04-09 15:39:04 +00:00
# ifdef __APPLE__
2019-04-05 16:53:02 +00:00
const float scale_factor = win ! = nullptr ? win - > GetContentScaleFactor ( ) : 1.0f ;
2019-04-09 15:39:04 +00:00
# else
( void ) ( win ) ;
const float scale_factor = 1.0f ;
# endif
2019-04-05 16:53:02 +00:00
2019-04-05 09:18:13 +00:00
unsigned int height , width = height = 0 ;
unsigned int & scale_base = is_horizontal ? width : height ;
2019-04-05 16:53:02 +00:00
2019-04-17 19:35:53 +00:00
scale_base = ( unsigned int ) ( em_unit ( win ) * px_cnt * 0.1f + 0.5f ) ;
2019-04-08 07:37:23 +00:00
2019-04-05 09:18:13 +00:00
std : : string bmp_name = bmp_name_in ;
2019-04-09 12:18:03 +00:00
boost : : replace_last ( bmp_name , " .png " , " " ) ;
2019-04-05 16:53:02 +00:00
// Try loading an SVG first, then PNG if SVG is not found:
2019-04-09 12:18:03 +00:00
wxBitmap * bmp = cache . load_svg ( bmp_name , width , height , scale_factor ) ;
if ( bmp = = nullptr ) {
bmp = cache . load_png ( bmp_name , width , height ) ;
2019-04-05 16:53:02 +00:00
}
2019-04-09 12:18:03 +00:00
if ( bmp = = nullptr ) {
2019-04-05 16:53:02 +00:00
// Neither SVG nor PNG has been found, raise error
throw std : : runtime_error ( " Could not load bitmap: " + bmp_name ) ;
}
2019-04-08 07:37:23 +00:00
2019-04-04 07:20:11 +00:00
return * bmp ;
2019-02-06 14:29:13 +00:00
}
2019-04-08 07:37:23 +00:00
// *****************************************************************************
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
// ObjectDataViewModelNode
2019-04-08 07:37:23 +00:00
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
void ObjectDataViewModelNode : : set_action_icon ( )
2019-04-16 08:05:45 +00:00
{
m_action_icon_name = m_type = = itObject ? " advanced_plus " :
m_type = = itVolume ? " cog " : " set_separate_obj " ;
m_action_icon = create_scaled_bitmap ( nullptr , m_action_icon_name ) ; // FIXME: pass window ptr
}
2018-07-04 06:54:30 +00:00
2018-09-17 13:12:13 +00:00
Slic3r : : GUI : : BitmapCache * m_bitmap_cache = nullptr ;
2019-04-24 23:45:00 +00:00
void ObjectDataViewModelNode : : update_settings_digest_bitmaps ( )
2019-04-16 08:05:45 +00:00
{
m_bmp = m_empty_bmp ;
std : : map < std : : string , wxBitmap > & categories_icon = Slic3r : : GUI : : wxGetApp ( ) . obj_list ( ) - > CATEGORY_ICON ;
std : : string scaled_bitmap_name = m_name . ToUTF8 ( ) . data ( ) ;
scaled_bitmap_name + = " -em " + std : : to_string ( Slic3r : : GUI : : wxGetApp ( ) . em_unit ( ) ) ;
wxBitmap * bmp = m_bitmap_cache - > find ( scaled_bitmap_name ) ;
if ( bmp = = nullptr ) {
std : : vector < wxBitmap > bmps ;
for ( auto & cat : m_opt_categories )
bmps . emplace_back ( categories_icon . find ( cat ) = = categories_icon . end ( ) ?
wxNullBitmap : categories_icon . at ( cat ) ) ;
bmp = m_bitmap_cache - > insert ( scaled_bitmap_name , bmps ) ;
}
m_bmp = * bmp ;
}
2019-04-24 23:45:00 +00:00
bool ObjectDataViewModelNode : : update_settings_digest ( const std : : vector < std : : string > & categories )
2018-09-17 13:12:13 +00:00
{
2018-10-16 09:08:37 +00:00
if ( m_type ! = itSettings | | m_opt_categories = = categories )
2018-09-17 13:12:13 +00:00
return false ;
m_opt_categories = categories ;
m_name = wxEmptyString ;
for ( auto & cat : m_opt_categories )
m_name + = cat + " ; " ;
2018-11-23 10:54:06 +00:00
if ( ! m_name . IsEmpty ( ) )
m_name . erase ( m_name . Length ( ) - 2 , 2 ) ; // Delete last "; "
2019-04-16 08:05:45 +00:00
update_settings_digest_bitmaps ( ) ;
2018-09-17 13:12:13 +00:00
return true ;
}
2019-04-24 23:45:00 +00:00
void ObjectDataViewModelNode : : msw_rescale ( )
2019-04-16 08:05:45 +00:00
{
if ( ! m_action_icon_name . empty ( ) )
m_action_icon = create_scaled_bitmap ( nullptr , m_action_icon_name ) ;
if ( ! m_opt_categories . empty ( ) )
update_settings_digest_bitmaps ( ) ;
}
2018-05-04 16:32:20 +00:00
// *****************************************************************************
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
// ObjectDataViewModel
2018-05-04 16:32:20 +00:00
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
ObjectDataViewModel : : ObjectDataViewModel ( )
2018-09-17 13:12:13 +00:00
{
m_bitmap_cache = new Slic3r : : GUI : : BitmapCache ;
}
2019-04-24 23:45:00 +00:00
ObjectDataViewModel : : ~ ObjectDataViewModel ( )
2018-09-17 13:12:13 +00:00
{
for ( auto object : m_objects )
delete object ;
delete m_bitmap_cache ;
m_bitmap_cache = nullptr ;
}
2019-04-29 13:27:59 +00:00
wxDataViewItem ObjectDataViewModel : : Add ( const wxString & name ,
const int extruder ,
const bool has_errors /* = false*/ )
2018-05-04 16:32:20 +00:00
{
2018-12-11 07:53:18 +00:00
const wxString extruder_str = extruder = = 0 ? " default " : wxString : : Format ( " %d " , extruder ) ;
2019-04-24 23:45:00 +00:00
auto root = new ObjectDataViewModelNode ( name , extruder_str ) ;
2019-04-29 13:27:59 +00:00
// Add error icon if detected auto-repaire
if ( has_errors )
root - > m_bmp = * m_warning_bmp ;
2018-05-30 15:52:28 +00:00
m_objects . push_back ( root ) ;
2018-05-29 20:45:35 +00:00
// notify control
wxDataViewItem child ( ( void * ) root ) ;
wxDataViewItem parent ( ( void * ) NULL ) ;
2019-04-29 13:27:59 +00:00
2018-05-29 20:45:35 +00:00
ItemAdded ( parent , child ) ;
2018-05-30 15:52:28 +00:00
return child ;
2018-05-29 20:45:35 +00:00
}
2019-04-24 23:45:00 +00:00
wxDataViewItem ObjectDataViewModel : : AddVolumeChild ( const wxDataViewItem & parent_item ,
const wxString & name ,
const Slic3r : : ModelVolumeType volume_type ,
2019-04-29 13:27:59 +00:00
const bool has_errors /* = false*/ ,
2019-04-24 23:45:00 +00:00
const int extruder /* = 0*/ ,
const bool create_frst_child /* = true*/ )
2018-05-29 20:45:35 +00:00
{
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * root = ( ObjectDataViewModelNode * ) parent_item . GetID ( ) ;
2018-05-30 15:52:28 +00:00
if ( ! root ) return wxDataViewItem ( 0 ) ;
2018-05-29 20:45:35 +00:00
2018-11-02 22:27:31 +00:00
wxString extruder_str = extruder = = 0 ? " default " : wxString : : Format ( " %d " , extruder ) ;
2018-08-15 11:59:33 +00:00
2018-11-06 10:39:38 +00:00
// because of istance_root is a last item of the object
int insert_position = root - > GetChildCount ( ) - 1 ;
if ( insert_position < 0 | | root - > GetNthChild ( insert_position ) - > m_type ! = itInstanceRoot )
insert_position = - 1 ;
2019-04-29 13:27:59 +00:00
const bool obj_errors = root - > m_bmp . IsOk ( ) ;
2018-10-18 08:40:26 +00:00
if ( create_frst_child & & root - > m_volumes_cnt = = 0 )
2019-04-10 07:27:42 +00:00
{
2019-04-29 13:27:59 +00:00
const Slic3r : : ModelVolumeType type = Slic3r : : ModelVolumeType : : MODEL_PART ;
const auto node = new ObjectDataViewModelNode ( root , root - > m_name , GetVolumeIcon ( type , obj_errors ) , extruder_str , 0 ) ;
node - > m_volume_type = type ;
2018-11-06 10:39:38 +00:00
insert_position < 0 ? root - > Append ( node ) : root - > Insert ( node , insert_position ) ;
2018-05-29 22:36:44 +00:00
// notify control
2018-09-17 13:12:13 +00:00
const wxDataViewItem child ( ( void * ) node ) ;
2018-05-29 22:36:44 +00:00
ItemAdded ( parent_item , child ) ;
2018-10-18 08:40:26 +00:00
root - > m_volumes_cnt + + ;
2018-11-06 10:39:38 +00:00
if ( insert_position > 0 ) insert_position + + ;
2018-10-18 08:40:26 +00:00
}
2018-09-17 13:12:13 +00:00
2019-04-29 13:27:59 +00:00
const auto node = new ObjectDataViewModelNode ( root , name , GetVolumeIcon ( volume_type , has_errors ) , extruder_str , root - > m_volumes_cnt ) ;
2018-11-06 10:39:38 +00:00
insert_position < 0 ? root - > Append ( node ) : root - > Insert ( node , insert_position ) ;
2019-04-29 13:27:59 +00:00
// if part with errors is added, but object wasn't marked, then mark it
if ( ! obj_errors & & has_errors )
root - > SetBitmap ( * m_warning_bmp ) ;
2018-05-29 20:45:35 +00:00
// notify control
2018-09-17 13:12:13 +00:00
const wxDataViewItem child ( ( void * ) node ) ;
2018-10-18 08:40:26 +00:00
ItemAdded ( parent_item , child ) ;
root - > m_volumes_cnt + + ;
2019-04-16 08:05:45 +00:00
node - > m_volume_type = volume_type ;
2018-05-30 15:52:28 +00:00
return child ;
2018-05-29 20:45:35 +00:00
}
2019-04-24 23:45:00 +00:00
wxDataViewItem ObjectDataViewModel : : AddSettingsChild ( const wxDataViewItem & parent_item )
2018-09-17 13:12:13 +00:00
{
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * root = ( ObjectDataViewModelNode * ) parent_item . GetID ( ) ;
2018-09-17 13:12:13 +00:00
if ( ! root ) return wxDataViewItem ( 0 ) ;
2019-04-24 23:45:00 +00:00
const auto node = new ObjectDataViewModelNode ( root , itSettings ) ;
2018-09-17 13:12:13 +00:00
root - > Insert ( node , 0 ) ;
// notify control
const wxDataViewItem child ( ( void * ) node ) ;
ItemAdded ( parent_item , child ) ;
return child ;
}
2019-04-24 23:45:00 +00:00
int get_istances_root_idx ( ObjectDataViewModelNode * parent_node )
2018-10-18 08:40:26 +00:00
{
2018-11-06 10:39:38 +00:00
// because of istance_root is a last item of the object
const int inst_root_idx = parent_node - > GetChildCount ( ) - 1 ;
2019-04-24 23:45:00 +00:00
if ( inst_root_idx < 0 | | parent_node - > GetNthChild ( inst_root_idx ) - > GetType ( ) = = itInstanceRoot )
2018-11-06 10:39:38 +00:00
return inst_root_idx ;
return - 1 ;
2018-10-18 08:40:26 +00:00
}
2019-04-24 23:45:00 +00:00
wxDataViewItem ObjectDataViewModel : : AddInstanceChild ( const wxDataViewItem & parent_item , size_t num )
2018-10-18 08:40:26 +00:00
{
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * parent_node = ( ObjectDataViewModelNode * ) parent_item . GetID ( ) ;
2018-10-18 08:40:26 +00:00
if ( ! parent_node ) return wxDataViewItem ( 0 ) ;
// Check and create/get instances root node
const int inst_root_id = get_istances_root_idx ( parent_node ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * inst_root_node = inst_root_id < 0 ?
new ObjectDataViewModelNode ( parent_node , itInstanceRoot ) :
2018-10-18 08:40:26 +00:00
parent_node - > GetNthChild ( inst_root_id ) ;
const wxDataViewItem inst_root_item ( ( void * ) inst_root_node ) ;
if ( inst_root_id < 0 ) {
2018-11-06 10:39:38 +00:00
parent_node - > Append ( inst_root_node ) ;
2018-10-18 08:40:26 +00:00
// notify control
ItemAdded ( parent_item , inst_root_item ) ;
2018-11-07 12:40:24 +00:00
// if (num == 1) num++;
2018-10-18 08:40:26 +00:00
}
// Add instance nodes
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * instance_node = nullptr ;
2018-10-18 08:40:26 +00:00
size_t counter = 0 ;
2018-10-31 11:56:08 +00:00
while ( counter < num ) {
2019-04-24 23:45:00 +00:00
instance_node = new ObjectDataViewModelNode ( inst_root_node , itInstance ) ;
2018-10-18 08:40:26 +00:00
inst_root_node - > Append ( instance_node ) ;
// notify control
const wxDataViewItem instance_item ( ( void * ) instance_node ) ;
ItemAdded ( inst_root_item , instance_item ) ;
+ + counter ;
}
return wxDataViewItem ( ( void * ) instance_node ) ;
}
2019-04-24 23:45:00 +00:00
wxDataViewItem ObjectDataViewModel : : Delete ( const wxDataViewItem & item )
2018-05-29 20:45:35 +00:00
{
2018-05-30 15:52:28 +00:00
auto ret_item = wxDataViewItem ( 0 ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-05-29 20:45:35 +00:00
if ( ! node ) // happens if item.IsOk()==false
2018-05-30 15:52:28 +00:00
return ret_item ;
2018-05-29 20:45:35 +00:00
2018-05-29 22:36:44 +00:00
auto node_parent = node - > GetParent ( ) ;
wxDataViewItem parent ( node_parent ) ;
2018-05-29 20:45:35 +00:00
// first remove the node from the parent's array of children;
// NOTE: MyObjectTreeModelNodePtrArray is only an array of _pointers_
// thus removing the node from it doesn't result in freeing it
2018-10-31 11:56:08 +00:00
if ( node_parent ) {
2018-11-12 12:47:24 +00:00
if ( node - > m_type = = itInstanceRoot )
{
for ( int i = node - > GetChildCount ( ) - 1 ; i > 0 ; i - - )
Delete ( wxDataViewItem ( node - > GetNthChild ( i ) ) ) ;
return parent ;
}
2018-05-30 15:52:28 +00:00
auto id = node_parent - > GetChildren ( ) . Index ( node ) ;
2018-10-16 09:08:37 +00:00
auto idx = node - > GetIdx ( ) ;
2018-11-02 22:27:31 +00:00
2018-11-12 12:47:24 +00:00
if ( node - > m_type = = itVolume ) {
2018-11-02 22:27:31 +00:00
node_parent - > m_volumes_cnt - - ;
2018-11-12 12:47:24 +00:00
DeleteSettings ( item ) ;
}
node_parent - > GetChildren ( ) . Remove ( node ) ;
2018-11-02 22:27:31 +00:00
2018-10-31 11:56:08 +00:00
if ( id > 0 ) {
2018-05-30 15:52:28 +00:00
if ( id = = node_parent - > GetChildCount ( ) ) id - - ;
ret_item = wxDataViewItem ( node_parent - > GetChildren ( ) . Item ( id ) ) ;
}
2018-06-18 13:26:09 +00:00
2018-10-16 09:08:37 +00:00
//update idx value for remaining child-nodes
2018-06-18 13:26:09 +00:00
auto children = node_parent - > GetChildren ( ) ;
2018-10-16 09:08:37 +00:00
for ( size_t i = 0 ; i < node_parent - > GetChildCount ( ) & & idx > = 0 ; i + + )
2018-06-18 13:26:09 +00:00
{
2018-10-16 09:08:37 +00:00
auto cur_idx = children [ i ] - > GetIdx ( ) ;
if ( cur_idx > idx )
children [ i ] - > SetIdx ( cur_idx - 1 ) ;
2018-06-18 13:26:09 +00:00
}
2018-10-18 08:40:26 +00:00
// if there is last instance item, delete both of it and instance root item
if ( node_parent - > GetChildCount ( ) = = 1 & & node_parent - > GetNthChild ( 0 ) - > m_type = = itInstance )
{
delete node ;
ItemDeleted ( parent , item ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * last_instance_node = node_parent - > GetNthChild ( 0 ) ;
2018-10-18 08:40:26 +00:00
node_parent - > GetChildren ( ) . Remove ( last_instance_node ) ;
delete last_instance_node ;
ItemDeleted ( parent , wxDataViewItem ( last_instance_node ) ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * obj_node = node_parent - > GetParent ( ) ;
2018-10-18 08:40:26 +00:00
obj_node - > GetChildren ( ) . Remove ( node_parent ) ;
delete node_parent ;
ret_item = wxDataViewItem ( obj_node ) ;
# ifndef __WXGTK__
if ( obj_node - > GetChildCount ( ) = = 0 )
obj_node - > m_container = false ;
# endif //__WXGTK__
2018-11-12 12:47:24 +00:00
ItemDeleted ( ret_item , wxDataViewItem ( node_parent ) ) ;
2018-10-18 08:40:26 +00:00
return ret_item ;
}
2018-11-12 12:47:24 +00:00
// if there is last volume item after deleting, delete this last volume too
if ( node_parent - > GetChildCount ( ) < = 3 )
{
int vol_cnt = 0 ;
int vol_idx = 0 ;
for ( int i = 0 ; i < node_parent - > GetChildCount ( ) ; + + i ) {
if ( node_parent - > GetNthChild ( i ) - > GetType ( ) = = itVolume ) {
vol_idx = i ;
vol_cnt + + ;
}
if ( vol_cnt > 1 )
break ;
}
if ( vol_cnt = = 1 ) {
delete node ;
ItemDeleted ( parent , item ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * last_child_node = node_parent - > GetNthChild ( vol_idx ) ;
2018-11-12 12:47:24 +00:00
DeleteSettings ( wxDataViewItem ( last_child_node ) ) ;
node_parent - > GetChildren ( ) . Remove ( last_child_node ) ;
2018-11-12 15:03:29 +00:00
node_parent - > m_volumes_cnt = 0 ;
2018-11-12 12:47:24 +00:00
delete last_child_node ;
# ifndef __WXGTK__
if ( node_parent - > GetChildCount ( ) = = 0 )
node_parent - > m_container = false ;
# endif //__WXGTK__
ItemDeleted ( parent , wxDataViewItem ( last_child_node ) ) ;
wxCommandEvent event ( wxCUSTOMEVT_LAST_VOLUME_IS_DELETED ) ;
auto it = find ( m_objects . begin ( ) , m_objects . end ( ) , node_parent ) ;
event . SetInt ( it = = m_objects . end ( ) ? - 1 : it - m_objects . begin ( ) ) ;
wxPostEvent ( m_ctrl , event ) ;
ret_item = parent ;
return ret_item ;
}
}
2018-05-30 15:52:28 +00:00
}
2018-05-29 22:36:44 +00:00
else
{
2018-05-30 15:52:28 +00:00
auto it = find ( m_objects . begin ( ) , m_objects . end ( ) , node ) ;
auto id = it - m_objects . begin ( ) ;
2018-05-29 22:36:44 +00:00
if ( it ! = m_objects . end ( ) )
2018-11-12 12:47:24 +00:00
{
// Delete all sub-items
int i = m_objects [ id ] - > GetChildCount ( ) - 1 ;
while ( i > = 0 ) {
Delete ( wxDataViewItem ( m_objects [ id ] - > GetNthChild ( i ) ) ) ;
i = m_objects [ id ] - > GetChildCount ( ) - 1 ;
}
2018-05-29 22:36:44 +00:00
m_objects . erase ( it ) ;
2018-11-12 12:47:24 +00:00
}
2018-10-31 11:56:08 +00:00
if ( id > 0 ) {
2018-05-30 15:52:28 +00:00
if ( id = = m_objects . size ( ) ) id - - ;
ret_item = wxDataViewItem ( m_objects [ id ] ) ;
}
2018-05-29 22:36:44 +00:00
}
2018-05-29 20:45:35 +00:00
// free the node
delete node ;
2018-05-29 22:36:44 +00:00
// set m_containet to FALSE if parent has no child
2018-09-17 13:12:13 +00:00
if ( node_parent ) {
2018-07-31 13:31:12 +00:00
# ifndef __WXGTK__
2018-09-17 13:12:13 +00:00
if ( node_parent - > GetChildCount ( ) = = 0 )
node_parent - > m_container = false ;
2018-07-31 13:31:12 +00:00
# endif //__WXGTK__
2018-05-30 15:52:28 +00:00
ret_item = parent ;
}
2018-05-29 22:36:44 +00:00
2018-05-29 20:45:35 +00:00
// notify control
ItemDeleted ( parent , item ) ;
2018-05-30 15:52:28 +00:00
return ret_item ;
2018-05-04 16:32:20 +00:00
}
2019-04-24 23:45:00 +00:00
wxDataViewItem ObjectDataViewModel : : DeleteLastInstance ( const wxDataViewItem & parent_item , size_t num )
2018-10-18 08:40:26 +00:00
{
auto ret_item = wxDataViewItem ( 0 ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * parent_node = ( ObjectDataViewModelNode * ) parent_item . GetID ( ) ;
2018-10-18 08:40:26 +00:00
if ( ! parent_node ) return ret_item ;
const int inst_root_id = get_istances_root_idx ( parent_node ) ;
if ( inst_root_id < 0 ) return ret_item ;
wxDataViewItemArray items ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * inst_root_node = parent_node - > GetNthChild ( inst_root_id ) ;
2018-10-18 08:40:26 +00:00
const wxDataViewItem inst_root_item ( ( void * ) inst_root_node ) ;
const int inst_cnt = inst_root_node - > GetChildCount ( ) ;
const bool delete_inst_root_item = inst_cnt - num < 2 ? true : false ;
int stop = delete_inst_root_item ? 0 : inst_cnt - num ;
for ( int i = inst_cnt - 1 ; i > = stop ; - - i ) {
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * last_instance_node = inst_root_node - > GetNthChild ( i ) ;
2018-10-18 08:40:26 +00:00
inst_root_node - > GetChildren ( ) . Remove ( last_instance_node ) ;
delete last_instance_node ;
ItemDeleted ( inst_root_item , wxDataViewItem ( last_instance_node ) ) ;
}
if ( delete_inst_root_item ) {
ret_item = parent_item ;
parent_node - > GetChildren ( ) . Remove ( inst_root_node ) ;
ItemDeleted ( parent_item , inst_root_item ) ;
# ifndef __WXGTK__
if ( parent_node - > GetChildCount ( ) = = 0 )
parent_node - > m_container = false ;
# endif //__WXGTK__
}
return ret_item ;
}
2019-04-24 23:45:00 +00:00
void ObjectDataViewModel : : DeleteAll ( )
2018-06-04 13:59:55 +00:00
{
while ( ! m_objects . empty ( ) )
{
auto object = m_objects . back ( ) ;
// object->RemoveAllChildren();
Delete ( wxDataViewItem ( object ) ) ;
}
}
2019-04-24 23:45:00 +00:00
void ObjectDataViewModel : : DeleteChildren ( wxDataViewItem & parent )
2018-07-31 13:31:12 +00:00
{
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * root = ( ObjectDataViewModelNode * ) parent . GetID ( ) ;
2018-07-31 13:31:12 +00:00
if ( ! root ) // happens if item.IsOk()==false
return ;
// first remove the node from the parent's array of children;
// NOTE: MyObjectTreeModelNodePtrArray is only an array of _pointers_
// thus removing the node from it doesn't result in freeing it
auto & children = root - > GetChildren ( ) ;
for ( int id = root - > GetChildCount ( ) - 1 ; id > = 0 ; - - id )
{
auto node = children [ id ] ;
auto item = wxDataViewItem ( node ) ;
children . RemoveAt ( id ) ;
2018-11-02 22:27:31 +00:00
if ( node - > m_type = = itVolume )
root - > m_volumes_cnt - - ;
2018-07-31 13:31:12 +00:00
// free the node
delete node ;
// notify control
ItemDeleted ( parent , item ) ;
}
// set m_containet to FALSE if parent has no child
# ifndef __WXGTK__
root - > m_container = false ;
# endif //__WXGTK__
}
2019-04-24 23:45:00 +00:00
void ObjectDataViewModel : : DeleteVolumeChildren ( wxDataViewItem & parent )
2018-11-06 08:06:26 +00:00
{
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * root = ( ObjectDataViewModelNode * ) parent . GetID ( ) ;
2018-11-06 08:06:26 +00:00
if ( ! root ) // happens if item.IsOk()==false
return ;
// first remove the node from the parent's array of children;
// NOTE: MyObjectTreeModelNodePtrArray is only an array of _pointers_
// thus removing the node from it doesn't result in freeing it
auto & children = root - > GetChildren ( ) ;
for ( int id = root - > GetChildCount ( ) - 1 ; id > = 0 ; - - id )
{
auto node = children [ id ] ;
if ( node - > m_type ! = itVolume )
continue ;
auto item = wxDataViewItem ( node ) ;
2018-11-12 12:47:24 +00:00
DeleteSettings ( item ) ;
2018-11-06 08:06:26 +00:00
children . RemoveAt ( id ) ;
// free the node
delete node ;
// notify control
ItemDeleted ( parent , item ) ;
}
2018-11-12 12:47:24 +00:00
root - > m_volumes_cnt = 0 ;
2018-11-06 08:06:26 +00:00
// set m_containet to FALSE if parent has no child
# ifndef __WXGTK__
root - > m_container = false ;
# endif //__WXGTK__
}
2019-04-24 23:45:00 +00:00
void ObjectDataViewModel : : DeleteSettings ( const wxDataViewItem & parent )
2018-11-12 12:47:24 +00:00
{
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) parent . GetID ( ) ;
2018-11-12 12:47:24 +00:00
if ( ! node ) return ;
// if volume has a "settings"item, than delete it before volume deleting
if ( node - > GetChildCount ( ) > 0 & & node - > GetNthChild ( 0 ) - > GetType ( ) = = itSettings ) {
auto settings_node = node - > GetNthChild ( 0 ) ;
auto settings_item = wxDataViewItem ( settings_node ) ;
node - > GetChildren ( ) . RemoveAt ( 0 ) ;
delete settings_node ;
ItemDeleted ( parent , settings_item ) ;
}
}
2019-04-24 23:45:00 +00:00
wxDataViewItem ObjectDataViewModel : : GetItemById ( int obj_idx )
2018-06-04 13:59:55 +00:00
{
if ( obj_idx > = m_objects . size ( ) )
{
printf ( " Error! Out of objects range. \n " ) ;
return wxDataViewItem ( 0 ) ;
}
return wxDataViewItem ( m_objects [ obj_idx ] ) ;
}
2019-04-24 23:45:00 +00:00
wxDataViewItem ObjectDataViewModel : : GetItemByVolumeId ( int obj_idx , int volume_idx )
2018-09-17 13:12:13 +00:00
{
2018-11-05 12:53:30 +00:00
if ( obj_idx > = m_objects . size ( ) | | obj_idx < 0 ) {
2018-09-17 13:12:13 +00:00
printf ( " Error! Out of objects range. \n " ) ;
return wxDataViewItem ( 0 ) ;
}
auto parent = m_objects [ obj_idx ] ;
2018-10-12 10:00:37 +00:00
if ( parent - > GetChildCount ( ) = = 0 | |
2018-10-16 09:08:37 +00:00
( parent - > GetChildCount ( ) = = 1 & & parent - > GetNthChild ( 0 ) - > GetType ( ) & itSettings ) ) {
2018-10-11 13:57:09 +00:00
if ( volume_idx = = 0 )
return GetItemById ( obj_idx ) ;
2018-09-17 13:12:13 +00:00
printf ( " Error! Object has no one volume. \n " ) ;
return wxDataViewItem ( 0 ) ;
}
for ( size_t i = 0 ; i < parent - > GetChildCount ( ) ; i + + )
2018-11-09 17:39:07 +00:00
if ( parent - > GetNthChild ( i ) - > m_idx = = volume_idx & & parent - > GetNthChild ( i ) - > GetType ( ) & itVolume )
2018-09-17 13:12:13 +00:00
return wxDataViewItem ( parent - > GetNthChild ( i ) ) ;
return wxDataViewItem ( 0 ) ;
}
2019-04-24 23:45:00 +00:00
wxDataViewItem ObjectDataViewModel : : GetItemByInstanceId ( int obj_idx , int inst_idx )
2018-11-05 12:53:30 +00:00
{
if ( obj_idx > = m_objects . size ( ) | | obj_idx < 0 ) {
printf ( " Error! Out of objects range. \n " ) ;
return wxDataViewItem ( 0 ) ;
}
auto instances_item = GetInstanceRootItem ( wxDataViewItem ( m_objects [ obj_idx ] ) ) ;
if ( ! instances_item )
return wxDataViewItem ( 0 ) ;
2019-04-24 23:45:00 +00:00
auto parent = ( ObjectDataViewModelNode * ) instances_item . GetID ( ) ; ;
2018-11-05 12:53:30 +00:00
for ( size_t i = 0 ; i < parent - > GetChildCount ( ) ; i + + )
if ( parent - > GetNthChild ( i ) - > m_idx = = inst_idx )
return wxDataViewItem ( parent - > GetNthChild ( i ) ) ;
return wxDataViewItem ( 0 ) ;
}
2019-04-24 23:45:00 +00:00
int ObjectDataViewModel : : GetIdByItem ( const wxDataViewItem & item ) const
2018-06-06 22:55:09 +00:00
{
wxASSERT ( item . IsOk ( ) ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-06-06 22:55:09 +00:00
auto it = find ( m_objects . begin ( ) , m_objects . end ( ) , node ) ;
if ( it = = m_objects . end ( ) )
return - 1 ;
return it - m_objects . begin ( ) ;
}
2019-04-24 23:45:00 +00:00
int ObjectDataViewModel : : GetIdByItemAndType ( const wxDataViewItem & item , const ItemType type ) const
2018-06-18 12:20:29 +00:00
{
wxASSERT ( item . IsOk ( ) ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-10-18 08:40:26 +00:00
if ( ! node | | node - > m_type ! = type )
2018-06-18 12:20:29 +00:00
return - 1 ;
2018-10-16 09:08:37 +00:00
return node - > GetIdx ( ) ;
2018-06-18 12:20:29 +00:00
}
2019-04-24 23:45:00 +00:00
int ObjectDataViewModel : : GetObjectIdByItem ( const wxDataViewItem & item ) const
2018-12-12 07:40:10 +00:00
{
return GetIdByItem ( GetTopParent ( item ) ) ;
}
2019-04-24 23:45:00 +00:00
int ObjectDataViewModel : : GetVolumeIdByItem ( const wxDataViewItem & item ) const
2018-10-18 08:40:26 +00:00
{
return GetIdByItemAndType ( item , itVolume ) ;
}
2019-04-24 23:45:00 +00:00
int ObjectDataViewModel : : GetInstanceIdByItem ( const wxDataViewItem & item ) const
2018-10-18 08:40:26 +00:00
{
return GetIdByItemAndType ( item , itInstance ) ;
2018-06-18 12:20:29 +00:00
}
2019-04-24 23:45:00 +00:00
void ObjectDataViewModel : : GetItemInfo ( const wxDataViewItem & item , ItemType & type , int & obj_idx , int & idx )
2018-10-12 10:00:37 +00:00
{
wxASSERT ( item . IsOk ( ) ) ;
2018-10-16 09:08:37 +00:00
type = itUndef ;
2018-10-12 10:00:37 +00:00
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-11-12 12:47:24 +00:00
if ( ! node | | node - > GetIdx ( ) < - 1 | | node - > GetIdx ( ) = = - 1 & & ! ( node - > GetType ( ) & ( itObject | itSettings | itInstanceRoot ) ) )
2018-10-18 08:40:26 +00:00
return ;
2018-10-16 09:08:37 +00:00
idx = node - > GetIdx ( ) ;
2018-10-18 08:40:26 +00:00
type = node - > GetType ( ) ;
2018-10-12 10:00:37 +00:00
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * parent_node = node - > GetParent ( ) ;
2018-10-12 10:00:37 +00:00
if ( ! parent_node ) return ;
2018-10-16 09:08:37 +00:00
if ( type = = itInstance )
parent_node = node - > GetParent ( ) - > GetParent ( ) ;
2018-10-18 08:40:26 +00:00
if ( ! parent_node | | parent_node - > m_type ! = itObject ) { type = itUndef ; return ; }
2018-10-12 10:00:37 +00:00
auto it = find ( m_objects . begin ( ) , m_objects . end ( ) , parent_node ) ;
if ( it ! = m_objects . end ( ) )
obj_idx = it - m_objects . begin ( ) ;
2018-10-18 08:40:26 +00:00
else
type = itUndef ;
2018-10-12 10:00:37 +00:00
}
2019-04-24 23:45:00 +00:00
int ObjectDataViewModel : : GetRowByItem ( const wxDataViewItem & item ) const
2018-12-17 11:46:36 +00:00
{
if ( m_objects . empty ( ) )
return - 1 ;
int row_num = 0 ;
for ( int i = 0 ; i < m_objects . size ( ) ; i + + )
{
row_num + + ;
if ( item = = wxDataViewItem ( m_objects [ i ] ) )
return row_num ;
for ( int j = 0 ; j < m_objects [ i ] - > GetChildCount ( ) ; j + + )
{
row_num + + ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * cur_node = m_objects [ i ] - > GetNthChild ( j ) ;
2018-12-17 11:46:36 +00:00
if ( item = = wxDataViewItem ( cur_node ) )
return row_num ;
if ( cur_node - > m_type = = itVolume & & cur_node - > GetChildCount ( ) = = 1 )
row_num + + ;
if ( cur_node - > m_type = = itInstanceRoot )
{
row_num + + ;
for ( int t = 0 ; t < cur_node - > GetChildCount ( ) ; t + + )
{
row_num + + ;
if ( item = = wxDataViewItem ( cur_node - > GetNthChild ( t ) ) )
return row_num ;
}
}
}
}
return - 1 ;
}
2019-04-24 23:45:00 +00:00
wxString ObjectDataViewModel : : GetName ( const wxDataViewItem & item ) const
2018-05-04 16:32:20 +00:00
{
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-05-04 16:32:20 +00:00
if ( ! node ) // happens if item.IsOk()==false
return wxEmptyString ;
return node - > m_name ;
}
2019-04-24 23:45:00 +00:00
wxBitmap & ObjectDataViewModel : : GetBitmap ( const wxDataViewItem & item ) const
2018-09-17 13:12:13 +00:00
{
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-09-17 13:12:13 +00:00
return node - > m_bmp ;
}
2019-04-24 23:45:00 +00:00
void ObjectDataViewModel : : GetValue ( wxVariant & variant , const wxDataViewItem & item , unsigned int col ) const
2018-05-04 16:32:20 +00:00
{
wxASSERT ( item . IsOk ( ) ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-05-04 16:32:20 +00:00
switch ( col )
{
2018-10-18 09:28:31 +00:00
case 0 :
2019-04-24 23:45:00 +00:00
variant < < DataViewBitmapText ( node - > m_name , node - > m_bmp ) ;
2018-05-04 16:32:20 +00:00
break ;
2018-10-18 09:28:31 +00:00
case 1 :
2018-07-04 06:54:30 +00:00
variant = node - > m_extruder ;
break ;
2018-10-18 09:28:31 +00:00
case 2 :
2018-07-04 06:54:30 +00:00
variant < < node - > m_action_icon ;
break ;
2018-05-04 16:32:20 +00:00
default :
2018-06-04 13:59:55 +00:00
;
2018-05-04 16:32:20 +00:00
}
}
2019-04-24 23:45:00 +00:00
bool ObjectDataViewModel : : SetValue ( const wxVariant & variant , const wxDataViewItem & item , unsigned int col )
2018-05-04 16:32:20 +00:00
{
wxASSERT ( item . IsOk ( ) ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-06-05 11:17:24 +00:00
return node - > SetValue ( variant , col ) ;
2018-05-04 16:32:20 +00:00
}
2019-04-24 23:45:00 +00:00
bool ObjectDataViewModel : : SetValue ( const wxVariant & variant , const int item_idx , unsigned int col )
2018-06-05 08:41:20 +00:00
{
if ( item_idx < 0 | | item_idx > = m_objects . size ( ) )
return false ;
return m_objects [ item_idx ] - > SetValue ( variant , col ) ;
}
2018-06-19 10:24:16 +00:00
2019-04-24 23:45:00 +00:00
wxDataViewItem ObjectDataViewModel : : ReorganizeChildren ( const int current_volume_id ,
const int new_volume_id ,
const wxDataViewItem & parent )
2018-08-13 12:15:43 +00:00
{
auto ret_item = wxDataViewItem ( 0 ) ;
if ( current_volume_id = = new_volume_id )
return ret_item ;
wxASSERT ( parent . IsOk ( ) ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node_parent = ( ObjectDataViewModelNode * ) parent . GetID ( ) ;
2018-08-13 12:15:43 +00:00
if ( ! node_parent ) // happens if item.IsOk()==false
return ret_item ;
2018-10-16 09:08:37 +00:00
const size_t shift = node_parent - > GetChildren ( ) . Item ( 0 ) - > m_type = = itSettings ? 1 : 0 ;
2018-09-17 13:12:13 +00:00
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * deleted_node = node_parent - > GetNthChild ( current_volume_id + shift ) ;
2018-08-13 12:15:43 +00:00
node_parent - > GetChildren ( ) . Remove ( deleted_node ) ;
ItemDeleted ( parent , wxDataViewItem ( deleted_node ) ) ;
2018-09-17 13:12:13 +00:00
node_parent - > Insert ( deleted_node , new_volume_id + shift ) ;
2018-08-13 12:15:43 +00:00
ItemAdded ( parent , wxDataViewItem ( deleted_node ) ) ;
2018-10-16 09:08:37 +00:00
const auto settings_item = GetSettingsItem ( wxDataViewItem ( deleted_node ) ) ;
2018-09-17 13:12:13 +00:00
if ( settings_item )
ItemAdded ( wxDataViewItem ( deleted_node ) , settings_item ) ;
2018-08-13 12:15:43 +00:00
//update volume_id value for child-nodes
auto children = node_parent - > GetChildren ( ) ;
int id_frst = current_volume_id < new_volume_id ? current_volume_id : new_volume_id ;
int id_last = current_volume_id > new_volume_id ? current_volume_id : new_volume_id ;
for ( int id = id_frst ; id < = id_last ; + + id )
2018-10-16 09:08:37 +00:00
children [ id + shift ] - > SetIdx ( id ) ;
2018-08-13 12:15:43 +00:00
2018-09-17 13:12:13 +00:00
return wxDataViewItem ( node_parent - > GetNthChild ( new_volume_id + shift ) ) ;
2018-08-13 12:15:43 +00:00
}
2019-04-24 23:45:00 +00:00
bool ObjectDataViewModel : : IsEnabled ( const wxDataViewItem & item , unsigned int col ) const
2018-09-17 13:12:13 +00:00
{
wxASSERT ( item . IsOk ( ) ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-09-17 13:12:13 +00:00
2018-12-04 17:14:02 +00:00
// disable extruder selection for the non "itObject|itVolume" item
return ! ( col = = 1 & & node - > m_extruder . IsEmpty ( ) ) ;
2018-09-17 13:12:13 +00:00
}
2018-05-04 16:32:20 +00:00
2019-04-24 23:45:00 +00:00
wxDataViewItem ObjectDataViewModel : : GetParent ( const wxDataViewItem & item ) const
2018-05-04 16:32:20 +00:00
{
// the invisible root node has no parent
if ( ! item . IsOk ( ) )
return wxDataViewItem ( 0 ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-05-04 16:32:20 +00:00
2018-05-29 20:45:35 +00:00
// objects nodes has no parent too
2018-10-18 08:40:26 +00:00
if ( node - > m_type = = itObject )
2018-05-04 16:32:20 +00:00
return wxDataViewItem ( 0 ) ;
return wxDataViewItem ( ( void * ) node - > GetParent ( ) ) ;
}
2019-04-24 23:45:00 +00:00
wxDataViewItem ObjectDataViewModel : : GetTopParent ( const wxDataViewItem & item ) const
2018-10-18 08:40:26 +00:00
{
// the invisible root node has no parent
if ( ! item . IsOk ( ) )
return wxDataViewItem ( 0 ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-10-18 08:40:26 +00:00
if ( node - > m_type = = itObject )
return item ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * parent_node = node - > GetParent ( ) ;
2018-10-18 08:40:26 +00:00
while ( parent_node - > m_type ! = itObject )
{
node = parent_node ;
parent_node = node - > GetParent ( ) ;
}
return wxDataViewItem ( ( void * ) parent_node ) ;
}
2019-04-24 23:45:00 +00:00
bool ObjectDataViewModel : : IsContainer ( const wxDataViewItem & item ) const
2018-05-04 16:32:20 +00:00
{
2018-05-29 22:36:44 +00:00
// the invisible root node can have children
2018-05-04 16:32:20 +00:00
if ( ! item . IsOk ( ) )
return true ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-05-04 16:32:20 +00:00
return node - > IsContainer ( ) ;
}
2019-04-24 23:45:00 +00:00
unsigned int ObjectDataViewModel : : GetChildren ( const wxDataViewItem & parent , wxDataViewItemArray & array ) const
2018-05-04 16:32:20 +00:00
{
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) parent . GetID ( ) ;
2018-05-04 16:32:20 +00:00
if ( ! node )
{
2018-05-09 12:36:20 +00:00
for ( auto object : m_objects )
array . Add ( wxDataViewItem ( ( void * ) object ) ) ;
2018-05-04 16:32:20 +00:00
return m_objects . size ( ) ;
}
if ( node - > GetChildCount ( ) = = 0 )
{
return 0 ;
}
unsigned int count = node - > GetChildren ( ) . GetCount ( ) ;
for ( unsigned int pos = 0 ; pos < count ; pos + + )
{
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * child = node - > GetChildren ( ) . Item ( pos ) ;
2018-05-04 16:32:20 +00:00
array . Add ( wxDataViewItem ( ( void * ) child ) ) ;
}
return count ;
}
2018-08-21 00:03:10 +00:00
2019-04-24 23:45:00 +00:00
void ObjectDataViewModel : : GetAllChildren ( const wxDataViewItem & parent , wxDataViewItemArray & array ) const
2019-03-29 13:36:09 +00:00
{
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) parent . GetID ( ) ;
2019-03-29 13:36:09 +00:00
if ( ! node ) {
for ( auto object : m_objects )
array . Add ( wxDataViewItem ( ( void * ) object ) ) ;
}
else if ( node - > GetChildCount ( ) = = 0 )
return ;
else {
const size_t count = node - > GetChildren ( ) . GetCount ( ) ;
for ( size_t pos = 0 ; pos < count ; pos + + ) {
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * child = node - > GetChildren ( ) . Item ( pos ) ;
2019-03-29 13:36:09 +00:00
array . Add ( wxDataViewItem ( ( void * ) child ) ) ;
}
}
wxDataViewItemArray new_array = array ;
for ( const auto item : new_array )
{
wxDataViewItemArray children ;
GetAllChildren ( item , children ) ;
WX_APPEND_ARRAY ( array , children ) ;
}
}
2019-04-24 23:45:00 +00:00
ItemType ObjectDataViewModel : : GetItemType ( const wxDataViewItem & item ) const
2018-10-16 09:08:37 +00:00
{
if ( ! item . IsOk ( ) )
return itUndef ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-10-16 09:08:37 +00:00
return node - > m_type ;
}
2019-04-24 23:45:00 +00:00
wxDataViewItem ObjectDataViewModel : : GetItemByType ( const wxDataViewItem & parent_item , ItemType type ) const
2018-09-17 13:12:13 +00:00
{
2018-11-05 12:53:30 +00:00
if ( ! parent_item . IsOk ( ) )
2018-09-17 13:12:13 +00:00
return wxDataViewItem ( 0 ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) parent_item . GetID ( ) ;
2018-09-17 13:12:13 +00:00
if ( node - > GetChildCount ( ) = = 0 )
return wxDataViewItem ( 0 ) ;
2018-11-05 12:53:30 +00:00
for ( int i = 0 ; i < node - > GetChildCount ( ) ; i + + ) {
if ( node - > GetNthChild ( i ) - > m_type = = type )
return wxDataViewItem ( ( void * ) node - > GetNthChild ( i ) ) ;
}
2018-09-17 13:12:13 +00:00
return wxDataViewItem ( 0 ) ;
}
2019-04-24 23:45:00 +00:00
wxDataViewItem ObjectDataViewModel : : GetSettingsItem ( const wxDataViewItem & item ) const
2018-11-05 12:53:30 +00:00
{
return GetItemByType ( item , itSettings ) ;
}
2019-04-24 23:45:00 +00:00
wxDataViewItem ObjectDataViewModel : : GetInstanceRootItem ( const wxDataViewItem & item ) const
2018-11-05 12:53:30 +00:00
{
return GetItemByType ( item , itInstanceRoot ) ;
}
2019-04-24 23:45:00 +00:00
bool ObjectDataViewModel : : IsSettingsItem ( const wxDataViewItem & item ) const
2018-09-17 13:12:13 +00:00
{
if ( ! item . IsOk ( ) )
return false ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-10-16 09:08:37 +00:00
return node - > m_type = = itSettings ;
2018-09-17 13:12:13 +00:00
}
2019-04-24 23:45:00 +00:00
void ObjectDataViewModel : : UpdateSettingsDigest ( const wxDataViewItem & item ,
2018-09-17 13:12:13 +00:00
const std : : vector < std : : string > & categories )
{
if ( ! item . IsOk ( ) ) return ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-09-17 13:12:13 +00:00
if ( ! node - > update_settings_digest ( categories ) )
return ;
ItemChanged ( item ) ;
}
2019-04-24 23:45:00 +00:00
void ObjectDataViewModel : : SetVolumeType ( const wxDataViewItem & item , const Slic3r : : ModelVolumeType type )
2018-11-02 22:27:31 +00:00
{
if ( ! item . IsOk ( ) | | GetItemType ( item ) ! = itVolume )
return ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2019-02-22 11:12:10 +00:00
node - > SetBitmap ( * m_volume_bmps [ int ( type ) ] ) ;
2018-11-02 22:27:31 +00:00
ItemChanged ( item ) ;
}
2019-04-24 23:45:00 +00:00
void ObjectDataViewModel : : Rescale ( )
2019-04-16 08:05:45 +00:00
{
wxDataViewItemArray all_items ;
GetAllChildren ( wxDataViewItem ( 0 ) , all_items ) ;
for ( wxDataViewItem item : all_items )
{
if ( ! item . IsOk ( ) )
continue ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
node - > msw_rescale ( ) ;
2019-04-16 08:05:45 +00:00
if ( node - > m_type & itVolume )
2019-04-29 13:27:59 +00:00
node - > m_bmp = GetVolumeIcon ( node - > m_volume_type , node - > m_bmp . GetWidth ( ) ! = node - > m_bmp . GetHeight ( ) ) ;
2019-04-16 08:05:45 +00:00
if ( node - > m_type & itObject & & node - > m_bmp . IsOk ( ) )
2019-04-29 13:27:59 +00:00
node - > m_bmp = * m_warning_bmp ;
2019-04-16 08:05:45 +00:00
ItemChanged ( item ) ;
}
}
2019-04-29 13:27:59 +00:00
wxBitmap ObjectDataViewModel : : GetVolumeIcon ( const Slic3r : : ModelVolumeType vol_type , const bool is_marked /* = false*/ )
{
if ( ! is_marked )
return * m_volume_bmps [ static_cast < int > ( vol_type ) ] ;
std : : string scaled_bitmap_name = " warning " + std : : to_string ( static_cast < int > ( vol_type ) ) ;
scaled_bitmap_name + = " -em " + std : : to_string ( Slic3r : : GUI : : wxGetApp ( ) . em_unit ( ) ) ;
wxBitmap * bmp = m_bitmap_cache - > find ( scaled_bitmap_name ) ;
if ( bmp = = nullptr ) {
std : : vector < wxBitmap > bmps ;
bmps . emplace_back ( * m_warning_bmp ) ;
bmps . emplace_back ( * m_volume_bmps [ static_cast < int > ( vol_type ) ] ) ;
bmp = m_bitmap_cache - > insert ( scaled_bitmap_name , bmps ) ;
}
return * bmp ;
}
void ObjectDataViewModel : : DeleteWarningIcon ( const wxDataViewItem & item , const bool unmark_object /* = false*/ )
{
if ( ! item . IsOk ( ) )
return ;
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
if ( ! node - > GetBitmap ( ) . IsOk ( ) | | ! ( node - > GetType ( ) & ( itVolume | itObject ) ) )
return ;
if ( node - > GetType ( ) & itVolume ) {
node - > SetBitmap ( * m_volume_bmps [ static_cast < int > ( node - > volume_type ( ) ) ] ) ;
return ;
}
node - > SetBitmap ( wxNullBitmap ) ;
if ( unmark_object )
{
wxDataViewItemArray children ;
GetChildren ( item , children ) ;
for ( const wxDataViewItem & child : children )
DeleteWarningIcon ( child ) ;
}
}
2018-10-15 11:25:22 +00:00
//-----------------------------------------------------------------------------
// PrusaDataViewBitmapText
//-----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
wxIMPLEMENT_DYNAMIC_CLASS ( DataViewBitmapText , wxObject )
2018-10-15 11:25:22 +00:00
2019-04-24 23:45:00 +00:00
IMPLEMENT_VARIANT_OBJECT ( DataViewBitmapText )
2018-10-15 11:25:22 +00:00
2018-09-17 13:12:13 +00:00
// ---------------------------------------------------------
2019-04-24 23:45:00 +00:00
// BitmapTextRenderer
2018-09-17 13:12:13 +00:00
// ---------------------------------------------------------
2018-12-17 07:37:50 +00:00
# if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
2019-04-24 23:45:00 +00:00
BitmapTextRenderer : : BitmapTextRenderer ( wxDataViewCellMode mode /*= wxDATAVIEW_CELL_EDITABLE*/ ,
2018-12-17 07:37:50 +00:00
int align /*= wxDVR_DEFAULT_ALIGNMENT*/ ) :
wxDataViewRenderer ( wxT ( " PrusaDataViewBitmapText " ) , mode , align )
{
SetMode ( mode ) ;
SetAlignment ( align ) ;
}
# endif // ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
2019-04-24 23:45:00 +00:00
bool BitmapTextRenderer : : SetValue ( const wxVariant & value )
2018-09-17 13:12:13 +00:00
{
m_value < < value ;
return true ;
}
2019-04-24 23:45:00 +00:00
bool BitmapTextRenderer : : GetValue ( wxVariant & WXUNUSED ( value ) ) const
2018-09-17 13:12:13 +00:00
{
return false ;
}
2018-12-17 07:37:50 +00:00
# if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING && wxUSE_ACCESSIBILITY
2019-04-24 23:45:00 +00:00
wxString BitmapTextRenderer : : GetAccessibleDescription ( ) const
2018-12-14 15:07:28 +00:00
{
return m_value . GetText ( ) ;
}
2018-12-17 07:37:50 +00:00
# endif // wxUSE_ACCESSIBILITY && ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
2018-12-14 15:07:28 +00:00
2019-04-24 23:45:00 +00:00
bool BitmapTextRenderer : : Render ( wxRect rect , wxDC * dc , int state )
2018-09-17 13:12:13 +00:00
{
int xoffset = 0 ;
const wxBitmap & icon = m_value . GetBitmap ( ) ;
if ( icon . IsOk ( ) )
{
dc - > DrawBitmap ( icon , rect . x , rect . y + ( rect . height - icon . GetHeight ( ) ) / 2 ) ;
xoffset = icon . GetWidth ( ) + 4 ;
}
RenderText ( m_value . GetText ( ) , xoffset , rect , dc , state ) ;
return true ;
}
2019-04-24 23:45:00 +00:00
wxSize BitmapTextRenderer : : GetSize ( ) const
2018-09-17 13:12:13 +00:00
{
if ( ! m_value . GetText ( ) . empty ( ) )
{
wxSize size = GetTextExtent ( m_value . GetText ( ) ) ;
if ( m_value . GetBitmap ( ) . IsOk ( ) )
size . x + = m_value . GetBitmap ( ) . GetWidth ( ) + 4 ;
return size ;
}
return wxSize ( 80 , 20 ) ;
}
2018-08-29 09:21:22 +00:00
2019-04-24 23:45:00 +00:00
wxWindow * BitmapTextRenderer : : CreateEditorCtrl ( wxWindow * parent , wxRect labelRect , const wxVariant & value )
2018-12-12 12:18:38 +00:00
{
wxDataViewCtrl * const dv_ctrl = GetOwner ( ) - > GetOwner ( ) ;
2019-04-24 23:45:00 +00:00
ObjectDataViewModel * const model = dynamic_cast < ObjectDataViewModel * > ( dv_ctrl - > GetModel ( ) ) ;
2018-12-12 12:18:38 +00:00
if ( ! ( model - > GetItemType ( dv_ctrl - > GetSelection ( ) ) & ( itVolume | itObject ) ) )
return nullptr ;
2019-04-24 23:45:00 +00:00
DataViewBitmapText data ;
2018-12-12 12:18:38 +00:00
data < < value ;
2018-12-14 15:07:28 +00:00
2018-12-12 13:35:18 +00:00
m_was_unusable_symbol = false ;
2018-12-12 12:18:38 +00:00
wxPoint position = labelRect . GetPosition ( ) ;
2018-12-14 15:07:28 +00:00
if ( data . GetBitmap ( ) . IsOk ( ) ) {
const int bmp_width = data . GetBitmap ( ) . GetWidth ( ) ;
2018-12-12 12:18:38 +00:00
position . x + = bmp_width ;
labelRect . SetWidth ( labelRect . GetWidth ( ) - bmp_width ) ;
}
wxTextCtrl * text_editor = new wxTextCtrl ( parent , wxID_ANY , data . GetText ( ) ,
position , labelRect . GetSize ( ) , wxTE_PROCESS_ENTER ) ;
text_editor - > SetInsertionPointEnd ( ) ;
2018-12-14 15:07:28 +00:00
text_editor - > SelectAll ( ) ;
2018-12-12 12:18:38 +00:00
return text_editor ;
}
2019-04-24 23:45:00 +00:00
bool BitmapTextRenderer : : GetValueFromEditorCtrl ( wxWindow * ctrl , wxVariant & value )
2018-12-12 12:18:38 +00:00
{
wxTextCtrl * text_editor = wxDynamicCast ( ctrl , wxTextCtrl ) ;
2018-12-12 13:35:18 +00:00
if ( ! text_editor | | text_editor - > GetValue ( ) . IsEmpty ( ) )
2018-12-12 12:18:38 +00:00
return false ;
2018-12-12 13:35:18 +00:00
std : : string chosen_name = Slic3r : : normalize_utf8_nfc ( text_editor - > GetValue ( ) . ToUTF8 ( ) ) ;
const char * unusable_symbols = " <>:/ \\ |?* \" " ;
for ( size_t i = 0 ; i < std : : strlen ( unusable_symbols ) ; i + + ) {
if ( chosen_name . find_first_of ( unusable_symbols [ i ] ) ! = std : : string : : npos ) {
m_was_unusable_symbol = true ;
return false ;
}
}
2018-12-14 15:07:28 +00:00
// The icon can't be edited so get its old value and reuse it.
wxVariant valueOld ;
GetView ( ) - > GetModel ( ) - > GetValue ( valueOld , m_item , 0 ) ;
2019-04-24 23:45:00 +00:00
DataViewBitmapText bmpText ;
2018-12-14 15:07:28 +00:00
bmpText < < valueOld ;
// But replace the text with the value entered by user.
bmpText . SetText ( text_editor - > GetValue ( ) ) ;
value < < bmpText ;
2018-12-12 12:18:38 +00:00
return true ;
}
2018-08-29 09:21:22 +00:00
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
// DoubleSlider
2018-08-29 09:21:22 +00:00
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
DoubleSlider : : DoubleSlider ( wxWindow * parent ,
wxWindowID id ,
int lowerValue ,
int higherValue ,
int minValue ,
int maxValue ,
const wxPoint & pos ,
const wxSize & size ,
long style ,
const wxValidator & val ,
const wxString & name ) :
2018-08-21 15:47:05 +00:00
wxControl ( parent , id , pos , size , wxWANTS_CHARS | wxBORDER_NONE ) ,
2018-08-21 00:03:10 +00:00
m_lower_value ( lowerValue ) , m_higher_value ( higherValue ) ,
m_min_value ( minValue ) , m_max_value ( maxValue ) ,
2018-08-22 08:44:11 +00:00
m_style ( style = = wxSL_HORIZONTAL | | style = = wxSL_VERTICAL ? style : wxSL_HORIZONTAL )
2018-08-21 00:03:10 +00:00
{
2019-02-26 14:51:23 +00:00
# ifdef __WXOSX__
is_osx = true ;
2018-08-22 06:54:07 +00:00
# endif //__WXOSX__
2019-02-26 14:51:23 +00:00
if ( ! is_osx )
SetDoubleBuffered ( true ) ; // SetDoubleBuffered exists on Win and Linux/GTK, but is missing on OSX
2018-08-21 00:03:10 +00:00
2019-04-24 23:45:00 +00:00
m_bmp_thumb_higher = ( style = = wxSL_HORIZONTAL ? ScalableBitmap ( this , " right_half_circle.png " ) : ScalableBitmap ( this , " up_half_circle.png " , 16 , true ) ) ;
m_bmp_thumb_lower = ( style = = wxSL_HORIZONTAL ? ScalableBitmap ( this , " left_half_circle.png " ) : ScalableBitmap ( this , " down_half_circle.png " , 16 , true ) ) ;
2019-04-16 08:05:45 +00:00
m_thumb_size = m_bmp_thumb_lower . bmp ( ) . GetSize ( ) ;
2018-08-24 11:34:38 +00:00
2019-04-24 23:45:00 +00:00
m_bmp_add_tick_on = ScalableBitmap ( this , " colorchange_add_on.png " ) ;
m_bmp_add_tick_off = ScalableBitmap ( this , " colorchange_add_off.png " ) ;
m_bmp_del_tick_on = ScalableBitmap ( this , " colorchange_delete_on.png " ) ;
m_bmp_del_tick_off = ScalableBitmap ( this , " colorchange_delete_off.png " ) ;
2019-04-16 08:05:45 +00:00
m_tick_icon_dim = m_bmp_add_tick_on . bmp ( ) . GetSize ( ) . x ;
2018-08-24 11:34:38 +00:00
2019-04-24 23:45:00 +00:00
m_bmp_one_layer_lock_on = ScalableBitmap ( this , " one_layer_lock_on.png " ) ;
m_bmp_one_layer_lock_off = ScalableBitmap ( this , " one_layer_lock_off.png " ) ;
m_bmp_one_layer_unlock_on = ScalableBitmap ( this , " one_layer_unlock_on.png " ) ;
m_bmp_one_layer_unlock_off = ScalableBitmap ( this , " one_layer_unlock_off.png " ) ;
2019-04-16 08:05:45 +00:00
m_lock_icon_dim = m_bmp_one_layer_lock_on . bmp ( ) . GetSize ( ) . x ;
2018-08-23 11:01:18 +00:00
2018-08-21 00:03:10 +00:00
m_selection = ssUndef ;
// slider events
2019-04-24 23:45:00 +00:00
Bind ( wxEVT_PAINT , & DoubleSlider : : OnPaint , this ) ;
Bind ( wxEVT_LEFT_DOWN , & DoubleSlider : : OnLeftDown , this ) ;
Bind ( wxEVT_MOTION , & DoubleSlider : : OnMotion , this ) ;
Bind ( wxEVT_LEFT_UP , & DoubleSlider : : OnLeftUp , this ) ;
Bind ( wxEVT_MOUSEWHEEL , & DoubleSlider : : OnWheel , this ) ;
Bind ( wxEVT_ENTER_WINDOW , & DoubleSlider : : OnEnterWin , this ) ;
Bind ( wxEVT_LEAVE_WINDOW , & DoubleSlider : : OnLeaveWin , this ) ;
Bind ( wxEVT_KEY_DOWN , & DoubleSlider : : OnKeyDown , this ) ;
Bind ( wxEVT_KEY_UP , & DoubleSlider : : OnKeyUp , this ) ;
Bind ( wxEVT_RIGHT_DOWN , & DoubleSlider : : OnRightDown , this ) ;
Bind ( wxEVT_RIGHT_UP , & DoubleSlider : : OnRightUp , this ) ;
2018-08-21 00:03:10 +00:00
// control's view variables
2019-04-16 08:05:45 +00:00
SLIDER_MARGIN = 4 + Slic3r : : GUI : : wxGetApp ( ) . em_unit ( ) ;
2018-08-21 00:03:10 +00:00
DARK_ORANGE_PEN = wxPen ( wxColour ( 253 , 84 , 2 ) ) ;
ORANGE_PEN = wxPen ( wxColour ( 253 , 126 , 66 ) ) ;
LIGHT_ORANGE_PEN = wxPen ( wxColour ( 254 , 177 , 139 ) ) ;
DARK_GREY_PEN = wxPen ( wxColour ( 128 , 128 , 128 ) ) ;
GREY_PEN = wxPen ( wxColour ( 164 , 164 , 164 ) ) ;
LIGHT_GREY_PEN = wxPen ( wxColour ( 204 , 204 , 204 ) ) ;
2019-04-24 23:45:00 +00:00
m_line_pens = { & DARK_GREY_PEN , & GREY_PEN , & LIGHT_GREY_PEN } ;
m_segm_pens = { & DARK_ORANGE_PEN , & ORANGE_PEN , & LIGHT_ORANGE_PEN } ;
2019-02-26 14:51:23 +00:00
2019-02-27 10:05:59 +00:00
const wxFont & font = GetFont ( ) ;
2019-02-26 14:51:23 +00:00
m_font = is_osx ? font . Smaller ( ) . Smaller ( ) : font . Smaller ( ) ;
2018-08-21 00:03:10 +00:00
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : msw_rescale ( )
2019-04-16 08:05:45 +00:00
{
const wxFont & font = Slic3r : : GUI : : wxGetApp ( ) . normal_font ( ) ;
m_font = is_osx ? font . Smaller ( ) . Smaller ( ) : font . Smaller ( ) ;
2019-04-24 23:45:00 +00:00
m_bmp_thumb_higher . msw_rescale ( ) ;
m_bmp_thumb_lower . msw_rescale ( ) ;
2019-04-16 08:05:45 +00:00
m_thumb_size = m_bmp_thumb_lower . bmp ( ) . GetSize ( ) ;
2019-04-24 23:45:00 +00:00
m_bmp_add_tick_on . msw_rescale ( ) ;
m_bmp_add_tick_off . msw_rescale ( ) ;
m_bmp_del_tick_on . msw_rescale ( ) ;
m_bmp_del_tick_off . msw_rescale ( ) ;
2019-04-16 08:05:45 +00:00
m_tick_icon_dim = m_bmp_add_tick_on . bmp ( ) . GetSize ( ) . x ;
2019-04-24 23:45:00 +00:00
m_bmp_one_layer_lock_on . msw_rescale ( ) ;
m_bmp_one_layer_lock_off . msw_rescale ( ) ;
m_bmp_one_layer_unlock_on . msw_rescale ( ) ;
m_bmp_one_layer_unlock_off . msw_rescale ( ) ;
2019-04-16 08:05:45 +00:00
m_lock_icon_dim = m_bmp_one_layer_lock_on . bmp ( ) . GetSize ( ) . x ;
SLIDER_MARGIN = 4 + Slic3r : : GUI : : wxGetApp ( ) . em_unit ( ) ;
SetMinSize ( get_min_size ( ) ) ;
GetParent ( ) - > Layout ( ) ;
}
2019-04-24 23:45:00 +00:00
int DoubleSlider : : GetActiveValue ( ) const
2018-08-23 12:37:17 +00:00
{
return m_selection = = ssLower ?
m_lower_value : m_selection = = ssHigher ?
m_higher_value : - 1 ;
}
2019-04-24 23:45:00 +00:00
wxSize DoubleSlider : : get_min_size ( ) const
2019-04-16 08:05:45 +00:00
{
const int min_side = is_horizontal ( ) ?
( is_osx ? 8 : 6 ) * Slic3r : : GUI : : wxGetApp ( ) . em_unit ( ) :
/*(is_osx ? 10 : 8)*/ 10 * Slic3r : : GUI : : wxGetApp ( ) . em_unit ( ) ;
return wxSize ( min_side , min_side ) ;
}
2019-04-24 23:45:00 +00:00
wxSize DoubleSlider : : DoGetBestSize ( ) const
2018-08-22 08:44:11 +00:00
{
2018-08-22 12:24:30 +00:00
const wxSize size = wxControl : : DoGetBestSize ( ) ;
2018-08-22 08:44:11 +00:00
if ( size . x > 1 & & size . y > 1 )
return size ;
2019-04-16 08:05:45 +00:00
return get_min_size ( ) ;
2018-08-22 08:44:11 +00:00
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : SetLowerValue ( const int lower_val )
2018-08-21 00:03:10 +00:00
{
2018-09-17 13:12:13 +00:00
m_selection = ssLower ;
2018-08-21 00:03:10 +00:00
m_lower_value = lower_val ;
2018-09-17 13:12:13 +00:00
correct_lower_value ( ) ;
2018-08-21 00:03:10 +00:00
Refresh ( ) ;
Update ( ) ;
2018-09-17 13:12:13 +00:00
wxCommandEvent e ( wxEVT_SCROLL_CHANGED ) ;
e . SetEventObject ( this ) ;
ProcessWindowEvent ( e ) ;
2018-08-21 00:03:10 +00:00
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : SetHigherValue ( const int higher_val )
2018-08-21 00:03:10 +00:00
{
2018-09-17 13:12:13 +00:00
m_selection = ssHigher ;
2018-08-21 00:03:10 +00:00
m_higher_value = higher_val ;
2018-09-17 13:12:13 +00:00
correct_higher_value ( ) ;
2018-08-21 00:03:10 +00:00
Refresh ( ) ;
Update ( ) ;
2018-09-17 13:12:13 +00:00
wxCommandEvent e ( wxEVT_SCROLL_CHANGED ) ;
e . SetEventObject ( this ) ;
ProcessWindowEvent ( e ) ;
2018-08-21 00:03:10 +00:00
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : SetSelectionSpan ( const int lower_val , const int higher_val )
2018-12-20 09:55:50 +00:00
{
m_lower_value = std : : max ( lower_val , m_min_value ) ;
m_higher_value = std : : max ( std : : min ( higher_val , m_max_value ) , m_lower_value ) ;
if ( m_lower_value < m_higher_value )
m_is_one_layer = false ;
Refresh ( ) ;
Update ( ) ;
wxCommandEvent e ( wxEVT_SCROLL_CHANGED ) ;
e . SetEventObject ( this ) ;
ProcessWindowEvent ( e ) ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : SetMaxValue ( const int max_value )
2018-08-23 12:37:17 +00:00
{
m_max_value = max_value ;
Refresh ( ) ;
Update ( ) ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : draw_scroll_line ( wxDC & dc , const int lower_pos , const int higher_pos )
2018-08-21 00:03:10 +00:00
{
int width ;
int height ;
2018-08-24 11:34:38 +00:00
get_size ( & width , & height ) ;
2018-08-21 00:03:10 +00:00
wxCoord line_beg_x = is_horizontal ( ) ? SLIDER_MARGIN : width * 0.5 - 1 ;
wxCoord line_beg_y = is_horizontal ( ) ? height * 0.5 - 1 : SLIDER_MARGIN ;
wxCoord line_end_x = is_horizontal ( ) ? width - SLIDER_MARGIN + 1 : width * 0.5 - 1 ;
wxCoord line_end_y = is_horizontal ( ) ? height * 0.5 - 1 : height - SLIDER_MARGIN + 1 ;
wxCoord segm_beg_x = is_horizontal ( ) ? lower_pos : width * 0.5 - 1 ;
2019-02-26 14:51:23 +00:00
wxCoord segm_beg_y = is_horizontal ( ) ? height * 0.5 - 1 : lower_pos /*-1*/ ;
2018-08-21 00:03:10 +00:00
wxCoord segm_end_x = is_horizontal ( ) ? higher_pos : width * 0.5 - 1 ;
wxCoord segm_end_y = is_horizontal ( ) ? height * 0.5 - 1 : higher_pos - 1 ;
2019-04-24 23:45:00 +00:00
for ( int id = 0 ; id < m_line_pens . size ( ) ; id + + )
2018-08-21 00:03:10 +00:00
{
2019-04-24 23:45:00 +00:00
dc . SetPen ( * m_line_pens [ id ] ) ;
2018-08-21 00:03:10 +00:00
dc . DrawLine ( line_beg_x , line_beg_y , line_end_x , line_end_y ) ;
2019-04-24 23:45:00 +00:00
dc . SetPen ( * m_segm_pens [ id ] ) ;
2018-08-21 00:03:10 +00:00
dc . DrawLine ( segm_beg_x , segm_beg_y , segm_end_x , segm_end_y ) ;
if ( is_horizontal ( ) )
line_beg_y = line_end_y = segm_beg_y = segm_end_y + = 1 ;
else
line_beg_x = line_end_x = segm_beg_x = segm_end_x + = 1 ;
}
}
2019-04-24 23:45:00 +00:00
double DoubleSlider : : get_scroll_step ( )
2018-08-21 00:03:10 +00:00
{
2018-08-24 11:34:38 +00:00
const wxSize sz = get_size ( ) ;
2018-08-21 00:03:10 +00:00
const int & slider_len = m_style = = wxSL_HORIZONTAL ? sz . x : sz . y ;
return double ( slider_len - SLIDER_MARGIN * 2 ) / ( m_max_value - m_min_value ) ;
}
2018-08-22 16:00:48 +00:00
// get position on the slider line from entered value
2019-04-24 23:45:00 +00:00
wxCoord DoubleSlider : : get_position_from_value ( const int value )
2018-08-22 16:00:48 +00:00
{
const double step = get_scroll_step ( ) ;
const int val = is_horizontal ( ) ? value : m_max_value - value ;
return wxCoord ( SLIDER_MARGIN + int ( val * step + 0.5 ) ) ;
}
2019-04-24 23:45:00 +00:00
wxSize DoubleSlider : : get_size ( )
2018-08-24 11:34:38 +00:00
{
int w , h ;
get_size ( & w , & h ) ;
return wxSize ( w , h ) ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : get_size ( int * w , int * h )
2018-08-24 11:34:38 +00:00
{
GetSize ( w , h ) ;
is_horizontal ( ) ? * w - = m_lock_icon_dim : * h - = m_lock_icon_dim ;
}
2019-04-24 23:45:00 +00:00
double DoubleSlider : : get_double_value ( const SelectedSlider & selection )
2018-09-17 13:12:13 +00:00
{
2018-11-28 11:32:43 +00:00
if ( m_values . empty ( ) | | m_lower_value < 0 )
2018-09-17 13:12:13 +00:00
return 0.0 ;
2018-11-27 11:19:39 +00:00
if ( m_values . size ( ) < = m_higher_value ) {
correct_higher_value ( ) ;
return m_values . back ( ) . second ;
}
2018-09-17 13:12:13 +00:00
return m_values [ selection = = ssLower ? m_lower_value : m_higher_value ] . second ;
}
2019-04-24 23:45:00 +00:00
std : : vector < double > DoubleSlider : : GetTicksValues ( ) const
2018-11-07 13:44:47 +00:00
{
std : : vector < double > values ;
if ( ! m_values . empty ( ) )
2019-02-26 14:51:23 +00:00
for ( auto tick : m_ticks ) {
if ( tick > m_values . size ( ) )
break ;
2018-11-07 13:44:47 +00:00
values . push_back ( m_values [ tick ] . second ) ;
2019-02-26 14:51:23 +00:00
}
2018-11-07 13:44:47 +00:00
return values ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : SetTicksValues ( const std : : vector < double > & heights )
2018-11-07 13:44:47 +00:00
{
if ( m_values . empty ( ) )
return ;
2019-02-27 12:37:16 +00:00
const bool was_empty = m_ticks . empty ( ) ;
2018-11-07 13:44:47 +00:00
m_ticks . clear ( ) ;
unsigned int i = 0 ;
for ( auto h : heights ) {
while ( i < m_values . size ( ) & & m_values [ i ] . second - 1e-6 < h )
+ + i ;
if ( i = = m_values . size ( ) )
return ;
2018-11-26 15:07:09 +00:00
m_ticks . insert ( i - 1 ) ;
2018-11-07 13:44:47 +00:00
}
2019-02-27 12:37:16 +00:00
if ( ! was_empty & & m_ticks . empty ( ) )
// Switch to the "Feature type"/"Tool" from the very beginning of a new object slicing after deleting of the old one
wxPostEvent ( this - > GetParent ( ) , wxCommandEvent ( wxCUSTOMEVT_TICKSCHANGED ) ) ;
2018-11-07 13:44:47 +00:00
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : get_lower_and_higher_position ( int & lower_pos , int & higher_pos )
2018-08-21 00:03:10 +00:00
{
const double step = get_scroll_step ( ) ;
if ( is_horizontal ( ) ) {
lower_pos = SLIDER_MARGIN + int ( m_lower_value * step + 0.5 ) ;
higher_pos = SLIDER_MARGIN + int ( m_higher_value * step + 0.5 ) ;
}
else {
lower_pos = SLIDER_MARGIN + int ( ( m_max_value - m_lower_value ) * step + 0.5 ) ;
higher_pos = SLIDER_MARGIN + int ( ( m_max_value - m_higher_value ) * step + 0.5 ) ;
}
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : draw_focus_rect ( )
2018-08-21 15:47:05 +00:00
{
if ( ! m_is_focused )
return ;
const wxSize sz = GetSize ( ) ;
wxPaintDC dc ( this ) ;
const wxPen pen = wxPen ( wxColour ( 128 , 128 , 10 ) , 1 , wxPENSTYLE_DOT ) ;
dc . SetPen ( pen ) ;
dc . SetBrush ( wxBrush ( wxColour ( 0 , 0 , 0 ) , wxBRUSHSTYLE_TRANSPARENT ) ) ;
2018-08-24 11:34:38 +00:00
dc . DrawRectangle ( 1 , 1 , sz . x - 2 , sz . y - 2 ) ;
2018-08-21 15:47:05 +00:00
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : render ( )
2018-08-21 00:03:10 +00:00
{
SetBackgroundColour ( GetParent ( ) - > GetBackgroundColour ( ) ) ;
2018-08-21 15:47:05 +00:00
draw_focus_rect ( ) ;
2018-08-21 00:03:10 +00:00
2018-08-23 11:01:18 +00:00
wxPaintDC dc ( this ) ;
2019-02-26 14:51:23 +00:00
dc . SetFont ( m_font ) ;
2018-08-21 00:03:10 +00:00
2018-08-22 16:00:48 +00:00
const wxCoord lower_pos = get_position_from_value ( m_lower_value ) ;
const wxCoord higher_pos = get_position_from_value ( m_higher_value ) ;
2018-08-21 00:03:10 +00:00
2019-01-10 16:24:23 +00:00
// draw colored band on the background of a scroll line
// and only in a case of no-empty m_values
2019-01-30 13:45:18 +00:00
draw_colored_band ( dc ) ;
2019-01-10 16:24:23 +00:00
2018-08-21 00:03:10 +00:00
// draw line
draw_scroll_line ( dc , lower_pos , higher_pos ) ;
2018-08-24 11:34:38 +00:00
// //lower slider:
// draw_thumb(dc, lower_pos, ssLower);
// //higher slider:
// draw_thumb(dc, higher_pos, ssHigher);
2018-08-21 00:03:10 +00:00
2018-08-24 11:34:38 +00:00
// draw both sliders
draw_thumbs ( dc , lower_pos , higher_pos ) ;
2018-08-22 16:00:48 +00:00
//draw color print ticks
draw_ticks ( dc ) ;
2018-08-24 11:34:38 +00:00
//draw color print ticks
draw_one_layer_icon ( dc ) ;
2018-08-21 00:03:10 +00:00
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : draw_action_icon ( wxDC & dc , const wxPoint pt_beg , const wxPoint pt_end )
2018-08-23 11:01:18 +00:00
{
const int tick = m_selection = = ssLower ? m_lower_value : m_higher_value ;
2019-04-24 23:45:00 +00:00
2019-04-16 08:05:45 +00:00
wxBitmap & icon = m_is_action_icon_focesed ? m_bmp_add_tick_off . bmp ( ) : m_bmp_add_tick_on . bmp ( ) ;
2018-08-23 11:01:18 +00:00
if ( m_ticks . find ( tick ) ! = m_ticks . end ( ) )
2019-04-16 08:05:45 +00:00
icon = m_is_action_icon_focesed ? m_bmp_del_tick_off . bmp ( ) : m_bmp_del_tick_on . bmp ( ) ;
2018-08-23 11:01:18 +00:00
wxCoord x_draw , y_draw ;
is_horizontal ( ) ? x_draw = pt_beg . x - 0.5 * m_tick_icon_dim : y_draw = pt_beg . y - 0.5 * m_tick_icon_dim ;
if ( m_selection = = ssLower )
is_horizontal ( ) ? y_draw = pt_end . y + 3 : x_draw = pt_beg . x - m_tick_icon_dim - 2 ;
else
is_horizontal ( ) ? y_draw = pt_beg . y - m_tick_icon_dim - 2 : x_draw = pt_end . x + 3 ;
2019-04-24 23:45:00 +00:00
dc . DrawBitmap ( icon , x_draw , y_draw ) ;
2018-08-23 11:01:18 +00:00
//update rect of the tick action icon
m_rect_tick_action = wxRect ( x_draw , y_draw , m_tick_icon_dim , m_tick_icon_dim ) ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : draw_info_line_with_icon ( wxDC & dc , const wxPoint & pos , const SelectedSlider selection )
2018-08-21 15:47:05 +00:00
{
if ( m_selection = = selection ) {
2018-08-23 11:01:18 +00:00
//draw info line
2018-08-21 15:47:05 +00:00
dc . SetPen ( DARK_ORANGE_PEN ) ;
2019-02-26 14:51:23 +00:00
const wxPoint pt_beg = is_horizontal ( ) ? wxPoint ( pos . x , pos . y - m_thumb_size . y ) : wxPoint ( pos . x - m_thumb_size . x , pos . y /* - 1*/ ) ;
const wxPoint pt_end = is_horizontal ( ) ? wxPoint ( pos . x , pos . y + m_thumb_size . y ) : wxPoint ( pos . x + m_thumb_size . x , pos . y /* - 1*/ ) ;
2018-08-23 11:01:18 +00:00
dc . DrawLine ( pt_beg , pt_end ) ;
//draw action icon
2018-11-28 15:02:29 +00:00
if ( m_is_enabled_tick_manipulation )
draw_action_icon ( dc , pt_beg , pt_end ) ;
2018-08-21 15:47:05 +00:00
}
}
2019-04-24 23:45:00 +00:00
wxString DoubleSlider : : get_label ( const SelectedSlider & selection ) const
2018-08-21 15:47:05 +00:00
{
2018-08-22 12:24:30 +00:00
const int value = selection = = ssLower ? m_lower_value : m_higher_value ;
2018-08-23 12:37:17 +00:00
if ( m_label_koef = = 1.0 & & m_values . empty ( ) )
2018-08-23 11:01:18 +00:00
return wxString : : Format ( " %d " , value ) ;
2018-11-01 13:16:03 +00:00
if ( value > = m_values . size ( ) )
return " ErrVal " ;
2018-08-23 11:01:18 +00:00
2018-08-23 12:37:17 +00:00
const wxString str = m_values . empty ( ) ?
wxNumberFormatter : : ToString ( m_label_koef * value , 2 , wxNumberFormatter : : Style_None ) :
2018-08-29 11:11:30 +00:00
wxNumberFormatter : : ToString ( m_values [ value ] . second , 2 , wxNumberFormatter : : Style_None ) ;
return wxString : : Format ( " %s \n (%d) " , str , m_values . empty ( ) ? value : m_values [ value ] . first ) ;
2018-08-21 15:47:05 +00:00
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : draw_thumb_text ( wxDC & dc , const wxPoint & pos , const SelectedSlider & selection ) const
2018-08-21 00:03:10 +00:00
{
2018-09-17 13:12:13 +00:00
if ( ( m_is_one_layer | | m_higher_value = = m_lower_value ) & & selection ! = m_selection | | ! selection )
2018-08-24 11:34:38 +00:00
return ;
2018-08-21 00:03:10 +00:00
wxCoord text_width , text_height ;
2018-08-22 12:24:30 +00:00
const wxString label = get_label ( selection ) ;
2018-08-23 11:01:18 +00:00
dc . GetMultiLineTextExtent ( label , & text_width , & text_height ) ;
2018-08-22 12:24:30 +00:00
wxPoint text_pos ;
if ( selection = = ssLower )
text_pos = is_horizontal ( ) ? wxPoint ( pos . x + 1 , pos . y + m_thumb_size . x ) :
wxPoint ( pos . x + m_thumb_size . x + 1 , pos . y - 0.5 * text_height - 1 ) ;
else
text_pos = is_horizontal ( ) ? wxPoint ( pos . x - text_width - 1 , pos . y - m_thumb_size . x - text_height ) :
wxPoint ( pos . x - text_width - 1 - m_thumb_size . x , pos . y - 0.5 * text_height + 1 ) ;
2018-08-21 15:47:05 +00:00
dc . DrawText ( label , text_pos ) ;
2018-08-21 00:03:10 +00:00
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : draw_thumb_item ( wxDC & dc , const wxPoint & pos , const SelectedSlider & selection )
2018-08-21 00:03:10 +00:00
{
wxCoord x_draw , y_draw ;
2018-08-22 12:24:30 +00:00
if ( selection = = ssLower ) {
if ( is_horizontal ( ) ) {
x_draw = pos . x - m_thumb_size . x ;
y_draw = pos . y - int ( 0.5 * m_thumb_size . y ) ;
}
else {
x_draw = pos . x - int ( 0.5 * m_thumb_size . x ) ;
2019-02-26 14:51:23 +00:00
y_draw = pos . y + 1 ;
2018-08-22 12:24:30 +00:00
}
2018-08-21 00:03:10 +00:00
}
2018-08-22 12:24:30 +00:00
else {
if ( is_horizontal ( ) ) {
x_draw = pos . x ;
y_draw = pos . y - int ( 0.5 * m_thumb_size . y ) ;
}
else {
x_draw = pos . x - int ( 0.5 * m_thumb_size . x ) ;
y_draw = pos . y - m_thumb_size . y ;
}
2018-08-21 00:03:10 +00:00
}
2019-04-16 08:05:45 +00:00
dc . DrawBitmap ( selection = = ssLower ? m_bmp_thumb_lower . bmp ( ) : m_bmp_thumb_higher . bmp ( ) , x_draw , y_draw ) ;
2018-08-22 12:24:30 +00:00
// Update thumb rect
update_thumb_rect ( x_draw , y_draw , selection ) ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : draw_thumb ( wxDC & dc , const wxCoord & pos_coord , const SelectedSlider & selection )
2018-08-22 12:24:30 +00:00
{
//calculate thumb position on slider line
int width , height ;
2018-08-24 11:34:38 +00:00
get_size ( & width , & height ) ;
2018-08-22 12:24:30 +00:00
const wxPoint pos = is_horizontal ( ) ? wxPoint ( pos_coord , height * 0.5 ) : wxPoint ( 0.5 * width , pos_coord ) ;
// Draw thumb
draw_thumb_item ( dc , pos , selection ) ;
2018-08-21 15:47:05 +00:00
// Draw info_line
2018-08-23 11:01:18 +00:00
draw_info_line_with_icon ( dc , pos , selection ) ;
2018-08-21 00:03:10 +00:00
// Draw thumb text
2018-08-22 12:24:30 +00:00
draw_thumb_text ( dc , pos , selection ) ;
}
2018-07-30 10:17:32 +00:00
2019-04-24 23:45:00 +00:00
void DoubleSlider : : draw_thumbs ( wxDC & dc , const wxCoord & lower_pos , const wxCoord & higher_pos )
2018-08-24 11:34:38 +00:00
{
//calculate thumb position on slider line
int width , height ;
get_size ( & width , & height ) ;
const wxPoint pos_l = is_horizontal ( ) ? wxPoint ( lower_pos , height * 0.5 ) : wxPoint ( 0.5 * width , lower_pos ) ;
const wxPoint pos_h = is_horizontal ( ) ? wxPoint ( higher_pos , height * 0.5 ) : wxPoint ( 0.5 * width , higher_pos ) ;
// Draw lower thumb
draw_thumb_item ( dc , pos_l , ssLower ) ;
// Draw lower info_line
draw_info_line_with_icon ( dc , pos_l , ssLower ) ;
// Draw higher thumb
draw_thumb_item ( dc , pos_h , ssHigher ) ;
// Draw higher info_line
draw_info_line_with_icon ( dc , pos_h , ssHigher ) ;
// Draw higher thumb text
draw_thumb_text ( dc , pos_h , ssHigher ) ;
// Draw lower thumb text
draw_thumb_text ( dc , pos_l , ssLower ) ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : draw_ticks ( wxDC & dc )
2018-08-22 16:00:48 +00:00
{
2018-11-28 15:02:29 +00:00
dc . SetPen ( m_is_enabled_tick_manipulation ? DARK_GREY_PEN : LIGHT_GREY_PEN ) ;
2018-08-22 16:00:48 +00:00
int height , width ;
2018-08-24 11:34:38 +00:00
get_size ( & width , & height ) ;
2018-08-22 16:00:48 +00:00
const wxCoord mid = is_horizontal ( ) ? 0.5 * height : 0.5 * width ;
for ( auto tick : m_ticks )
{
const wxCoord pos = get_position_from_value ( tick ) ;
is_horizontal ( ) ? dc . DrawLine ( pos , mid - 14 , pos , mid - 9 ) :
2019-02-26 14:51:23 +00:00
dc . DrawLine ( mid - 14 , pos /* - 1*/ , mid - 9 , pos /* - 1*/ ) ;
2018-08-22 16:00:48 +00:00
is_horizontal ( ) ? dc . DrawLine ( pos , mid + 14 , pos , mid + 9 ) :
2019-02-26 14:51:23 +00:00
dc . DrawLine ( mid + 14 , pos /* - 1*/ , mid + 9 , pos /* - 1*/ ) ;
2018-08-22 16:00:48 +00:00
}
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : draw_colored_band ( wxDC & dc )
2019-01-10 16:24:23 +00:00
{
int height , width ;
get_size ( & width , & height ) ;
wxRect main_band = m_rect_lower_thumb ;
if ( is_horizontal ( ) ) {
main_band . SetLeft ( SLIDER_MARGIN ) ;
main_band . SetRight ( width - SLIDER_MARGIN + 1 ) ;
}
else {
const int cut = 2 ;
main_band . x + = cut ;
main_band . width - = 2 * cut ;
main_band . SetTop ( SLIDER_MARGIN ) ;
main_band . SetBottom ( height - SLIDER_MARGIN + 1 ) ;
}
if ( m_ticks . empty ( ) ) {
dc . SetPen ( GetParent ( ) - > GetBackgroundColour ( ) ) ;
dc . SetBrush ( GetParent ( ) - > GetBackgroundColour ( ) ) ;
dc . DrawRectangle ( main_band ) ;
return ;
}
2019-01-30 13:45:18 +00:00
const std : : vector < std : : string > & colors = Slic3r : : GCodePreviewData : : ColorPrintColors ( ) ;
const size_t colors_cnt = colors . size ( ) ;
wxColour clr ( colors [ 0 ] ) ;
2019-01-10 16:24:23 +00:00
dc . SetPen ( clr ) ;
dc . SetBrush ( clr ) ;
dc . DrawRectangle ( main_band ) ;
int i = 1 ;
for ( auto tick : m_ticks )
{
2019-01-30 13:45:18 +00:00
if ( i = = colors_cnt )
2019-01-10 16:24:23 +00:00
i = 0 ;
const wxCoord pos = get_position_from_value ( tick ) ;
is_horizontal ( ) ? main_band . SetLeft ( SLIDER_MARGIN + pos ) :
main_band . SetBottom ( pos - 1 ) ;
2019-01-30 13:45:18 +00:00
clr = wxColour ( colors [ i ] ) ;
2019-01-10 16:24:23 +00:00
dc . SetPen ( clr ) ;
dc . SetBrush ( clr ) ;
dc . DrawRectangle ( main_band ) ;
i + + ;
}
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : draw_one_layer_icon ( wxDC & dc )
2018-08-24 11:34:38 +00:00
{
2019-04-16 08:05:45 +00:00
const wxBitmap & icon = m_is_one_layer ?
m_is_one_layer_icon_focesed ? m_bmp_one_layer_lock_off . bmp ( ) : m_bmp_one_layer_lock_on . bmp ( ) :
m_is_one_layer_icon_focesed ? m_bmp_one_layer_unlock_off . bmp ( ) : m_bmp_one_layer_unlock_on . bmp ( ) ;
2018-08-24 11:34:38 +00:00
int width , height ;
get_size ( & width , & height ) ;
wxCoord x_draw , y_draw ;
is_horizontal ( ) ? x_draw = width - 2 : x_draw = 0.5 * width - 0.5 * m_lock_icon_dim ;
is_horizontal ( ) ? y_draw = 0.5 * height - 0.5 * m_lock_icon_dim : y_draw = height - 2 ;
2019-04-24 23:45:00 +00:00
dc . DrawBitmap ( icon , x_draw , y_draw ) ;
2018-08-24 11:34:38 +00:00
//update rect of the lock/unlock icon
m_rect_one_layer_icon = wxRect ( x_draw , y_draw , m_lock_icon_dim , m_lock_icon_dim ) ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : update_thumb_rect ( const wxCoord & begin_x , const wxCoord & begin_y , const SelectedSlider & selection )
2018-08-22 12:24:30 +00:00
{
const wxRect & rect = wxRect ( begin_x , begin_y , m_thumb_size . x , m_thumb_size . y ) ;
if ( selection = = ssLower )
m_rect_lower_thumb = rect ;
else
m_rect_higher_thumb = rect ;
2018-08-21 00:03:10 +00:00
}
2019-04-24 23:45:00 +00:00
int DoubleSlider : : get_value_from_position ( const wxCoord x , const wxCoord y )
2018-08-21 00:03:10 +00:00
{
2018-08-24 11:34:38 +00:00
const int height = get_size ( ) . y ;
2018-08-21 00:03:10 +00:00
const double step = get_scroll_step ( ) ;
if ( is_horizontal ( ) )
return int ( double ( x - SLIDER_MARGIN ) / step + 0.5 ) ;
else
return int ( m_min_value + double ( height - SLIDER_MARGIN - y ) / step + 0.5 ) ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : detect_selected_slider ( const wxPoint & pt )
2018-08-21 00:03:10 +00:00
{
m_selection = is_point_in_rect ( pt , m_rect_lower_thumb ) ? ssLower :
is_point_in_rect ( pt , m_rect_higher_thumb ) ? ssHigher : ssUndef ;
}
2019-04-24 23:45:00 +00:00
bool DoubleSlider : : is_point_in_rect ( const wxPoint & pt , const wxRect & rect )
2018-08-21 00:03:10 +00:00
{
if ( rect . GetLeft ( ) < = pt . x & & pt . x < = rect . GetRight ( ) & &
rect . GetTop ( ) < = pt . y & & pt . y < = rect . GetBottom ( ) )
return true ;
return false ;
}
2019-04-24 23:45:00 +00:00
int DoubleSlider : : is_point_near_tick ( const wxPoint & pt )
2018-11-27 10:08:34 +00:00
{
for ( auto tick : m_ticks ) {
const wxCoord pos = get_position_from_value ( tick ) ;
if ( is_horizontal ( ) ) {
if ( pos - 4 < = pt . x & & pt . x < = pos + 4 )
return tick ;
}
else {
if ( pos - 4 < = pt . y & & pt . y < = pos + 4 )
return tick ;
}
}
return - 1 ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : ChangeOneLayerLock ( )
2018-09-17 13:12:13 +00:00
{
m_is_one_layer = ! m_is_one_layer ;
m_selection = = ssLower ? correct_lower_value ( ) : correct_higher_value ( ) ;
if ( ! m_selection ) m_selection = ssHigher ;
Refresh ( ) ;
Update ( ) ;
wxCommandEvent e ( wxEVT_SCROLL_CHANGED ) ;
e . SetEventObject ( this ) ;
ProcessWindowEvent ( e ) ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : OnLeftDown ( wxMouseEvent & event )
2018-08-21 00:03:10 +00:00
{
2018-08-24 11:34:38 +00:00
this - > CaptureMouse ( ) ;
2018-08-21 00:03:10 +00:00
wxClientDC dc ( this ) ;
wxPoint pos = event . GetLogicalPosition ( dc ) ;
2018-11-28 15:02:29 +00:00
if ( is_point_in_rect ( pos , m_rect_tick_action ) & & m_is_enabled_tick_manipulation ) {
2018-08-24 11:34:38 +00:00
action_tick ( taOnIcon ) ;
2018-08-23 11:01:18 +00:00
return ;
}
m_is_left_down = true ;
2018-10-31 11:56:08 +00:00
if ( is_point_in_rect ( pos , m_rect_one_layer_icon ) ) {
2018-08-24 11:34:38 +00:00
m_is_one_layer = ! m_is_one_layer ;
2018-11-27 10:08:34 +00:00
if ( ! m_is_one_layer ) {
SetLowerValue ( m_min_value ) ;
SetHigherValue ( m_max_value ) ;
}
2018-08-24 11:34:38 +00:00
m_selection = = ssLower ? correct_lower_value ( ) : correct_higher_value ( ) ;
if ( ! m_selection ) m_selection = ssHigher ;
}
else
detect_selected_slider ( pos ) ;
2018-11-28 15:02:29 +00:00
if ( ! m_selection & & m_is_enabled_tick_manipulation ) {
2018-11-27 10:08:34 +00:00
const auto tick = is_point_near_tick ( pos ) ;
if ( tick > = 0 )
{
if ( abs ( tick - m_lower_value ) < abs ( tick - m_higher_value ) ) {
SetLowerValue ( tick ) ;
correct_lower_value ( ) ;
m_selection = ssLower ;
}
else {
SetHigherValue ( tick ) ;
correct_higher_value ( ) ;
m_selection = ssHigher ;
}
}
}
2018-08-22 12:24:30 +00:00
Refresh ( ) ;
Update ( ) ;
2018-08-21 00:03:10 +00:00
event . Skip ( ) ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : correct_lower_value ( )
2018-08-21 00:03:10 +00:00
{
if ( m_lower_value < m_min_value )
m_lower_value = m_min_value ;
else if ( m_lower_value > m_max_value )
m_lower_value = m_max_value ;
2018-08-24 11:34:38 +00:00
if ( m_lower_value > = m_higher_value & & m_lower_value < = m_max_value | | m_is_one_layer )
m_higher_value = m_lower_value ;
2018-08-21 00:03:10 +00:00
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : correct_higher_value ( )
2018-08-21 00:03:10 +00:00
{
if ( m_higher_value > m_max_value )
m_higher_value = m_max_value ;
else if ( m_higher_value < m_min_value )
m_higher_value = m_min_value ;
2018-08-24 11:34:38 +00:00
if ( m_higher_value < = m_lower_value & & m_higher_value > = m_min_value | | m_is_one_layer )
m_lower_value = m_higher_value ;
2018-08-21 00:03:10 +00:00
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : OnMotion ( wxMouseEvent & event )
2018-08-21 00:03:10 +00:00
{
2018-11-27 13:50:57 +00:00
bool action = false ;
2018-08-24 11:34:38 +00:00
const wxClientDC dc ( this ) ;
const wxPoint pos = event . GetLogicalPosition ( dc ) ;
m_is_one_layer_icon_focesed = is_point_in_rect ( pos , m_rect_one_layer_icon ) ;
2018-10-31 11:56:08 +00:00
if ( ! m_is_left_down & & ! m_is_one_layer ) {
2018-08-23 11:01:18 +00:00
m_is_action_icon_focesed = is_point_in_rect ( pos , m_rect_tick_action ) ;
2018-08-21 00:03:10 +00:00
}
2018-10-31 11:56:08 +00:00
else if ( m_is_left_down | | m_is_right_down ) {
2018-08-23 11:01:18 +00:00
if ( m_selection = = ssLower ) {
2018-08-24 11:34:38 +00:00
m_lower_value = get_value_from_position ( pos . x , pos . y ) ;
2018-08-23 11:01:18 +00:00
correct_lower_value ( ) ;
2018-11-27 13:50:57 +00:00
action = true ;
2018-08-23 11:01:18 +00:00
}
else if ( m_selection = = ssHigher ) {
2018-08-24 11:34:38 +00:00
m_higher_value = get_value_from_position ( pos . x , pos . y ) ;
2018-08-23 11:01:18 +00:00
correct_higher_value ( ) ;
2018-11-27 13:50:57 +00:00
action = true ;
2018-08-23 11:01:18 +00:00
}
2018-08-21 00:03:10 +00:00
}
Refresh ( ) ;
Update ( ) ;
event . Skip ( ) ;
2018-09-17 13:12:13 +00:00
2018-11-27 13:50:57 +00:00
if ( action )
{
wxCommandEvent e ( wxEVT_SCROLL_CHANGED ) ;
e . SetEventObject ( this ) ;
ProcessWindowEvent ( e ) ;
}
2018-08-21 00:03:10 +00:00
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : OnLeftUp ( wxMouseEvent & event )
2018-08-21 00:03:10 +00:00
{
2019-01-11 08:00:35 +00:00
if ( ! HasCapture ( ) )
return ;
2018-08-24 11:34:38 +00:00
this - > ReleaseMouse ( ) ;
2018-08-21 00:03:10 +00:00
m_is_left_down = false ;
2018-08-21 15:47:05 +00:00
Refresh ( ) ;
Update ( ) ;
2018-08-21 00:03:10 +00:00
event . Skip ( ) ;
wxCommandEvent e ( wxEVT_SCROLL_CHANGED ) ;
e . SetEventObject ( this ) ;
ProcessWindowEvent ( e ) ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : enter_window ( wxMouseEvent & event , const bool enter )
2018-08-21 00:03:10 +00:00
{
2018-08-24 11:34:38 +00:00
m_is_focused = enter ;
2018-08-21 15:47:05 +00:00
Refresh ( ) ;
Update ( ) ;
event . Skip ( ) ;
}
2018-08-21 00:03:10 +00:00
2018-08-21 15:47:05 +00:00
// "condition" have to be true for:
// - value increase (if wxSL_VERTICAL)
// - value decrease (if wxSL_HORIZONTAL)
2019-04-24 23:45:00 +00:00
void DoubleSlider : : move_current_thumb ( const bool condition )
2018-08-21 15:47:05 +00:00
{
2018-12-19 14:58:01 +00:00
// m_is_one_layer = wxGetKeyState(WXK_CONTROL);
2018-08-21 15:47:05 +00:00
int delta = condition ? - 1 : 1 ;
2018-08-21 00:03:10 +00:00
if ( is_horizontal ( ) )
delta * = - 1 ;
2018-08-21 15:47:05 +00:00
2018-08-21 00:03:10 +00:00
if ( m_selection = = ssLower ) {
m_lower_value - = delta ;
correct_lower_value ( ) ;
}
else if ( m_selection = = ssHigher ) {
m_higher_value - = delta ;
correct_higher_value ( ) ;
}
Refresh ( ) ;
Update ( ) ;
wxCommandEvent e ( wxEVT_SCROLL_CHANGED ) ;
e . SetEventObject ( this ) ;
ProcessWindowEvent ( e ) ;
}
2018-08-21 15:47:05 +00:00
2019-04-24 23:45:00 +00:00
void DoubleSlider : : action_tick ( const TicksAction action )
2018-08-23 11:01:18 +00:00
{
if ( m_selection = = ssUndef )
return ;
const int tick = m_selection = = ssLower ? m_lower_value : m_higher_value ;
2018-11-26 15:07:09 +00:00
if ( action = = taOnIcon ) {
if ( ! m_ticks . insert ( tick ) . second )
m_ticks . erase ( tick ) ;
}
2018-08-24 11:34:38 +00:00
else {
const auto it = m_ticks . find ( tick ) ;
if ( it = = m_ticks . end ( ) & & action = = taAdd )
m_ticks . insert ( tick ) ;
else if ( it ! = m_ticks . end ( ) & & action = = taDel )
m_ticks . erase ( tick ) ;
}
2018-08-23 11:01:18 +00:00
2018-11-07 13:44:47 +00:00
wxPostEvent ( this - > GetParent ( ) , wxCommandEvent ( wxCUSTOMEVT_TICKSCHANGED ) ) ;
2018-08-23 11:01:18 +00:00
Refresh ( ) ;
Update ( ) ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : OnWheel ( wxMouseEvent & event )
2018-08-21 15:47:05 +00:00
{
2019-03-11 11:58:46 +00:00
// Set nearest to the mouse thumb as a selected, if there is not selected thumb
if ( m_selection = = ssUndef )
{
const wxPoint & pt = event . GetLogicalPosition ( wxClientDC ( this ) ) ;
if ( is_horizontal ( ) )
m_selection = abs ( pt . x - m_rect_lower_thumb . GetRight ( ) ) < =
abs ( pt . x - m_rect_higher_thumb . GetLeft ( ) ) ?
ssLower : ssHigher ;
else
m_selection = abs ( pt . y - m_rect_lower_thumb . GetTop ( ) ) < =
abs ( pt . y - m_rect_higher_thumb . GetBottom ( ) ) ?
ssLower : ssHigher ;
}
2018-08-21 15:47:05 +00:00
move_current_thumb ( event . GetWheelRotation ( ) > 0 ) ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : OnKeyDown ( wxKeyEvent & event )
2018-08-21 15:47:05 +00:00
{
2018-08-23 11:01:18 +00:00
const int key = event . GetKeyCode ( ) ;
if ( key = = ' + ' | | key = = WXK_NUMPAD_ADD )
action_tick ( taAdd ) ;
else if ( key = = ' - ' | | key = = 390 | | key = = WXK_DELETE | | key = = WXK_BACK )
action_tick ( taDel ) ;
else if ( is_horizontal ( ) )
2018-08-21 15:47:05 +00:00
{
2018-08-23 11:01:18 +00:00
if ( key = = WXK_LEFT | | key = = WXK_RIGHT )
move_current_thumb ( key = = WXK_LEFT ) ;
2018-10-31 11:56:08 +00:00
else if ( key = = WXK_UP | | key = = WXK_DOWN ) {
2018-08-23 11:01:18 +00:00
m_selection = key = = WXK_UP ? ssHigher : ssLower ;
2018-08-21 15:47:05 +00:00
Refresh ( ) ;
}
}
else {
2018-08-23 11:01:18 +00:00
if ( key = = WXK_LEFT | | key = = WXK_RIGHT ) {
m_selection = key = = WXK_LEFT ? ssHigher : ssLower ;
2018-08-21 15:47:05 +00:00
Refresh ( ) ;
}
2018-08-23 11:01:18 +00:00
else if ( key = = WXK_UP | | key = = WXK_DOWN )
move_current_thumb ( key = = WXK_UP ) ;
2018-08-21 15:47:05 +00:00
}
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : OnKeyUp ( wxKeyEvent & event )
2018-08-24 11:34:38 +00:00
{
if ( event . GetKeyCode ( ) = = WXK_CONTROL )
m_is_one_layer = false ;
Refresh ( ) ;
Update ( ) ;
event . Skip ( ) ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : OnRightDown ( wxMouseEvent & event )
2018-08-22 16:00:48 +00:00
{
2018-08-24 11:34:38 +00:00
this - > CaptureMouse ( ) ;
const wxClientDC dc ( this ) ;
detect_selected_slider ( event . GetLogicalPosition ( dc ) ) ;
if ( ! m_selection )
2018-08-22 16:00:48 +00:00
return ;
2018-08-24 11:34:38 +00:00
if ( m_selection = = ssLower )
m_higher_value = m_lower_value ;
else
m_lower_value = m_higher_value ;
m_is_right_down = m_is_one_layer = true ;
2018-08-22 16:00:48 +00:00
Refresh ( ) ;
Update ( ) ;
2018-08-24 11:34:38 +00:00
event . Skip ( ) ;
}
2019-04-24 23:45:00 +00:00
void DoubleSlider : : OnRightUp ( wxMouseEvent & event )
2018-08-24 11:34:38 +00:00
{
2019-01-11 08:00:35 +00:00
if ( ! HasCapture ( ) )
return ;
2018-08-24 11:34:38 +00:00
this - > ReleaseMouse ( ) ;
m_is_right_down = m_is_one_layer = false ;
Refresh ( ) ;
Update ( ) ;
event . Skip ( ) ;
2018-08-22 16:00:48 +00:00
}
2018-08-28 13:51:53 +00:00
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
// LockButton
2018-08-28 13:51:53 +00:00
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
LockButton : : LockButton ( wxWindow * parent ,
wxWindowID id ,
const wxPoint & pos /*= wxDefaultPosition*/ ,
const wxSize & size /*= wxDefaultSize*/ ) :
wxButton ( parent , id , wxEmptyString , pos , size , wxBU_EXACTFIT | wxNO_BORDER )
2018-08-28 13:51:53 +00:00
{
2019-04-24 23:45:00 +00:00
m_bmp_lock_on = ScalableBitmap ( this , " one_layer_lock_on.png " ) ;
m_bmp_lock_off = ScalableBitmap ( this , " one_layer_lock_off.png " ) ;
m_bmp_unlock_on = ScalableBitmap ( this , " one_layer_unlock_on.png " ) ;
m_bmp_unlock_off = ScalableBitmap ( this , " one_layer_unlock_off.png " ) ;
2018-08-28 13:51:53 +00:00
# ifdef __WXMSW__
SetBackgroundColour ( wxSystemSettings : : GetColour ( wxSYS_COLOUR_WINDOW ) ) ;
# endif // __WXMSW__
2019-04-16 08:05:45 +00:00
SetBitmap ( m_bmp_unlock_on . bmp ( ) ) ;
SetBitmapDisabled ( m_bmp_lock_on . bmp ( ) ) ;
2018-08-28 13:51:53 +00:00
//button events
2019-04-24 23:45:00 +00:00
Bind ( wxEVT_BUTTON , & LockButton : : OnButton , this ) ;
Bind ( wxEVT_ENTER_WINDOW , & LockButton : : OnEnterBtn , this ) ;
Bind ( wxEVT_LEAVE_WINDOW , & LockButton : : OnLeaveBtn , this ) ;
2018-08-28 13:51:53 +00:00
}
2019-04-24 23:45:00 +00:00
void LockButton : : OnButton ( wxCommandEvent & event )
2018-08-28 13:51:53 +00:00
{
m_is_pushed = ! m_is_pushed ;
enter_button ( true ) ;
event . Skip ( ) ;
}
2019-04-24 23:45:00 +00:00
void LockButton : : SetLock ( bool lock )
2019-01-09 07:48:25 +00:00
{
m_is_pushed = lock ;
enter_button ( true ) ;
}
2019-04-24 23:45:00 +00:00
void LockButton : : msw_rescale ( )
2019-04-16 08:05:45 +00:00
{
2019-04-24 23:45:00 +00:00
m_bmp_lock_on . msw_rescale ( ) ;
m_bmp_lock_off . msw_rescale ( ) ;
m_bmp_unlock_on . msw_rescale ( ) ;
m_bmp_unlock_off . msw_rescale ( ) ;
2019-04-16 08:05:45 +00:00
}
2019-04-24 23:45:00 +00:00
void LockButton : : enter_button ( const bool enter )
2018-08-28 13:51:53 +00:00
{
2019-04-16 08:05:45 +00:00
const wxBitmap & icon = m_is_pushed ?
enter ? m_bmp_lock_off . bmp ( ) : m_bmp_lock_on . bmp ( ) :
enter ? m_bmp_unlock_off . bmp ( ) : m_bmp_unlock_on . bmp ( ) ;
SetBitmap ( icon ) ;
2018-08-28 13:51:53 +00:00
Refresh ( ) ;
Update ( ) ;
}
2019-01-10 10:05:58 +00:00
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
// ModeButton
2019-01-10 10:05:58 +00:00
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
ModeButton : : ModeButton ( wxWindow * parent ,
wxWindowID id ,
const std : : string & icon_name /* = ""*/ ,
const wxString & mode /* = wxEmptyString*/ ,
const wxSize & size /* = wxDefaultSize*/ ,
const wxPoint & pos /* = wxDefaultPosition*/ ) :
2019-04-13 21:46:52 +00:00
// wxButton(parent, id, mode, pos, wxDefaultSize/*size*/, wxBU_EXACTFIT | wxNO_BORDER),
2019-04-24 23:45:00 +00:00
ScalableButton ( parent , id , icon_name , mode , size , pos )
2019-01-10 10:05:58 +00:00
{
2019-02-26 09:50:00 +00:00
m_tt_focused = wxString : : Format ( _ ( L ( " Switch to the %s mode " ) ) , mode ) ;
m_tt_selected = wxString : : Format ( _ ( L ( " Current mode is %s " ) ) , mode ) ;
2019-01-10 10:05:58 +00:00
//button events
2019-04-24 23:45:00 +00:00
Bind ( wxEVT_BUTTON , & ModeButton : : OnButton , this ) ;
Bind ( wxEVT_ENTER_WINDOW , & ModeButton : : OnEnterBtn , this ) ;
Bind ( wxEVT_LEAVE_WINDOW , & ModeButton : : OnLeaveBtn , this ) ;
2019-01-10 10:05:58 +00:00
}
2019-04-24 23:45:00 +00:00
void ModeButton : : OnButton ( wxCommandEvent & event )
2019-01-10 10:05:58 +00:00
{
m_is_selected = true ;
focus_button ( m_is_selected ) ;
event . Skip ( ) ;
}
2019-04-24 23:45:00 +00:00
void ModeButton : : SetState ( const bool state )
2019-01-10 10:05:58 +00:00
{
m_is_selected = state ;
focus_button ( m_is_selected ) ;
2019-02-26 09:50:00 +00:00
SetToolTip ( state ? m_tt_selected : m_tt_focused ) ;
2019-01-10 10:05:58 +00:00
}
2019-04-24 23:45:00 +00:00
void ModeButton : : focus_button ( const bool focus )
2019-01-10 10:05:58 +00:00
{
2019-04-29 07:43:42 +00:00
const wxFont & new_font = focus ?
Slic3r : : GUI : : wxGetApp ( ) . bold_font ( ) :
Slic3r : : GUI : : wxGetApp ( ) . normal_font ( ) ;
2019-04-10 07:56:32 +00:00
2019-01-10 10:05:58 +00:00
SetFont ( new_font ) ;
Refresh ( ) ;
Update ( ) ;
}
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
// ModeSizer
2019-01-10 10:05:58 +00:00
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
ModeSizer : : ModeSizer ( wxWindow * parent , int hgap /* = 10*/ ) :
2019-02-11 14:36:05 +00:00
wxFlexGridSizer ( 3 , 0 , hgap )
2019-01-10 10:05:58 +00:00
{
SetFlexibleDirection ( wxHORIZONTAL ) ;
2019-04-13 21:46:52 +00:00
std : : vector < std : : pair < wxString , std : : string > > buttons = {
2019-04-24 23:45:00 +00:00
{ _ ( L ( " Simple " ) ) , " mode_simple_sq.png " } ,
{ _ ( L ( " Advanced " ) ) , " mode_middle_sq.png " } ,
{ _ ( L ( " Expert " ) ) , " mode_expert_sq.png " }
2019-02-11 13:14:35 +00:00
} ;
2019-02-06 14:29:13 +00:00
2019-04-24 23:45:00 +00:00
m_mode_btns . reserve ( 3 ) ;
2019-02-11 13:14:35 +00:00
for ( const auto & button : buttons ) {
2019-04-29 13:27:59 +00:00
m_mode_btns . push_back ( new ModeButton ( parent , wxID_ANY , button . second , button . first ) ) ;
2019-02-11 13:14:35 +00:00
}
2019-01-10 10:05:58 +00:00
2019-04-24 23:45:00 +00:00
for ( auto btn : m_mode_btns )
2019-01-10 10:05:58 +00:00
{
btn - > Bind ( wxEVT_BUTTON , [ btn , this ] ( wxCommandEvent & event ) {
event . Skip ( ) ;
int mode_id = 0 ;
2019-04-24 23:45:00 +00:00
for ( auto cur_btn : m_mode_btns ) {
2019-01-10 10:05:58 +00:00
if ( cur_btn = = btn )
break ;
else
mode_id + + ;
}
Slic3r : : GUI : : wxGetApp ( ) . save_mode ( mode_id ) ;
} ) ;
Add ( btn ) ;
}
}
2019-04-24 23:45:00 +00:00
void ModeSizer : : SetMode ( const int mode )
2019-01-10 10:05:58 +00:00
{
2019-04-24 23:45:00 +00:00
for ( int m = 0 ; m < m_mode_btns . size ( ) ; m + + )
m_mode_btns [ m ] - > SetState ( m = = mode ) ;
2019-01-10 10:05:58 +00:00
}
2019-01-25 12:16:32 +00:00
2019-04-24 23:45:00 +00:00
void ModeSizer : : msw_rescale ( )
2019-04-13 21:46:52 +00:00
{
2019-04-24 23:45:00 +00:00
for ( int m = 0 ; m < m_mode_btns . size ( ) ; m + + )
m_mode_btns [ m ] - > msw_rescale ( ) ;
2019-04-13 21:46:52 +00:00
}
2019-01-25 12:16:32 +00:00
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
// MenuWithSeparators
2019-01-25 12:16:32 +00:00
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
void MenuWithSeparators : : DestroySeparators ( )
2019-01-25 12:16:32 +00:00
{
if ( m_separator_frst ) {
Destroy ( m_separator_frst ) ;
m_separator_frst = nullptr ;
}
if ( m_separator_scnd ) {
Destroy ( m_separator_scnd ) ;
m_separator_scnd = nullptr ;
}
}
2019-04-24 23:45:00 +00:00
void MenuWithSeparators : : SetFirstSeparator ( )
{
m_separator_frst = this - > AppendSeparator ( ) ;
}
void MenuWithSeparators : : SetSecondSeparator ( )
{
m_separator_scnd = this - > AppendSeparator ( ) ;
}
2019-01-25 12:16:32 +00:00
2019-04-13 21:46:52 +00:00
// ----------------------------------------------------------------------------
// PrusaBitmap
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
ScalableBitmap : : ScalableBitmap ( wxWindow * parent ,
const std : : string & icon_name /* = ""*/ ,
const int px_cnt /* = 16*/ ,
const bool is_horizontal /* = false*/ ) :
m_parent ( parent ) , m_icon_name ( icon_name ) ,
m_px_cnt ( px_cnt ) , m_is_horizontal ( is_horizontal )
2019-04-13 21:46:52 +00:00
{
2019-04-16 08:05:45 +00:00
m_bmp = create_scaled_bitmap ( parent , icon_name , px_cnt , is_horizontal ) ;
2019-04-13 21:46:52 +00:00
}
2019-04-24 23:45:00 +00:00
void ScalableBitmap : : msw_rescale ( )
2019-04-13 21:46:52 +00:00
{
2019-04-16 08:05:45 +00:00
m_bmp = create_scaled_bitmap ( m_parent , m_icon_name , m_px_cnt , m_is_horizontal ) ;
2019-04-13 21:46:52 +00:00
}
// ----------------------------------------------------------------------------
// PrusaButton
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
ScalableButton : : ScalableButton ( wxWindow * parent ,
wxWindowID id ,
const std : : string & icon_name /*= ""*/ ,
const wxString & label /* = wxEmptyString*/ ,
const wxSize & size /* = wxDefaultSize*/ ,
const wxPoint & pos /* = wxDefaultPosition*/ ,
long style /*= wxBU_EXACTFIT | wxNO_BORDER*/ ) :
2019-04-13 21:46:52 +00:00
m_current_icon_name ( icon_name ) ,
m_parent ( parent )
{
Create ( parent , id , label , pos , size , style ) ;
# ifdef __WXMSW__
if ( style & wxNO_BORDER )
SetBackgroundColour ( wxSystemSettings : : GetColour ( wxSYS_COLOUR_WINDOW ) ) ;
# endif // __WXMSW__
2019-04-16 08:05:45 +00:00
SetBitmap ( create_scaled_bitmap ( parent , icon_name ) ) ;
2019-04-13 21:46:52 +00:00
}
2019-04-24 23:45:00 +00:00
ScalableButton : : ScalableButton ( wxWindow * parent ,
wxWindowID id ,
const ScalableBitmap & bitmap ,
const wxString & label /*= wxEmptyString*/ ,
long style /*= wxBU_EXACTFIT | wxNO_BORDER*/ ) :
2019-04-13 21:46:52 +00:00
m_current_icon_name ( bitmap . name ( ) ) ,
m_parent ( parent )
{
Create ( parent , id , label , wxDefaultPosition , wxDefaultSize , style ) ;
# ifdef __WXMSW__
if ( style & wxNO_BORDER )
SetBackgroundColour ( wxSystemSettings : : GetColour ( wxSYS_COLOUR_WINDOW ) ) ;
# endif // __WXMSW__
2019-04-16 08:05:45 +00:00
SetBitmap ( bitmap . bmp ( ) ) ;
2019-04-13 21:46:52 +00:00
}
2019-04-24 23:45:00 +00:00
void ScalableButton : : SetBitmap_ ( const ScalableBitmap & bmp )
2019-04-13 21:46:52 +00:00
{
SetBitmap ( bmp . bmp ( ) ) ;
m_current_icon_name = bmp . name ( ) ;
}
2019-04-24 23:45:00 +00:00
void ScalableButton : : msw_rescale ( )
2019-04-13 21:46:52 +00:00
{
const wxBitmap bmp = create_scaled_bitmap ( m_parent , m_current_icon_name ) ;
SetBitmap ( bmp ) ;
}
2018-08-29 09:21:22 +00:00
2018-08-28 13:51:53 +00:00
2018-08-29 09:21:22 +00:00