2018-02-02 11:38:35 +00:00
# include "wxExtensions.hpp"
2019-04-05 16:53:02 +00:00
# include <stdexcept>
2019-05-17 17:12:52 +00:00
# include <cmath>
2019-04-05 16:53:02 +00:00
2018-11-26 13:41:58 +00:00
# include "libslic3r/Utils.hpp"
# include "libslic3r/Model.hpp"
2020-01-15 14:35:56 +00:00
# include "libslic3r/Print.hpp"
2018-05-10 14:36:12 +00:00
# include <wx/sizer.h>
2019-09-30 12:03:50 +00:00
# include <wx/bmpcbox.h>
2018-05-10 14:36:12 +00:00
# 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>
2019-11-07 15:36:24 +00:00
# include <wx/colordlg.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"
2019-09-30 12:03:50 +00:00
# include "PresetBundle.hpp"
2019-10-18 10:35:35 +00:00
# include "ExtruderSequenceDialog.hpp"
2019-05-17 17:12:52 +00:00
# include "../Utils/MacDarkMode.hpp"
2018-05-10 14:36:12 +00:00
2019-01-07 18:17:10 +00:00
using Slic3r : : GUI : : from_u8 ;
2019-11-27 13:44:33 +00:00
using Slic3r : : GUI : : into_u8 ;
2019-01-07 18:17:10 +00:00
2018-11-12 12:47:24 +00:00
wxDEFINE_EVENT ( wxCUSTOMEVT_LAST_VOLUME_IS_DELETED , wxCommandEvent ) ;
2018-11-07 13:44:47 +00:00
2019-05-13 12:27:51 +00:00
# ifndef __WXGTK__ // msw_menuitem_bitmaps is used for MSW and OSX
2019-05-07 11:35:37 +00:00
static std : : map < int , std : : string > msw_menuitem_bitmaps ;
2019-05-13 12:27:51 +00:00
# ifdef __WXMSW__
2019-05-03 07:44:19 +00:00
void msw_rescale_menu ( wxMenu * menu )
{
2019-05-07 11:35:37 +00:00
struct update_icons {
static void run ( wxMenuItem * item ) {
const auto it = msw_menuitem_bitmaps . find ( item - > GetId ( ) ) ;
if ( it ! = msw_menuitem_bitmaps . end ( ) ) {
const wxBitmap & item_icon = create_scaled_bitmap ( nullptr , it - > second ) ;
if ( item_icon . IsOk ( ) )
item - > SetBitmap ( item_icon ) ;
}
if ( item - > IsSubMenu ( ) )
for ( wxMenuItem * sub_item : item - > GetSubMenu ( ) - > GetMenuItems ( ) )
update_icons : : run ( sub_item ) ;
}
} ;
for ( wxMenuItem * item : menu - > GetMenuItems ( ) )
update_icons : : run ( item ) ;
2019-05-03 07:44:19 +00:00
}
2019-05-07 11:35:37 +00:00
# endif /* __WXMSW__ */
2019-05-13 12:27:51 +00:00
# endif /* no __WXGTK__ */
2019-12-18 14:54:01 +00:00
void enable_menu_item ( wxUpdateUIEvent & evt , std : : function < bool ( ) > const cb_condition , wxMenuItem * item , wxWindow * win )
2019-05-13 12:27:51 +00:00
{
const bool enable = cb_condition ( ) ;
evt . Enable ( enable ) ;
# ifdef __WXOSX__
const auto it = msw_menuitem_bitmaps . find ( item - > GetId ( ) ) ;
if ( it ! = msw_menuitem_bitmaps . end ( ) )
{
2019-12-18 14:54:01 +00:00
const wxBitmap & item_icon = create_scaled_bitmap ( win , it - > second , 16 , false , ! enable ) ;
2019-05-13 15:57:31 +00:00
if ( item_icon . IsOk ( ) )
item - > SetBitmap ( item_icon ) ;
2019-05-13 12:27:51 +00:00
}
# endif // __WXOSX__
}
2019-05-03 07:44:19 +00:00
2018-10-17 10:17:25 +00:00
wxMenuItem * append_menu_item ( wxMenu * menu , int id , const wxString & string , const wxString & description ,
2019-05-13 12:27:51 +00:00
std : : function < void ( wxCommandEvent & event ) > cb , const wxBitmap & icon , wxEvtHandler * event_handler ,
std : : function < bool ( ) > const cb_condition , wxWindow * parent )
2018-10-17 10:17:25 +00:00
{
if ( id = = wxID_ANY )
id = wxNewId ( ) ;
2019-05-07 11:35:37 +00:00
auto * item = new wxMenuItem ( menu , id , string , description ) ;
if ( icon . IsOk ( ) ) {
2019-05-03 07:44:19 +00:00
item - > SetBitmap ( icon ) ;
}
2019-05-07 11:35:37 +00:00
menu - > Append ( item ) ;
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 ) ;
2019-05-13 12:27:51 +00:00
if ( parent ) {
2019-12-18 14:54:01 +00:00
parent - > Bind ( wxEVT_UPDATE_UI , [ cb_condition , item , parent ] ( wxUpdateUIEvent & evt ) {
enable_menu_item ( evt , cb_condition , item , parent ) ; } , id ) ;
2019-05-13 12:27:51 +00:00
}
2018-10-18 12:42:21 +00:00
return item ;
}
2018-12-06 13:49:14 +00:00
wxMenuItem * append_menu_item ( wxMenu * menu , int id , const wxString & string , const wxString & description ,
2019-05-13 12:27:51 +00:00
std : : function < void ( wxCommandEvent & event ) > cb , const std : : string & icon , wxEvtHandler * event_handler ,
std : : function < bool ( ) > const cb_condition , wxWindow * parent )
2018-12-06 13:49:14 +00:00
{
2019-05-03 07:44:19 +00:00
if ( id = = wxID_ANY )
id = wxNewId ( ) ;
2019-12-18 14:54:01 +00:00
const wxBitmap & bmp = ! icon . empty ( ) ? create_scaled_bitmap ( parent , icon ) : wxNullBitmap ; // FIXME: pass window ptr
2019-05-13 12:27:51 +00:00
//#ifdef __WXMSW__
# ifndef __WXGTK__
2019-05-03 07:44:19 +00:00
if ( bmp . IsOk ( ) )
2019-05-07 11:35:37 +00:00
msw_menuitem_bitmaps [ id ] = icon ;
# endif /* __WXMSW__ */
2019-05-03 07:44:19 +00:00
2019-05-13 12:27:51 +00:00
return append_menu_item ( menu , id , string , description , cb , bmp , event_handler , cb_condition , parent ) ;
2018-12-06 13:49:14 +00:00
}
2019-05-13 12:27:51 +00:00
wxMenuItem * append_submenu ( wxMenu * menu , wxMenu * sub_menu , int id , const wxString & string , const wxString & description , const std : : string & icon ,
std : : function < bool ( ) > const cb_condition , wxWindow * parent )
2018-10-18 12:42:21 +00:00
{
if ( id = = wxID_ANY )
id = wxNewId ( ) ;
wxMenuItem * item = new wxMenuItem ( menu , id , string , description ) ;
2019-05-07 11:35:37 +00:00
if ( ! icon . empty ( ) ) {
2019-12-18 14:54:01 +00:00
item - > SetBitmap ( create_scaled_bitmap ( parent , icon ) ) ; // FIXME: pass window ptr
2019-05-13 12:27:51 +00:00
//#ifdef __WXMSW__
# ifndef __WXGTK__
2019-05-07 11:35:37 +00:00
msw_menuitem_bitmaps [ id ] = icon ;
# endif /* __WXMSW__ */
}
2018-10-18 12:42:21 +00:00
item - > SetSubMenu ( sub_menu ) ;
menu - > Append ( item ) ;
2019-05-13 12:27:51 +00:00
if ( parent ) {
2019-12-18 14:54:01 +00:00
parent - > Bind ( wxEVT_UPDATE_UI , [ cb_condition , item , parent ] ( wxUpdateUIEvent & evt ) {
enable_menu_item ( evt , cb_condition , item , parent ) ; } , id ) ;
2019-05-13 12:27:51 +00:00
}
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 ;
}
2019-07-31 08:12:13 +00:00
wxMenuItem * append_menu_check_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 - > AppendCheckItem ( 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 )
{
2019-05-06 16:28:23 +00:00
wxTopLevelWindow * toplevel = Slic3r : : GUI : : find_toplevel_parent ( win ) ;
Slic3r : : GUI : : DPIDialog * dlg = dynamic_cast < Slic3r : : GUI : : DPIDialog * > ( toplevel ) ;
2019-04-17 19:35:53 +00:00
if ( dlg )
2019-04-18 13:05:17 +00:00
return dlg - > em_unit ( ) ;
2019-05-06 16:28:23 +00:00
Slic3r : : GUI : : DPIFrame * frame = dynamic_cast < Slic3r : : GUI : : DPIFrame * > ( toplevel ) ;
if ( frame )
return frame - > em_unit ( ) ;
2019-04-17 19:35:53 +00:00
}
return Slic3r : : GUI : : wxGetApp ( ) . em_unit ( ) ;
}
2018-07-04 06:54:30 +00:00
2020-01-23 14:07:31 +00:00
float get_svg_scale_factor ( wxWindow * win )
2019-11-08 13:52:11 +00:00
{
# ifdef __APPLE__
// Note: win->GetContentScaleFactor() is not used anymore here because it tends to
// return bogus results quite often (such as 1.0 on Retina or even 0.0).
// We're using the max scaling factor across all screens because it's very likely to be good enough.
static float max_scaling_factor = NAN ;
if ( std : : isnan ( max_scaling_factor ) ) {
max_scaling_factor = Slic3r : : GUI : : mac_max_scaling_factor ( ) ;
}
return win ! = nullptr ? max_scaling_factor : 1.0f ;
# else
return 1.0f ;
# endif
}
2019-04-05 09:18:13 +00:00
// If an icon has horizontal orientation (width > height) call this function with is_horizontal = true
2019-05-13 15:57:31 +00:00
wxBitmap create_scaled_bitmap ( wxWindow * win , const std : : string & bmp_name_in ,
const int px_cnt /* = 16*/ , const bool is_horizontal /* = false*/ , const bool grayscale /* = 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-05-17 17:12:52 +00:00
// Note: win->GetContentScaleFactor() is not used anymore here because it tends to
// return bogus results quite often (such as 1.0 on Retina or even 0.0).
// We're using the max scaling factor across all screens because it's very likely to be good enough.
static float max_scaling_factor = NAN ;
if ( std : : isnan ( max_scaling_factor ) ) {
max_scaling_factor = Slic3r : : GUI : : mac_max_scaling_factor ( ) ;
}
const float scale_factor = win ! = nullptr ? max_scaling_factor : 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
2020-01-02 12:41:49 +00:00
std : : string bmp_name = bmp_name_in ;
boost : : replace_last ( bmp_name , " .png " , " " ) ;
2019-12-18 14:54:01 +00:00
2020-01-02 12:41:49 +00:00
// std::string bmp_name = icon_name_respected_to_mode(bmp_name_in);
2019-04-05 16:53:02 +00:00
// Try loading an SVG first, then PNG if SVG is not found:
2020-01-02 12:41:49 +00:00
wxBitmap * bmp = cache . load_svg ( bmp_name , width , height , scale_factor , grayscale , Slic3r : : GUI : : wxGetApp ( ) . dark_mode ( ) ) ;
2019-04-09 12:18:03 +00:00
if ( bmp = = nullptr ) {
2019-05-13 15:57:31 +00:00
bmp = cache . load_png ( bmp_name , width , height , grayscale ) ;
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-10-01 16:19:28 +00:00
Slic3r : : GUI : : BitmapCache * m_bitmap_cache = nullptr ;
2019-10-24 08:38:36 +00:00
std : : vector < wxBitmap * > get_extruder_color_icons ( bool thin_icon /* = false*/ )
2019-10-01 16:19:28 +00:00
{
// Create the bitmap with color bars.
std : : vector < wxBitmap * > bmps ;
std : : vector < std : : string > colors = Slic3r : : GUI : : wxGetApp ( ) . plater ( ) - > get_extruder_colors_from_plater_config ( ) ;
2019-10-08 09:05:59 +00:00
if ( colors . empty ( ) )
2019-10-07 10:36:16 +00:00
return bmps ;
2019-10-01 16:19:28 +00:00
unsigned char rgb [ 3 ] ;
/* It's supposed that standard size of an icon is 36px*16px for 100% scaled display.
* So set sizes for solid_colored icons used for filament preset
* and scale them in respect to em_unit value
*/
const double em = Slic3r : : GUI : : wxGetApp ( ) . em_unit ( ) ;
2019-10-24 08:38:36 +00:00
const int icon_width = lround ( ( thin_icon ? 1 : 3.2 ) * em ) ;
2019-10-01 16:19:28 +00:00
const int icon_height = lround ( 1.6 * em ) ;
for ( const std : : string & color : colors )
{
2019-10-24 08:38:36 +00:00
std : : string bitmap_key = color + " -h " + std : : to_string ( icon_height ) + " -w " + std : : to_string ( icon_width ) ;
wxBitmap * bitmap = m_bitmap_cache - > find ( bitmap_key ) ;
2019-10-01 16:19:28 +00:00
if ( bitmap = = nullptr ) {
// Paint the color icon.
Slic3r : : PresetBundle : : parse_color ( color , rgb ) ;
2019-10-24 08:38:36 +00:00
bitmap = m_bitmap_cache - > insert ( bitmap_key , m_bitmap_cache - > mksolid ( icon_width , icon_height , rgb ) ) ;
2019-10-01 16:19:28 +00:00
}
bmps . emplace_back ( bitmap ) ;
}
return bmps ;
}
2019-10-24 08:38:36 +00:00
static wxBitmap get_extruder_color_icon ( size_t extruder_idx , bool thin_icon = false )
2019-10-01 16:19:28 +00:00
{
// Create the bitmap with color bars.
2019-10-24 08:38:36 +00:00
std : : vector < wxBitmap * > bmps = get_extruder_color_icons ( thin_icon ) ;
2019-10-07 10:36:16 +00:00
if ( bmps . empty ( ) )
return wxNullBitmap ;
2019-10-01 16:19:28 +00:00
return * bmps [ extruder_idx > = bmps . size ( ) ? 0 : extruder_idx ] ;
}
2019-10-18 10:35:35 +00:00
void apply_extruder_selector ( wxBitmapComboBox * * ctrl ,
wxWindow * parent ,
const std : : string & first_item /* = ""*/ ,
wxPoint pos /* = wxDefaultPosition*/ ,
2019-10-24 08:38:36 +00:00
wxSize size /* = wxDefaultSize*/ ,
bool use_thin_icon /* = false*/ )
2019-10-18 10:35:35 +00:00
{
2019-10-24 08:38:36 +00:00
std : : vector < wxBitmap * > icons = get_extruder_color_icons ( use_thin_icon ) ;
2019-10-18 10:35:35 +00:00
if ( ! * ctrl )
* ctrl = new wxBitmapComboBox ( parent , wxID_ANY , wxEmptyString , pos , size ,
0 , nullptr , wxCB_READONLY ) ;
else
{
( * ctrl ) - > SetPosition ( pos ) ;
( * ctrl ) - > SetMinSize ( size ) ;
( * ctrl ) - > SetSize ( size ) ;
( * ctrl ) - > Clear ( ) ;
}
2019-11-15 15:44:17 +00:00
if ( first_item . empty ( ) )
( * ctrl ) - > Hide ( ) ; // to avoid unwanted rendering before layout (ExtruderSequenceDialog)
2019-10-18 10:35:35 +00:00
2019-11-08 10:24:57 +00:00
if ( icons . empty ( ) & & ! first_item . empty ( ) ) {
( * ctrl ) - > Append ( _ ( first_item ) , wxNullBitmap ) ;
return ;
}
// For ObjectList we use short extruder name (just a number)
const bool use_full_item_name = dynamic_cast < Slic3r : : GUI : : ObjectList * > ( parent ) = = nullptr ;
2019-10-18 10:35:35 +00:00
int i = 0 ;
2019-10-24 08:38:36 +00:00
wxString str = _ ( L ( " Extruder " ) ) ;
2019-10-18 10:35:35 +00:00
for ( wxBitmap * bmp : icons ) {
if ( i = = 0 ) {
if ( ! first_item . empty ( ) )
( * ctrl ) - > Append ( _ ( first_item ) , * bmp ) ;
+ + i ;
}
2019-11-08 10:24:57 +00:00
( * ctrl ) - > Append ( use_full_item_name ? wxString : : Format ( " %s %d " , str , i ) : std : : to_string ( i ) , * bmp ) ;
2019-10-18 10:35:35 +00:00
+ + i ;
}
( * ctrl ) - > SetSelection ( 0 ) ;
}
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
2019-08-01 12:58:04 +00:00
void ObjectDataViewModelNode : : init_container ( )
{
# ifdef __WXGTK__
// it's necessary on GTK because of control have to know if this item will be container
// in another case you couldn't to add subitem for this item
// it will be produce "segmentation fault"
m_container = true ;
# endif //__WXGTK__
}
2019-09-17 11:41:44 +00:00
# define LAYER_ROOT_ICON "edit_layers_all"
# define LAYER_ICON "edit_layers_some"
2019-05-04 00:07:07 +00:00
ObjectDataViewModelNode : : ObjectDataViewModelNode ( ObjectDataViewModelNode * parent , const ItemType type ) :
m_parent ( parent ) ,
m_type ( type ) ,
2020-01-27 15:30:09 +00:00
m_extruder ( wxEmptyString ) ,
m_ctrl ( parent - > m_ctrl )
2019-05-04 00:07:07 +00:00
{
2019-05-27 11:07:37 +00:00
if ( type = = itSettings )
2019-05-04 00:07:07 +00:00
m_name = " Settings to modified " ;
2019-05-27 11:07:37 +00:00
else if ( type = = itInstanceRoot )
2019-05-04 00:07:07 +00:00
m_name = _ ( L ( " Instances " ) ) ;
2019-05-27 11:07:37 +00:00
else if ( type = = itInstance )
{
2019-05-04 00:07:07 +00:00
m_idx = parent - > GetChildCount ( ) ;
2019-05-09 16:18:21 +00:00
m_name = wxString : : Format ( _ ( L ( " Instance %d " ) ) , m_idx + 1 ) ;
2019-05-04 00:07:07 +00:00
2019-10-01 16:19:28 +00:00
set_action_and_extruder_icons ( ) ;
2019-05-04 00:07:07 +00:00
}
2019-05-27 11:07:37 +00:00
else if ( type = = itLayerRoot )
{
2020-01-27 15:30:09 +00:00
m_bmp = create_scaled_bitmap ( m_ctrl , LAYER_ROOT_ICON ) ; // FIXME: pass window ptr
2019-05-27 11:07:37 +00:00
m_name = _ ( L ( " Layers " ) ) ;
}
2019-05-30 12:41:16 +00:00
if ( type & ( itInstanceRoot | itLayerRoot ) )
2019-08-01 12:58:04 +00:00
init_container ( ) ;
2019-05-04 00:07:07 +00:00
}
2019-05-30 12:41:16 +00:00
ObjectDataViewModelNode : : ObjectDataViewModelNode ( ObjectDataViewModelNode * parent ,
2019-06-06 12:14:29 +00:00
const t_layer_height_range & layer_range ,
2019-05-31 13:29:09 +00:00
const int idx /*= -1 */ ,
const wxString & extruder ) :
2019-05-30 12:41:16 +00:00
m_parent ( parent ) ,
m_type ( itLayer ) ,
m_idx ( idx ) ,
2019-06-06 12:14:29 +00:00
m_layer_range ( layer_range ) ,
2020-01-27 15:30:09 +00:00
m_extruder ( extruder ) ,
m_ctrl ( parent - > m_ctrl )
2019-05-30 12:41:16 +00:00
{
2019-05-31 13:29:09 +00:00
const int children_cnt = parent - > GetChildCount ( ) ;
if ( idx < 0 )
m_idx = children_cnt ;
else
{
// update indexes for another Laeyr Nodes
for ( int i = m_idx ; i < children_cnt ; i + + )
parent - > GetNthChild ( i ) - > SetIdx ( i + 1 ) ;
}
2019-06-06 12:14:29 +00:00
const std : : string label_range = ( boost : : format ( " %.2f-%.2f " ) % layer_range . first % layer_range . second ) . str ( ) ;
2019-05-30 14:53:17 +00:00
m_name = _ ( L ( " Range " ) ) + label_range + " ( " + _ ( L ( " mm " ) ) + " ) " ;
2020-01-27 15:30:09 +00:00
m_bmp = create_scaled_bitmap ( m_ctrl , LAYER_ICON ) ; // FIXME: pass window ptr
2019-05-30 12:41:16 +00:00
2019-10-01 16:19:28 +00:00
set_action_and_extruder_icons ( ) ;
2019-08-01 12:58:04 +00:00
init_container ( ) ;
2019-05-30 12:41:16 +00:00
}
2019-07-31 14:36:56 +00:00
# ifndef NDEBUG
bool ObjectDataViewModelNode : : valid ( )
{
// Verify that the object was not deleted yet.
assert ( m_idx > = - 1 ) ;
return m_idx > = - 1 ;
}
# endif /* NDEBUG */
2019-10-01 16:19:28 +00:00
void ObjectDataViewModelNode : : set_action_and_extruder_icons ( )
2019-04-16 08:05:45 +00:00
{
2019-05-27 11:07:37 +00:00
m_action_icon_name = m_type & itObject ? " advanced_plus " :
m_type & ( itVolume | itLayer ) ? " cog " : /*m_type & itInstance*/ " set_separate_obj " ;
2020-01-27 15:30:09 +00:00
m_action_icon = create_scaled_bitmap ( m_ctrl , m_action_icon_name ) ; // FIXME: pass window ptr
2019-10-01 16:19:28 +00:00
2019-10-09 10:36:13 +00:00
if ( m_type & itInstance )
return ; // don't set colored bitmap for Instance
2019-10-01 16:19:28 +00:00
// set extruder bitmap
int extruder_idx = atoi ( m_extruder . c_str ( ) ) ;
if ( extruder_idx > 0 ) - - extruder_idx ;
m_extruder_bmp = get_extruder_color_icon ( extruder_idx ) ;
2019-04-16 08:05:45 +00:00
}
2018-07-04 06:54:30 +00:00
2019-08-01 12:58:04 +00:00
void ObjectDataViewModelNode : : set_printable_icon ( PrintIndicator printable )
{
m_printable = printable ;
m_printable_icon = m_printable = = piUndef ? m_empty_bmp :
2020-01-27 15:30:09 +00:00
create_scaled_bitmap ( m_ctrl , m_printable = = piPrintable ? " eye_open.png " : " eye_closed.png " ) ;
2019-08-01 12:58:04 +00:00
}
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 )
2019-05-04 00:07:07 +00:00
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 ( ) )
2020-01-27 15:30:09 +00:00
m_action_icon = create_scaled_bitmap ( m_ctrl , m_action_icon_name ) ;
2019-04-16 08:05:45 +00:00
2019-09-17 11:41:44 +00:00
if ( m_printable ! = piUndef )
2020-01-27 15:30:09 +00:00
m_printable_icon = create_scaled_bitmap ( m_ctrl , m_printable = = piPrintable ? " eye_open.png " : " eye_closed.png " ) ;
2019-09-17 11:41:44 +00:00
2019-04-16 08:05:45 +00:00
if ( ! m_opt_categories . empty ( ) )
update_settings_digest_bitmaps ( ) ;
}
2019-07-22 08:28:25 +00:00
bool ObjectDataViewModelNode : : SetValue ( const wxVariant & variant , unsigned col )
{
switch ( col )
{
2019-08-01 12:58:04 +00:00
case colPrint :
m_printable_icon < < variant ;
return true ;
case colName : {
2019-07-22 08:28:25 +00:00
DataViewBitmapText data ;
data < < variant ;
m_bmp = data . GetBitmap ( ) ;
m_name = data . GetText ( ) ;
return true ; }
2019-08-01 12:58:04 +00:00
case colExtruder : {
2019-10-01 16:19:28 +00:00
DataViewBitmapText data ;
data < < variant ;
m_extruder_bmp = data . GetBitmap ( ) ;
m_extruder = data . GetText ( ) = = " 0 " ? _ ( L ( " default " ) ) : data . GetText ( ) ;
2019-07-22 08:28:25 +00:00
return true ; }
2019-08-01 12:58:04 +00:00
case colEditing :
2019-07-22 08:28:25 +00:00
m_action_icon < < variant ;
return true ;
default :
printf ( " MyObjectTreeModel::SetValue: wrong column " ) ;
}
return false ;
}
2019-05-09 16:18:21 +00:00
void ObjectDataViewModelNode : : SetIdx ( const int & idx )
{
m_idx = idx ;
// update name if this node is instance
if ( m_type = = itInstance )
m_name = wxString : : Format ( _ ( L ( " Instance %d " ) ) , m_idx + 1 ) ;
}
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-05-27 14:13:24 +00:00
static int get_root_idx ( ObjectDataViewModelNode * parent_node , const ItemType root_type )
{
// because of istance_root and layers_root are at the end of the list, so
// start locking from the end
for ( int root_idx = parent_node - > GetChildCount ( ) - 1 ; root_idx > = 0 ; root_idx - - )
{
// if there is SettingsItem or VolumeItem, then RootItems don't exist in current ObjectItem
if ( parent_node - > GetNthChild ( root_idx ) - > GetType ( ) & ( itSettings | itVolume ) )
break ;
if ( parent_node - > GetNthChild ( root_idx ) - > GetType ( ) & root_type )
return root_idx ;
}
return - 1 ;
}
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
{
2019-05-10 10:54:20 +00:00
const wxString extruder_str = extruder = = 0 ? _ ( L ( " default " ) ) : wxString : : Format ( " %d " , extruder ) ;
2020-01-27 15:30:09 +00:00
auto root = new ObjectDataViewModelNode ( name , extruder_str , m_ctrl ) ;
2019-04-29 13:27:59 +00:00
// Add error icon if detected auto-repaire
if ( has_errors )
root - > m_bmp = * m_warning_bmp ;
2019-09-24 14:01:01 +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
2019-05-10 10:54:20 +00:00
wxString extruder_str = extruder = = 0 ? _ ( L ( " default " ) ) : wxString : : Format ( " %d " , extruder ) ;
2018-08-15 11:59:33 +00:00
2019-05-27 14:13:24 +00:00
// get insertion position according to the existed Layers and/or Instances Items
int insert_position = get_root_idx ( root , itLayerRoot ) ;
if ( insert_position < 0 )
insert_position = get_root_idx ( root , itInstanceRoot ) ;
2018-11-06 10:39:38 +00:00
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 + + ;
2019-05-27 14:13:24 +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
2019-09-24 14:01:01 +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-05-27 11:07:37 +00:00
/* return values:
* true = > root_node is created and added to the parent_root
* false = > root node alredy exists
*/
static bool append_root_node ( ObjectDataViewModelNode * parent_node ,
ObjectDataViewModelNode * * root_node ,
const ItemType root_type )
{
const int inst_root_id = get_root_idx ( parent_node , root_type ) ;
* root_node = inst_root_id < 0 ?
new ObjectDataViewModelNode ( parent_node , root_type ) :
parent_node - > GetNthChild ( inst_root_id ) ;
if ( inst_root_id < 0 ) {
if ( ( root_type & itInstanceRoot ) | |
2019-09-03 08:27:16 +00:00
( ( root_type & itLayerRoot ) & & get_root_idx ( parent_node , itInstanceRoot ) < 0 ) )
2019-05-27 11:07:37 +00:00
parent_node - > Append ( * root_node ) ;
else if ( root_type & itLayerRoot )
2019-05-30 12:41:16 +00:00
parent_node - > Insert ( * root_node , static_cast < unsigned int > ( get_root_idx ( parent_node , itInstanceRoot ) ) ) ;
2019-05-27 11:07:37 +00:00
return true ;
}
return false ;
}
2019-08-01 12:58:04 +00:00
wxDataViewItem ObjectDataViewModel : : AddRoot ( const wxDataViewItem & parent_item , ItemType root_type )
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 ) ;
2019-05-27 11:07:37 +00:00
// get InstanceRoot node
2019-08-01 12:58:04 +00:00
ObjectDataViewModelNode * root_node { nullptr } ;
const bool appended = append_root_node ( parent_node , & root_node , root_type ) ;
if ( ! root_node ) return wxDataViewItem ( 0 ) ;
2018-10-18 08:40:26 +00:00
2019-08-01 12:58:04 +00:00
const wxDataViewItem root_item ( ( void * ) root_node ) ;
2018-10-18 08:40:26 +00:00
2019-05-27 11:07:37 +00:00
if ( appended )
2019-08-01 12:58:04 +00:00
ItemAdded ( parent_item , root_item ) ; // notify control
return root_item ;
}
wxDataViewItem ObjectDataViewModel : : AddInstanceRoot ( const wxDataViewItem & parent_item )
{
return AddRoot ( parent_item , itInstanceRoot ) ;
}
wxDataViewItem ObjectDataViewModel : : AddInstanceChild ( const wxDataViewItem & parent_item , size_t num )
{
2019-09-02 08:03:07 +00:00
std : : vector < bool > print_indicator ( num , true ) ;
// if InstanceRoot item isn't created for this moment
if ( ! GetInstanceRootItem ( parent_item ) . IsOk ( ) )
// use object's printable state to first instance
print_indicator [ 0 ] = IsPrintable ( parent_item ) ;
2019-08-01 12:58:04 +00:00
return wxDataViewItem ( ( void * ) AddInstanceChild ( parent_item , print_indicator ) ) ;
}
wxDataViewItem ObjectDataViewModel : : AddInstanceChild ( const wxDataViewItem & parent_item ,
const std : : vector < bool > & print_indicator )
{
const wxDataViewItem inst_root_item = AddInstanceRoot ( parent_item ) ;
if ( ! inst_root_item ) return wxDataViewItem ( 0 ) ;
ObjectDataViewModelNode * inst_root_node = ( ObjectDataViewModelNode * ) inst_root_item . GetID ( ) ;
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 ;
2019-08-01 12:58:04 +00:00
while ( counter < print_indicator . size ( ) ) {
2019-04-24 23:45:00 +00:00
instance_node = new ObjectDataViewModelNode ( inst_root_node , itInstance ) ;
2019-08-13 16:15:12 +00:00
2019-08-30 07:35:34 +00:00
instance_node - > set_printable_icon ( print_indicator [ counter ] ? piPrintable : piUnprintable ) ;
2019-08-05 06:44:55 +00:00
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 ;
}
2019-08-07 12:11:41 +00:00
// update object_node printable property
UpdateObjectPrintable ( parent_item ) ;
2018-10-18 08:40:26 +00:00
return wxDataViewItem ( ( void * ) instance_node ) ;
}
2019-08-07 12:11:41 +00:00
void ObjectDataViewModel : : UpdateObjectPrintable ( wxDataViewItem parent_item )
{
const wxDataViewItem inst_root_item = GetInstanceRootItem ( parent_item ) ;
if ( ! inst_root_item )
return ;
ObjectDataViewModelNode * inst_root_node = ( ObjectDataViewModelNode * ) inst_root_item . GetID ( ) ;
const size_t child_cnt = inst_root_node - > GetChildren ( ) . Count ( ) ;
PrintIndicator obj_pi = piUnprintable ;
for ( size_t i = 0 ; i < child_cnt ; i + + )
if ( inst_root_node - > GetNthChild ( i ) - > IsPrintable ( ) & piPrintable ) {
obj_pi = piPrintable ;
break ;
}
// and set printable state for object_node to piUndef
ObjectDataViewModelNode * obj_node = ( ObjectDataViewModelNode * ) parent_item . GetID ( ) ;
obj_node - > set_printable_icon ( obj_pi ) ;
ItemChanged ( parent_item ) ;
}
// update printable property for all instances from object
void ObjectDataViewModel : : UpdateInstancesPrintable ( wxDataViewItem parent_item )
{
const wxDataViewItem inst_root_item = GetInstanceRootItem ( parent_item ) ;
if ( ! inst_root_item )
return ;
ObjectDataViewModelNode * obj_node = ( ObjectDataViewModelNode * ) parent_item . GetID ( ) ;
const PrintIndicator obj_pi = obj_node - > IsPrintable ( ) ;
ObjectDataViewModelNode * inst_root_node = ( ObjectDataViewModelNode * ) inst_root_item . GetID ( ) ;
const size_t child_cnt = inst_root_node - > GetChildren ( ) . Count ( ) ;
for ( size_t i = 0 ; i < child_cnt ; i + + )
{
ObjectDataViewModelNode * inst_node = inst_root_node - > GetNthChild ( i ) ;
// and set printable state for object_node to piUndef
inst_node - > set_printable_icon ( obj_pi ) ;
ItemChanged ( wxDataViewItem ( ( void * ) inst_node ) ) ;
}
}
bool ObjectDataViewModel : : IsPrintable ( const wxDataViewItem & item ) const
{
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
if ( ! node )
return false ;
return node - > IsPrintable ( ) = = piPrintable ;
}
2019-05-27 11:07:37 +00:00
wxDataViewItem ObjectDataViewModel : : AddLayersRoot ( const wxDataViewItem & parent_item )
{
2019-08-01 12:58:04 +00:00
return AddRoot ( parent_item , itLayerRoot ) ;
2019-05-27 11:07:37 +00:00
}
2019-05-31 13:29:09 +00:00
wxDataViewItem ObjectDataViewModel : : AddLayersChild ( const wxDataViewItem & parent_item ,
2019-06-07 09:32:46 +00:00
const t_layer_height_range & layer_range ,
const int extruder /* = 0*/ ,
2019-05-31 13:29:09 +00:00
const int index /* = -1*/ )
2019-05-27 11:07:37 +00:00
{
ObjectDataViewModelNode * parent_node = ( ObjectDataViewModelNode * ) parent_item . GetID ( ) ;
if ( ! parent_node ) return wxDataViewItem ( 0 ) ;
2019-06-07 09:32:46 +00:00
wxString extruder_str = extruder = = 0 ? _ ( L ( " default " ) ) : wxString : : Format ( " %d " , extruder ) ;
2019-05-27 11:07:37 +00:00
// get LayerRoot node
2019-05-27 14:13:24 +00:00
ObjectDataViewModelNode * layer_root_node ;
2019-05-30 12:41:16 +00:00
wxDataViewItem layer_root_item ;
2019-05-27 14:13:24 +00:00
2019-05-30 12:41:16 +00:00
if ( parent_node - > GetType ( ) & itLayerRoot ) {
2019-05-27 14:13:24 +00:00
layer_root_node = parent_node ;
2019-05-30 12:41:16 +00:00
layer_root_item = parent_item ;
}
2019-05-27 14:13:24 +00:00
else {
const int root_idx = get_root_idx ( parent_node , itLayerRoot ) ;
if ( root_idx < 0 ) return wxDataViewItem ( 0 ) ;
layer_root_node = parent_node - > GetNthChild ( root_idx ) ;
2019-05-30 12:41:16 +00:00
layer_root_item = wxDataViewItem ( ( void * ) layer_root_node ) ;
2019-05-27 14:13:24 +00:00
}
2019-05-27 11:07:37 +00:00
// Add layer node
2019-06-07 09:32:46 +00:00
ObjectDataViewModelNode * layer_node = new ObjectDataViewModelNode ( layer_root_node , layer_range , index , extruder_str ) ;
2019-05-31 13:29:09 +00:00
if ( index < 0 )
layer_root_node - > Append ( layer_node ) ;
else
layer_root_node - > Insert ( layer_node , index ) ;
2019-05-27 11:07:37 +00:00
// notify control
2019-05-30 12:41:16 +00:00
const wxDataViewItem layer_item ( ( void * ) layer_node ) ;
ItemAdded ( layer_root_item , layer_item ) ;
2019-05-27 11:07:37 +00:00
2019-05-30 12:41:16 +00:00
return layer_item ;
2019-05-27 11:07:37 +00:00
}
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 ) {
2019-05-27 14:13:24 +00:00
if ( node - > m_type & ( itInstanceRoot | itLayerRoot ) )
2018-11-12 12:47:24 +00:00
{
2019-07-15 15:09:06 +00:00
// node can be deleted by the Delete, let's check its type while we safely can
bool is_instance_root = ( node - > m_type & itInstanceRoot ) ;
2019-09-06 15:46:55 +00:00
for ( int i = int ( node - > GetChildCount ( ) - 1 ) ; i > = ( is_instance_root ? 1 : 0 ) ; i - - )
2018-11-12 12:47:24 +00:00
Delete ( wxDataViewItem ( node - > GetNthChild ( i ) ) ) ;
2019-07-15 15:09:06 +00:00
2018-11-12 12:47:24 +00:00
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
2019-05-27 14:13:24 +00:00
if ( node - > m_type & ( itVolume | itLayer ) ) {
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 ) {
2019-10-29 09:40:34 +00:00
if ( size_t ( id ) = = node_parent - > GetChildCount ( ) ) id - - ;
2018-05-30 15:52:28 +00:00
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 ) ;
2019-08-05 06:44:55 +00:00
PrintIndicator last_instance_printable = last_instance_node - > IsPrintable ( ) ;
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 ( ) ;
2019-08-05 06:44:55 +00:00
obj_node - > set_printable_icon ( last_instance_printable ) ;
2018-10-18 08:40:26 +00:00
obj_node - > GetChildren ( ) . Remove ( node_parent ) ;
delete node_parent ;
ret_item = wxDataViewItem ( obj_node ) ;
2019-05-27 14:13:24 +00:00
# ifndef __WXGTK__
if ( obj_node - > GetChildCount ( ) = = 0 )
obj_node - > m_container = false ;
# endif //__WXGTK__
ItemDeleted ( ret_item , wxDataViewItem ( node_parent ) ) ;
return ret_item ;
}
2019-08-07 12:11:41 +00:00
if ( node - > m_type & itInstance )
UpdateObjectPrintable ( wxDataViewItem ( node_parent - > GetParent ( ) ) ) ;
2019-05-27 14:13:24 +00:00
// if there was last layer item, delete this one and layers root item
if ( node_parent - > GetChildCount ( ) = = 0 & & node_parent - > m_type = = itLayerRoot )
{
ObjectDataViewModelNode * obj_node = node_parent - > GetParent ( ) ;
obj_node - > GetChildren ( ) . Remove ( node_parent ) ;
delete node_parent ;
ret_item = wxDataViewItem ( obj_node ) ;
2018-10-18 08:40:26 +00:00
# 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
2019-05-27 14:13:24 +00:00
if ( node_parent - > GetChildCount ( ) < = 3 ) // 3??? #ys_FIXME
2018-11-12 12:47:24 +00:00
{
int vol_cnt = 0 ;
int vol_idx = 0 ;
2019-09-06 15:46:55 +00:00
for ( size_t i = 0 ; i < node_parent - > GetChildCount ( ) ; + + i ) {
2018-11-12 12:47:24 +00:00
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 ) ;
2019-09-06 15:46:55 +00:00
size_t 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 ;
2019-05-27 11:07:37 +00:00
const int inst_root_id = get_root_idx ( parent_node , itInstanceRoot ) ;
2018-10-18 08:40:26 +00:00
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 ;
2019-08-05 06:44:55 +00:00
PrintIndicator last_inst_printable = piUndef ;
2018-10-18 08:40:26 +00:00
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 ) ;
2019-08-05 06:44:55 +00:00
if ( i = = 0 ) last_inst_printable = last_instance_node - > IsPrintable ( ) ;
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 ) ;
2019-08-05 06:44:55 +00:00
parent_node - > set_printable_icon ( last_inst_printable ) ;
2018-10-18 08:40:26 +00:00
ItemDeleted ( parent_item , inst_root_item ) ;
2019-08-05 06:44:55 +00:00
ItemChanged ( parent_item ) ;
2018-10-18 08:40:26 +00:00
# ifndef __WXGTK__
if ( parent_node - > GetChildCount ( ) = = 0 )
parent_node - > m_container = false ;
# endif //__WXGTK__
}
2019-08-07 12:11:41 +00:00
// update object_node printable property
UpdateObjectPrintable ( parent_item ) ;
2018-10-18 08:40:26 +00:00
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
{
2019-09-06 15:46:55 +00:00
if ( size_t ( obj_idx ) > = m_objects . size ( ) )
2018-06-04 13:59:55 +00:00
{
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
{
2019-09-06 15:46:55 +00:00
if ( size_t ( obj_idx ) > = m_objects . size ( ) ) {
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-05-31 08:54:52 +00:00
wxDataViewItem ObjectDataViewModel : : GetItemById ( const int obj_idx , const int sub_obj_idx , const ItemType parent_type )
2018-11-05 12:53:30 +00:00
{
2019-09-06 15:46:55 +00:00
if ( size_t ( obj_idx ) > = m_objects . size ( ) ) {
2018-11-05 12:53:30 +00:00
printf ( " Error! Out of objects range. \n " ) ;
return wxDataViewItem ( 0 ) ;
}
2019-05-31 08:54:52 +00:00
auto item = GetItemByType ( wxDataViewItem ( m_objects [ obj_idx ] ) , parent_type ) ;
if ( ! item )
2018-11-05 12:53:30 +00:00
return wxDataViewItem ( 0 ) ;
2019-06-06 12:14:29 +00:00
auto parent = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
2018-11-05 12:53:30 +00:00
for ( size_t i = 0 ; i < parent - > GetChildCount ( ) ; i + + )
2019-05-31 08:54:52 +00:00
if ( parent - > GetNthChild ( i ) - > m_idx = = sub_obj_idx )
2018-11-05 12:53:30 +00:00
return wxDataViewItem ( parent - > GetNthChild ( i ) ) ;
return wxDataViewItem ( 0 ) ;
}
2019-05-31 08:54:52 +00:00
wxDataViewItem ObjectDataViewModel : : GetItemByInstanceId ( int obj_idx , int inst_idx )
{
return GetItemById ( obj_idx , inst_idx , itInstanceRoot ) ;
}
wxDataViewItem ObjectDataViewModel : : GetItemByLayerId ( int obj_idx , int layer_idx )
{
return GetItemById ( obj_idx , layer_idx , itLayerRoot ) ;
}
2019-06-06 12:14:29 +00:00
wxDataViewItem ObjectDataViewModel : : GetItemByLayerRange ( const int obj_idx , const t_layer_height_range & layer_range )
{
2019-09-06 15:46:55 +00:00
if ( size_t ( obj_idx ) > = m_objects . size ( ) ) {
2019-06-06 12:14:29 +00:00
printf ( " Error! Out of objects range. \n " ) ;
return wxDataViewItem ( 0 ) ;
}
auto item = GetItemByType ( wxDataViewItem ( m_objects [ obj_idx ] ) , itLayerRoot ) ;
if ( ! item )
return wxDataViewItem ( 0 ) ;
auto parent = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
for ( size_t i = 0 ; i < parent - > GetChildCount ( ) ; i + + )
if ( parent - > GetNthChild ( i ) - > m_layer_range = = layer_range )
return wxDataViewItem ( parent - > GetNthChild ( i ) ) ;
return wxDataViewItem ( 0 ) ;
}
int ObjectDataViewModel : : GetItemIdByLayerRange ( const int obj_idx , const t_layer_height_range & layer_range )
{
wxDataViewItem item = GetItemByLayerRange ( obj_idx , layer_range ) ;
if ( ! item )
return - 1 ;
return GetLayerIdByItem ( item ) ;
}
2019-04-24 23:45:00 +00:00
int ObjectDataViewModel : : GetIdByItem ( const wxDataViewItem & item ) const
2018-06-06 22:55:09 +00:00
{
2019-06-10 13:22:09 +00:00
if ( ! item . IsOk ( ) )
return - 1 ;
2018-06-06 22:55:09 +00:00
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-05-30 12:41:16 +00:00
int ObjectDataViewModel : : GetLayerIdByItem ( const wxDataViewItem & item ) const
{
return GetIdByItemAndType ( item , itLayer ) ;
}
2019-06-06 12:14:29 +00:00
t_layer_height_range ObjectDataViewModel : : GetLayerRangeByItem ( const wxDataViewItem & item ) const
{
wxASSERT ( item . IsOk ( ) ) ;
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
if ( ! node | | node - > m_type ! = itLayer )
return { 0.0f , 0.0f } ;
return node - > GetLayerRange ( ) ;
}
2019-10-01 16:19:28 +00:00
bool ObjectDataViewModel : : UpdateColumValues ( unsigned col )
{
switch ( col )
{
case colPrint :
case colName :
case colEditing :
return true ;
case colExtruder :
{
wxDataViewItemArray items ;
GetAllChildren ( wxDataViewItem ( nullptr ) , items ) ;
if ( items . IsEmpty ( ) ) return false ;
for ( auto item : items )
UpdateExtruderBitmap ( item ) ;
return true ;
}
default :
printf ( " MyObjectTreeModel::SetValue: wrong column " ) ;
}
return false ;
}
void ObjectDataViewModel : : UpdateExtruderBitmap ( wxDataViewItem item )
{
wxString extruder = GetExtruder ( item ) ;
if ( extruder . IsEmpty ( ) )
return ;
// set extruder bitmap
int extruder_idx = atoi ( extruder . c_str ( ) ) ;
if ( extruder_idx > 0 ) - - extruder_idx ;
const DataViewBitmapText extruder_val ( extruder , get_extruder_color_icon ( extruder_idx ) ) ;
wxVariant value ;
value < < extruder_val ;
SetValue ( value , item , colExtruder ) ;
}
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 ( ) ;
2019-09-03 08:27:16 +00:00
if ( ! node | |
node - > GetIdx ( ) < - 1 | |
( node - > GetIdx ( ) = = - 1 & &
! ( node - > GetType ( ) & ( itObject | itSettings | itInstanceRoot | itLayerRoot /* | itLayer*/ ) )
)
)
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 ;
2019-06-06 12:14:29 +00:00
// get top parent (Object) node
while ( parent_node - > m_type ! = itObject )
parent_node = parent_node - > GetParent ( ) ;
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 ;
2019-09-06 15:46:55 +00:00
for ( size_t i = 0 ; i < m_objects . size ( ) ; i + + )
2018-12-17 11:46:36 +00:00
{
row_num + + ;
if ( item = = wxDataViewItem ( m_objects [ i ] ) )
return row_num ;
2019-09-06 15:46:55 +00:00
for ( size_t j = 0 ; j < m_objects [ i ] - > GetChildCount ( ) ; j + + )
2018-12-17 11:46:36 +00:00
{
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 + + ;
2019-09-06 15:46:55 +00:00
for ( size_t t = 0 ; t < cur_node - > GetChildCount ( ) ; t + + )
2018-12-17 11:46:36 +00:00
{
row_num + + ;
if ( item = = wxDataViewItem ( cur_node - > GetNthChild ( t ) ) )
return row_num ;
}
}
}
}
return - 1 ;
}
2019-08-02 15:53:12 +00:00
bool ObjectDataViewModel : : InvalidItem ( const wxDataViewItem & item )
{
if ( ! item )
return true ;
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
if ( ! node | | node - > invalid ( ) )
return true ;
return false ;
}
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-10-01 16:19:28 +00:00
wxString ObjectDataViewModel : : GetExtruder ( const wxDataViewItem & item ) const
{
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
if ( ! node ) // happens if item.IsOk()==false
return wxEmptyString ;
return node - > m_extruder ;
}
int ObjectDataViewModel : : GetExtruderNumber ( const wxDataViewItem & item ) const
{
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
if ( ! node ) // happens if item.IsOk()==false
return 0 ;
return atoi ( node - > m_extruder . c_str ( ) ) ;
}
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 )
{
2019-08-01 12:58:04 +00:00
case colPrint :
variant < < node - > m_printable_icon ;
break ;
case colName :
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 ;
2019-08-01 12:58:04 +00:00
case colExtruder :
2019-10-01 16:19:28 +00:00
variant < < DataViewBitmapText ( node - > m_extruder , node - > m_extruder_bmp ) ;
2018-07-04 06:54:30 +00:00
break ;
2019-08-01 12:58:04 +00:00
case colEditing :
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
{
2019-09-06 15:46:55 +00:00
if ( size_t ( item_idx ) > = m_objects . size ( ) )
2018-06-05 08:41:20 +00:00
return false ;
return m_objects [ item_idx ] - > SetValue ( variant , col ) ;
}
2018-06-19 10:24:16 +00:00
2019-10-01 16:19:28 +00:00
void ObjectDataViewModel : : SetExtruder ( const wxString & extruder , wxDataViewItem item )
{
DataViewBitmapText extruder_val ;
extruder_val . SetText ( extruder ) ;
// set extruder bitmap
int extruder_idx = atoi ( extruder . c_str ( ) ) ;
if ( extruder_idx > 0 ) - - extruder_idx ;
extruder_val . SetBitmap ( get_extruder_color_icon ( extruder_idx ) ) ;
wxVariant value ;
value < < extruder_val ;
SetValue ( value , item , colExtruder ) ;
}
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
2019-08-01 12:58:04 +00:00
return ! ( col = = colExtruder & & 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 ( ) ;
2019-07-31 14:36:56 +00:00
assert ( node ! = nullptr & & node - > valid ( ) ) ;
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 )
2019-06-06 12:14:29 +00:00
parent_node = parent_node - > GetParent ( ) ;
2018-10-18 08:40:26 +00:00
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 ( ) ;
2019-07-23 15:09:19 +00:00
return node - > m_type < 0 ? itUndef : node - > m_type ;
2018-10-16 09:08:37 +00:00
}
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 ) ;
2019-09-06 15:46:55 +00:00
for ( size_t i = 0 ; i < node - > GetChildCount ( ) ; i + + ) {
2018-11-05 12:53:30 +00:00
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-05-31 08:54:52 +00:00
wxDataViewItem ObjectDataViewModel : : GetLayerRootItem ( const wxDataViewItem & item ) const
{
return GetItemByType ( item , itLayerRoot ) ;
}
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-08-05 06:44:55 +00:00
wxDataViewItem ObjectDataViewModel : : SetPrintableState (
2019-08-05 08:05:28 +00:00
PrintIndicator printable ,
2019-08-05 06:44:55 +00:00
int obj_idx ,
int subobj_idx /* = -1*/ ,
ItemType subobj_type /* = itInstance*/ )
{
wxDataViewItem item = wxDataViewItem ( 0 ) ;
if ( subobj_idx < 0 )
item = GetItemById ( obj_idx ) ;
else
item = subobj_type & itInstance ? GetItemByInstanceId ( obj_idx , subobj_idx ) :
GetItemByVolumeId ( obj_idx , subobj_idx ) ;
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) item . GetID ( ) ;
if ( ! node )
return wxDataViewItem ( 0 ) ;
node - > set_printable_icon ( printable ) ;
2019-08-05 08:05:28 +00:00
ItemChanged ( item ) ;
2019-08-05 06:44:55 +00:00
2019-08-07 12:11:41 +00:00
if ( subobj_idx > = 0 )
UpdateObjectPrintable ( GetItemById ( obj_idx ) ) ;
2019-08-05 06:44:55 +00:00
return item ;
}
2019-08-07 12:11:41 +00:00
wxDataViewItem ObjectDataViewModel : : SetObjectPrintableState (
PrintIndicator printable ,
wxDataViewItem obj_item )
{
ObjectDataViewModelNode * node = ( ObjectDataViewModelNode * ) obj_item . GetID ( ) ;
if ( ! node )
return wxDataViewItem ( 0 ) ;
node - > set_printable_icon ( printable ) ;
ItemChanged ( obj_item ) ;
UpdateInstancesPrintable ( obj_item ) ;
return obj_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
2019-09-17 11:41:44 +00:00
switch ( node - > m_type )
{
case itObject :
if ( node - > m_bmp . IsOk ( ) ) node - > m_bmp = * m_warning_bmp ;
break ;
case 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-09-17 11:41:44 +00:00
break ;
case itLayerRoot :
2020-01-27 15:30:09 +00:00
node - > m_bmp = create_scaled_bitmap ( m_ctrl , LAYER_ROOT_ICON ) ;
2019-09-17 11:41:44 +00:00
case itLayer :
2020-01-27 15:30:09 +00:00
node - > m_bmp = create_scaled_bitmap ( m_ctrl , LAYER_ICON ) ;
2019-09-17 11:41:44 +00:00
break ;
default : break ;
}
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
//-----------------------------------------------------------------------------
2019-09-30 12:03:50 +00:00
// DataViewBitmapText
2018-10-15 11:25:22 +00:00
//-----------------------------------------------------------------------------
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 ( ) )
{
2020-01-27 15:30:09 +00:00
float sf = ( float ) 1.0 / get_svg_scale_factor ( m_parent ) ;
wxSize icon_sz = icon . GetSize ( ) * sf ;
dc - > DrawBitmap ( icon , rect . x , rect . y + ( rect . height - icon_sz . y ) / 2 ) ;
xoffset = icon_sz . x + 4 ;
2018-09-17 13:12:13 +00:00
}
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 ;
2019-08-01 12:58:04 +00:00
GetView ( ) - > GetModel ( ) - > GetValue ( valueOld , m_item , colName ) ;
2018-12-14 15:07:28 +00:00
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 ;
}
2019-09-30 12:03:50 +00:00
// ----------------------------------------------------------------------------
2019-10-01 16:19:28 +00:00
// BitmapChoiceRenderer
2019-09-30 12:03:50 +00:00
// ----------------------------------------------------------------------------
2019-10-01 16:19:28 +00:00
bool BitmapChoiceRenderer : : SetValue ( const wxVariant & value )
2019-09-30 12:03:50 +00:00
{
m_value < < value ;
return true ;
}
2019-10-01 16:19:28 +00:00
bool BitmapChoiceRenderer : : GetValue ( wxVariant & value ) const
2019-09-30 12:03:50 +00:00
{
value < < m_value ;
return true ;
}
2019-10-01 16:19:28 +00:00
bool BitmapChoiceRenderer : : Render ( wxRect rect , wxDC * dc , int state )
2019-09-30 12:03:50 +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 ;
}
2019-10-01 16:19:28 +00:00
if ( rect . height = = 0 )
rect . height = icon . GetHeight ( ) ;
2019-09-30 12:03:50 +00:00
RenderText ( m_value . GetText ( ) , xoffset , rect , dc , state ) ;
return true ;
}
2019-10-01 16:19:28 +00:00
wxSize BitmapChoiceRenderer : : GetSize ( ) const
2019-09-30 12:03:50 +00:00
{
2019-10-01 16:19:28 +00:00
wxSize sz = GetTextExtent ( m_value . GetText ( ) ) ;
2019-09-30 12:03:50 +00:00
2019-10-01 16:19:28 +00:00
if ( m_value . GetBitmap ( ) . IsOk ( ) )
sz . x + = m_value . GetBitmap ( ) . GetWidth ( ) + 4 ;
2019-09-30 12:03:50 +00:00
return sz ;
}
2019-10-01 16:19:28 +00:00
wxWindow * BitmapChoiceRenderer : : CreateEditorCtrl ( wxWindow * parent , wxRect labelRect , const wxVariant & value )
2019-09-30 12:03:50 +00:00
{
wxDataViewCtrl * const dv_ctrl = GetOwner ( ) - > GetOwner ( ) ;
ObjectDataViewModel * const model = dynamic_cast < ObjectDataViewModel * > ( dv_ctrl - > GetModel ( ) ) ;
2019-10-09 10:36:13 +00:00
if ( ! ( model - > GetItemType ( dv_ctrl - > GetSelection ( ) ) & ( itVolume | itLayer | itObject ) ) )
2019-09-30 12:03:50 +00:00
return nullptr ;
2019-10-01 16:19:28 +00:00
std : : vector < wxBitmap * > icons = get_extruder_color_icons ( ) ;
if ( icons . empty ( ) )
return nullptr ;
2019-09-30 12:03:50 +00:00
DataViewBitmapText data ;
data < < value ;
2019-10-01 16:19:28 +00:00
auto c_editor = new wxBitmapComboBox ( parent , wxID_ANY , wxEmptyString ,
labelRect . GetTopLeft ( ) , wxSize ( labelRect . GetWidth ( ) , - 1 ) ,
0 , nullptr , wxCB_READONLY ) ;
2019-09-30 12:03:50 +00:00
2019-10-01 16:19:28 +00:00
int i = 0 ;
for ( wxBitmap * bmp : icons ) {
if ( i = = 0 ) {
c_editor - > Append ( _ ( L ( " default " ) ) , * bmp ) ;
+ + i ;
}
c_editor - > Append ( wxString : : Format ( " %d " , i ) , * bmp ) ;
+ + i ;
2019-09-30 12:03:50 +00:00
}
2019-10-01 16:19:28 +00:00
c_editor - > SetSelection ( atoi ( data . GetText ( ) . c_str ( ) ) ) ;
2019-09-30 12:03:50 +00:00
2019-10-01 16:19:28 +00:00
// to avoid event propagation to other sidebar items
2019-10-10 09:03:55 +00:00
c_editor - > Bind ( wxEVT_COMBOBOX , [ this ] ( wxCommandEvent & evt ) {
evt . StopPropagation ( ) ;
// FinishEditing grabs new selection and triggers config update. We better call
// it explicitly, automatic update on KILL_FOCUS didn't work on Linux.
this - > FinishEditing ( ) ;
} ) ;
2019-09-30 12:03:50 +00:00
return c_editor ;
}
2019-10-01 16:19:28 +00:00
bool BitmapChoiceRenderer : : GetValueFromEditorCtrl ( wxWindow * ctrl , wxVariant & value )
2019-09-30 12:03:50 +00:00
{
wxBitmapComboBox * c = ( wxBitmapComboBox * ) ctrl ;
int selection = c - > GetSelection ( ) ;
if ( selection < 0 )
return false ;
DataViewBitmapText bmpText ;
bmpText . SetText ( c - > GetString ( selection ) ) ;
bmpText . SetBitmap ( c - > GetItemBitmap ( selection ) ) ;
value < < bmpText ;
return true ;
}
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-07-31 15:14:32 +00:00
m_bmp_lock_closed = ScalableBitmap ( this , " lock_closed " ) ;
m_bmp_lock_closed_f = ScalableBitmap ( this , " lock_closed_f " ) ;
m_bmp_lock_open = ScalableBitmap ( this , " lock_open " ) ;
m_bmp_lock_open_f = ScalableBitmap ( this , " lock_open_f " ) ;
2018-08-28 13:51:53 +00:00
# ifdef __WXMSW__
SetBackgroundColour ( wxSystemSettings : : GetColour ( wxSYS_COLOUR_WINDOW ) ) ;
# endif // __WXMSW__
2019-07-31 15:14:32 +00:00
SetBitmap ( m_bmp_lock_open . bmp ( ) ) ;
SetBitmapDisabled ( m_bmp_lock_open . bmp ( ) ) ;
SetBitmapHover ( m_bmp_lock_closed_f . bmp ( ) ) ;
2018-08-28 13:51:53 +00:00
//button events
2019-07-31 15:14:32 +00:00
Bind ( wxEVT_BUTTON , & LockButton : : OnButton , 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
{
2019-06-20 10:56:23 +00:00
if ( m_disabled )
return ;
2018-08-28 13:51:53 +00:00
m_is_pushed = ! m_is_pushed ;
2019-07-31 15:14:32 +00:00
update_button_bitmaps ( ) ;
2018-08-28 13:51:53 +00:00
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 ;
2019-07-31 15:14:32 +00:00
update_button_bitmaps ( ) ;
2019-01-09 07:48:25 +00:00
}
2019-04-24 23:45:00 +00:00
void LockButton : : msw_rescale ( )
2019-04-16 08:05:45 +00:00
{
2019-07-31 15:14:32 +00:00
m_bmp_lock_closed . msw_rescale ( ) ;
m_bmp_lock_closed_f . msw_rescale ( ) ;
m_bmp_lock_open . msw_rescale ( ) ;
m_bmp_lock_open_f . msw_rescale ( ) ;
2019-09-18 13:10:36 +00:00
update_button_bitmaps ( ) ;
2019-04-16 08:05:45 +00:00
}
2019-07-31 15:14:32 +00:00
void LockButton : : update_button_bitmaps ( )
2018-08-28 13:51:53 +00:00
{
2019-07-31 15:14:32 +00:00
SetBitmap ( m_is_pushed ? m_bmp_lock_closed . bmp ( ) : m_bmp_lock_open . bmp ( ) ) ;
SetBitmapHover ( m_is_pushed ? m_bmp_lock_closed_f . bmp ( ) : m_bmp_lock_open_f . bmp ( ) ) ;
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-07-25 14:23:32 +00:00
ScalableButton ( parent , id , icon_name , mode , size , pos , wxBU_EXACTFIT )
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-07-25 14:23:32 +00:00
SetBitmapMargins ( 3 , 0 ) ;
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 ) ;
2019-07-25 14:23:32 +00:00
SetForegroundColour ( wxSystemSettings : : GetColour ( focus ? wxSYS_COLOUR_BTNTEXT : wxSYS_COLOUR_BTNSHADOW ) ) ;
2019-01-10 10:05:58 +00:00
Refresh ( ) ;
Update ( ) ;
}
// ----------------------------------------------------------------------------
2019-04-24 23:45:00 +00:00
// ModeSizer
2019-01-10 10:05:58 +00:00
// ----------------------------------------------------------------------------
2019-07-25 14:23:32 +00:00
ModeSizer : : ModeSizer ( wxWindow * parent , int hgap /* = 0*/ ) :
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 " } ,
2019-05-13 10:13:28 +00:00
{ _ ( L ( " Advanced " ) ) , " mode_advanced_sq.png " } ,
2019-04-24 23:45:00 +00:00
{ _ ( L ( " Expert " ) ) , " mode_expert_sq.png " }
2019-02-11 13:14:35 +00:00
} ;
2019-02-06 14:29:13 +00:00
2019-05-21 12:06:43 +00:00
auto modebtnfn = [ ] ( wxCommandEvent & event , int mode_id ) {
Slic3r : : GUI : : wxGetApp ( ) . save_mode ( mode_id ) ;
event . Skip ( ) ;
} ;
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-07-25 14:23:32 +00:00
m_mode_btns . push_back ( new ModeButton ( parent , wxID_ANY , button . second , button . first ) ) ;
2019-05-27 11:07:37 +00:00
m_mode_btns . back ( ) - > Bind ( wxEVT_BUTTON , std : : bind ( modebtnfn , std : : placeholders : : _1 , int ( m_mode_btns . size ( ) - 1 ) ) ) ;
2019-05-21 12:06:43 +00:00
Add ( m_mode_btns . back ( ) ) ;
2019-02-11 13:14:35 +00:00
}
2019-01-10 10:05:58 +00:00
}
2019-04-24 23:45:00 +00:00
void ModeSizer : : SetMode ( const int mode )
2019-01-10 10:05:58 +00:00
{
2019-05-21 12:06:43 +00:00
for ( size_t m = 0 ; m < m_mode_btns . size ( ) ; m + + )
m_mode_btns [ m ] - > SetState ( int ( 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-05-21 12:06:43 +00:00
for ( size_t m = 0 ; m < m_mode_btns . size ( ) ; m + + )
2019-04-24 23:45:00 +00:00
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-05-17 17:11:11 +00:00
SetBitmap ( create_scaled_bitmap ( parent , icon_name ) ) ;
2019-08-01 09:35:43 +00:00
if ( size ! = wxDefaultSize )
{
const int em = em_unit ( parent ) ;
m_width = size . x / em ;
m_height = size . y / em ;
}
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-12-13 12:23:55 +00:00
m_parent ( parent ) ,
2019-04-13 21:46:52 +00:00
m_current_icon_name ( bitmap . name ( ) ) ,
2019-12-13 12:23:55 +00:00
m_px_cnt ( bitmap . px_cnt ( ) ) ,
m_is_horizontal ( bitmap . is_horizontal ( ) )
2019-04-13 21:46:52 +00:00
{
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-08-01 09:35:43 +00:00
void ScalableButton : : SetBitmapDisabled_ ( const ScalableBitmap & bmp )
{
SetBitmapDisabled ( bmp . bmp ( ) ) ;
m_disabled_icon_name = bmp . name ( ) ;
}
2019-12-13 16:56:04 +00:00
int ScalableButton : : GetBitmapHeight ( )
{
const float scale_factor = get_svg_scale_factor ( m_parent ) ;
return int ( ( float ) GetBitmap ( ) . GetHeight ( ) / scale_factor ) ;
}
2019-04-24 23:45:00 +00:00
void ScalableButton : : msw_rescale ( )
2019-04-13 21:46:52 +00:00
{
2019-12-13 12:23:55 +00:00
SetBitmap ( create_scaled_bitmap ( m_parent , m_current_icon_name , m_px_cnt , m_is_horizontal ) ) ;
2019-08-01 09:35:43 +00:00
if ( ! m_disabled_icon_name . empty ( ) )
2019-12-13 12:23:55 +00:00
SetBitmapDisabled ( create_scaled_bitmap ( m_parent , m_disabled_icon_name , m_px_cnt , m_is_horizontal ) ) ;
2019-04-13 21:46:52 +00:00
2019-08-01 09:35:43 +00:00
if ( m_width > 0 | | m_height > 0 )
{
const int em = em_unit ( m_parent ) ;
wxSize size ( m_width * em , m_height * em ) ;
SetMinSize ( size ) ;
}
2019-04-13 21:46:52 +00:00
}
2018-08-29 09:21:22 +00:00
2018-08-28 13:51:53 +00:00
2018-08-29 09:21:22 +00:00