mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 04:02:52 -06:00 
			
		
		
		
	Merge remote-tracking branch 'origin/profile_changes_reset'
This commit is contained in:
		
						commit
						eb58e29245
					
				
					 19 changed files with 747 additions and 238 deletions
				
			
		
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 616 B After Width: | Height: | Size: 491 B | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 448 B After Width: | Height: | Size: 510 B | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 454 B After Width: | Height: | Size: 419 B | 
|  | @ -6,7 +6,7 @@ namespace GUI { | |||
| 
 | ||||
| class Bed_2D : public wxPanel | ||||
| { | ||||
| 	bool		m_user_drawn_background = false; | ||||
| 	bool		m_user_drawn_background = true; | ||||
| 
 | ||||
| 	bool		m_painted = false; | ||||
| 	bool		m_interactive = false; | ||||
|  | @ -26,7 +26,9 @@ public: | |||
| 	{ | ||||
| 		Create(parent, wxID_ANY, wxDefaultPosition, wxSize(250, -1), wxTAB_TRAVERSAL); | ||||
| //		m_user_drawn_background = $^O ne 'darwin';
 | ||||
| 		m_user_drawn_background = true; | ||||
| #ifdef __APPLE__ | ||||
| 		m_user_drawn_background = false; | ||||
| #endif /*__APPLE__*/ | ||||
| 		Bind(wxEVT_PAINT, ([this](wxPaintEvent e) { repaint(); })); | ||||
| //		EVT_ERASE_BACKGROUND($self, sub{}) if $self->{user_drawn_background};
 | ||||
| //		Bind(EVT_MOUSE_EVENTS, ([this](wxMouseEvent  event){/*mouse_event()*/; }));
 | ||||
|  |  | |||
|  | @ -1,5 +1,14 @@ | |||
| #include "BitmapCache.hpp" | ||||
| 
 | ||||
| #if ! defined(WIN32) && ! defined(__APPLE__) | ||||
| #define BROKEN_ALPHA | ||||
| #endif | ||||
| 
 | ||||
| #ifdef BROKEN_ALPHA | ||||
|     #include <wx/mstream.h> | ||||
|     #include <wx/rawbmp.h> | ||||
| #endif /* BROKEN_ALPHA */ | ||||
| 
 | ||||
| namespace Slic3r { namespace GUI { | ||||
| 
 | ||||
| void BitmapCache::clear() | ||||
|  | @ -8,19 +17,31 @@ void BitmapCache::clear() | |||
|         delete bitmap.second; | ||||
| } | ||||
| 
 | ||||
| static wxBitmap wxImage_to_wxBitmap_with_alpha(wxImage &&image) | ||||
| { | ||||
| #ifdef BROKEN_ALPHA | ||||
|     wxMemoryOutputStream stream; | ||||
|     image.SaveFile(stream, wxBITMAP_TYPE_PNG); | ||||
|     wxStreamBuffer *buf = stream.GetOutputStreamBuffer(); | ||||
|     return wxBitmap::NewFromPNGData(buf->GetBufferStart(), buf->GetBufferSize()); | ||||
| #else | ||||
|     return wxBitmap(std::move(image)); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| wxBitmap* BitmapCache::insert(const std::string &bitmap_key, size_t width, size_t height) | ||||
| { | ||||
| 	wxBitmap *bitmap = nullptr; | ||||
| 	auto 	  it     = m_map.find(bitmap_key); | ||||
| 	if (it == m_map.end()) { | ||||
| 		bitmap = new wxBitmap(width, height); | ||||
|     	m_map[bitmap_key] = bitmap; | ||||
| 	} else { | ||||
| 		bitmap = it->second; | ||||
| 		if (bitmap->GetWidth() != width || bitmap->GetHeight() != height) | ||||
| 			bitmap->Create(width, height); | ||||
| 	} | ||||
| #if defined(__APPLE__) || defined(_MSC_VER) | ||||
|     wxBitmap *bitmap = nullptr; | ||||
|     auto      it     = m_map.find(bitmap_key); | ||||
|     if (it == m_map.end()) { | ||||
|         bitmap = new wxBitmap(width, height); | ||||
|         m_map[bitmap_key] = bitmap; | ||||
|     } else { | ||||
|         bitmap = it->second; | ||||
|         if (bitmap->GetWidth() != width || bitmap->GetHeight() != height) | ||||
|             bitmap->Create(width, height); | ||||
|     } | ||||
| #ifndef BROKEN_ALPHA | ||||
|     bitmap->UseAlpha(); | ||||
| #endif | ||||
|     return bitmap; | ||||
|  | @ -28,77 +49,108 @@ wxBitmap* BitmapCache::insert(const std::string &bitmap_key, size_t width, size_ | |||
| 
 | ||||
| wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap &bmp) | ||||
| { | ||||
| 	wxBitmap *bitmap = this->insert(bitmap_key, bmp.GetWidth(), bmp.GetHeight()); | ||||
| 
 | ||||
|     wxMemoryDC memDC; | ||||
|     memDC.SelectObject(*bitmap); | ||||
|     memDC.SetBackground(*wxTRANSPARENT_BRUSH); | ||||
|     memDC.Clear(); | ||||
|     memDC.DrawBitmap(bmp, 0, 0, true); | ||||
|     memDC.SelectObject(wxNullBitmap); | ||||
| 
 | ||||
| 	return bitmap; | ||||
|     wxBitmap *bitmap = nullptr; | ||||
|     auto      it     = m_map.find(bitmap_key); | ||||
|     if (it == m_map.end()) { | ||||
|         bitmap = new wxBitmap(bmp); | ||||
|         m_map[bitmap_key] = bitmap; | ||||
|     } else { | ||||
|         bitmap = it->second; | ||||
|         *bitmap = bmp; | ||||
|     } | ||||
|     return bitmap; | ||||
| } | ||||
| 
 | ||||
| wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap &bmp, const wxBitmap &bmp2) | ||||
| { | ||||
| 	wxBitmap *bitmap = this->insert(bitmap_key, bmp.GetWidth() + bmp2.GetWidth(), std::max(bmp.GetHeight(), bmp2.GetHeight())); | ||||
| 
 | ||||
|     wxMemoryDC memDC; | ||||
|     memDC.SelectObject(*bitmap); | ||||
|     memDC.SetBackground(*wxTRANSPARENT_BRUSH); | ||||
|     memDC.Clear(); | ||||
|     if (bmp.GetWidth() > 0) | ||||
|     	memDC.DrawBitmap(bmp,  0, 				0, true); | ||||
|     if (bmp2.GetWidth() > 0) | ||||
| 	    memDC.DrawBitmap(bmp2, bmp.GetWidth(), 	0, true); | ||||
|     memDC.SelectObject(wxNullBitmap); | ||||
| 
 | ||||
| 	return bitmap; | ||||
|     // Copying the wxBitmaps is cheap as the bitmap's content is reference counted.
 | ||||
|     const wxBitmap bmps[2] = { bmp, bmp2 }; | ||||
|     return this->insert(bitmap_key, bmps, bmps + 2); | ||||
| } | ||||
| 
 | ||||
| wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap &bmp, const wxBitmap &bmp2, const wxBitmap &bmp3) | ||||
| { | ||||
| 	wxBitmap *bitmap = this->insert(bitmap_key, bmp.GetWidth() + bmp2.GetWidth() + bmp3.GetWidth(), std::max(std::max(bmp.GetHeight(), bmp2.GetHeight()), bmp3.GetHeight())); | ||||
| 
 | ||||
|     wxMemoryDC memDC; | ||||
|     memDC.SelectObject(*bitmap); | ||||
|     memDC.SetBackground(*wxTRANSPARENT_BRUSH); | ||||
|     memDC.Clear(); | ||||
|     if (bmp.GetWidth() > 0) | ||||
| 	    memDC.DrawBitmap(bmp,  0, 									0, true); | ||||
|     if (bmp2.GetWidth() > 0) | ||||
|     	memDC.DrawBitmap(bmp2, bmp.GetWidth(), 						0, true); | ||||
|     if (bmp3.GetWidth() > 0) | ||||
| 	    memDC.DrawBitmap(bmp3, bmp.GetWidth() + bmp2.GetWidth(), 	0, true); | ||||
|     memDC.SelectObject(wxNullBitmap); | ||||
| 
 | ||||
| 	return bitmap; | ||||
|     // Copying the wxBitmaps is cheap as the bitmap's content is reference counted.
 | ||||
|     const wxBitmap bmps[3] = { bmp, bmp2, bmp3 }; | ||||
|     return this->insert(bitmap_key, bmps, bmps + 3); | ||||
| } | ||||
| 
 | ||||
| wxBitmap* BitmapCache::insert(const std::string &bitmap_key, std::vector<wxBitmap> &bmps) | ||||
| wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap *begin, const wxBitmap *end) | ||||
| { | ||||
| 	size_t width  = 0; | ||||
| 	size_t height = 0; | ||||
| 	for (wxBitmap &bmp : bmps) { | ||||
| 		width += bmp.GetWidth(); | ||||
| 		height = std::max<size_t>(height, bmp.GetHeight()); | ||||
| 	} | ||||
| 	wxBitmap *bitmap = this->insert(bitmap_key, width, height); | ||||
|     size_t width  = 0; | ||||
|     size_t height = 0; | ||||
|     for (const wxBitmap *bmp = begin; bmp != end; ++ bmp) { | ||||
|         width += bmp->GetWidth(); | ||||
|         height = std::max<size_t>(height, bmp->GetHeight()); | ||||
|     } | ||||
| 
 | ||||
| #ifdef BROKEN_ALPHA | ||||
| 
 | ||||
|     wxImage image(width, height); | ||||
|     image.InitAlpha(); | ||||
|     // Fill in with a white color.
 | ||||
|     memset(image.GetData(), 0x0ff, width * height * 3); | ||||
|     // Fill in with full transparency.
 | ||||
|     memset(image.GetAlpha(),    0, width * height); | ||||
|     size_t x = 0; | ||||
|     for (const wxBitmap *bmp = begin; bmp != end; ++ bmp) { | ||||
|         if (bmp->GetWidth() > 0) { | ||||
|             if (bmp->GetDepth() == 32) { | ||||
|                 wxAlphaPixelData data(*const_cast<wxBitmap*>(bmp)); | ||||
|                 data.UseAlpha(); | ||||
|                 if (data) { | ||||
|                     for (int r = 0; r < bmp->GetHeight(); ++ r) { | ||||
|                         wxAlphaPixelData::Iterator src(data); | ||||
|                         src.Offset(data, 0, r); | ||||
|                         unsigned char *dst_pixels = image.GetData()  + (x + r * width) * 3; | ||||
|                         unsigned char *dst_alpha  = image.GetAlpha() +  x + r * width; | ||||
|                         for (int c = 0; c < bmp->GetWidth(); ++ c, ++ src) { | ||||
|                             *dst_pixels ++ = src.Red(); | ||||
|                             *dst_pixels ++ = src.Green(); | ||||
|                             *dst_pixels ++ = src.Blue(); | ||||
|                             *dst_alpha  ++ = src.Alpha(); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } else if (bmp->GetDepth() == 24) { | ||||
|                 wxNativePixelData data(*const_cast<wxBitmap*>(bmp)); | ||||
|                 if (data) { | ||||
|                     for (int r = 0; r < bmp->GetHeight(); ++ r) { | ||||
|                         wxNativePixelData::Iterator src(data); | ||||
|                         src.Offset(data, 0, r); | ||||
|                         unsigned char *dst_pixels = image.GetData()  + (x + r * width) * 3; | ||||
|                         unsigned char *dst_alpha  = image.GetAlpha() +  x + r * width; | ||||
|                         for (int c = 0; c < bmp->GetWidth(); ++ c, ++ src) { | ||||
|                             *dst_pixels ++ = src.Red(); | ||||
|                             *dst_pixels ++ = src.Green(); | ||||
|                             *dst_pixels ++ = src.Blue(); | ||||
|                             *dst_alpha  ++ = wxALPHA_OPAQUE; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         x += bmp->GetWidth(); | ||||
|     } | ||||
|     return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image))); | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
|     wxBitmap *bitmap = this->insert(bitmap_key, width, height); | ||||
|     wxMemoryDC memDC; | ||||
|     memDC.SelectObject(*bitmap); | ||||
|     memDC.SetBackground(*wxTRANSPARENT_BRUSH); | ||||
|     memDC.Clear(); | ||||
|     size_t x = 0; | ||||
| 	for (wxBitmap &bmp : bmps) { | ||||
| 	    if (bmp.GetWidth() > 0) | ||||
| 		    memDC.DrawBitmap(bmp, x, 0, true); | ||||
| 		x += bmp.GetWidth(); | ||||
| 	} | ||||
|     for (const wxBitmap *bmp = begin; bmp != end; ++ bmp) { | ||||
|         if (bmp->GetWidth() > 0) | ||||
|             memDC.DrawBitmap(*bmp, x, 0, true); | ||||
|         x += bmp->GetWidth(); | ||||
|     } | ||||
|     memDC.SelectObject(wxNullBitmap); | ||||
|     return bitmap; | ||||
| 
 | ||||
| 	return bitmap; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency) | ||||
|  | @ -113,7 +165,7 @@ wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsi | |||
|         *imgdata ++ = b; | ||||
|         *imgalpha ++ = transparency; | ||||
|     } | ||||
|     return wxBitmap(std::move(image)); | ||||
|     return wxImage_to_wxBitmap_with_alpha(std::move(image)); | ||||
| } | ||||
| 
 | ||||
| } // namespace GUI
 | ||||
|  |  | |||
|  | @ -27,7 +27,8 @@ public: | |||
| 	wxBitmap* 		insert(const std::string &name, const wxBitmap &bmp); | ||||
| 	wxBitmap* 		insert(const std::string &name, const wxBitmap &bmp, const wxBitmap &bmp2); | ||||
| 	wxBitmap* 		insert(const std::string &name, const wxBitmap &bmp, const wxBitmap &bmp2, const wxBitmap &bmp3); | ||||
| 	wxBitmap* 		insert(const std::string &name, std::vector<wxBitmap> &bmps); | ||||
| 	wxBitmap* 		insert(const std::string &name, const std::vector<wxBitmap> &bmps) { return this->insert(name, &bmps.front(), &bmps.front() + bmps.size()); } | ||||
| 	wxBitmap* 		insert(const std::string &name, const wxBitmap *begin, const wxBitmap *end); | ||||
| 
 | ||||
| 	static wxBitmap mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency); | ||||
| 	static wxBitmap mksolid(size_t width, size_t height, const unsigned char rgb[3]) { return mksolid(width, height, rgb[0], rgb[1], rgb[2], wxALPHA_OPAQUE); } | ||||
|  |  | |||
|  | @ -75,13 +75,13 @@ namespace Slic3r { namespace GUI { | |||
| 		return tooltip_text; | ||||
| 	} | ||||
| 
 | ||||
| 	bool Field::is_matched(std::string string, std::string pattern) | ||||
| 	bool Field::is_matched(const std::string& string, const std::string& pattern) | ||||
| 	{ | ||||
| 		std::regex regex_pattern(pattern, std::regex_constants::icase); // use ::icase to make the matching case insensitive like /i in perl
 | ||||
| 		return std::regex_match(string, regex_pattern); | ||||
| 	} | ||||
| 
 | ||||
| 	boost::any Field::get_value_by_opt_type(wxString str) | ||||
| 	boost::any Field::get_value_by_opt_type(wxString& str) | ||||
| 	{ | ||||
| 		boost::any ret_val; | ||||
| 		switch (m_opt.type){ | ||||
|  | @ -173,8 +173,7 @@ namespace Slic3r { namespace GUI { | |||
| 
 | ||||
| 		temp->Bind(wxEVT_KILL_FOCUS, ([this, temp](wxEvent& e) | ||||
| 		{ | ||||
| //			on_kill_focus(e);
 | ||||
| 			e.Skip(); | ||||
| 			e.Skip();//	on_kill_focus(e);
 | ||||
| 			temp->GetToolTip()->Enable(true); | ||||
| 		}), temp->GetId()); | ||||
| 
 | ||||
|  | @ -378,7 +377,7 @@ void Choice::set_selection() | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| void Choice::set_value(const std::string value, bool change_event)  //! Redundant?
 | ||||
| void Choice::set_value(const std::string& value, bool change_event)  //! Redundant?
 | ||||
| { | ||||
| 	m_disable_change_event = !change_event; | ||||
| 
 | ||||
|  | @ -397,7 +396,7 @@ void Choice::set_value(const std::string value, bool change_event)  //! Redundan | |||
| 	m_disable_change_event = false; | ||||
| } | ||||
| 
 | ||||
| void Choice::set_value(boost::any value, bool change_event) | ||||
| void Choice::set_value(const boost::any& value, bool change_event) | ||||
| { | ||||
| 	m_disable_change_event = !change_event; | ||||
| 
 | ||||
|  | @ -436,7 +435,7 @@ void Choice::set_value(boost::any value, bool change_event) | |||
| } | ||||
| 
 | ||||
| //! it's needed for _update_serial_ports()
 | ||||
| void Choice::set_values(const std::vector<std::string> values) | ||||
| void Choice::set_values(const std::vector<std::string>& values) | ||||
| { | ||||
| 	if (values.empty()) | ||||
| 		return; | ||||
|  | @ -555,7 +554,7 @@ void PointCtrl::BUILD() | |||
| 	y_textctrl->SetToolTip(get_tooltip_text(X+", "+Y)); | ||||
| } | ||||
| 
 | ||||
| void PointCtrl::set_value(const Pointf value, bool change_event) | ||||
| void PointCtrl::set_value(const Pointf& value, bool change_event) | ||||
| { | ||||
| 	m_disable_change_event = !change_event; | ||||
| 
 | ||||
|  | @ -567,10 +566,10 @@ void PointCtrl::set_value(const Pointf value, bool change_event) | |||
| 	m_disable_change_event = false; | ||||
| } | ||||
| 
 | ||||
| void PointCtrl::set_value(boost::any value, bool change_event) | ||||
| void PointCtrl::set_value(const boost::any& value, bool change_event) | ||||
| { | ||||
| 	Pointf pt; | ||||
| 	Pointf *ptf = boost::any_cast<Pointf>(&value); | ||||
| 	const Pointf *ptf = boost::any_cast<Pointf>(&value); | ||||
| 	if (!ptf) | ||||
| 	{ | ||||
| 		ConfigOptionPoints* pts = boost::any_cast<ConfigOptionPoints*>(value); | ||||
|  | @ -578,21 +577,6 @@ void PointCtrl::set_value(boost::any value, bool change_event) | |||
| 	} | ||||
| 	else | ||||
| 		pt = *ptf; | ||||
| // 	try
 | ||||
| // 	{
 | ||||
| // 		pt = boost::any_cast<ConfigOptionPoints*>(value)->values.at(0);
 | ||||
| // 	}
 | ||||
| // 	catch (const std::exception &e)
 | ||||
| // 	{
 | ||||
| // 		try{
 | ||||
| // 			pt = boost::any_cast<Pointf>(value);
 | ||||
| // 		}
 | ||||
| // 		catch (const std::exception &e)
 | ||||
| // 		{
 | ||||
| // 			std::cerr << "Error! Can't cast PointCtrl value" << m_opt_id << "\n";
 | ||||
| // 			return;
 | ||||
| // 		}		
 | ||||
| // 	}	
 | ||||
| 	set_value(pt, change_event); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -31,8 +31,8 @@ namespace Slic3r { namespace GUI { | |||
| class Field; | ||||
| using t_field = std::unique_ptr<Field>; | ||||
| using t_kill_focus = std::function<void()>; | ||||
| using t_change = std::function<void(t_config_option_key, boost::any)>; | ||||
| using t_back_to_init = std::function<void(std::string)>; | ||||
| using t_change = std::function<void(t_config_option_key, const boost::any&)>; | ||||
| using t_back_to_init = std::function<void(const std::string&)>; | ||||
| 
 | ||||
| wxString double_to_string(double const value); | ||||
| 
 | ||||
|  | @ -81,7 +81,7 @@ public: | |||
|     /// Sets a value for this control.
 | ||||
|     /// subclasses should overload with a specific version
 | ||||
|     /// Postcondition: Method does not fire the on_change event.
 | ||||
|     virtual void		set_value(boost::any value, bool change_event) = 0; | ||||
|     virtual void		set_value(const boost::any& value, bool change_event) = 0; | ||||
|      | ||||
|     /// Gets a boost::any representing this control.
 | ||||
|     /// subclasses should overload with a specific version
 | ||||
|  | @ -100,7 +100,7 @@ public: | |||
| 	virtual wxString	get_tooltip_text(const wxString& default_string); | ||||
| 
 | ||||
|     // set icon to "UndoToSystemValue" button according to an inheritance of preset
 | ||||
| 	void set_nonsys_btn_icon(const std::string& icon); | ||||
| 	void				set_nonsys_btn_icon(const std::string& icon); | ||||
| 
 | ||||
|     Field(const ConfigOptionDef& opt, const t_config_option_key& id) : m_opt(opt), m_opt_id(id) {}; | ||||
|     Field(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : m_parent(parent), m_opt(opt), m_opt_id(id) {}; | ||||
|  | @ -109,8 +109,8 @@ public: | |||
|     virtual wxSizer*	getSizer()  { return nullptr; } | ||||
|     virtual wxWindow*	getWindow() { return nullptr; } | ||||
| 
 | ||||
| 	bool		is_matched(std::string string, std::string pattern); | ||||
| 	boost::any	get_value_by_opt_type(wxString str); | ||||
| 	bool				is_matched(const std::string& string, const std::string& pattern); | ||||
| 	boost::any			get_value_by_opt_type(wxString& str); | ||||
| 
 | ||||
|     /// Factory method for generating new derived classes.
 | ||||
|     template<class T> | ||||
|  | @ -137,16 +137,17 @@ class TextCtrl : public Field { | |||
| public: | ||||
| 	TextCtrl(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt,  id) {} | ||||
| 	TextCtrl(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {} | ||||
| 	~TextCtrl() {} | ||||
| 
 | ||||
|     void BUILD(); | ||||
|     wxWindow* window {nullptr}; | ||||
| 
 | ||||
|     virtual void	set_value(std::string value, bool change_event = false) { | ||||
|     virtual void	set_value(const std::string& value, bool change_event = false) { | ||||
| 		m_disable_change_event = !change_event; | ||||
|         dynamic_cast<wxTextCtrl*>(window)->SetValue(wxString(value)); | ||||
| 		m_disable_change_event = false; | ||||
|     } | ||||
|     virtual void	set_value(boost::any value, bool change_event = false) { | ||||
| 	virtual void	set_value(const boost::any& value, bool change_event = false) { | ||||
| 		m_disable_change_event = !change_event; | ||||
| 		dynamic_cast<wxTextCtrl*>(window)->SetValue(boost::any_cast<wxString>(value)); | ||||
| 		m_disable_change_event = false; | ||||
|  | @ -164,6 +165,7 @@ class CheckBox : public Field { | |||
| public: | ||||
| 	CheckBox(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {} | ||||
| 	CheckBox(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {} | ||||
| 	~CheckBox() {} | ||||
| 
 | ||||
| 	wxWindow*		window{ nullptr }; | ||||
| 	void			BUILD() override; | ||||
|  | @ -173,7 +175,7 @@ public: | |||
| 		dynamic_cast<wxCheckBox*>(window)->SetValue(value); | ||||
| 		m_disable_change_event = false; | ||||
| 	} | ||||
| 	void			set_value(boost::any value, bool change_event = false) { | ||||
| 	void			set_value(const boost::any& value, bool change_event = false) { | ||||
| 		m_disable_change_event = !change_event; | ||||
| 		dynamic_cast<wxCheckBox*>(window)->SetValue(boost::any_cast<bool>(value)); | ||||
| 		m_disable_change_event = false; | ||||
|  | @ -190,21 +192,22 @@ class SpinCtrl : public Field { | |||
| public: | ||||
| 	SpinCtrl(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id), tmp_value(-9999) {} | ||||
| 	SpinCtrl(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id), tmp_value(-9999) {} | ||||
| 	~SpinCtrl() {} | ||||
| 
 | ||||
| 	int				tmp_value; | ||||
| 
 | ||||
| 	wxWindow*		window{ nullptr }; | ||||
| 	void			BUILD() override; | ||||
| 
 | ||||
| 	void			set_value(const std::string value, bool change_event = false) { | ||||
| 	void			set_value(const std::string& value, bool change_event = false) { | ||||
| 		m_disable_change_event = !change_event; | ||||
| 		dynamic_cast<wxSpinCtrl*>(window)->SetValue(value); | ||||
| 		m_disable_change_event = false; | ||||
| 	} | ||||
| 	void			set_value(boost::any value, bool change_event = false) { | ||||
| 	void			set_value(const boost::any& value, bool change_event = false) { | ||||
| 		m_disable_change_event = !change_event; | ||||
| 		tmp_value = boost::any_cast<int>(value); | ||||
| 		dynamic_cast<wxSpinCtrl*>(window)->SetValue(tmp_value/*boost::any_cast<int>(value)*/); | ||||
| 		dynamic_cast<wxSpinCtrl*>(window)->SetValue(tmp_value); | ||||
| 		m_disable_change_event = false; | ||||
| 	} | ||||
| 	boost::any		get_value() override { | ||||
|  | @ -221,14 +224,15 @@ class Choice : public Field { | |||
| public: | ||||
| 	Choice(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {} | ||||
| 	Choice(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {} | ||||
| 	~Choice() {} | ||||
| 
 | ||||
| 	wxWindow*		window{ nullptr }; | ||||
| 	void			BUILD() override; | ||||
| 
 | ||||
| 	void			set_selection(); | ||||
| 	void			set_value(const std::string value, bool change_event = false); | ||||
| 	void			set_value(boost::any value, bool change_event = false); | ||||
| 	void			set_values(const std::vector<std::string> values); | ||||
| 	void			set_value(const std::string& value, bool change_event = false); | ||||
| 	void			set_value(const boost::any& value, bool change_event = false); | ||||
| 	void			set_values(const std::vector<std::string> &values); | ||||
| 	boost::any		get_value() override; | ||||
| 
 | ||||
| 	void			enable() override { dynamic_cast<wxComboBox*>(window)->Enable(); }; | ||||
|  | @ -241,16 +245,17 @@ class ColourPicker : public Field { | |||
| public: | ||||
| 	ColourPicker(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {} | ||||
| 	ColourPicker(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {} | ||||
| 	~ColourPicker() {} | ||||
| 
 | ||||
| 	wxWindow*		window{ nullptr }; | ||||
| 	void			BUILD()  override; | ||||
| 
 | ||||
| 	void			set_value(const std::string value, bool change_event = false) { | ||||
| 	void			set_value(const std::string& value, bool change_event = false) { | ||||
| 		m_disable_change_event = !change_event; | ||||
| 		dynamic_cast<wxColourPickerCtrl*>(window)->SetColour(value); | ||||
| 		m_disable_change_event = false; | ||||
| 	 	} | ||||
| 	void			set_value(boost::any value, bool change_event = false) { | ||||
| 	void			set_value(const boost::any& value, bool change_event = false) { | ||||
| 		m_disable_change_event = !change_event; | ||||
| 		dynamic_cast<wxColourPickerCtrl*>(window)->SetColour(boost::any_cast<wxString>(value)); | ||||
| 		m_disable_change_event = false; | ||||
|  | @ -268,23 +273,24 @@ class PointCtrl : public Field { | |||
| public: | ||||
| 	PointCtrl(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {} | ||||
| 	PointCtrl(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {} | ||||
| 	~PointCtrl() {} | ||||
| 
 | ||||
| 	wxSizer*		sizer{ nullptr }; | ||||
| 	wxTextCtrl*		x_textctrl; | ||||
| 	wxTextCtrl*		y_textctrl; | ||||
| 	wxTextCtrl*		x_textctrl{ nullptr }; | ||||
| 	wxTextCtrl*		y_textctrl{ nullptr }; | ||||
| 
 | ||||
| 	void			BUILD()  override; | ||||
| 
 | ||||
| 	void			set_value(const Pointf value, bool change_event = false); | ||||
| 	void			set_value(boost::any value, bool change_event = false); | ||||
| 	void			set_value(const Pointf& value, bool change_event = false); | ||||
| 	void			set_value(const boost::any& value, bool change_event = false); | ||||
| 	boost::any		get_value() override; | ||||
| 
 | ||||
| 	void			enable() override { | ||||
| 		x_textctrl->Enable(); | ||||
| 		y_textctrl->Enable(); }; | ||||
| 		y_textctrl->Enable(); } | ||||
| 	void			disable() override{ | ||||
| 		x_textctrl->Disable(); | ||||
| 		y_textctrl->Disable(); }; | ||||
| 		y_textctrl->Disable(); } | ||||
| 	wxSizer*		getSizer() override { return sizer; } | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -405,7 +405,7 @@ TabIface* get_preset_tab_iface(char *name) | |||
| } | ||||
| 
 | ||||
| // opt_index = 0, by the reason of zero-index in ConfigOptionVector by default (in case only one element)
 | ||||
| void change_opt_value(DynamicPrintConfig& config, t_config_option_key opt_key, boost::any value, int opt_index /*= 0*/) | ||||
| void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index /*= 0*/) | ||||
| { | ||||
| 	try{ | ||||
| 		switch (config.def()->get(opt_key)->type){ | ||||
|  | @ -441,11 +441,18 @@ void change_opt_value(DynamicPrintConfig& config, t_config_option_key opt_key, b | |||
| 			config.set_key_value(opt_key, new ConfigOptionString(boost::any_cast<std::string>(value))); | ||||
| 			break; | ||||
| 		case coStrings:{ | ||||
| 			if (opt_key.compare("compatible_printers") == 0 || | ||||
| 				config.def()->get(opt_key)->gui_flags.compare("serialized") == 0){ | ||||
| 				config.option<ConfigOptionStrings>(opt_key)->values.resize(0); | ||||
| 				std::vector<std::string> values = boost::any_cast<std::vector<std::string>>(value); | ||||
| 				if (values.size() == 1 && values[0] == "") | ||||
| 			if (opt_key.compare("compatible_printers") == 0) { | ||||
| 				config.option<ConfigOptionStrings>(opt_key)->values =  | ||||
| 					boost::any_cast<std::vector<std::string>>(value); | ||||
| 			} | ||||
| 			else if (config.def()->get(opt_key)->gui_flags.compare("serialized") == 0){ | ||||
| 				std::string str = boost::any_cast<std::string>(value); | ||||
| 				if (str.back() == ';') str.pop_back(); | ||||
| 				// Split a string to multiple strings by a semi - colon.This is the old way of storing multi - string values.
 | ||||
| 				// Currently used for the post_process config value only.
 | ||||
| 				std::vector<std::string> values; | ||||
| 				boost::split(values, str, boost::is_any_of(";")); | ||||
| 				if (values.size() == 1 && values[0] == "")  | ||||
| 					break; | ||||
| 				config.option<ConfigOptionStrings>(opt_key)->values = values; | ||||
| 			} | ||||
|  | @ -512,17 +519,17 @@ void add_created_tab(Tab* panel) | |||
| 	g_wxTabPanel->AddPage(panel, panel->title()); | ||||
| } | ||||
| 
 | ||||
| void show_error(wxWindow* parent, wxString message){ | ||||
| void show_error(wxWindow* parent, const wxString& message){ | ||||
| 	auto msg_wingow = new wxMessageDialog(parent, message, _(L("Error")), wxOK | wxICON_ERROR); | ||||
| 	msg_wingow->ShowModal(); | ||||
| } | ||||
| 
 | ||||
| void show_info(wxWindow* parent, wxString message, wxString title){ | ||||
| void show_info(wxWindow* parent, const wxString& message, const wxString& title){ | ||||
| 	auto msg_wingow = new wxMessageDialog(parent, message, title.empty() ? _(L("Notice")) : title, wxOK | wxICON_INFORMATION); | ||||
| 	msg_wingow->ShowModal(); | ||||
| } | ||||
| 
 | ||||
| void warning_catcher(wxWindow* parent, wxString message){ | ||||
| void warning_catcher(wxWindow* parent, const wxString& message){ | ||||
| 	if (message == _(L("GLUquadricObjPtr | Attempt to free unreferenced scalar")) ) | ||||
| 		return; | ||||
| 	auto msg = new wxMessageDialog(parent, message, _(L("Warning")), wxOK | wxICON_WARNING); | ||||
|  |  | |||
|  | @ -97,11 +97,11 @@ TabIface* get_preset_tab_iface(char *name); | |||
| // add it at the end of the tab panel.
 | ||||
| void add_created_tab(Tab* panel); | ||||
| // Change option value in config
 | ||||
| void change_opt_value(DynamicPrintConfig& config, t_config_option_key opt_key, boost::any value, int opt_index = 0); | ||||
| void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index = 0); | ||||
| 
 | ||||
| void show_error(wxWindow* parent, wxString message); | ||||
| void show_info(wxWindow* parent, wxString message, wxString title); | ||||
| void warning_catcher(wxWindow* parent, wxString message); | ||||
| void show_error(wxWindow* parent, const wxString& message); | ||||
| void show_info(wxWindow* parent, const wxString& message, const wxString& title); | ||||
| void warning_catcher(wxWindow* parent, const wxString& message); | ||||
| 
 | ||||
| // load language saved at application config 
 | ||||
| bool load_language(); | ||||
|  |  | |||
|  | @ -97,7 +97,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co | |||
|     return field; | ||||
| } | ||||
| 
 | ||||
| void OptionsGroup::append_line(const Line& line) { | ||||
| void OptionsGroup::append_line(const Line& line, wxStaticText**	colored_Label/* = nullptr*/) { | ||||
| //!    if (line.sizer != nullptr || (line.widget != nullptr && line.full_width > 0)){
 | ||||
| 	if ( (line.sizer != nullptr || line.widget != nullptr) && line.full_width){ | ||||
| 		if (line.sizer != nullptr) { | ||||
|  | @ -149,7 +149,8 @@ void OptionsGroup::append_line(const Line& line) { | |||
|     // If there's a widget, build it and add the result to the sizer.
 | ||||
| 	if (line.widget != nullptr) { | ||||
| 		auto wgt = line.widget(parent()); | ||||
| 		grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, wxOSX ? 0 : 1); | ||||
| 		grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, wxOSX ? 0 : 5); | ||||
| 		if (colored_Label != nullptr) *colored_Label = label; | ||||
| 		return; | ||||
| 	} | ||||
| 	 | ||||
|  | @ -227,12 +228,12 @@ Line OptionsGroup::create_single_option_line(const Option& option) const { | |||
|     return retval; | ||||
| } | ||||
| 
 | ||||
| void OptionsGroup::on_change_OG(t_config_option_key id, /*config_value*/boost::any value) { | ||||
| void OptionsGroup::on_change_OG(const t_config_option_key& opt_id, const boost::any& value) { | ||||
| 	if (m_on_change != nullptr) | ||||
| 		m_on_change(id, value); | ||||
| 		m_on_change(opt_id, value); | ||||
| } | ||||
| 
 | ||||
| Option ConfigOptionsGroup::get_option(const std::string opt_key, int opt_index /*= -1*/) | ||||
| Option ConfigOptionsGroup::get_option(const std::string& opt_key, int opt_index /*= -1*/) | ||||
| { | ||||
| 	if (!m_config->has(opt_key)) { | ||||
| 		std::cerr << "No " << opt_key << " in ConfigOptionsGroup config."; | ||||
|  | @ -245,7 +246,7 @@ Option ConfigOptionsGroup::get_option(const std::string opt_key, int opt_index / | |||
| 	return Option(*m_config->def()->get(opt_key), opt_id); | ||||
| } | ||||
| 
 | ||||
| void ConfigOptionsGroup::on_change_OG(t_config_option_key opt_id, boost::any value) | ||||
| void ConfigOptionsGroup::on_change_OG(const t_config_option_key& opt_id, const boost::any& value) | ||||
| { | ||||
| 	if (!m_opt_map.empty()) | ||||
| 	{ | ||||
|  | @ -268,16 +269,7 @@ void ConfigOptionsGroup::on_change_OG(t_config_option_key opt_id, boost::any val | |||
| 			if (opt_index != -1){ | ||||
| 				// 		die "Can't set serialized option indexed value" ;
 | ||||
| 			} | ||||
| 			// 		# Split a string to multiple strings by a semi - colon.This is the old way of storing multi - string values.
 | ||||
| 			// 		# Currently used for the post_process config value only.
 | ||||
| 			// 		my @values = split / ; / , $field_value;
 | ||||
| 			// 		$self->config->set($opt_key, \@values);
 | ||||
| 			std::string str = boost::any_cast<std::string>(value); | ||||
| 			if (str.back() == ';') | ||||
| 				str.pop_back(); | ||||
| 			std::vector<std::string> values; | ||||
| 			boost::split(values, str, boost::is_any_of(";")); | ||||
| 			change_opt_value(*m_config, opt_key, values); | ||||
| 			change_opt_value(*m_config, opt_key, value); | ||||
| 		} | ||||
| 		else { | ||||
| 			if (opt_index == -1) { | ||||
|  | @ -297,14 +289,14 @@ void ConfigOptionsGroup::on_change_OG(t_config_option_key opt_id, boost::any val | |||
| 	OptionsGroup::on_change_OG(opt_id, value); //!? Why doing this
 | ||||
| } | ||||
| 
 | ||||
| void ConfigOptionsGroup::back_to_initial_value(const std::string opt_key) | ||||
| void ConfigOptionsGroup::back_to_initial_value(const std::string& opt_key) | ||||
| { | ||||
| 	if (m_get_initial_config == nullptr) | ||||
| 		return; | ||||
| 	back_to_config_value(m_get_initial_config(), opt_key); | ||||
| } | ||||
| 
 | ||||
| void ConfigOptionsGroup::back_to_sys_value(const std::string opt_key) | ||||
| void ConfigOptionsGroup::back_to_sys_value(const std::string& opt_key) | ||||
| { | ||||
| 	if (m_get_sys_config == nullptr) | ||||
| 		return; | ||||
|  | @ -313,7 +305,7 @@ void ConfigOptionsGroup::back_to_sys_value(const std::string opt_key) | |||
| 	back_to_config_value(m_get_sys_config(), opt_key); | ||||
| } | ||||
| 
 | ||||
| void ConfigOptionsGroup::back_to_config_value(const DynamicPrintConfig& config, const std::string opt_key) | ||||
| void ConfigOptionsGroup::back_to_config_value(const DynamicPrintConfig& config, const std::string& opt_key) | ||||
| { | ||||
| 	boost::any value; | ||||
| 	if (opt_key == "extruders_count"){ | ||||
|  | @ -348,7 +340,7 @@ void ConfigOptionsGroup::reload_config(){ | |||
| 
 | ||||
| } | ||||
| 
 | ||||
| boost::any ConfigOptionsGroup::config_value(std::string opt_key, int opt_index, bool deserialize){ | ||||
| boost::any ConfigOptionsGroup::config_value(const std::string& opt_key, int opt_index, bool deserialize){ | ||||
| 
 | ||||
| 	if (deserialize) { | ||||
| 		// Want to edit a vector value(currently only multi - strings) in a single edit box.
 | ||||
|  | @ -365,7 +357,7 @@ boost::any ConfigOptionsGroup::config_value(std::string opt_key, int opt_index, | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config, std::string opt_key, int opt_index /*= -1*/) | ||||
| boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config, const std::string& opt_key, int opt_index /*= -1*/) | ||||
| { | ||||
| 	size_t idx = opt_index == -1 ? 0 : opt_index; | ||||
| 	 | ||||
|  | @ -405,6 +397,10 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config | |||
| 		ret = static_cast<wxString>(config.opt_string(opt_key)); | ||||
| 		break; | ||||
| 	case coStrings: | ||||
| 		if (opt_key.compare("compatible_printers") == 0){ | ||||
| 			ret = config.option<ConfigOptionStrings>(opt_key)->values; | ||||
| 			break; | ||||
| 		} | ||||
| 		if (config.option<ConfigOptionStrings>(opt_key)->values.empty()) | ||||
| 			ret = text_value; | ||||
| 		else if (opt->gui_flags.compare("serialized") == 0){ | ||||
|  | @ -457,7 +453,7 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| Field* ConfigOptionsGroup::get_fieldc(t_config_option_key opt_key, int opt_index){ | ||||
| Field* ConfigOptionsGroup::get_fieldc(const t_config_option_key& opt_key, int opt_index){ | ||||
| 	Field* field = get_field(opt_key); | ||||
| 	if (field != nullptr) | ||||
| 		return field; | ||||
|  | @ -471,7 +467,7 @@ Field* ConfigOptionsGroup::get_fieldc(t_config_option_key opt_key, int opt_index | |||
| 	return opt_id.empty() ? nullptr : get_field(opt_id); | ||||
| } | ||||
| 
 | ||||
| void ogStaticText::SetText(wxString value) | ||||
| void ogStaticText::SetText(const wxString& value) | ||||
| { | ||||
| 	SetLabel(value); | ||||
| 	Wrap(400); | ||||
|  |  | |||
|  | @ -93,21 +93,21 @@ public: | |||
|     /// but defining it as const means a lot of const_casts to deal with wx functions.
 | ||||
|     inline wxWindow* parent() const { return m_parent; } | ||||
| 
 | ||||
|     void		append_line(const Line& line); | ||||
| 	void		append_line(const Line& line, wxStaticText** colored_Label = nullptr); | ||||
|     Line		create_single_option_line(const Option& option) const; | ||||
|     void		append_single_option_line(const Option& option) { append_line(create_single_option_line(option)); } | ||||
| 
 | ||||
|     // return a non-owning pointer reference 
 | ||||
|     inline Field*	get_field(t_config_option_key id) const{ | ||||
|     inline Field*	get_field(const t_config_option_key& id) const{ | ||||
| 							if (m_fields.find(id) == m_fields.end()) return nullptr; | ||||
| 							return m_fields.at(id).get(); | ||||
|     } | ||||
| 	bool			set_value(t_config_option_key id, boost::any value, bool change_event = false) { | ||||
| 	bool			set_value(const t_config_option_key& id, const boost::any& value, bool change_event = false) { | ||||
| 							if (m_fields.find(id) == m_fields.end()) return false; | ||||
| 							m_fields.at(id)->set_value(value, change_event); | ||||
| 							return true; | ||||
|     } | ||||
| 	boost::any		get_value(t_config_option_key id) { | ||||
| 	boost::any		get_value(const t_config_option_key& id) { | ||||
| 							boost::any out;  | ||||
|     						if (m_fields.find(id) == m_fields.end()) ; | ||||
| 							else  | ||||
|  | @ -118,7 +118,7 @@ public: | |||
| 	inline void		enable() { for (auto& field : m_fields) field.second->enable(); } | ||||
|     inline void		disable() { for (auto& field : m_fields) field.second->disable(); } | ||||
| 
 | ||||
|     OptionsGroup(wxWindow* _parent, wxString title, bool is_tab_opt=false) :  | ||||
|     OptionsGroup(wxWindow* _parent, const wxString& title, bool is_tab_opt=false) :  | ||||
| 		m_parent(_parent), title(title), m_is_tab_opt(is_tab_opt), staticbox(title!="") { | ||||
|         sizer = (staticbox ? new wxStaticBoxSizer(new wxStaticBox(_parent, wxID_ANY, title), wxVERTICAL) : new wxBoxSizer(wxVERTICAL)); | ||||
|         auto num_columns = 1U; | ||||
|  | @ -152,14 +152,14 @@ protected: | |||
| 	const t_field&		build_field(const Option& opt, wxStaticText* label = nullptr); | ||||
| 
 | ||||
|     virtual void		on_kill_focus (){}; | ||||
| 	virtual void		on_change_OG(t_config_option_key opt_id, boost::any value); | ||||
| 	virtual void		back_to_initial_value(const std::string opt_key){}; | ||||
| 	virtual void		back_to_sys_value(const std::string opt_key){}; | ||||
| 	virtual void		on_change_OG(const t_config_option_key& opt_id, const boost::any& value); | ||||
| 	virtual void		back_to_initial_value(const std::string& opt_key){} | ||||
| 	virtual void		back_to_sys_value(const std::string& opt_key){} | ||||
| }; | ||||
| 
 | ||||
| class ConfigOptionsGroup: public OptionsGroup { | ||||
| public: | ||||
| 	ConfigOptionsGroup(wxWindow* parent, wxString title, DynamicPrintConfig* _config = nullptr, bool is_tab_opt = false) : | ||||
| 	ConfigOptionsGroup(wxWindow* parent, const wxString& title, DynamicPrintConfig* _config = nullptr, bool is_tab_opt = false) : | ||||
| 		OptionsGroup(parent, title, is_tab_opt), m_config(_config) {} | ||||
| 
 | ||||
|     /// reference to libslic3r config, non-owning pointer (?).
 | ||||
|  | @ -167,8 +167,8 @@ public: | |||
|     bool					m_full_labels {0}; | ||||
| 	t_opt_map				m_opt_map; | ||||
| 
 | ||||
| 	Option		get_option(const std::string opt_key, int opt_index = -1); | ||||
| 	Line		create_single_option_line(const std::string title, int idx = -1) /*const*/{ | ||||
| 	Option		get_option(const std::string& opt_key, int opt_index = -1); | ||||
| 	Line		create_single_option_line(const std::string& title, int idx = -1) /*const*/{ | ||||
| 		Option option = get_option(title, idx); | ||||
| 		return OptionsGroup::create_single_option_line(option); | ||||
| 	} | ||||
|  | @ -181,16 +181,16 @@ public: | |||
| 		append_single_option_line(option);		 | ||||
| 	} | ||||
| 
 | ||||
| 	void		on_change_OG(t_config_option_key opt_id, boost::any value) override; | ||||
| 	void		back_to_initial_value(const std::string opt_key) override; | ||||
| 	void		back_to_sys_value(const std::string opt_key) override; | ||||
| 	void back_to_config_value(const DynamicPrintConfig& config, const std::string opt_key); | ||||
| 	void		on_change_OG(const t_config_option_key& opt_id, const boost::any& value) override; | ||||
| 	void		back_to_initial_value(const std::string& opt_key) override; | ||||
| 	void		back_to_sys_value(const std::string& opt_key) override; | ||||
| 	void		back_to_config_value(const DynamicPrintConfig& config, const std::string& opt_key); | ||||
| 	void		on_kill_focus() override{ reload_config();} | ||||
| 	void		reload_config(); | ||||
| 	boost::any	config_value(std::string opt_key, int opt_index, bool deserialize); | ||||
| 	boost::any	config_value(const std::string& opt_key, int opt_index, bool deserialize); | ||||
| 	// return option value from config 
 | ||||
| 	boost::any get_config_value(const DynamicPrintConfig& config, std::string opt_key, int opt_index = -1); | ||||
| 	Field*		get_fieldc(t_config_option_key opt_key, int opt_index); | ||||
| 	boost::any	get_config_value(const DynamicPrintConfig& config, const std::string& opt_key, int opt_index = -1); | ||||
| 	Field*		get_fieldc(const t_config_option_key& opt_key, int opt_index); | ||||
| }; | ||||
| 
 | ||||
| //  Static text shown among the options.
 | ||||
|  | @ -200,7 +200,7 @@ public: | |||
| 	ogStaticText(wxWindow* parent, const char *text) : wxStaticText(parent, wxID_ANY, text, wxDefaultPosition, wxDefaultSize){} | ||||
| 	~ogStaticText(){} | ||||
| 
 | ||||
| 	void SetText(wxString value); | ||||
| 	void		SetText(const wxString& value); | ||||
| }; | ||||
| 
 | ||||
| }} | ||||
|  |  | |||
|  | @ -416,6 +416,20 @@ const Preset* PresetCollection::get_selected_preset_parent() const | |||
|     return (preset == nullptr || preset->is_default || preset->is_external) ? nullptr : preset; | ||||
| } | ||||
| 
 | ||||
| const Preset* PresetCollection::get_preset_parent(const Preset& child) const | ||||
| { | ||||
|     auto *inherits = dynamic_cast<const ConfigOptionString*>(child.config.option("inherits")); | ||||
|     if (inherits == nullptr || inherits->value.empty()) | ||||
| // 		return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr; 
 | ||||
| 		return nullptr;  | ||||
|     const Preset* preset = this->find_preset(inherits->value, false); | ||||
|     return (preset == nullptr/* || preset->is_default */|| preset->is_external) ? nullptr : preset; | ||||
| } | ||||
| 
 | ||||
| const std::string& PresetCollection::get_suffix_modified() { | ||||
| 	return g_suffix_modified; | ||||
| } | ||||
| 
 | ||||
| // Return a preset by its name. If the preset is active, a temporary copy is returned.
 | ||||
| // If a preset is not found by its name, null is returned.
 | ||||
| Preset* PresetCollection::find_preset(const std::string &name, bool first_visible_if_not_found) | ||||
|  | @ -497,16 +511,44 @@ void PresetCollection::update_platter_ui(wxBitmapComboBox *ui) | |||
|     // Otherwise fill in the list from scratch.
 | ||||
|     ui->Freeze(); | ||||
|     ui->Clear(); | ||||
| 	std::map<wxString, bool> nonsys_presets; | ||||
| 	wxString selected = ""; | ||||
|     for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++ i) { | ||||
|         const Preset &preset = this->m_presets[i]; | ||||
|         if (! preset.is_visible || (! preset.is_compatible && i != m_idx_selected)) | ||||
|             continue; | ||||
|         const wxBitmap *bmp = (i == 0 || preset.is_compatible) ? m_bitmap_main_frame : m_bitmap_incompatible; | ||||
|         ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), | ||||
|             (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); | ||||
| 		if (i == m_idx_selected) | ||||
|             ui->SetSelection(ui->GetCount() - 1); | ||||
|     } | ||||
| //         ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()),
 | ||||
| //             (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp);
 | ||||
| // 		if (i == m_idx_selected)
 | ||||
| //             ui->SetSelection(ui->GetCount() - 1);
 | ||||
| 
 | ||||
| 		if (preset.is_default || preset.is_system){ | ||||
| 			ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), | ||||
| 				(bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); | ||||
| 			if (i == m_idx_selected) | ||||
| 				ui->SetSelection(ui->GetCount() - 1); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), preset.is_compatible); | ||||
| 			if (i == m_idx_selected) | ||||
| 				selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); | ||||
| 		} | ||||
| 		if (preset.is_default) | ||||
| 			ui->Append("------------------------------------", wxNullBitmap); | ||||
| 	} | ||||
| 	if (!nonsys_presets.empty()) | ||||
| 	{ | ||||
| 		ui->Append("------------------------------------", wxNullBitmap); | ||||
| 		for (std::map<wxString, bool>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { | ||||
| 			const wxBitmap *bmp = it->second ? m_bitmap_compatible : m_bitmap_incompatible; | ||||
| 			ui->Append(it->first, | ||||
| 				(bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); | ||||
| 			if (it->first == selected) | ||||
| 				ui->SetSelection(ui->GetCount() - 1); | ||||
| 		} | ||||
| 	} | ||||
|     ui->Thaw(); | ||||
| } | ||||
| 
 | ||||
|  | @ -516,16 +558,44 @@ void PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompatibl | |||
|         return; | ||||
|     ui->Freeze(); | ||||
|     ui->Clear(); | ||||
| 	std::map<wxString, bool> nonsys_presets; | ||||
| 	wxString selected = ""; | ||||
|     for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++ i) { | ||||
|         const Preset &preset = this->m_presets[i]; | ||||
|         if (! preset.is_visible || (! show_incompatible && ! preset.is_compatible && i != m_idx_selected)) | ||||
|             continue; | ||||
|         const wxBitmap *bmp = preset.is_compatible ? m_bitmap_compatible : m_bitmap_incompatible; | ||||
|         ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), | ||||
|             (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); | ||||
| 		if (i == m_idx_selected) | ||||
|             ui->SetSelection(ui->GetCount() - 1); | ||||
| //         ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()),
 | ||||
| //             (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp);
 | ||||
| // 		if (i == m_idx_selected)
 | ||||
| //             ui->SetSelection(ui->GetCount() - 1);
 | ||||
| 
 | ||||
| 		if (preset.is_default || preset.is_system){ | ||||
| 			ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), | ||||
| 				(bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); | ||||
| 			if (i == m_idx_selected) | ||||
| 				ui->SetSelection(ui->GetCount() - 1); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), preset.is_compatible); | ||||
| 			if (i == m_idx_selected) | ||||
| 				selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); | ||||
| 		} | ||||
| 		if (preset.is_default) | ||||
| 			ui->Append("------------------------------------", wxNullBitmap); | ||||
|     } | ||||
| 	if (!nonsys_presets.empty()) | ||||
| 	{ | ||||
| 		ui->Append("------------------------------------", wxNullBitmap); | ||||
| 		for (std::map<wxString, bool>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { | ||||
| 			const wxBitmap *bmp = it->second ? m_bitmap_compatible : m_bitmap_incompatible; | ||||
| 			ui->Append(it->first, | ||||
| 				(bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp); | ||||
| 			if (it->first == selected) | ||||
| 				ui->SetSelection(ui->GetCount() - 1); | ||||
| 		} | ||||
| 	} | ||||
|     ui->Thaw(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -209,9 +209,17 @@ public: | |||
|     // The parent preset may be a system preset or a user preset, which will be
 | ||||
|     // reflected by the UI.
 | ||||
|     const Preset*   get_selected_preset_parent() const; | ||||
|     // Return the selected preset including the user modifications.
 | ||||
| 	// get parent preset for some child preset
 | ||||
| 	const Preset*	get_preset_parent(const Preset& child) const; | ||||
| 	// Return the selected preset including the user modifications.
 | ||||
|     Preset&         get_edited_preset()         { return m_edited_preset; } | ||||
|     const Preset&   get_edited_preset() const   { return m_edited_preset; } | ||||
| 
 | ||||
| 	// used to update preset_choice from Tab
 | ||||
| 	const std::deque<Preset>&	get_presets()	{ return m_presets; } | ||||
| 	int						get_idx_selected()	{ return m_idx_selected; } | ||||
| 	const std::string&		get_suffix_modified(); | ||||
| 
 | ||||
|     // Return a preset possibly with modifications.
 | ||||
|     const Preset&   default_preset() const      { return m_presets.front(); } | ||||
|     // Return a preset by an index. If the preset is active, a temporary copy is returned.
 | ||||
|  |  | |||
|  | @ -261,8 +261,8 @@ bool PresetBundle::load_compatible_bitmaps() | |||
| { | ||||
|     const std::string path_bitmap_compatible   = "flag-green-icon.png"; | ||||
|     const std::string path_bitmap_incompatible = "flag-red-icon.png"; | ||||
|     const std::string path_bitmap_lock         = "lock.png"; | ||||
|     const std::string path_bitmap_lock_open    = "lock_open.png"; | ||||
|     const std::string path_bitmap_lock         = "sys_lock.png";//"lock.png";
 | ||||
| 	const std::string path_bitmap_lock_open    = "sys_unlock.png";//"lock_open.png";
 | ||||
|     bool loaded_compatible   = m_bitmapCompatible  ->LoadFile( | ||||
|         wxString::FromUTF8(Slic3r::var(path_bitmap_compatible).c_str()), wxBITMAP_TYPE_PNG); | ||||
|     bool loaded_incompatible = m_bitmapIncompatible->LoadFile( | ||||
|  | @ -1025,6 +1025,8 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, wxBitma | |||
|     // and draw a red flag in front of the selected preset.
 | ||||
|     bool          wide_icons      = selected_preset != nullptr && ! selected_preset->is_compatible && m_bitmapIncompatible != nullptr; | ||||
|     assert(selected_preset != nullptr); | ||||
| 	std::map<wxString, wxBitmap> nonsys_presets; | ||||
| 	wxString selected_str = ""; | ||||
|     for (int i = this->filaments().front().is_visible ? 0 : 1; i < int(this->filaments().size()); ++ i) { | ||||
|         const Preset &preset    = this->filaments.preset(i); | ||||
|         bool          selected  = this->filament_presets[idx_extruder] == preset.name; | ||||
|  | @ -1062,10 +1064,36 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, wxBitma | |||
|                 (preset.is_dirty ? *m_bitmapLockOpen : *m_bitmapLock) : m_bitmapCache->mkclear(16, 16)); | ||||
|             bitmap = m_bitmapCache->insert(bitmap_key, bmps); | ||||
| 		} | ||||
| 		ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), (bitmap == 0) ? wxNullBitmap : *bitmap); | ||||
|         if (selected) | ||||
|             ui->SetSelection(ui->GetCount() - 1); | ||||
| // 		ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), (bitmap == 0) ? wxNullBitmap : *bitmap);
 | ||||
| //         if (selected)
 | ||||
| //             ui->SetSelection(ui->GetCount() - 1);
 | ||||
| 
 | ||||
| 		if (preset.is_default || preset.is_system){ | ||||
| 			ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()),  | ||||
| 				(bitmap == 0) ? wxNullBitmap : *bitmap); | ||||
| 			if (selected) | ||||
| 				ui->SetSelection(ui->GetCount() - 1); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()),  | ||||
| 				(bitmap == 0) ? wxNullBitmap : *bitmap); | ||||
| 			if (selected) | ||||
| 				selected_str = wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()); | ||||
| 		} | ||||
| 		if (preset.is_default) | ||||
| 			ui->Append("------------------------------------", wxNullBitmap); | ||||
|     } | ||||
| 
 | ||||
| 	if (!nonsys_presets.empty()) | ||||
| 	{ | ||||
| 		ui->Append("------------------------------------", wxNullBitmap); | ||||
| 		for (std::map<wxString, wxBitmap>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { | ||||
| 			ui->Append(it->first, it->second); | ||||
| 			if (it->first == selected_str) | ||||
| 				ui->SetSelection(ui->GetCount() - 1); | ||||
| 		} | ||||
| 	} | ||||
|     ui->Thaw(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ | |||
| #include <wx/filedlg.h> | ||||
| 
 | ||||
| #include <boost/algorithm/string/predicate.hpp> | ||||
| #include "wxExtensions.hpp" | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| namespace GUI { | ||||
|  | @ -39,7 +40,42 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle) | |||
| 
 | ||||
| 	// preset chooser
 | ||||
| 	m_presets_choice = new wxBitmapComboBox(panel, wxID_ANY, "", wxDefaultPosition, wxSize(270, -1), 0, 0,wxCB_READONLY); | ||||
| 	/*
 | ||||
| 	m_cc_presets_choice = new wxComboCtrl(panel, wxID_ANY, L(""), wxDefaultPosition, wxDefaultSize, wxCB_READONLY); | ||||
| 	wxDataViewTreeCtrlComboPopup* popup = new wxDataViewTreeCtrlComboPopup; | ||||
| 	if (popup != nullptr) | ||||
| 	{ | ||||
| 		// FIXME If the following line is removed, the combo box popup list will not react to mouse clicks.
 | ||||
| 		//  On the other side, with this line the combo box popup cannot be closed by clicking on the combo button on Windows 10.
 | ||||
| //		m_cc_presets_choice->UseAltPopupWindow();
 | ||||
| 
 | ||||
| //		m_cc_presets_choice->EnablePopupAnimation(false);
 | ||||
| 		m_cc_presets_choice->SetPopupControl(popup); | ||||
| 		popup->SetStringValue(from_u8("Text1")); | ||||
| 
 | ||||
| 		popup->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this, popup](wxCommandEvent& evt) | ||||
| 		{ | ||||
| 			auto selected = popup->GetItemText(popup->GetSelection()); | ||||
| 			if (selected != _(L("System presets")) && selected != _(L("Default presets"))) | ||||
| 			{ | ||||
| 				m_cc_presets_choice->SetText(selected); | ||||
| 				std::string selected_string = selected.ToUTF8().data(); | ||||
| #ifdef __APPLE__ | ||||
| #else | ||||
|  				select_preset(selected_string); | ||||
| #endif | ||||
| 			}				 | ||||
| 		}); | ||||
| 
 | ||||
| // 		popup->Bind(wxEVT_KEY_DOWN, [popup](wxKeyEvent& evt) { popup->OnKeyEvent(evt); });
 | ||||
| // 		popup->Bind(wxEVT_KEY_UP, [popup](wxKeyEvent& evt) { popup->OnKeyEvent(evt); });
 | ||||
| 
 | ||||
| 		auto icons = new wxImageList(16, 16, true, 1); | ||||
| 		popup->SetImageList(icons); | ||||
| 		icons->Add(*new wxIcon(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG)); | ||||
| 		icons->Add(*new wxIcon(from_u8(Slic3r::var("flag-red-icon.png")), wxBITMAP_TYPE_PNG)); | ||||
| 	} | ||||
| */ | ||||
| 	auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); | ||||
| 
 | ||||
| 	//buttons
 | ||||
|  | @ -84,11 +120,44 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle) | |||
| 	m_hsizer->AddSpacer(64); | ||||
| 	m_hsizer->Add(m_undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL); | ||||
| 	m_hsizer->Add(m_undo_btn, 0, wxALIGN_CENTER_VERTICAL); | ||||
| // 	m_hsizer->AddSpacer(64);
 | ||||
| // 	m_hsizer->Add(m_cc_presets_choice, 1, wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL, 3);
 | ||||
| 
 | ||||
| 	//Horizontal sizer to hold the tree and the selected page.
 | ||||
| 	m_hsizer = new wxBoxSizer(wxHORIZONTAL); | ||||
| 	sizer->Add(m_hsizer, 1, wxEXPAND, 0); | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| 
 | ||||
| 
 | ||||
| 	//temporary left vertical sizer
 | ||||
| 	m_left_sizer = new wxBoxSizer(wxVERTICAL); | ||||
| 	m_hsizer->Add(m_left_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 3); | ||||
| 
 | ||||
| 	// tree
 | ||||
| 	m_presetctrl = new wxDataViewTreeCtrl(panel, wxID_ANY, wxDefaultPosition, wxSize(200, -1), wxDV_NO_HEADER); | ||||
| 	m_left_sizer->Add(m_presetctrl, 1, wxEXPAND); | ||||
| 	m_preset_icons = new wxImageList(16, 16, true, 1); | ||||
| 	m_presetctrl->SetImageList(m_preset_icons); | ||||
| 	m_preset_icons->Add(*new wxIcon(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG)); | ||||
| 	m_preset_icons->Add(*new wxIcon(from_u8(Slic3r::var("flag-red-icon.png")), wxBITMAP_TYPE_PNG)); | ||||
| 
 | ||||
| 	m_presetctrl->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxCommandEvent& evt) | ||||
| 	{ | ||||
| 		auto selected = m_presetctrl->GetItemText(m_presetctrl->GetSelection()); | ||||
| 		if (selected != _(L("System presets")) && selected != _(L("Default presets"))) | ||||
| 		{ | ||||
| 			std::string selected_string = selected.ToUTF8().data(); | ||||
| #ifdef __APPLE__ | ||||
| #else | ||||
| 			select_preset(selected_string); | ||||
| #endif | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| 	//left vertical sizer
 | ||||
| 	m_left_sizer = new wxBoxSizer(wxVERTICAL); | ||||
| 	m_hsizer->Add(m_left_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 3); | ||||
|  | @ -136,11 +205,10 @@ void Tab::load_initial_data() | |||
| { | ||||
| 	m_config = &m_presets->get_edited_preset().config; | ||||
| 	m_nonsys_btn_icon = m_presets->get_selected_preset_parent() == nullptr ? | ||||
| 		"bullet_white.png" : | ||||
| 		wxMSW ? "sys_unlock.png" : "lock_open.png"; | ||||
| 						"bullet_white.png" : "sys_unlock.png"; | ||||
| } | ||||
| 
 | ||||
| PageShp Tab::add_options_page(wxString title, std::string icon, bool is_extruder_pages/* = false*/) | ||||
| PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages/* = false*/) | ||||
| { | ||||
| 	// Index of icon in an icon list $self->{icons}.
 | ||||
| 	auto icon_idx = 0; | ||||
|  | @ -260,13 +328,14 @@ void Tab::update_changed_ui() | |||
| 		m_dirty_options = dirty_options; | ||||
| 	} | ||||
| 
 | ||||
| 	Freeze(); | ||||
| 	//update options "decoration"
 | ||||
| 	for (const auto opt_key : m_full_options_list) | ||||
| 	{ | ||||
| 		bool is_nonsys_value = false; | ||||
| 		bool is_modified_value = true; | ||||
| 		std::string sys_icon = wxMSW ? "sys_lock.png" : "lock.png"; | ||||
| 		std::string icon = wxMSW ? "action_undo.png" : "arrow_undo.png"; | ||||
| 		std::string sys_icon = "sys_lock.png"; | ||||
| 		std::string icon = "action_undo.png"; | ||||
| 		wxColour color = get_sys_label_clr(); | ||||
| 		if (find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end()) { | ||||
| 			is_nonsys_value = true; | ||||
|  | @ -281,6 +350,14 @@ void Tab::update_changed_ui() | |||
| 			is_modified_value = false; | ||||
| 			icon = "bullet_white.png"; | ||||
| 		} | ||||
| 		if (opt_key == "bed_shape" || opt_key == "compatible_printers") { | ||||
| 			if (m_colored_Label != nullptr)	{ | ||||
| 				m_colored_Label->SetForegroundColour(color); | ||||
| 				m_colored_Label->Refresh(true); | ||||
| 			} | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		Field* field = get_field(opt_key); | ||||
| 		if (field == nullptr) continue; | ||||
| 		field->m_is_nonsys_value = is_nonsys_value; | ||||
|  | @ -292,6 +369,7 @@ void Tab::update_changed_ui() | |||
| 			field->m_Label->Refresh(true); | ||||
| 		} | ||||
| 	} | ||||
| 	Thaw(); | ||||
| 
 | ||||
| 	wxTheApp->CallAfter([this]() { | ||||
| 		update_changed_tree_ui(); | ||||
|  | @ -353,13 +431,20 @@ void Tab::update_sys_ui_after_sel_preset() | |||
| 	m_sys_options.resize(0); | ||||
| } | ||||
| 
 | ||||
| void Tab::get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page) | ||||
| { | ||||
| 	if (sys_page && find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end()) | ||||
| 		sys_page = false; | ||||
| 	if (!modified_page && find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) != m_dirty_options.end()) | ||||
| 		modified_page = true; | ||||
| } | ||||
| 
 | ||||
| void Tab::update_changed_tree_ui() | ||||
| { | ||||
| 	auto cur_item = m_treectrl->GetFirstVisibleItem(); | ||||
| 	auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection()); | ||||
| 	while (cur_item){ | ||||
| 		auto title = m_treectrl->GetItemText(cur_item); | ||||
| 		int i=0; | ||||
| 		for (auto page : m_pages) | ||||
| 		{ | ||||
| 			if (page->title() != title) | ||||
|  | @ -369,23 +454,20 @@ void Tab::update_changed_tree_ui() | |||
| 			if (title == _("General")){ | ||||
| 				std::initializer_list<const char*> optional_keys{ "extruders_count", "bed_shape" }; | ||||
| 				for (auto &opt_key : optional_keys) { | ||||
| 					if (sys_page && find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end()) | ||||
| 						sys_page = false; | ||||
| 					if (!modified_page && find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) != m_dirty_options.end()) | ||||
| 						modified_page = true; | ||||
| 					get_sys_and_mod_flags(opt_key, sys_page, modified_page); | ||||
| 				} | ||||
| 			} | ||||
| 			if (title == _("Dependencies")){ | ||||
| 				get_sys_and_mod_flags("compatible_printers", sys_page, modified_page); | ||||
| 			} | ||||
| 			for (auto group : page->m_optgroups) | ||||
| 			{ | ||||
| 				for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) { | ||||
| 					const std::string& opt_key = it->first; | ||||
| 					if (sys_page && find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end()) | ||||
| 						sys_page = false; | ||||
| 					if (!modified_page && find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) != m_dirty_options.end()) | ||||
| 						modified_page = true; | ||||
| 				} | ||||
| 				if (!sys_page && modified_page) | ||||
| 					break; | ||||
| 				for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) { | ||||
| 					const std::string& opt_key = it->first; | ||||
| 					get_sys_and_mod_flags(opt_key, sys_page, modified_page); | ||||
| 				} | ||||
| 			} | ||||
| 			if (sys_page) | ||||
| 				m_treectrl->SetItemTextColour(cur_item, get_sys_label_clr()); | ||||
|  | @ -411,10 +493,8 @@ void Tab::update_changed_tree_ui() | |||
| 
 | ||||
| void Tab::update_undo_buttons() | ||||
| { | ||||
| 	const std::string& undo_icon = !m_is_modified_values ? "bullet_white.png" : | ||||
| 									wxMSW ? "action_undo.png" : "arrow_undo.png"; | ||||
| 	const std::string& undo_to_sys_icon = m_is_nonsys_values ? m_nonsys_btn_icon : | ||||
| 									wxMSW ? "sys_lock.png" : "lock.png"; | ||||
| 	const std::string& undo_icon = !m_is_modified_values ? "bullet_white.png" : "action_undo.png"; | ||||
| 	const std::string& undo_to_sys_icon = m_is_nonsys_values ? m_nonsys_btn_icon : "sys_lock.png"; | ||||
| 
 | ||||
| 	m_undo_btn->SetBitmap(wxBitmap(from_u8(var(undo_icon)), wxBITMAP_TYPE_PNG)); | ||||
| 	m_undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var(undo_to_sys_icon)), wxBITMAP_TYPE_PNG)); | ||||
|  | @ -436,6 +516,14 @@ void Tab::on_back_to_initial_value() | |||
| 					if (find(m_dirty_options.begin(), m_dirty_options.end(), "bed_shape") != m_dirty_options.end()) | ||||
| 						group->back_to_initial_value("bed_shape"); | ||||
| 				} | ||||
| 				if (group->title == _("Profile dependencies")){ | ||||
| 					if (find(m_dirty_options.begin(), m_dirty_options.end(), "compatible_printers") != m_dirty_options.end()) | ||||
| 						group->back_to_initial_value("compatible_printers"); | ||||
| 
 | ||||
| 					bool is_empty = m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty(); | ||||
| 					m_compatible_printers_checkbox->SetValue(is_empty); | ||||
| 					is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable(); | ||||
| 				} | ||||
| 				for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) { | ||||
| 					const std::string& opt_key = it->first; | ||||
| 					if (find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) != m_dirty_options.end()) | ||||
|  | @ -463,6 +551,14 @@ void Tab::on_back_to_sys_value() | |||
| 					if (find(m_sys_options.begin(), m_sys_options.end(), "bed_shape") == m_sys_options.end()) | ||||
| 						group->back_to_sys_value("bed_shape"); | ||||
| 				} | ||||
| 				if (group->title == _("Profile dependencies")){ | ||||
| 					if (find(m_sys_options.begin(), m_sys_options.end(), "compatible_printers") == m_sys_options.end()) | ||||
| 						group->back_to_sys_value("compatible_printers"); | ||||
| 
 | ||||
| 					bool is_empty = m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty(); | ||||
| 					m_compatible_printers_checkbox->SetValue(is_empty); | ||||
| 					is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable(); | ||||
| 				} | ||||
| 				for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) { | ||||
| 					const std::string& opt_key = it->first; | ||||
| 					if (find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end()) | ||||
|  | @ -480,16 +576,19 @@ void Tab::update_dirty(){ | |||
| 	m_presets->update_dirty_ui(m_presets_choice); | ||||
| 	on_presets_changed();	 | ||||
| 	update_changed_ui(); | ||||
| //	update_dirty_presets(m_cc_presets_choice);
 | ||||
| } | ||||
| 
 | ||||
| void Tab::update_tab_ui() | ||||
| { | ||||
| 	m_presets->update_tab_ui(m_presets_choice, m_show_incompatible_presets); | ||||
| // 	update_tab_presets(m_cc_presets_choice, m_show_incompatible_presets);
 | ||||
| // 	update_presetsctrl(m_presetctrl, m_show_incompatible_presets);
 | ||||
| } | ||||
| 
 | ||||
| // Load a provied DynamicConfig into the tab, modifying the active preset.
 | ||||
| // This could be used for example by setting a Wipe Tower position by interactive manipulation in the 3D view.
 | ||||
| void Tab::load_config(DynamicPrintConfig config) | ||||
| void Tab::load_config(const DynamicPrintConfig& config) | ||||
| { | ||||
| 	bool modified = 0; | ||||
| 	for(auto opt_key : m_config->diff(config)) { | ||||
|  | @ -512,7 +611,7 @@ void Tab::reload_config(){ | |||
|  	Thaw(); | ||||
| } | ||||
| 
 | ||||
| Field* Tab::get_field(t_config_option_key opt_key, int opt_index/* = -1*/) const | ||||
| Field* Tab::get_field(const t_config_option_key& opt_key, int opt_index/* = -1*/) const | ||||
| { | ||||
| 	Field* field = nullptr; | ||||
| 	for (auto page : m_pages){ | ||||
|  | @ -526,7 +625,7 @@ Field* Tab::get_field(t_config_option_key opt_key, int opt_index/* = -1*/) const | |||
| // Set a key/value pair on this page. Return true if the value has been modified.
 | ||||
| // Currently used for distributing extruders_count over preset pages of Slic3r::GUI::Tab::Printer
 | ||||
| // after a preset is loaded.
 | ||||
| bool Tab::set_value(t_config_option_key opt_key, boost::any value){ | ||||
| bool Tab::set_value(const t_config_option_key& opt_key, const boost::any& value){ | ||||
| 	bool changed = false; | ||||
| 	for(auto page: m_pages) { | ||||
| 		if (page->set_value(opt_key, value)) | ||||
|  | @ -537,7 +636,7 @@ bool Tab::set_value(t_config_option_key opt_key, boost::any value){ | |||
| 
 | ||||
| // To be called by custom widgets, load a value into a config,
 | ||||
| // update the preset selection boxes (the dirty flags)
 | ||||
| void Tab::load_key_value(std::string opt_key, boost::any value) | ||||
| void Tab::load_key_value(const std::string& opt_key, const boost::any& value) | ||||
| { | ||||
| 	change_opt_value(*m_config, opt_key, value); | ||||
| 	// Mark the print & filament enabled if they are compatible with the currently selected preset.
 | ||||
|  | @ -551,7 +650,7 @@ void Tab::load_key_value(std::string opt_key, boost::any value) | |||
| 
 | ||||
| extern wxFrame *g_wxMainFrame; | ||||
| 
 | ||||
| void Tab::on_value_change(std::string opt_key, boost::any value) | ||||
| void Tab::on_value_change(const std::string& opt_key, const boost::any& value) | ||||
| { | ||||
| 	if (m_event_value_change > 0) { | ||||
| 		wxCommandEvent event(m_event_value_change); | ||||
|  | @ -566,8 +665,8 @@ void Tab::on_value_change(std::string opt_key, boost::any value) | |||
| 	} | ||||
| 	if (opt_key == "fill_density") | ||||
| 	{ | ||||
| 		value = get_optgroup()->get_config_value(*m_config, opt_key); | ||||
| 		get_optgroup()->set_value(opt_key, value); | ||||
| 		boost::any val = get_optgroup()->get_config_value(*m_config, opt_key); | ||||
| 		get_optgroup()->set_value(opt_key, val); | ||||
| 	} | ||||
| 	if (opt_key == "support_material" || opt_key == "support_material_buildplate_only") | ||||
| 	{ | ||||
|  | @ -858,7 +957,7 @@ void TabPrint::build() | |||
| 		line.widget = [this](wxWindow* parent){ | ||||
| 			return compatible_printers_widget(parent, &m_compatible_printers_checkbox, &m_compatible_printers_btn); | ||||
| 		}; | ||||
| 		optgroup->append_line(line); | ||||
| 		optgroup->append_line(line, &m_colored_Label); | ||||
| 
 | ||||
| 		option = optgroup->get_option("compatible_printers_condition"); | ||||
| 		option.opt.full_width = true; | ||||
|  | @ -1233,7 +1332,7 @@ void TabFilament::build() | |||
| 		line.widget = [this](wxWindow* parent){ | ||||
| 			return compatible_printers_widget(parent, &m_compatible_printers_checkbox, &m_compatible_printers_btn); | ||||
| 		}; | ||||
| 		optgroup->append_line(line); | ||||
| 		optgroup->append_line(line, &m_colored_Label); | ||||
| 
 | ||||
| 		option = optgroup->get_option("compatible_printers_condition"); | ||||
| 		option.opt.full_width = true; | ||||
|  | @ -1327,7 +1426,7 @@ void TabPrinter::build() | |||
| 
 | ||||
| 			return sizer; | ||||
| 		}; | ||||
| 		optgroup->append_line(line); | ||||
| 		optgroup->append_line(line, &m_colored_Label); | ||||
|         optgroup->append_single_option_line("max_print_height"); | ||||
|         optgroup->append_single_option_line("z_offset"); | ||||
| 
 | ||||
|  | @ -1755,9 +1854,7 @@ void Tab::load_current_preset() | |||
| 	// Reload preset pages with the new configuration values.
 | ||||
| 	reload_config(); | ||||
| 	const Preset* parent = m_presets->get_selected_preset_parent(); | ||||
| 	m_nonsys_btn_icon = parent == nullptr ? | ||||
| 		"bullet_white.png" : | ||||
| 		wxMSW ? "sys_unlock.png" : "lock_open.png"; | ||||
| 	m_nonsys_btn_icon = parent == nullptr ? "bullet_white.png" : "sys_unlock.png"; | ||||
| 
 | ||||
| 	// use CallAfter because some field triggers schedule on_change calls using CallAfter,
 | ||||
| 	// and we don't want them to be called after this update_dirty() as they would mark the 
 | ||||
|  | @ -1814,7 +1911,7 @@ void Tab::rebuild_page_tree() | |||
| // Called by the UI combo box when the user switches profiles.
 | ||||
| // Select a preset by a name.If !defined(name), then the default preset is selected.
 | ||||
| // If the current profile is modified, user is asked to save the changes.
 | ||||
| void Tab::select_preset(std::string preset_name /*= ""*/) | ||||
| void Tab::select_preset(const std::string& preset_name /*= ""*/) | ||||
| { | ||||
| 	std::string name = preset_name; | ||||
| 	auto force = false; | ||||
|  | @ -1881,7 +1978,7 @@ void Tab::select_preset(std::string preset_name /*= ""*/) | |||
| 
 | ||||
| // If the current preset is dirty, the user is asked whether the changes may be discarded.
 | ||||
| // if the current preset was not dirty, or the user agreed to discard the changes, 1 is returned.
 | ||||
| bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr*/, std::string new_printer_name /*= ""*/) | ||||
| bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr*/, const std::string& new_printer_name /*= ""*/) | ||||
| { | ||||
| 	if (presets == nullptr) presets = m_presets; | ||||
| 	// Display a dialog showing the dirty options in a human readable form.
 | ||||
|  | @ -2089,6 +2186,7 @@ wxSizer* Tab::compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox | |||
| 		if ((*checkbox)->GetValue()) | ||||
| 			load_key_value("compatible_printers", std::vector<std::string> {}); | ||||
| 		get_field("compatible_printers_condition")->toggle((*checkbox)->GetValue()); | ||||
| 		update_changed_ui(); | ||||
| 	}) ); | ||||
| 
 | ||||
| 	(*btn)->Bind(wxEVT_BUTTON, ([this, parent, checkbox, btn](wxCommandEvent e) | ||||
|  | @ -2131,18 +2229,186 @@ wxSizer* Tab::compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox | |||
| 			} | ||||
| 			// All printers have been made compatible with this preset.
 | ||||
| 			load_key_value("compatible_printers", value); | ||||
| 			update_changed_ui(); | ||||
| 		} | ||||
| 	})); | ||||
| 	return sizer;  | ||||
| } | ||||
| 
 | ||||
| void Tab::update_presetsctrl(wxDataViewTreeCtrl* ui, bool show_incompatible) | ||||
| { | ||||
| 	if (ui == nullptr) | ||||
| 		return; | ||||
| 	ui->Freeze(); | ||||
| 	ui->DeleteAllItems(); | ||||
| 	auto presets = m_presets->get_presets(); | ||||
| 	auto idx_selected = m_presets->get_idx_selected(); | ||||
| 	auto suffix_modified = m_presets->get_suffix_modified(); | ||||
| 	int icon_compatible = 0; | ||||
| 	int icon_incompatible = 1; | ||||
| 	int cnt_items = 0; | ||||
| 
 | ||||
| 	auto root_sys = ui->AppendContainer(wxDataViewItem(0), _(L("System presets"))); | ||||
| 	auto root_def = ui->AppendContainer(wxDataViewItem(0), _(L("Default presets"))); | ||||
| 
 | ||||
| 	auto show_def = get_app_config()->get("no_defaults")[0] != '1'; | ||||
| 
 | ||||
| 	for (size_t i = presets.front().is_visible ? 0 : 1; i < presets.size(); ++i) { | ||||
| 		const Preset &preset = presets[i]; | ||||
| 		if (!preset.is_visible || (!show_incompatible && !preset.is_compatible && i != idx_selected)) | ||||
| 			continue; | ||||
| 
 | ||||
| 		auto preset_name = wxString::FromUTF8((preset.name + (preset.is_dirty ? suffix_modified : "")).c_str()); | ||||
| 
 | ||||
| 		wxDataViewItem item; | ||||
| 		if (preset.is_system) | ||||
| 			item = ui->AppendItem(root_sys, preset_name, | ||||
| 			preset.is_compatible ? icon_compatible : icon_incompatible); | ||||
| 		else if (show_def && preset.is_default) | ||||
| 			item = ui->AppendItem(root_def, preset_name, | ||||
| 			preset.is_compatible ? icon_compatible : icon_incompatible); | ||||
| 		else | ||||
| 		{ | ||||
| 			auto parent = m_presets->get_preset_parent(preset); | ||||
| 			if (parent == nullptr) | ||||
| 				item = ui->AppendItem(root_def, preset_name, | ||||
| 				preset.is_compatible ? icon_compatible : icon_incompatible); | ||||
| 			else | ||||
| 			{ | ||||
| 				auto parent_name = parent->name; | ||||
| 
 | ||||
| 				wxDataViewTreeStoreContainerNode *node = ui->GetStore()->FindContainerNode(root_sys); | ||||
| 				if (node) | ||||
| 				{ | ||||
| 					wxDataViewTreeStoreNodeList::iterator iter; | ||||
| 					for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); iter++) | ||||
| 					{ | ||||
| 						wxDataViewTreeStoreNode* child = *iter; | ||||
| 						auto child_item = child->GetItem(); | ||||
| 						auto item_text = ui->GetItemText(child_item); | ||||
| 						if (item_text == parent_name) | ||||
| 						{ | ||||
| 							auto added_child = ui->AppendItem(child->GetItem(), preset_name, | ||||
| 								preset.is_compatible ? icon_compatible : icon_incompatible); | ||||
| 							if (!added_child){ | ||||
| 								ui->DeleteItem(child->GetItem()); | ||||
| 								auto new_parent = ui->AppendContainer(root_sys, parent_name, | ||||
| 									preset.is_compatible ? icon_compatible : icon_incompatible); | ||||
| 								ui->AppendItem(new_parent, preset_name, | ||||
| 									preset.is_compatible ? icon_compatible : icon_incompatible); | ||||
| 							} | ||||
| 							break; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		cnt_items++; | ||||
| 		if (i == idx_selected){ | ||||
| 			ui->Select(item); | ||||
| 			m_cc_presets_choice->SetText(preset_name); | ||||
| 		} | ||||
| 	} | ||||
| 	if (ui->GetStore()->GetChildCount(root_def) == 0) | ||||
| 		ui->DeleteItem(root_def); | ||||
| 
 | ||||
| 	ui->Thaw(); | ||||
| } | ||||
| 
 | ||||
| void Tab::update_tab_presets(wxComboCtrl* ui, bool show_incompatible) | ||||
| { | ||||
| 	if (ui == nullptr) | ||||
| 		return; | ||||
| 	ui->Freeze(); | ||||
| 	ui->Clear(); | ||||
| 	auto presets = m_presets->get_presets(); | ||||
| 	auto idx_selected = m_presets->get_idx_selected(); | ||||
| 	auto suffix_modified = m_presets->get_suffix_modified(); | ||||
| 	int icon_compatible = 0; | ||||
| 	int icon_incompatible = 1; | ||||
| 	int cnt_items = 0; | ||||
| 
 | ||||
| 	wxDataViewTreeCtrlComboPopup* popup = wxDynamicCast(m_cc_presets_choice->GetPopupControl(), wxDataViewTreeCtrlComboPopup); | ||||
| 	if (popup != nullptr) | ||||
| 	{ | ||||
| 		popup->DeleteAllItems(); | ||||
| 
 | ||||
| 		auto root_sys = popup->AppendContainer(wxDataViewItem(0), _(L("System presets"))); | ||||
| 		auto root_def = popup->AppendContainer(wxDataViewItem(0), _(L("Default presets"))); | ||||
| 
 | ||||
| 		auto show_def = get_app_config()->get("no_defaults")[0] != '1'; | ||||
| 
 | ||||
| 		for (size_t i = presets.front().is_visible ? 0 : 1; i < presets.size(); ++i) { | ||||
| 			const Preset &preset = presets[i]; | ||||
| 			if (!preset.is_visible || (!show_incompatible && !preset.is_compatible && i != idx_selected)) | ||||
| 				continue; | ||||
| 
 | ||||
| 			auto preset_name = wxString::FromUTF8((preset.name + (preset.is_dirty ? suffix_modified : "")).c_str()); | ||||
| 
 | ||||
| 			wxDataViewItem item; | ||||
| 			if (preset.is_system) | ||||
| 				item = popup->AppendItem(root_sys, preset_name,  | ||||
| 										 preset.is_compatible ? icon_compatible : icon_incompatible); | ||||
| 			else if (show_def && preset.is_default) | ||||
| 				item = popup->AppendItem(root_def, preset_name,  | ||||
| 										 preset.is_compatible ? icon_compatible : icon_incompatible); | ||||
| 			else  | ||||
| 			{ | ||||
| 				auto parent = m_presets->get_preset_parent(preset); | ||||
| 				if (parent == nullptr) | ||||
| 					item = popup->AppendItem(root_def, preset_name, | ||||
| 											 preset.is_compatible ? icon_compatible : icon_incompatible); | ||||
| 				else | ||||
| 				{ | ||||
| 					auto parent_name = parent->name; | ||||
| 
 | ||||
| 					wxDataViewTreeStoreContainerNode *node = popup->GetStore()->FindContainerNode(root_sys); | ||||
| 					if (node)  | ||||
| 					{ | ||||
| 						wxDataViewTreeStoreNodeList::iterator iter; | ||||
| 						for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); iter++) | ||||
| 						{ | ||||
| 							wxDataViewTreeStoreNode* child = *iter; | ||||
| 							auto child_item = child->GetItem(); | ||||
| 							auto item_text = popup->GetItemText(child_item); | ||||
| 							if (item_text == parent_name) | ||||
| 							{ | ||||
| 								auto added_child = popup->AppendItem(child->GetItem(), preset_name, | ||||
| 									preset.is_compatible ? icon_compatible : icon_incompatible); | ||||
| 								if (!added_child){ | ||||
| 									popup->DeleteItem(child->GetItem()); | ||||
| 									auto new_parent = popup->AppendContainer(root_sys, parent_name, | ||||
| 										preset.is_compatible ? icon_compatible : icon_incompatible); | ||||
| 									popup->AppendItem(new_parent, preset_name, | ||||
| 										preset.is_compatible ? icon_compatible : icon_incompatible); | ||||
| 								} | ||||
| 								break; | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			cnt_items++; | ||||
| 			if (i == idx_selected){ | ||||
| 				popup->Select(item); | ||||
| 				m_cc_presets_choice->SetText(preset_name); | ||||
| 			} | ||||
| 		} | ||||
| 		if (popup->GetStore()->GetChildCount(root_def) == 0) | ||||
| 			popup->DeleteItem(root_def); | ||||
| 	} | ||||
| 	ui->Thaw(); | ||||
| } | ||||
| 
 | ||||
| void Page::reload_config() | ||||
| { | ||||
| 	for (auto group : m_optgroups) | ||||
| 		group->reload_config(); | ||||
| } | ||||
| 
 | ||||
| Field* Page::get_field(t_config_option_key opt_key, int opt_index/* = -1*/) const | ||||
| Field* Page::get_field(const t_config_option_key& opt_key, int opt_index /*= -1*/) const | ||||
| { | ||||
| 	Field* field = nullptr; | ||||
| 	for (auto opt : m_optgroups){ | ||||
|  | @ -2153,7 +2419,7 @@ Field* Page::get_field(t_config_option_key opt_key, int opt_index/* = -1*/) cons | |||
| 	return field; | ||||
| } | ||||
| 
 | ||||
| bool Page::set_value(t_config_option_key opt_key, boost::any value){ | ||||
| bool Page::set_value(const t_config_option_key& opt_key, const boost::any& value){ | ||||
| 	bool changed = false; | ||||
| 	for(auto optgroup: m_optgroups) { | ||||
| 		if (optgroup->set_value(opt_key, value)) | ||||
|  | @ -2163,7 +2429,7 @@ bool Page::set_value(t_config_option_key opt_key, boost::any value){ | |||
| } | ||||
| 
 | ||||
| // package Slic3r::GUI::Tab::Page;
 | ||||
| ConfigOptionsGroupShp Page::new_optgroup(wxString title, int noncommon_label_width /*= -1*/) | ||||
| ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_label_width /*= -1*/) | ||||
| { | ||||
| 	//! config_ have to be "right"
 | ||||
| 	ConfigOptionsGroupShp optgroup = std::make_shared<ConfigOptionsGroup>(this, title, m_config, true); | ||||
|  | @ -2204,7 +2470,7 @@ ConfigOptionsGroupShp Page::new_optgroup(wxString title, int noncommon_label_wid | |||
| 	return optgroup; | ||||
| } | ||||
| 
 | ||||
| void SavePresetWindow::build(wxString title, std::string default_name, std::vector<std::string> &values) | ||||
| void SavePresetWindow::build(const wxString& title, const std::string& default_name, std::vector<std::string> &values) | ||||
| { | ||||
| 	auto text = new wxStaticText(this, wxID_ANY, _(L("Save ")) + title + _(L(" as:")),  | ||||
| 									wxDefaultPosition, wxDefaultSize); | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ | |||
| #include <wx/treectrl.h> | ||||
| #include <wx/imaglist.h> | ||||
| #include <wx/statbox.h> | ||||
| #include <wx/dataview.h> | ||||
| 
 | ||||
| #include <map> | ||||
| #include <vector> | ||||
|  | @ -67,9 +68,9 @@ public: | |||
| 	size_t		iconID() const { return m_iconID; } | ||||
| 	void		set_config(DynamicPrintConfig* config_in) { m_config = config_in; } | ||||
| 	void		reload_config(); | ||||
| 	Field*		get_field(t_config_option_key opt_key, int opt_index = -1) const; | ||||
| 	bool		set_value(t_config_option_key opt_key, boost::any value); | ||||
| 	ConfigOptionsGroupShp	new_optgroup(wxString title, int noncommon_label_width = -1); | ||||
| 	Field*		get_field(const t_config_option_key& opt_key, int opt_index = -1) const; | ||||
| 	bool		set_value(const t_config_option_key& opt_key, const boost::any& value); | ||||
| 	ConfigOptionsGroupShp	new_optgroup(const wxString& title, int noncommon_label_width = -1); | ||||
| }; | ||||
| 
 | ||||
| // Slic3r::GUI::Tab;
 | ||||
|  | @ -95,6 +96,9 @@ protected: | |||
| 	wxButton*			m_compatible_printers_btn; | ||||
| 	wxButton*			m_undo_btn; | ||||
| 	wxButton*			m_undo_to_sys_btn; | ||||
| 	wxComboCtrl*		m_cc_presets_choice; | ||||
| 	wxDataViewTreeCtrl*	m_presetctrl; | ||||
| 	wxImageList*		m_preset_icons; | ||||
| 
 | ||||
| 	int					m_icon_count; | ||||
| 	std::map<std::string, size_t>	m_icon_index;		// Map from an icon file name to its index
 | ||||
|  | @ -122,10 +126,11 @@ public: | |||
| 	DynamicPrintConfig*	m_config; | ||||
| 	std::string			m_nonsys_btn_icon; | ||||
| 	ogStaticText*		m_parent_preset_description_line; | ||||
| 	wxStaticText*		m_colored_Label = nullptr; | ||||
| 
 | ||||
| public: | ||||
| 	Tab() {} | ||||
| 	Tab(wxNotebook* parent, wxString title, const char* name, bool no_controller) :  | ||||
| 	Tab(wxNotebook* parent, const wxString& title, const char* name, bool no_controller) :  | ||||
| 		m_parent(parent), m_title(title), m_name(name), m_no_controller(no_controller) { | ||||
| 		Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL); | ||||
| 		get_tabs_list().push_back(this); | ||||
|  | @ -143,11 +148,12 @@ public: | |||
| 	void		create_preset_tab(PresetBundle *preset_bundle); | ||||
| 	void		load_current_preset(); | ||||
| 	void		rebuild_page_tree(); | ||||
| 	void		select_preset(std::string preset_name = ""); | ||||
| 	bool		may_discard_current_dirty_preset(PresetCollection* presets = nullptr, std::string new_printer_name = ""); | ||||
| 	void		select_preset(const std::string& preset_name = ""); | ||||
| 	bool		may_discard_current_dirty_preset(PresetCollection* presets = nullptr, const std::string& new_printer_name = ""); | ||||
| 	wxSizer*	compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox, wxButton** btn); | ||||
| 
 | ||||
| 	void		load_key_value(std::string opt_key, boost::any value); | ||||
| 	void		update_presetsctrl(wxDataViewTreeCtrl* ui, bool show_incompatible); | ||||
| 	void		load_key_value(const std::string& opt_key, const boost::any& value); | ||||
| 	void		reload_compatible_printers_widget(); | ||||
| 
 | ||||
| 	void		OnTreeSelChange(wxTreeEvent& event); | ||||
|  | @ -161,13 +167,14 @@ public: | |||
| 	void		update_changed_ui(); | ||||
| 	void		update_full_options_list(); | ||||
| 	void		update_sys_ui_after_sel_preset(); | ||||
| 	void		get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page); | ||||
| 	void		update_changed_tree_ui(); | ||||
| 	void		update_undo_buttons(); | ||||
| 
 | ||||
| 	void		on_back_to_initial_value(); | ||||
| 	void		on_back_to_sys_value(); | ||||
| 
 | ||||
| 	PageShp		add_options_page(wxString title, std::string icon, bool is_extruder_pages = false); | ||||
| 	PageShp		add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages = false); | ||||
| 
 | ||||
| 	virtual void	OnActivate(){} | ||||
| 	virtual void	on_preset_loaded(){} | ||||
|  | @ -176,10 +183,10 @@ public: | |||
| 	void			load_initial_data(); | ||||
| 	void			update_dirty(); | ||||
| 	void			update_tab_ui(); | ||||
| 	void			load_config(DynamicPrintConfig config); | ||||
| 	void			load_config(const DynamicPrintConfig& config); | ||||
| 	virtual void	reload_config(); | ||||
| 	Field*			get_field(t_config_option_key opt_key, int opt_index = -1) const; | ||||
| 	bool			set_value(t_config_option_key opt_key, boost::any value); | ||||
| 	Field*			get_field(const t_config_option_key& opt_key, int opt_index = -1) const; | ||||
| 	bool			set_value(const t_config_option_key& opt_key, const boost::any& value); | ||||
| 	wxSizer*		description_line_widget(wxWindow* parent, ogStaticText** StaticText); | ||||
| 	bool			current_preset_is_dirty(); | ||||
| 	DynamicPrintConfig*	get_config() { return m_config; } | ||||
|  | @ -189,12 +196,13 @@ public: | |||
| 	} | ||||
| 	std::vector<std::string>	get_dependent_tabs() { return m_reload_dependent_tabs; } | ||||
| 
 | ||||
| 	void			on_value_change(std::string opt_key, boost::any value); | ||||
| 	void			on_value_change(const std::string& opt_key, const boost::any& value); | ||||
| 
 | ||||
| protected: | ||||
| 	void			on_presets_changed(); | ||||
| 	void			update_frequently_changed_parameters(); | ||||
|     void            update_wiping_button_visibility(); | ||||
| 	void			update_tab_presets(wxComboCtrl* ui, bool show_incompatible); | ||||
| }; | ||||
| 
 | ||||
| //Slic3r::GUI::Tab::Print;
 | ||||
|  | @ -265,7 +273,7 @@ public: | |||
| 	std::string		m_chosen_name; | ||||
| 	wxComboBox*		m_combo; | ||||
| 
 | ||||
| 	void			build(wxString title, std::string default_name, std::vector<std::string> &values); | ||||
| 	void			build(const wxString& title, const std::string& default_name, std::vector<std::string> &values); | ||||
| 	void			accept(); | ||||
| 	std::string		get_name() { return m_chosen_name; } | ||||
| }; | ||||
|  |  | |||
|  | @ -109,3 +109,59 @@ void wxCheckListBoxComboPopup::OnListBoxSelection(wxCommandEvent& evt) | |||
|         ProcessEvent(event); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // ***  wxDataViewTreeCtrlComboPopup  ***
 | ||||
| 
 | ||||
| const unsigned int wxDataViewTreeCtrlComboPopup::DefaultWidth = 270; | ||||
| const unsigned int wxDataViewTreeCtrlComboPopup::DefaultHeight = 200; | ||||
| const unsigned int wxDataViewTreeCtrlComboPopup::DefaultItemHeight = 22; | ||||
| 
 | ||||
| bool wxDataViewTreeCtrlComboPopup::Create(wxWindow* parent) | ||||
| { | ||||
| 	return wxDataViewTreeCtrl::Create(parent, wxID_ANY/*HIGHEST + 1*/, wxPoint(0, 0), wxDefaultSize/*wxSize(270, -1)*/, wxDV_NO_HEADER); | ||||
| } | ||||
| /*
 | ||||
| wxSize wxDataViewTreeCtrlComboPopup::GetAdjustedSize(int minWidth, int prefHeight, int maxHeight) | ||||
| { | ||||
| 	// matches owner wxComboCtrl's width
 | ||||
| 	// and sets height dinamically in dependence of contained items count
 | ||||
| 	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); | ||||
| } | ||||
| */ | ||||
| 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); | ||||
| } | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| 
 | ||||
| #include <wx/checklst.h> | ||||
| #include <wx/combo.h> | ||||
| #include <wx/dataview.h> | ||||
| 
 | ||||
| class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup | ||||
| { | ||||
|  | @ -25,4 +26,28 @@ public: | |||
|     void OnListBoxSelection(wxCommandEvent& evt); | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| // ***  wxDataViewTreeCtrlComboBox  ***
 | ||||
| 
 | ||||
| class wxDataViewTreeCtrlComboPopup: public wxDataViewTreeCtrl, public wxComboPopup | ||||
| { | ||||
| 	static const unsigned int DefaultWidth; | ||||
| 	static const unsigned int DefaultHeight; | ||||
| 	static const unsigned int DefaultItemHeight; | ||||
| 
 | ||||
| 	wxString	m_text; | ||||
| 	int			m_cnt_open_items{0}; | ||||
| 
 | ||||
| public: | ||||
| 	virtual bool		Create(wxWindow* parent); | ||||
| 	virtual wxWindow*	GetControl() { return this; } | ||||
| 	virtual void		SetStringValue(const wxString& value) { m_text = value; } | ||||
| 	virtual wxString	GetStringValue() const { return m_text; } | ||||
| //	virtual wxSize		GetAdjustedSize(int minWidth, int prefHeight, int maxHeight);
 | ||||
| 
 | ||||
| 	virtual void		OnKeyEvent(wxKeyEvent& evt); | ||||
| 	void				OnDataViewTreeCtrlSelection(wxCommandEvent& evt); | ||||
| 	void				SetItemsCnt(int cnt) { m_cnt_open_items = cnt; } | ||||
| }; | ||||
| 
 | ||||
| #endif // slic3r_GUI_wxExtensions_hpp_
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv