Custom control: first implementation
This commit is contained in:
parent
e6ddcbab0c
commit
74d6aea4d4
@ -111,6 +111,8 @@ set(SLIC3R_GUI_SOURCES
|
|||||||
GUI/Field.hpp
|
GUI/Field.hpp
|
||||||
GUI/OptionsGroup.cpp
|
GUI/OptionsGroup.cpp
|
||||||
GUI/OptionsGroup.hpp
|
GUI/OptionsGroup.hpp
|
||||||
|
GUI/OG_CustomCtrl.cpp
|
||||||
|
GUI/OG_CustomCtrl.hpp
|
||||||
GUI/BedShapeDialog.cpp
|
GUI/BedShapeDialog.cpp
|
||||||
GUI/BedShapeDialog.hpp
|
GUI/BedShapeDialog.hpp
|
||||||
GUI/2DBed.cpp
|
GUI/2DBed.cpp
|
||||||
|
@ -63,18 +63,23 @@ Field::~Field()
|
|||||||
m_back_to_initial_value = nullptr;
|
m_back_to_initial_value = nullptr;
|
||||||
if (m_back_to_sys_value)
|
if (m_back_to_sys_value)
|
||||||
m_back_to_sys_value = nullptr;
|
m_back_to_sys_value = nullptr;
|
||||||
|
if (getWindow()) {
|
||||||
|
wxWindow* win = getWindow();
|
||||||
|
win->Destroy();
|
||||||
|
win = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Field::PostInitialize()
|
void Field::PostInitialize()
|
||||||
{
|
{
|
||||||
auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||||
m_Undo_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_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_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_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)
|
switch (m_opt.type)
|
||||||
{
|
{
|
||||||
|
@ -168,7 +168,7 @@ public:
|
|||||||
bool set_undo_bitmap(const ScalableBitmap *bmp) {
|
bool set_undo_bitmap(const ScalableBitmap *bmp) {
|
||||||
if (m_undo_bitmap != bmp) {
|
if (m_undo_bitmap != bmp) {
|
||||||
m_undo_bitmap = bmp;
|
m_undo_bitmap = bmp;
|
||||||
m_Undo_btn->SetBitmap_(*bmp);
|
// m_Undo_btn->SetBitmap_(*bmp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -177,33 +177,33 @@ public:
|
|||||||
bool set_undo_to_sys_bitmap(const ScalableBitmap *bmp) {
|
bool set_undo_to_sys_bitmap(const ScalableBitmap *bmp) {
|
||||||
if (m_undo_to_sys_bitmap != bmp) {
|
if (m_undo_to_sys_bitmap != bmp) {
|
||||||
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool set_label_colour(const wxColour *clr) {
|
bool set_label_colour(const wxColour *clr) {
|
||||||
if (m_Label == nullptr) return false;
|
// if (m_Label == nullptr) return false;
|
||||||
if (m_label_color != clr) {
|
if (m_label_color != clr) {
|
||||||
m_label_color = clr;
|
m_label_color = clr;
|
||||||
m_Label->SetForegroundColour(*clr);
|
// m_Label->SetForegroundColour(*clr);
|
||||||
m_Label->Refresh(true);
|
// m_Label->Refresh(true);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool set_label_colour_force(const wxColour *clr) {
|
bool set_label_colour_force(const wxColour *clr) {
|
||||||
if (m_Label == nullptr) return false;
|
if (m_Label == nullptr) return false;
|
||||||
m_Label->SetForegroundColour(*clr);
|
// m_Label->SetForegroundColour(*clr);
|
||||||
m_Label->Refresh(true);
|
// m_Label->Refresh(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool set_undo_tooltip(const wxString *tip) {
|
bool set_undo_tooltip(const wxString *tip) {
|
||||||
if (m_undo_tooltip != tip) {
|
if (m_undo_tooltip != tip) {
|
||||||
m_undo_tooltip = tip;
|
m_undo_tooltip = tip;
|
||||||
m_Undo_btn->SetToolTip(*tip);
|
// m_Undo_btn->SetToolTip(*tip);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -212,7 +212,7 @@ public:
|
|||||||
bool set_undo_to_sys_tooltip(const wxString *tip) {
|
bool set_undo_to_sys_tooltip(const wxString *tip) {
|
||||||
if (m_undo_to_sys_tooltip != tip) {
|
if (m_undo_to_sys_tooltip != tip) {
|
||||||
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -235,6 +235,12 @@ public:
|
|||||||
|
|
||||||
BlinkingBitmap* blinking_bitmap() const { return m_blinking_bmp;}
|
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:
|
protected:
|
||||||
RevertButton* m_Undo_btn = nullptr;
|
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.
|
// 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 "ConfigExceptions.hpp"
|
||||||
#include "Plater.hpp"
|
#include "Plater.hpp"
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
|
#include "OG_CustomCtrl.hpp"
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <wx/numformatter.h>
|
#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)
|
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_btn->set_as_hidden();
|
||||||
field->m_Undo_to_sys_btn->set_as_hidden();
|
field->m_Undo_to_sys_btn->set_as_hidden();
|
||||||
field->m_blinking_bmp->Hide();
|
field->m_blinking_bmp->Hide();
|
||||||
@ -147,11 +148,14 @@ void OptionsGroup::append_line(const Line& line)
|
|||||||
|
|
||||||
void OptionsGroup::activate_line(Line& line)
|
void OptionsGroup::activate_line(Line& line)
|
||||||
{
|
{
|
||||||
|
m_use_custom_ctrl_as_parent = false;
|
||||||
|
|
||||||
if (line.full_width && (
|
if (line.full_width && (
|
||||||
line.widget != nullptr ||
|
line.widget != nullptr ||
|
||||||
!line.get_extra_widgets().empty())
|
!line.get_extra_widgets().empty())
|
||||||
) {
|
) {
|
||||||
if (line.widget != nullptr) {
|
if (line.widget != nullptr) {
|
||||||
|
// description lines
|
||||||
sizer->Add(line.widget(this->ctrl_parent()), 0, wxEXPAND | wxALL, wxOSX ? 0 : 15);
|
sizer->Add(line.widget(this->ctrl_parent()), 0, wxEXPAND | wxALL, wxOSX ? 0 : 15);
|
||||||
return;
|
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();
|
auto option_set = line.get_options();
|
||||||
|
|
||||||
// Set sidetext width for a better alignment of options in line
|
// 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.label.empty() &&
|
||||||
option_set.front().opt.sidetext.size() == 0 && option_set.front().side_widget == nullptr &&
|
option_set.front().opt.sidetext.size() == 0 && option_set.front().side_widget == nullptr &&
|
||||||
line.get_extra_widgets().size() == 0) {
|
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& option = option_set.front();
|
||||||
const auto& field = build_field(option);
|
const auto& field = build_field(option);
|
||||||
|
|
||||||
|
if (!custom_ctrl) {
|
||||||
auto btn_sizer = new wxBoxSizer(wxHORIZONTAL);
|
auto btn_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
add_undo_buttons_to_sizer(btn_sizer, field);
|
add_undo_buttons_to_sizer(btn_sizer, field);
|
||||||
tmp_sizer->Add(btn_sizer, 0, wxEXPAND | wxALL, 0);
|
sizer->Add(btn_sizer, 0, wxEXPAND | wxALL, 0);
|
||||||
|
}
|
||||||
if (is_window_field(field))
|
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))
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto grid_sizer = m_grid_sizer;
|
auto grid_sizer = m_grid_sizer;
|
||||||
#if 0//#ifdef __WXGTK__
|
|
||||||
m_panel->SetSizer(m_grid_sizer);
|
if (custom_ctrl)
|
||||||
m_panel->Layout();
|
m_use_custom_ctrl_as_parent = true;
|
||||||
#endif /* __WXGTK__ */
|
|
||||||
|
|
||||||
// if we have an extra column, build it
|
// 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));
|
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);
|
grid_sizer->Add(m_extra_column_item_ptrs.back(), 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 3);
|
||||||
@ -219,7 +221,16 @@ void OptionsGroup::activate_line(Line& line)
|
|||||||
// Build a label if we have it
|
// Build a label if we have it
|
||||||
wxStaticText* label=nullptr;
|
wxStaticText* label=nullptr;
|
||||||
if (label_width != 0) {
|
if (label_width != 0) {
|
||||||
if (! line.near_label_widget || ! line.label.IsEmpty()) {
|
if (custom_ctrl) {
|
||||||
|
if (line.near_label_widget) {
|
||||||
|
m_near_label_widget_ptrs.push_back(line.near_label_widget(this->ctrl_parent()));
|
||||||
|
|
||||||
|
wxPoint pos = custom_ctrl->get_pos(line);
|
||||||
|
m_near_label_widget_ptrs.back()->SetPosition(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!line.near_label_widget || !line.label.IsEmpty()) {
|
||||||
// Only create the label if it is going to be displayed.
|
// Only create the label if it is going to be displayed.
|
||||||
long label_style = staticbox ? 0 : wxALIGN_RIGHT;
|
long label_style = staticbox ? 0 : wxALIGN_RIGHT;
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
@ -232,7 +243,7 @@ void OptionsGroup::activate_line(Line& line)
|
|||||||
wxDefaultPosition, wxSize(label_width * wxGetApp().em_unit(), -1), label_style);
|
wxDefaultPosition, wxSize(label_width * wxGetApp().em_unit(), -1), label_style);
|
||||||
label->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
label->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||||
label->SetFont(wxGetApp().normal_font());
|
label->SetFont(wxGetApp().normal_font());
|
||||||
label->Wrap(label_width*wxGetApp().em_unit()); // avoid a Linux/GTK bug
|
label->Wrap(label_width * wxGetApp().em_unit()); // avoid a Linux/GTK bug
|
||||||
}
|
}
|
||||||
if (!line.near_label_widget)
|
if (!line.near_label_widget)
|
||||||
grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, line.label.IsEmpty() ? 0 : 5);
|
grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, line.label.IsEmpty() ? 0 : 5);
|
||||||
@ -253,13 +264,24 @@ void OptionsGroup::activate_line(Line& line)
|
|||||||
if (label != nullptr && line.label_tooltip != "")
|
if (label != nullptr && line.label_tooltip != "")
|
||||||
label->SetToolTip(line.label_tooltip);
|
label->SetToolTip(line.label_tooltip);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (line.full_Label != nullptr)
|
if (line.full_Label != nullptr)
|
||||||
*line.full_Label = label; // Initiate the pointer to the control of the full label, if we need this one.
|
*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 there's a widget, build it and add the result to the sizer.
|
||||||
if (line.widget != nullptr) {
|
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
|
// If widget doesn't have label, don't use border
|
||||||
|
else
|
||||||
grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, (wxOSX || line.label.IsEmpty()) ? 0 : 5);
|
grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, (wxOSX || line.label.IsEmpty()) ? 0 : 5);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -267,6 +289,7 @@ void OptionsGroup::activate_line(Line& line)
|
|||||||
// If we're here, we have more than one option or a single option with sidetext
|
// 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
|
// so we need a horizontal sizer to arrange these things
|
||||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
if (!custom_ctrl)
|
||||||
grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1);
|
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 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 &&
|
if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 &&
|
||||||
@ -275,12 +298,20 @@ void OptionsGroup::activate_line(Line& line)
|
|||||||
const auto& option = option_set.front();
|
const auto& option = option_set.front();
|
||||||
const auto& field = build_field(option, label);
|
const auto& field = build_field(option, label);
|
||||||
|
|
||||||
|
if (!custom_ctrl)
|
||||||
add_undo_buttons_to_sizer(sizer, field);
|
add_undo_buttons_to_sizer(sizer, field);
|
||||||
if (is_window_field(field))
|
if (is_window_field(field)) {
|
||||||
sizer->Add(field->getWindow(), option.opt.full_width ? 1 : 0, //(option.opt.full_width ? wxEXPAND : 0) |
|
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);
|
wxBOTTOM | wxTOP | (option.opt.full_width ? wxEXPAND : wxALIGN_CENTER_VERTICAL), (wxOSX || !staticbox) ? 0 : 2);
|
||||||
|
}
|
||||||
if (is_sizer_field(field))
|
if (is_sizer_field(field))
|
||||||
sizer->Add(field->getSizer(), 1, /*(*/option.opt.full_width ? wxEXPAND : /*0) |*/ wxALIGN_CENTER_VERTICAL, 0);
|
sizer->Add(field->getSizer(), 1, option.opt.full_width ? wxEXPAND : wxALIGN_CENTER_VERTICAL, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,7 +319,7 @@ void OptionsGroup::activate_line(Line& line)
|
|||||||
ConfigOptionDef option = opt.opt;
|
ConfigOptionDef option = opt.opt;
|
||||||
wxSizer* sizer_tmp = sizer;
|
wxSizer* sizer_tmp = sizer;
|
||||||
// add label if any
|
// 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
|
//! 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")) ?
|
wxString str_label = (option.label == L_CONTEXT("Top", "Layers") || option.label == L_CONTEXT("Bottom", "Layers")) ?
|
||||||
_CTX(option.label, "Layers") :
|
_CTX(option.label, "Layers") :
|
||||||
@ -303,22 +334,40 @@ void OptionsGroup::activate_line(Line& line)
|
|||||||
// add field
|
// add field
|
||||||
const Option& opt_ref = opt;
|
const Option& opt_ref = opt;
|
||||||
auto& field = build_field(opt_ref, label);
|
auto& field = build_field(opt_ref, label);
|
||||||
|
if (!custom_ctrl)
|
||||||
add_undo_buttons_to_sizer(sizer_tmp, field);
|
add_undo_buttons_to_sizer(sizer_tmp, field);
|
||||||
if (option_set.size() == 1 && option_set.front().opt.full_width)
|
if (option_set.size() == 1 && option_set.front().opt.full_width)
|
||||||
{
|
{
|
||||||
|
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);
|
const auto v_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
sizer_tmp->Add(v_sizer, 1, wxEXPAND);
|
sizer_tmp->Add(v_sizer, 1, wxEXPAND);
|
||||||
is_sizer_field(field) ?
|
is_sizer_field(field) ?
|
||||||
v_sizer->Add(field->getSizer(), 0, wxEXPAND) :
|
v_sizer->Add(field->getSizer(), 0, wxEXPAND) :
|
||||||
v_sizer->Add(field->getWindow(), 0, wxEXPAND);
|
v_sizer->Add(field->getWindow(), 0, wxEXPAND);
|
||||||
|
}
|
||||||
break;//return;
|
break;//return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (custom_ctrl) {
|
||||||
|
if (is_window_field(field))
|
||||||
|
field->getWindow()->SetPosition(custom_ctrl->get_pos(line, field.get()));
|
||||||
|
else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
is_sizer_field(field) ?
|
is_sizer_field(field) ?
|
||||||
sizer_tmp->Add(field->getSizer(), 0, wxALIGN_CENTER_VERTICAL, 0) :
|
sizer_tmp->Add(field->getSizer(), 0, wxALIGN_CENTER_VERTICAL, 0) :
|
||||||
sizer_tmp->Add(field->getWindow(), 0, wxALIGN_CENTER_VERTICAL, 0);
|
sizer_tmp->Add(field->getWindow(), 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// add sidetext if any
|
// add sidetext if any
|
||||||
|
if (!custom_ctrl)
|
||||||
if (!option.sidetext.empty() || sidetext_width > 0) {
|
if (!option.sidetext.empty() || sidetext_width > 0) {
|
||||||
auto sidetext = new wxStaticText( this->ctrl_parent(), wxID_ANY, _(option.sidetext), wxDefaultPosition,
|
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);
|
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
|
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())
|
if (opt.opt_id != option_set.back().opt_id) //! istead of (opt != option_set.back())
|
||||||
{
|
{
|
||||||
sizer_tmp->AddSpacer(6);
|
sizer_tmp->AddSpacer(6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (custom_ctrl)
|
||||||
|
return;
|
||||||
|
|
||||||
// add extra sizers if any
|
// add extra sizers if any
|
||||||
for (auto extra_widget : line.get_extra_widgets())
|
for (auto extra_widget : line.get_extra_widgets())
|
||||||
{
|
{
|
||||||
@ -417,6 +473,15 @@ void OptionsGroup::clear()
|
|||||||
if(line.full_Label)
|
if(line.full_Label)
|
||||||
*line.full_Label = nullptr;
|
*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_extra_column_item_ptrs.clear();
|
||||||
m_near_label_widget_ptrs.clear();
|
m_near_label_widget_ptrs.clear();
|
||||||
m_fields.clear();
|
m_fields.clear();
|
||||||
|
@ -26,6 +26,7 @@ namespace Slic3r { namespace GUI {
|
|||||||
|
|
||||||
// Thrown if the building of a parameter page is canceled.
|
// Thrown if the building of a parameter page is canceled.
|
||||||
class UIBuildCanceled : public std::exception {};
|
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).
|
/// 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*)>;
|
using widget_t = std::function<wxSizer*(wxWindow*)>;//!std::function<wxWindow*(wxWindow*)>;
|
||||||
@ -52,6 +53,7 @@ public:
|
|||||||
wxString label_tooltip {wxString("")};
|
wxString label_tooltip {wxString("")};
|
||||||
size_t full_width {0};
|
size_t full_width {0};
|
||||||
wxStaticText** full_Label {nullptr};
|
wxStaticText** full_Label {nullptr};
|
||||||
|
wxColor* full_Label_color {nullptr};
|
||||||
widget_t widget {nullptr};
|
widget_t widget {nullptr};
|
||||||
std::function<wxWindow*(wxWindow*)> near_label_widget{ nullptr };
|
std::function<wxWindow*(wxWindow*)> near_label_widget{ nullptr };
|
||||||
|
|
||||||
@ -84,6 +86,7 @@ public:
|
|||||||
const wxString title;
|
const wxString title;
|
||||||
size_t label_width = 20 ;// {200};
|
size_t label_width = 20 ;// {200};
|
||||||
wxSizer* sizer {nullptr};
|
wxSizer* sizer {nullptr};
|
||||||
|
OG_CustomCtrl* custom_ctrl{ nullptr };
|
||||||
column_t extra_column {nullptr};
|
column_t extra_column {nullptr};
|
||||||
t_change m_on_change { nullptr };
|
t_change m_on_change { nullptr };
|
||||||
// To be called when the field loses focus, to assign a new initial value to the field.
|
// To be called when the field loses focus, to assign a new initial value to the field.
|
||||||
@ -119,7 +122,7 @@ public:
|
|||||||
#endif /* __WXGTK__ */
|
#endif /* __WXGTK__ */
|
||||||
|
|
||||||
wxWindow* ctrl_parent() const {
|
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);
|
void append_line(const Line& line);
|
||||||
@ -188,6 +191,8 @@ public:
|
|||||||
|
|
||||||
wxGridSizer* get_grid_sizer() { return m_grid_sizer; }
|
wxGridSizer* get_grid_sizer() { return m_grid_sizer; }
|
||||||
|
|
||||||
|
const std::vector<Line>& get_lines() { return m_lines; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::map<t_config_option_key, Option> m_options;
|
std::map<t_config_option_key, Option> m_options;
|
||||||
wxWindow* m_parent {nullptr};
|
wxWindow* m_parent {nullptr};
|
||||||
@ -206,6 +211,9 @@ protected:
|
|||||||
// "true" if option is created in preset tabs
|
// "true" if option is created in preset tabs
|
||||||
bool m_show_modified_btns{ false };
|
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
|
// 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
|
// Tooltips on GTK doesn't work inside wxStaticBoxSizer unless you insert a panel
|
||||||
// inside it before you insert the other controls.
|
// inside it before you insert the other controls.
|
||||||
|
@ -348,6 +348,8 @@ public:
|
|||||||
void activate();
|
void activate();
|
||||||
void blink();
|
void blink();
|
||||||
|
|
||||||
|
const wxBitmap& get_bmp() const { return bmp.bmp(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ScalableBitmap bmp;
|
ScalableBitmap bmp;
|
||||||
bool show {false};
|
bool show {false};
|
||||||
|
Loading…
Reference in New Issue
Block a user