mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Custom control: first implementation
This commit is contained in:
		
							parent
							
								
									e6ddcbab0c
								
							
						
					
					
						commit
						74d6aea4d4
					
				
					 8 changed files with 645 additions and 84 deletions
				
			
		|  | @ -111,6 +111,8 @@ set(SLIC3R_GUI_SOURCES | |||
|     GUI/Field.hpp | ||||
|     GUI/OptionsGroup.cpp | ||||
|     GUI/OptionsGroup.hpp | ||||
|     GUI/OG_CustomCtrl.cpp | ||||
|     GUI/OG_CustomCtrl.hpp | ||||
|     GUI/BedShapeDialog.cpp | ||||
|     GUI/BedShapeDialog.hpp | ||||
|     GUI/2DBed.cpp | ||||
|  |  | |||
|  | @ -63,18 +63,23 @@ Field::~Field() | |||
| 		m_back_to_initial_value = nullptr; | ||||
| 	if (m_back_to_sys_value) | ||||
| 		m_back_to_sys_value = nullptr; | ||||
| 	if (getWindow()) { | ||||
| 		wxWindow* win = getWindow(); | ||||
| 		win->Destroy(); | ||||
| 		win = nullptr; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void Field::PostInitialize() | ||||
| { | ||||
| 	auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); | ||||
| 	m_Undo_btn			= new RevertButton(m_parent, "bullet_white.png"); | ||||
| 	m_Undo_to_sys_btn	= new RevertButton(m_parent, "bullet_white.png"); | ||||
| //	m_Undo_btn			= new RevertButton(m_parent, "bullet_white.png");
 | ||||
| //	m_Undo_to_sys_btn	= new RevertButton(m_parent, "bullet_white.png");
 | ||||
| 
 | ||||
|     m_Undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_back_to_initial_value(); })); | ||||
| 	m_Undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_back_to_sys_value(); })); | ||||
| //    m_Undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_back_to_initial_value(); }));
 | ||||
| //	m_Undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_back_to_sys_value(); }));
 | ||||
| 
 | ||||
| 	m_blinking_bmp		= new BlinkingBitmap(m_parent); | ||||
| //	m_blinking_bmp		= new BlinkingBitmap(m_parent);
 | ||||
| 
 | ||||
| 	switch (m_opt.type) | ||||
| 	{ | ||||
|  |  | |||
|  | @ -168,7 +168,7 @@ public: | |||
|     bool 	set_undo_bitmap(const ScalableBitmap *bmp) { | ||||
|     	if (m_undo_bitmap != bmp) { | ||||
|     		m_undo_bitmap = bmp; | ||||
|     		m_Undo_btn->SetBitmap_(*bmp); | ||||
| //    		m_Undo_btn->SetBitmap_(*bmp);
 | ||||
|     		return true; | ||||
|     	} | ||||
|     	return false; | ||||
|  | @ -177,33 +177,33 @@ public: | |||
|     bool 	set_undo_to_sys_bitmap(const ScalableBitmap *bmp) { | ||||
|     	if (m_undo_to_sys_bitmap != bmp) { | ||||
|     		m_undo_to_sys_bitmap = bmp; | ||||
|     		m_Undo_to_sys_btn->SetBitmap_(*bmp); | ||||
| //    		m_Undo_to_sys_btn->SetBitmap_(*bmp);
 | ||||
|     		return true; | ||||
|     	} | ||||
|     	return false; | ||||
|     } | ||||
| 
 | ||||
| 	bool	set_label_colour(const wxColour *clr) { | ||||
| 		if (m_Label == nullptr) return false; | ||||
| //		if (m_Label == nullptr) return false;
 | ||||
| 		if (m_label_color != clr) { | ||||
| 			m_label_color = clr; | ||||
| 			m_Label->SetForegroundColour(*clr); | ||||
| 			m_Label->Refresh(true); | ||||
| //			m_Label->SetForegroundColour(*clr);
 | ||||
| //			m_Label->Refresh(true);
 | ||||
| 		} | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	bool	set_label_colour_force(const wxColour *clr) { | ||||
| 		if (m_Label == nullptr) return false; | ||||
| 		m_Label->SetForegroundColour(*clr); | ||||
| 		m_Label->Refresh(true); | ||||
| //		m_Label->SetForegroundColour(*clr);
 | ||||
| //		m_Label->Refresh(true);
 | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	bool 	set_undo_tooltip(const wxString *tip) { | ||||
| 		if (m_undo_tooltip != tip) { | ||||
| 			m_undo_tooltip = tip; | ||||
| 			m_Undo_btn->SetToolTip(*tip); | ||||
| //			m_Undo_btn->SetToolTip(*tip);
 | ||||
| 			return true; | ||||
| 		} | ||||
| 		return false; | ||||
|  | @ -212,7 +212,7 @@ public: | |||
| 	bool 	set_undo_to_sys_tooltip(const wxString *tip) { | ||||
| 		if (m_undo_to_sys_tooltip != tip) { | ||||
| 			m_undo_to_sys_tooltip = tip; | ||||
| 			m_Undo_to_sys_btn->SetToolTip(*tip); | ||||
| //			m_Undo_to_sys_btn->SetToolTip(*tip);
 | ||||
| 			return true; | ||||
| 		} | ||||
| 		return false; | ||||
|  | @ -235,6 +235,12 @@ public: | |||
| 
 | ||||
| 	BlinkingBitmap*			blinking_bitmap() const { return m_blinking_bmp;} | ||||
| 
 | ||||
| 	const ScalableBitmap*	undo_bitmap()			{ return m_undo_bitmap; } | ||||
| 	const wxString*			undo_tooltip()			{ return m_undo_tooltip; } | ||||
| 	const ScalableBitmap*	undo_to_sys_bitmap()	{ return m_undo_to_sys_bitmap; } | ||||
| 	const wxString*			undo_to_sys_tooltip()	{ return m_undo_to_sys_tooltip; } | ||||
| 	const wxColour*			label_color()			{ return m_label_color; } | ||||
| 
 | ||||
| protected: | ||||
| 	RevertButton*			m_Undo_btn = nullptr; | ||||
| 	// Bitmap and Tooltip text for m_Undo_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
 | ||||
|  |  | |||
							
								
								
									
										384
									
								
								src/slic3r/GUI/OG_CustomCtrl.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										384
									
								
								src/slic3r/GUI/OG_CustomCtrl.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,384 @@ | |||
| #include "OG_CustomCtrl.hpp" | ||||
| #include "OptionsGroup.hpp" | ||||
| #include "ConfigExceptions.hpp" | ||||
| #include "Plater.hpp" | ||||
| #include "GUI_App.hpp" | ||||
| 
 | ||||
| #include <utility> | ||||
| #include <wx/numformatter.h> | ||||
| #include <boost/algorithm/string/split.hpp> | ||||
| #include <boost/algorithm/string/classification.hpp> | ||||
| #include "libslic3r/Exception.hpp" | ||||
| #include "libslic3r/Utils.hpp" | ||||
| #include "I18N.hpp" | ||||
| 
 | ||||
| namespace Slic3r { namespace GUI { | ||||
| 
 | ||||
| OG_CustomCtrl::OG_CustomCtrl(   wxWindow*            parent, | ||||
|                                 OptionsGroup*        og, | ||||
|                                 const wxPoint&       pos /* = wxDefaultPosition*/, | ||||
|                                 const wxSize&        size/* = wxDefaultSize*/, | ||||
|                                 const wxValidator&   val /* = wxDefaultValidator*/, | ||||
|                                 const wxString&      name/* = wxEmptyString*/) : | ||||
|     wxControl(parent, wxID_ANY, pos, size, wxWANTS_CHARS | wxBORDER_NONE), | ||||
|     m_og(og) | ||||
| { | ||||
|     if (!wxOSX) | ||||
|         SetDoubleBuffered(true);// SetDoubleBuffered exists on Win and Linux/GTK, but is missing on OSX
 | ||||
| 
 | ||||
|     // init bitmaps
 | ||||
|     m_bmp_mode_simple    = ScalableBitmap(this, "mode_simple"  , wxOSX ? 10 : 12); | ||||
|     m_bmp_mode_advanced    = ScalableBitmap(this, "mode_advanced", wxOSX ? 10 : 12); | ||||
|     m_bmp_mode_expert    = ScalableBitmap(this, "mode_expert"  , wxOSX ? 10 : 12); | ||||
|     m_bmp_blinking        = ScalableBitmap(this, "search_blink"); | ||||
| 
 | ||||
|     m_border = lround(0.2 * wxGetApp().em_unit()); | ||||
|     m_v_gap     = lround(1.0 * wxGetApp().em_unit()); | ||||
|     m_h_gap     = lround(0.2 * wxGetApp().em_unit()); | ||||
| 
 | ||||
|     init_ctrl_lines();// from og.lines()
 | ||||
| 
 | ||||
|     this->Bind(wxEVT_PAINT,     &OG_CustomCtrl::OnPaint, this); | ||||
|     this->Bind(wxEVT_MOTION,    &OG_CustomCtrl::OnMotion, this); | ||||
|     this->Bind(wxEVT_LEFT_DOWN, &OG_CustomCtrl::OnLeftDown, this); | ||||
|     this->Bind(wxEVT_LEFT_UP,   &OG_CustomCtrl::OnLeftUp, this); | ||||
| 
 | ||||
|     const wxFont& font = wxGetApp().normal_font(); | ||||
|     m_font = wxOSX ? font.Smaller() : font; | ||||
| } | ||||
| 
 | ||||
| void OG_CustomCtrl::init_ctrl_lines() | ||||
| { | ||||
|     wxCoord    v_pos = 0; | ||||
| 
 | ||||
|     for (const Line& line : m_og->get_lines()) | ||||
|     { | ||||
|         if (line.full_width && ( | ||||
|             // description line
 | ||||
|             line.widget != nullptr || | ||||
|             // description line with widget (button)
 | ||||
|             !line.get_extra_widgets().empty()) | ||||
|             ) | ||||
|             continue; | ||||
| 
 | ||||
|         auto option_set = line.get_options(); | ||||
| 
 | ||||
|         wxCoord height = 0; | ||||
| 
 | ||||
|         // if we have a single option with no label, no sidetext just add it directly to sizer
 | ||||
|         if (option_set.size() == 1 && m_og->label_width == 0 && option_set.front().opt.full_width && | ||||
|             option_set.front().opt.label.empty() && | ||||
|             option_set.front().opt.sidetext.size() == 0 && option_set.front().side_widget == nullptr && | ||||
|             line.get_extra_widgets().size() == 0) | ||||
|         { | ||||
|             height = m_bmp_blinking.bmp().GetHeight() + m_v_gap; | ||||
|             ctrl_lines.emplace_back(CtrlLine{ height, this, line, true }); | ||||
|         } | ||||
|         else if (m_og->label_width != 0 && !line.label.IsEmpty()) | ||||
|         { | ||||
|             wxSize label_sz = GetTextExtent(line.label); | ||||
|             height = label_sz.y * (label_sz.GetWidth() > (m_og->label_width*wxGetApp().em_unit()) ? 2 : 1) + m_v_gap; | ||||
|             ctrl_lines.emplace_back(CtrlLine{ height, this, line }); | ||||
|         } | ||||
|         else | ||||
|             int i = 0; | ||||
|         v_pos += height; | ||||
|     } | ||||
| 
 | ||||
|     this->SetMinSize(wxSize(wxDefaultCoord, v_pos)); | ||||
| } | ||||
| 
 | ||||
| wxPoint OG_CustomCtrl::get_pos(const Line& line, Field* field_in/* = nullptr*/) | ||||
| { | ||||
|     wxCoord v_pos = 0; | ||||
|     wxCoord h_pos = 0; | ||||
|     for (auto ctrl_line : ctrl_lines) { | ||||
|         if (&ctrl_line.m_og_line == &line) | ||||
|         { | ||||
|             h_pos = m_bmp_mode_simple.bmp().GetWidth() + m_h_gap; | ||||
|             if (line.near_label_widget) { | ||||
|                 if (field_in) | ||||
|                     h_pos += m_bmp_blinking.bmp().GetWidth() + m_h_gap; // ysFIXME
 | ||||
|                 else | ||||
|                     break; | ||||
|             } | ||||
| 
 | ||||
|             wxString label = line.label; | ||||
|             if (m_og->label_width != 0 && !label.IsEmpty()) | ||||
|                 h_pos += m_og->label_width * wxGetApp().em_unit(); | ||||
| 
 | ||||
|             if (line.widget) | ||||
|                 break; | ||||
| 
 | ||||
|             // If we have a single option with no sidetext
 | ||||
|             const std::vector<Option>& option_set = line.get_options(); | ||||
|             if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 && | ||||
|                 option_set.front().opt.label.empty() && | ||||
|                 option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0) | ||||
|             { | ||||
|                 h_pos += 3 * (m_bmp_blinking.bmp().GetWidth() + m_h_gap); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|             for (auto opt : option_set) { | ||||
|                 Field* field = m_og->get_field(opt.opt_id); | ||||
|                 ConfigOptionDef option = opt.opt; | ||||
|                 // add label if any
 | ||||
|                 if (!option.label.empty()) { | ||||
|                     //!            To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1
 | ||||
|                     label = (option.label == L_CONTEXT("Top", "Layers") || option.label == L_CONTEXT("Bottom", "Layers")) ? | ||||
|                         _CTX(option.label, "Layers") : _(option.label); | ||||
|                     label += ":"; | ||||
| 
 | ||||
|                     h_pos += GetTextExtent(label).x + m_h_gap; | ||||
|                 }                 | ||||
|                 h_pos += 3 * (m_bmp_blinking.bmp().GetWidth() + m_h_gap); | ||||
|                  | ||||
|                 if (field == field_in) | ||||
|                     break;     | ||||
|                 h_pos += field->getWindow()->GetSize().x; | ||||
| 
 | ||||
|                 if (option_set.size() == 1 && option_set.front().opt.full_width) | ||||
|                     break; | ||||
| 
 | ||||
|                 // add sidetext if any
 | ||||
|                 if (!option.sidetext.empty() || m_og->sidetext_width > 0) | ||||
|                     h_pos += m_og->sidetext_width * wxGetApp().em_unit(); | ||||
| 
 | ||||
|                 if (opt.opt_id != option_set.back().opt_id) //! istead of (opt != option_set.back())
 | ||||
|                     h_pos += lround(0.6 * wxGetApp().em_unit()); | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|         v_pos += ctrl_line.m_height; | ||||
|     } | ||||
| 
 | ||||
|     return wxPoint(h_pos, v_pos); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void OG_CustomCtrl::OnPaint(wxPaintEvent&) | ||||
| { | ||||
| #ifdef _WIN32  | ||||
|     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); | ||||
| #else | ||||
|     SetBackgroundColour(GetParent()->GetBackgroundColour()); | ||||
| #endif // _WIN32 
 | ||||
| 
 | ||||
|     wxPaintDC dc(this); | ||||
|     dc.SetFont(m_font); | ||||
| 
 | ||||
|     wxCoord v_pos = 0; | ||||
|     for (auto line : ctrl_lines) { | ||||
|         if (!line.is_visible) | ||||
|             continue; | ||||
|         line.render(dc, v_pos); | ||||
|         v_pos += line.m_height; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void OG_CustomCtrl::OnMotion(wxMouseEvent& event) | ||||
| { | ||||
|     bool action = false; | ||||
| 
 | ||||
|     const wxPoint pos = event.GetLogicalPosition(wxClientDC(this)); | ||||
|     Refresh(); | ||||
|     Update(); | ||||
|     event.Skip(); | ||||
| } | ||||
| 
 | ||||
| void OG_CustomCtrl::OnLeftDown(wxMouseEvent& event) | ||||
| { | ||||
|     if (HasCapture()) | ||||
|         return; | ||||
|     this->CaptureMouse(); | ||||
| 
 | ||||
|     event.Skip(); | ||||
| } | ||||
| 
 | ||||
| void OG_CustomCtrl::OnLeftUp(wxMouseEvent& event) | ||||
| { | ||||
|     if (HasCapture()) | ||||
|         return; | ||||
|     this->CaptureMouse(); | ||||
| 
 | ||||
|     event.Skip(); | ||||
| } | ||||
| 
 | ||||
| bool OG_CustomCtrl::update_visibility(ConfigOptionMode mode) | ||||
| { | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void OG_CustomCtrl::msw_rescale() | ||||
| { | ||||
|     const wxFont& font = GUI::wxGetApp().normal_font(); | ||||
|     m_font = wxOSX ? font.Smaller() : font; | ||||
| 
 | ||||
|     wxSize new_sz = GUI::wxGetApp().em_unit() * this->GetSize(); | ||||
|     SetMinSize(new_sz); | ||||
|     GetParent()->Layout(); | ||||
| } | ||||
| 
 | ||||
| void OG_CustomCtrl::sys_color_changed() | ||||
| { | ||||
|      | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord v_pos) | ||||
| { | ||||
|     Field* field = nullptr; | ||||
|     field = m_ctrl->m_og->get_field(m_og_line.get_options().front().opt_id); | ||||
| 
 | ||||
|     if (draw_just_act_buttons) { | ||||
|         if (field) | ||||
|             draw_act_bmps(dc, wxPoint(0, v_pos), m_ctrl->m_bmp_blinking.bmp(), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp()); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     wxCoord h_pos = draw_mode_bmp(dc, v_pos); | ||||
| 
 | ||||
|     if (m_og_line.near_label_widget) | ||||
|         h_pos += m_ctrl->m_bmp_blinking.bmp().GetWidth() + m_ctrl->m_h_gap;//m_og_line.near_label_widget->GetSize().x;;
 | ||||
| 
 | ||||
|     const std::vector<Option>& option_set = m_og_line.get_options(); | ||||
| 
 | ||||
|     wxString label = m_og_line.label; | ||||
|     if (m_ctrl->m_og->label_width != 0 && !label.IsEmpty()) | ||||
|         h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label+":", (option_set.size() == 1 && field ? field->label_color() : m_og_line.full_Label_color),  m_ctrl->m_og->label_width*wxGetApp().em_unit()); | ||||
| 
 | ||||
|     // If there's a widget, build it and add the result to the sizer.
 | ||||
|     if (m_og_line.widget != nullptr) | ||||
|         return; | ||||
| 
 | ||||
|     // If we're here, we have more than one option or a single option with sidetext
 | ||||
|     // so we need a horizontal sizer to arrange these things
 | ||||
| 
 | ||||
|     // If we have a single option with no sidetext just add it directly to the grid sizer
 | ||||
|     if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 && | ||||
|         option_set.front().opt.label.empty() && | ||||
|         option_set.front().side_widget == nullptr && m_og_line.get_extra_widgets().size() == 0) | ||||
|     { | ||||
|         if (field) | ||||
|             draw_act_bmps(dc, wxPoint(h_pos, v_pos), m_ctrl->m_bmp_blinking.bmp(), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp()); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     for (auto opt : option_set) { | ||||
|         field = m_ctrl->m_og->get_field(opt.opt_id); | ||||
|         ConfigOptionDef option = opt.opt; | ||||
|         // add label if any
 | ||||
|         if (!option.label.empty()) { | ||||
|             //!            To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1
 | ||||
|             label = (option.label == L_CONTEXT("Top", "Layers") || option.label == L_CONTEXT("Bottom", "Layers")) ? | ||||
|                     _CTX(option.label, "Layers") : _(option.label); | ||||
|             label += ":"; | ||||
| 
 | ||||
|             h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label, field ? field->label_color() : nullptr, m_ctrl->m_og->sublabel_width * wxGetApp().em_unit()); | ||||
|         } | ||||
| 
 | ||||
|         if (field) { | ||||
|             h_pos = draw_act_bmps(dc, wxPoint(h_pos, v_pos), m_ctrl->m_bmp_blinking.bmp(), field->undo_to_sys_bitmap()->bmp(), field->undo_bitmap()->bmp()); | ||||
|             h_pos += field->getWindow()->GetSize().x; | ||||
|         } | ||||
| 
 | ||||
|         // add field
 | ||||
|         if (option_set.size() == 1 && option_set.front().opt.full_width) | ||||
|             break; | ||||
| 
 | ||||
|         // add sidetext if any
 | ||||
|         if (!option.sidetext.empty() || m_ctrl->m_og->sidetext_width > 0) | ||||
|             h_pos = draw_text(dc, wxPoint(h_pos, v_pos), _(option.sidetext), nullptr, m_ctrl->m_og->sidetext_width * wxGetApp().em_unit()); | ||||
| 
 | ||||
|         if (opt.opt_id != option_set.back().opt_id) //! istead of (opt != option_set.back())
 | ||||
|             h_pos += lround(0.6 * wxGetApp().em_unit()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| wxCoord OG_CustomCtrl::CtrlLine::draw_mode_bmp(wxDC& dc, wxCoord v_pos) | ||||
| { | ||||
|     ConfigOptionMode mode = m_og_line.get_options()[0].opt.mode; | ||||
|     const wxBitmap&  bmp  = mode == ConfigOptionMode::comSimple   ? m_ctrl->m_bmp_mode_simple.bmp()   : | ||||
|                             mode == ConfigOptionMode::comAdvanced ? m_ctrl->m_bmp_mode_advanced.bmp() : m_ctrl->m_bmp_mode_expert.bmp(); | ||||
| 
 | ||||
|     wxCoord y_draw = v_pos + lround((m_height - bmp.GetHeight()) / 2); | ||||
| 
 | ||||
|     dc.DrawBitmap(bmp, m_ctrl->m_border, y_draw); | ||||
| 
 | ||||
|     return m_ctrl->m_border + bmp.GetWidth() + m_ctrl->m_h_gap; | ||||
| } | ||||
| 
 | ||||
| wxCoord    OG_CustomCtrl::CtrlLine::draw_text(wxDC& dc, wxPoint pos, const wxString& text, const wxColour* color, int width) | ||||
| { | ||||
|     wxString multiline_text; | ||||
|     if (width > 0 && dc.GetTextExtent(text).x > width) { | ||||
|         multiline_text = text; | ||||
| 
 | ||||
|         size_t idx = size_t(-1); | ||||
|         for (size_t i = 0; i < multiline_text.Len(); i++) | ||||
|         { | ||||
|             if (multiline_text[i] == ' ') | ||||
|             { | ||||
|                 if (dc.GetTextExtent(multiline_text.SubString(0, i)).x < width) | ||||
|                     idx = i; | ||||
|                 else { | ||||
|                     if (idx != size_t(-1)) | ||||
|                         multiline_text[idx] = '\n'; | ||||
|                     else | ||||
|                         multiline_text[i] = '\n'; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (idx != size_t(-1)) | ||||
|             multiline_text[idx] = '\n'; | ||||
|     } | ||||
| 
 | ||||
|     const wxString& out_text = multiline_text.IsEmpty() ? text : multiline_text; | ||||
|     wxCoord text_width, text_height; | ||||
|     dc.GetMultiLineTextExtent(out_text, &text_width, &text_height); | ||||
| 
 | ||||
|     pos.y = pos.y + lround((m_height - text_height) / 2); | ||||
|      | ||||
|     wxColour old_clr = dc.GetTextForeground(); | ||||
|     dc.SetTextForeground(color ? *color : wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); | ||||
|     dc.DrawText(out_text, pos); | ||||
|     dc.SetTextForeground(old_clr); | ||||
| 
 | ||||
|     if (width < 1) | ||||
|         width = text_width; | ||||
| 
 | ||||
|     return pos.x + width + m_ctrl->m_h_gap; | ||||
| } | ||||
| 
 | ||||
| wxCoord    OG_CustomCtrl::CtrlLine::draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_blinking, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo) | ||||
| { | ||||
|     wxCoord h_pos = pos.x; | ||||
|     wxCoord pos_y = pos.y + lround((m_height - bmp_blinking.GetHeight()) / 2); | ||||
| 
 | ||||
|     dc.DrawBitmap(bmp_blinking, h_pos, pos_y); | ||||
| 
 | ||||
|     int bmp_dim = bmp_blinking.GetWidth(); | ||||
|     m_rect_blinking = wxRect(h_pos, pos_y, bmp_dim, bmp_dim); | ||||
| 
 | ||||
|     h_pos += bmp_dim + m_ctrl->m_h_gap; | ||||
|     dc.DrawBitmap(bmp_undo_to_sys, h_pos, pos_y); | ||||
| 
 | ||||
|     bmp_dim = bmp_undo_to_sys.GetWidth(); | ||||
|     m_rect_undo_to_sys_icon = wxRect(h_pos, pos_y, bmp_dim, bmp_dim); | ||||
| 
 | ||||
|     h_pos += bmp_dim + m_ctrl->m_h_gap; | ||||
|     dc.DrawBitmap(bmp_undo, h_pos, pos_y); | ||||
| 
 | ||||
|     bmp_dim = bmp_undo.GetWidth(); | ||||
|     m_rect_undo_icon = wxRect(h_pos, pos_y, bmp_dim, bmp_dim); | ||||
| 
 | ||||
|     h_pos += bmp_dim + m_ctrl->m_h_gap; | ||||
| 
 | ||||
|     return h_pos; | ||||
| } | ||||
| 
 | ||||
| } // GUI
 | ||||
| } // Slic3r
 | ||||
							
								
								
									
										89
									
								
								src/slic3r/GUI/OG_CustomCtrl.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/slic3r/GUI/OG_CustomCtrl.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,89 @@ | |||
| #ifndef slic3r_OG_CustomCtrl_hpp_ | ||||
| #define slic3r_OG_CustomCtrl_hpp_ | ||||
| 
 | ||||
| #include <wx/stattext.h> | ||||
| #include <wx/settings.h> | ||||
| 
 | ||||
| #include <map> | ||||
| #include <functional> | ||||
| 
 | ||||
| #include "libslic3r/Config.hpp" | ||||
| #include "libslic3r/PrintConfig.hpp" | ||||
| 
 | ||||
| #include "OptionsGroup.hpp" | ||||
| #include "I18N.hpp" | ||||
| 
 | ||||
| // Translate the ifdef 
 | ||||
| #ifdef __WXOSX__ | ||||
|     #define wxOSX true | ||||
| #else | ||||
|     #define wxOSX false | ||||
| #endif | ||||
| 
 | ||||
| //#define BORDER(a, b) ((wxOSX ? a : b))
 | ||||
| 
 | ||||
| namespace Slic3r { namespace GUI { | ||||
| 
 | ||||
| //  Static text shown among the options.
 | ||||
| class OG_CustomCtrl :public wxControl | ||||
| { | ||||
|     wxFont            m_font; | ||||
| 
 | ||||
|     ScalableBitmap    m_bmp_mode_simple; | ||||
|     ScalableBitmap    m_bmp_mode_advanced; | ||||
|     ScalableBitmap    m_bmp_mode_expert; | ||||
|     ScalableBitmap    m_bmp_blinking; | ||||
| 
 | ||||
|     struct CtrlLine { | ||||
|         wxCoord           m_height  { wxDefaultCoord }; | ||||
|         OG_CustomCtrl*    m_ctrl    { nullptr }; | ||||
|         const Line&       m_og_line; | ||||
| 
 | ||||
|         bool draw_just_act_buttons  { false }; | ||||
|         bool is_visible             { true }; | ||||
| 
 | ||||
|         void    render(wxDC& dc, wxCoord v_pos); | ||||
|         wxCoord draw_mode_bmp(wxDC& dc, wxCoord v_pos); | ||||
|         wxCoord draw_text      (wxDC& dc, wxPoint pos, const wxString& text, const wxColour* color, int width); | ||||
|         wxCoord draw_act_bmps(wxDC& dc, wxPoint pos, const wxBitmap& bmp_blinking, const wxBitmap& bmp_undo_to_sys, const wxBitmap& bmp_undo); | ||||
| 
 | ||||
|         void    set_visible(bool show) { is_visible = show; } | ||||
| 
 | ||||
|         wxRect      m_rect_blinking; | ||||
|         wxRect      m_rect_undo_icon; | ||||
|         wxRect      m_rect_undo_to_sys_icon; | ||||
|     }; | ||||
| 
 | ||||
|     std::vector<CtrlLine> ctrl_lines; | ||||
| 
 | ||||
| public: | ||||
|     OG_CustomCtrl(  wxWindow* parent, | ||||
|                     OptionsGroup* og, | ||||
|                     const wxPoint& pos = wxDefaultPosition, | ||||
|                     const wxSize& size = wxDefaultSize, | ||||
|                     const wxValidator& val = wxDefaultValidator, | ||||
|                     const wxString& name = wxEmptyString); | ||||
|     ~OG_CustomCtrl() {} | ||||
| 
 | ||||
|     void    OnPaint(wxPaintEvent&); | ||||
|     void    OnMotion(wxMouseEvent& event); | ||||
|     void    OnLeftDown(wxMouseEvent& event); | ||||
|     void    OnLeftUp(wxMouseEvent& event); | ||||
| 
 | ||||
|     void    init_ctrl_lines(); | ||||
|     bool    update_visibility(ConfigOptionMode mode); | ||||
|     void    msw_rescale(); | ||||
|     void    sys_color_changed(); | ||||
| 
 | ||||
|     wxPoint get_pos(const Line& line, Field* field = nullptr); | ||||
| 
 | ||||
|     OptionsGroup*  m_og; | ||||
|     int            m_border; | ||||
|     int            m_v_gap; | ||||
|     int            m_h_gap; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| }} | ||||
| 
 | ||||
| #endif /* slic3r_OG_CustomCtrl_hpp_ */ | ||||
|  | @ -2,6 +2,7 @@ | |||
| #include "ConfigExceptions.hpp" | ||||
| #include "Plater.hpp" | ||||
| #include "GUI_App.hpp" | ||||
| #include "OG_CustomCtrl.hpp" | ||||
| 
 | ||||
| #include <utility> | ||||
| #include <wx/numformatter.h> | ||||
|  | @ -114,7 +115,7 @@ OptionsGroup::OptionsGroup(	wxWindow* _parent, const wxString& title, | |||
| 
 | ||||
| void OptionsGroup::add_undo_buttons_to_sizer(wxSizer* sizer, const t_field& field) | ||||
| { | ||||
| 	if (!m_show_modified_btns) { | ||||
| 	if (!m_show_modified_btns && field->m_Undo_btn) { | ||||
|         field->m_Undo_btn->set_as_hidden(); | ||||
| 		field->m_Undo_to_sys_btn->set_as_hidden(); | ||||
| 		field->m_blinking_bmp->Hide(); | ||||
|  | @ -147,11 +148,14 @@ void OptionsGroup::append_line(const Line& line) | |||
| 
 | ||||
| void OptionsGroup::activate_line(Line& line) | ||||
| { | ||||
| 	m_use_custom_ctrl_as_parent = false; | ||||
| 
 | ||||
| 	if (line.full_width && ( | ||||
| 		line.widget != nullptr || | ||||
| 		!line.get_extra_widgets().empty()) | ||||
| 		) { | ||||
|         if (line.widget != nullptr) { | ||||
| 			// description lines
 | ||||
|             sizer->Add(line.widget(this->ctrl_parent()), 0, wxEXPAND | wxALL, wxOSX ? 0 : 15); | ||||
|             return; | ||||
|         } | ||||
|  | @ -168,6 +172,11 @@ void OptionsGroup::activate_line(Line& line) | |||
| 		} | ||||
|     } | ||||
| 
 | ||||
|     if (!custom_ctrl && m_show_modified_btns) { | ||||
|         custom_ctrl = new OG_CustomCtrl((wxWindow*)this->stb, this); | ||||
|         sizer->Add(custom_ctrl, 0, wxEXPAND | wxALL, wxOSX || !staticbox ? 0 : 5); | ||||
|     } | ||||
| 
 | ||||
| 	auto option_set = line.get_options(); | ||||
| 
 | ||||
| 	// Set sidetext width for a better alignment of options in line
 | ||||
|  | @ -181,36 +190,29 @@ void OptionsGroup::activate_line(Line& line) | |||
|         option_set.front().opt.label.empty() && | ||||
| 		option_set.front().opt.sidetext.size() == 0 && option_set.front().side_widget == nullptr &&  | ||||
| 		line.get_extra_widgets().size() == 0) { | ||||
| 		wxSizer* tmp_sizer; | ||||
| #if 0//#ifdef __WXGTK__
 | ||||
| 		tmp_sizer = new wxBoxSizer(wxVERTICAL); | ||||
|         m_panel->SetSizer(tmp_sizer); | ||||
|         m_panel->Layout(); | ||||
| #else | ||||
|         tmp_sizer = sizer; | ||||
| #endif /* __WXGTK__ */ | ||||
| 
 | ||||
| 		const auto& option = option_set.front(); | ||||
| 		const auto& field = build_field(option); | ||||
| 
 | ||||
| 		auto btn_sizer = new wxBoxSizer(wxHORIZONTAL); | ||||
| 		add_undo_buttons_to_sizer(btn_sizer, field); | ||||
| 		tmp_sizer->Add(btn_sizer, 0, wxEXPAND | wxALL, 0); | ||||
| 		if (!custom_ctrl) { | ||||
| 			auto btn_sizer = new wxBoxSizer(wxHORIZONTAL); | ||||
| 			add_undo_buttons_to_sizer(btn_sizer, field); | ||||
| 			sizer->Add(btn_sizer, 0, wxEXPAND | wxALL, 0); | ||||
| 		} | ||||
| 		if (is_window_field(field)) | ||||
| 			tmp_sizer->Add(field->getWindow(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5); | ||||
| 			sizer->Add(field->getWindow(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5); | ||||
| 		if (is_sizer_field(field)) | ||||
| 			tmp_sizer->Add(field->getSizer(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5); | ||||
| 			sizer->Add(field->getSizer(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
|     auto grid_sizer = m_grid_sizer; | ||||
| #if 0//#ifdef __WXGTK__
 | ||||
| 	m_panel->SetSizer(m_grid_sizer); | ||||
| 	m_panel->Layout(); | ||||
| #endif /* __WXGTK__ */ | ||||
| 
 | ||||
|     if (custom_ctrl) | ||||
|         m_use_custom_ctrl_as_parent = true; | ||||
| 
 | ||||
| 	// if we have an extra column, build it
 | ||||
| 	if (extra_column) | ||||
| 	if (extra_column && !m_show_modified_btns) | ||||
| 	{ | ||||
| 		m_extra_column_item_ptrs.push_back(extra_column(this->ctrl_parent(), line)); | ||||
| 		grid_sizer->Add(m_extra_column_item_ptrs.back(), 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 3); | ||||
|  | @ -219,55 +221,76 @@ void OptionsGroup::activate_line(Line& line) | |||
|     // Build a label if we have it
 | ||||
| 	wxStaticText* label=nullptr; | ||||
|     if (label_width != 0) { | ||||
|     	if (! line.near_label_widget || ! line.label.IsEmpty()) { | ||||
|     		// Only create the label if it is going to be displayed.
 | ||||
| 			long label_style = staticbox ? 0 : wxALIGN_RIGHT; | ||||
| #ifdef __WXGTK__ | ||||
| 			// workaround for correct text align of the StaticBox on Linux
 | ||||
| 			// flags wxALIGN_RIGHT and wxALIGN_CENTRE don't work when Ellipsize flags are _not_ given.
 | ||||
| 			// Text is properly aligned only when Ellipsize is checked.
 | ||||
| 			label_style |= staticbox ? 0 : wxST_ELLIPSIZE_END; | ||||
| #endif /* __WXGTK__ */ | ||||
| 			label = new wxStaticText(this->ctrl_parent(), wxID_ANY, line.label + (line.label.IsEmpty() ? "" : ": "), | ||||
| 				wxDefaultPosition, wxSize(label_width * wxGetApp().em_unit(), -1), label_style); | ||||
| 			label->SetBackgroundStyle(wxBG_STYLE_PAINT); | ||||
| 	        label->SetFont(wxGetApp().normal_font()); | ||||
| 	        label->Wrap(label_width*wxGetApp().em_unit()); // avoid a Linux/GTK bug
 | ||||
| 	    } | ||||
|         if (!line.near_label_widget) | ||||
|             grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, line.label.IsEmpty() ? 0 : 5); | ||||
|         else { | ||||
|             m_near_label_widget_ptrs.push_back(line.near_label_widget(this->ctrl_parent())); | ||||
|         if (custom_ctrl) { | ||||
|             if (line.near_label_widget) { | ||||
|                 m_near_label_widget_ptrs.push_back(line.near_label_widget(this->ctrl_parent())); | ||||
| 
 | ||||
|             if (line.label.IsEmpty()) | ||||
|                 grid_sizer->Add(m_near_label_widget_ptrs.back(), 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 7); | ||||
|             else { | ||||
|                 // If we're here, we have some widget near the label
 | ||||
|                 // so we need a horizontal sizer to arrange these things
 | ||||
|                 auto sizer = new wxBoxSizer(wxHORIZONTAL); | ||||
|                 grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1); | ||||
|                 sizer->Add(m_near_label_widget_ptrs.back(), 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 7); | ||||
|                 sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5); | ||||
|                 wxPoint pos = custom_ctrl->get_pos(line); | ||||
|                 m_near_label_widget_ptrs.back()->SetPosition(pos); | ||||
|             } | ||||
|         } | ||||
| 		if (label != nullptr && line.label_tooltip != "") | ||||
| 			label->SetToolTip(line.label_tooltip); | ||||
|         else { | ||||
|             if (!line.near_label_widget || !line.label.IsEmpty()) { | ||||
|                 // Only create the label if it is going to be displayed.
 | ||||
|                 long label_style = staticbox ? 0 : wxALIGN_RIGHT; | ||||
| #ifdef __WXGTK__ | ||||
|                 // workaround for correct text align of the StaticBox on Linux
 | ||||
|                 // flags wxALIGN_RIGHT and wxALIGN_CENTRE don't work when Ellipsize flags are _not_ given.
 | ||||
|                 // Text is properly aligned only when Ellipsize is checked.
 | ||||
|                 label_style |= staticbox ? 0 : wxST_ELLIPSIZE_END; | ||||
| #endif /* __WXGTK__ */ | ||||
|                 label = new wxStaticText(this->ctrl_parent(), wxID_ANY, line.label + (line.label.IsEmpty() ? "" : ": "), | ||||
|                     wxDefaultPosition, wxSize(label_width * wxGetApp().em_unit(), -1), label_style); | ||||
|                 label->SetBackgroundStyle(wxBG_STYLE_PAINT); | ||||
|                 label->SetFont(wxGetApp().normal_font()); | ||||
|                 label->Wrap(label_width * wxGetApp().em_unit()); // avoid a Linux/GTK bug
 | ||||
|             } | ||||
|             if (!line.near_label_widget) | ||||
|                 grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, line.label.IsEmpty() ? 0 : 5); | ||||
|             else { | ||||
|                 m_near_label_widget_ptrs.push_back(line.near_label_widget(this->ctrl_parent())); | ||||
| 
 | ||||
|                 if (line.label.IsEmpty()) | ||||
|                     grid_sizer->Add(m_near_label_widget_ptrs.back(), 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 7); | ||||
|                 else { | ||||
|                     // If we're here, we have some widget near the label
 | ||||
|                     // so we need a horizontal sizer to arrange these things
 | ||||
|                     auto sizer = new wxBoxSizer(wxHORIZONTAL); | ||||
|                     grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1); | ||||
|                     sizer->Add(m_near_label_widget_ptrs.back(), 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 7); | ||||
|                     sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5); | ||||
|                 } | ||||
|             } | ||||
|             if (label != nullptr && line.label_tooltip != "") | ||||
|                 label->SetToolTip(line.label_tooltip); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 	if (line.full_Label != nullptr) | ||||
| 		*line.full_Label = label; // Initiate the pointer to the control of the full label, if we need this one.
 | ||||
| 	// If there's a widget, build it and add the result to the sizer.
 | ||||
| 	if (line.widget != nullptr) { | ||||
| 		auto wgt = line.widget(this->ctrl_parent()); | ||||
| 		auto wgt = line.widget(custom_ctrl ? custom_ctrl : this->ctrl_parent()); | ||||
|         if (custom_ctrl) { | ||||
|             auto children = wgt->GetChildren(); | ||||
|             wxPoint pos = custom_ctrl->get_pos(line); | ||||
|             for (auto child : children) | ||||
|                 if (child->IsWindow()) { | ||||
|                     child->GetWindow()->SetPosition(pos); | ||||
|                     pos.x += child->GetWindow()->GetBestSize().x + custom_ctrl->m_h_gap; | ||||
|                 } | ||||
|         } | ||||
| 		// If widget doesn't have label, don't use border
 | ||||
| 		grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, (wxOSX || line.label.IsEmpty()) ? 0 : 5); | ||||
|         else | ||||
|             grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, (wxOSX || line.label.IsEmpty()) ? 0 : 5); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	// If we're here, we have more than one option or a single option with sidetext
 | ||||
|     // so we need a horizontal sizer to arrange these things
 | ||||
| 	auto sizer = new wxBoxSizer(wxHORIZONTAL); | ||||
| 	grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1); | ||||
|     if (!custom_ctrl) | ||||
|         grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1); | ||||
| 	// If we have a single option with no sidetext just add it directly to the grid sizer
 | ||||
| 	if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 && | ||||
|         option_set.front().opt.label.empty() && | ||||
|  | @ -275,20 +298,28 @@ void OptionsGroup::activate_line(Line& line) | |||
| 		const auto& option = option_set.front(); | ||||
| 		const auto& field = build_field(option, label); | ||||
| 
 | ||||
| 		add_undo_buttons_to_sizer(sizer, field); | ||||
| 		if (is_window_field(field)) | ||||
| 			sizer->Add(field->getWindow(), option.opt.full_width ? 1 : 0, //(option.opt.full_width ? wxEXPAND : 0) |
 | ||||
| 				wxBOTTOM | wxTOP | (option.opt.full_width ? wxEXPAND : wxALIGN_CENTER_VERTICAL), (wxOSX || !staticbox) ? 0 : 2); | ||||
| 		if (is_sizer_field(field)) | ||||
| 			sizer->Add(field->getSizer(), 1, /*(*/option.opt.full_width ? wxEXPAND : /*0) |*/ wxALIGN_CENTER_VERTICAL, 0); | ||||
| 		return; | ||||
|         if (!custom_ctrl) | ||||
|             add_undo_buttons_to_sizer(sizer, field); | ||||
|         if (is_window_field(field)) { | ||||
|             if (custom_ctrl) { | ||||
|                 field->getWindow()->SetPosition(custom_ctrl->get_pos(line, field.get())); | ||||
|                 if (option.opt.full_width) | ||||
|                     field->getWindow()->SetSize(wxSize(3 * Field::def_width_wider() * wxGetApp().em_unit(), -1)); | ||||
|             } | ||||
|             else | ||||
|                 sizer->Add(field->getWindow(), option.opt.full_width ? 1 : 0, | ||||
|                     wxBOTTOM | wxTOP | (option.opt.full_width ? wxEXPAND : wxALIGN_CENTER_VERTICAL), (wxOSX || !staticbox) ? 0 : 2); | ||||
|         } | ||||
|         if (is_sizer_field(field)) | ||||
|             sizer->Add(field->getSizer(), 1, option.opt.full_width ? wxEXPAND : wxALIGN_CENTER_VERTICAL, 0); | ||||
|         return; | ||||
| 	} | ||||
| 
 | ||||
|     for (auto opt : option_set) { | ||||
| 		ConfigOptionDef option = opt.opt; | ||||
| 		wxSizer* sizer_tmp = sizer; | ||||
| 		// add label if any
 | ||||
| 		if (!option.label.empty()) { | ||||
| 		if (!option.label.empty() && !custom_ctrl) { | ||||
| //!			To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1
 | ||||
| 			wxString str_label = (option.label == L_CONTEXT("Top", "Layers") || option.label == L_CONTEXT("Bottom", "Layers")) ? | ||||
| 				_CTX(option.label, "Layers") : | ||||
|  | @ -303,22 +334,40 @@ void OptionsGroup::activate_line(Line& line) | |||
| 		// add field
 | ||||
| 		const Option& opt_ref = opt; | ||||
| 		auto& field = build_field(opt_ref, label); | ||||
| 		add_undo_buttons_to_sizer(sizer_tmp, field); | ||||
|         if (!custom_ctrl) | ||||
|             add_undo_buttons_to_sizer(sizer_tmp, field); | ||||
|         if (option_set.size() == 1 && option_set.front().opt.full_width) | ||||
|         { | ||||
|             const auto v_sizer = new wxBoxSizer(wxVERTICAL); | ||||
|             sizer_tmp->Add(v_sizer, 1, wxEXPAND); | ||||
|             is_sizer_field(field) ? | ||||
|                 v_sizer->Add(field->getSizer(), 0, wxEXPAND) : | ||||
|                 v_sizer->Add(field->getWindow(), 0, wxEXPAND); | ||||
|             if (custom_ctrl) { | ||||
|                 if (is_window_field(field)) | ||||
|                     field->getWindow()->SetPosition(custom_ctrl->get_pos(line, field.get())); | ||||
|                 else { | ||||
|                 } | ||||
|             } | ||||
|             else { | ||||
|                 const auto v_sizer = new wxBoxSizer(wxVERTICAL); | ||||
|                 sizer_tmp->Add(v_sizer, 1, wxEXPAND); | ||||
|                 is_sizer_field(field) ? | ||||
|                     v_sizer->Add(field->getSizer(), 0, wxEXPAND) : | ||||
|                     v_sizer->Add(field->getWindow(), 0, wxEXPAND); | ||||
|             } | ||||
|             break;//return;
 | ||||
|         } | ||||
| 
 | ||||
| 		is_sizer_field(field) ? | ||||
| 			sizer_tmp->Add(field->getSizer(), 0, wxALIGN_CENTER_VERTICAL, 0) : | ||||
| 			sizer_tmp->Add(field->getWindow(), 0, wxALIGN_CENTER_VERTICAL, 0); | ||||
|         if (custom_ctrl) { | ||||
|             if (is_window_field(field)) | ||||
|                 field->getWindow()->SetPosition(custom_ctrl->get_pos(line, field.get())); | ||||
|             else { | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             is_sizer_field(field) ? | ||||
|                 sizer_tmp->Add(field->getSizer(), 0, wxALIGN_CENTER_VERTICAL, 0) : | ||||
|                 sizer_tmp->Add(field->getWindow(), 0, wxALIGN_CENTER_VERTICAL, 0); | ||||
|         } | ||||
| 
 | ||||
| 		// add sidetext if any
 | ||||
| 		if (!custom_ctrl) | ||||
| 		if (!option.sidetext.empty() || sidetext_width > 0) { | ||||
| 			auto sidetext = new wxStaticText(	this->ctrl_parent(), wxID_ANY, _(option.sidetext), wxDefaultPosition,  | ||||
| 												wxSize(sidetext_width != -1 ? sidetext_width*wxGetApp().em_unit() : -1, -1), wxALIGN_LEFT); | ||||
|  | @ -333,11 +382,18 @@ void OptionsGroup::activate_line(Line& line) | |||
| 			sizer_tmp->Add(opt.side_widget(this->ctrl_parent())/*!.target<wxWindow>()*/, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 1);	//! requires verification
 | ||||
| 		} | ||||
| 
 | ||||
|         if (custom_ctrl) | ||||
|             continue; | ||||
| 
 | ||||
| 		if (opt.opt_id != option_set.back().opt_id) //! istead of (opt != option_set.back())
 | ||||
| 		{ | ||||
| 			sizer_tmp->AddSpacer(6); | ||||
| 	    } | ||||
| 	} | ||||
| 
 | ||||
|     if (custom_ctrl) | ||||
|         return; | ||||
| 
 | ||||
| 	// add extra sizers if any
 | ||||
| 	for (auto extra_widget : line.get_extra_widgets())  | ||||
|     { | ||||
|  | @ -417,6 +473,15 @@ void OptionsGroup::clear() | |||
| 		if(line.full_Label) | ||||
| 			*line.full_Label = nullptr; | ||||
| 
 | ||||
|     if (custom_ctrl) { | ||||
|         for (auto const &item : m_fields) { | ||||
|             wxWindow* win = item.second.get()->getWindow(); | ||||
|             if (win) | ||||
|                 win = nullptr; | ||||
|         } | ||||
|         custom_ctrl = nullptr; | ||||
|     } | ||||
| 
 | ||||
| 	m_extra_column_item_ptrs.clear(); | ||||
| 	m_near_label_widget_ptrs.clear(); | ||||
| 	m_fields.clear(); | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ namespace Slic3r { namespace GUI { | |||
| 
 | ||||
| // Thrown if the building of a parameter page is canceled.
 | ||||
| class UIBuildCanceled : public std::exception {}; | ||||
| class OG_CustomCtrl; | ||||
| 
 | ||||
| /// Widget type describes a function object that returns a wxWindow (our widget) and accepts a wxWidget (parent window).
 | ||||
| using widget_t = std::function<wxSizer*(wxWindow*)>;//!std::function<wxWindow*(wxWindow*)>;
 | ||||
|  | @ -52,6 +53,7 @@ public: | |||
|     wxString	label_tooltip {wxString("")}; | ||||
|     size_t		full_width {0};  | ||||
| 	wxStaticText**	full_Label {nullptr}; | ||||
| 	wxColor*		full_Label_color {nullptr}; | ||||
|     widget_t	widget {nullptr}; | ||||
|     std::function<wxWindow*(wxWindow*)>	near_label_widget{ nullptr }; | ||||
| 
 | ||||
|  | @ -84,6 +86,7 @@ public: | |||
|     const wxString	title; | ||||
|     size_t			label_width = 20 ;// {200};
 | ||||
|     wxSizer*		sizer {nullptr}; | ||||
| 	OG_CustomCtrl*  custom_ctrl{ nullptr }; | ||||
|     column_t		extra_column {nullptr}; | ||||
|     t_change		m_on_change { nullptr }; | ||||
| 	// To be called when the field loses focus, to assign a new initial value to the field.
 | ||||
|  | @ -119,7 +122,7 @@ public: | |||
| #endif /* __WXGTK__ */ | ||||
| 
 | ||||
|     wxWindow* ctrl_parent() const { | ||||
|     	return this->stb ? (wxWindow*)this->stb : this->parent(); | ||||
|     	return this->stb ? (this->custom_ctrl && m_use_custom_ctrl_as_parent ? (wxWindow*)this->custom_ctrl : (wxWindow*)this->stb) : this->parent(); | ||||
|     } | ||||
| 
 | ||||
| 	void		append_line(const Line& line); | ||||
|  | @ -188,6 +191,8 @@ public: | |||
| 
 | ||||
|     wxGridSizer*        get_grid_sizer() { return m_grid_sizer; } | ||||
| 
 | ||||
| 	const std::vector<Line>& get_lines() { return m_lines; } | ||||
| 
 | ||||
| protected: | ||||
| 	std::map<t_config_option_key, Option>	m_options; | ||||
|     wxWindow*				m_parent {nullptr}; | ||||
|  | @ -206,6 +211,9 @@ protected: | |||
| 	// "true" if option is created in preset tabs
 | ||||
| 	bool					m_show_modified_btns{ false }; | ||||
| 
 | ||||
| 	// "true" if control should be created on custom_ctrl
 | ||||
| 	bool					m_use_custom_ctrl_as_parent { false }; | ||||
| 
 | ||||
| 	// This panel is needed for correct showing of the ToolTips for Button, StaticText and CheckBox
 | ||||
| 	// Tooltips on GTK doesn't work inside wxStaticBoxSizer unless you insert a panel 
 | ||||
| 	// inside it before you insert the other controls.
 | ||||
|  |  | |||
|  | @ -348,6 +348,8 @@ public: | |||
|     void    activate(); | ||||
|     void    blink(); | ||||
| 
 | ||||
|     const wxBitmap& get_bmp() const { return bmp.bmp(); } | ||||
| 
 | ||||
| private: | ||||
|     ScalableBitmap  bmp; | ||||
|     bool            show {false}; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 YuSanka
						YuSanka