mirror of
https://github.com/QIDITECH/QIDISlicer.git
synced 2026-02-01 16:38:43 +03:00
PRUSA 2.7.0
This commit is contained in:
47
src/slic3r/GUI/Widgets/BitmapToggleButton.cpp
Normal file
47
src/slic3r/GUI/Widgets/BitmapToggleButton.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "BitmapToggleButton.hpp"
|
||||
|
||||
#include <wx/settings.h>
|
||||
|
||||
BitmapToggleButton::BitmapToggleButton(wxWindow* parent, const wxString& label, wxWindowID id)
|
||||
{
|
||||
const long style = wxBORDER_NONE | wxBU_EXACTFIT | wxBU_LEFT;
|
||||
if (label.IsEmpty())
|
||||
wxBitmapToggleButton::Create(parent, id, wxNullBitmap, wxDefaultPosition, wxDefaultSize, style);
|
||||
else {
|
||||
#ifdef __WXGTK3__
|
||||
wxSize label_size = parent->GetTextExtent(label);
|
||||
wxSize def_size = wxSize(label_size.GetX() + 20, label_size.GetY());
|
||||
#else
|
||||
wxSize def_size = wxDefaultSize;
|
||||
#endif
|
||||
// Call Create() from wxToggleButton instead of wxBitmapToggleButton to allow add Label text under Linux
|
||||
wxToggleButton::Create(parent, id, label, wxDefaultPosition, def_size, style);
|
||||
}
|
||||
|
||||
#ifdef __WXMSW__
|
||||
if (parent) {
|
||||
SetBackgroundColour(parent->GetBackgroundColour());
|
||||
SetForegroundColour(parent->GetForegroundColour());
|
||||
}
|
||||
#elif __WXGTK3__
|
||||
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
#endif
|
||||
|
||||
Bind(wxEVT_TOGGLEBUTTON, [this](auto& e) {
|
||||
update();
|
||||
|
||||
wxCommandEvent evt(wxEVT_CHECKBOX);
|
||||
evt.SetInt(int(GetValue()));
|
||||
wxPostEvent(this, evt);
|
||||
|
||||
e.Skip();
|
||||
});
|
||||
}
|
||||
|
||||
void BitmapToggleButton::update_size()
|
||||
{
|
||||
#ifndef __WXGTK3__
|
||||
wxSize best_sz = GetBestSize();
|
||||
SetSize(best_sz);
|
||||
#endif
|
||||
}
|
||||
17
src/slic3r/GUI/Widgets/BitmapToggleButton.hpp
Normal file
17
src/slic3r/GUI/Widgets/BitmapToggleButton.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef slic3r_GUI_BitmapToggleButton_hpp_
|
||||
#define slic3r_GUI_BitmapToggleButton_hpp_
|
||||
|
||||
#include <wx/tglbtn.h>
|
||||
|
||||
class BitmapToggleButton : public wxBitmapToggleButton
|
||||
{
|
||||
virtual void update() = 0;
|
||||
|
||||
public:
|
||||
BitmapToggleButton(wxWindow * parent = NULL, const wxString& label = wxEmptyString, wxWindowID id = wxID_ANY);
|
||||
|
||||
protected:
|
||||
void update_size();
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_BitmapToggleButton_hpp_
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "Button.hpp"
|
||||
#include "Label.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
#include <wx/dc.h>
|
||||
#include <wx/dcclient.h>
|
||||
|
||||
BEGIN_EVENT_TABLE(Button, StaticBox)
|
||||
|
||||
@@ -26,9 +27,9 @@ Button::Button()
|
||||
: paddingSize(10, 8)
|
||||
{
|
||||
background_color = StateColor(
|
||||
std::make_pair(0xF0F0F1, (int) StateColor::Disabled),
|
||||
std::make_pair(0x52c7b8, (int) StateColor::Hovered | StateColor::Checked),
|
||||
std::make_pair(0x009688, (int) StateColor::Checked),
|
||||
std::make_pair(0xF0F0F0, (int) StateColor::Disabled),
|
||||
std::make_pair(0x37EE7C, (int) StateColor::Hovered | StateColor::Checked),
|
||||
std::make_pair(0x00AE42, (int) StateColor::Checked),
|
||||
std::make_pair(*wxLIGHT_GREY, (int) StateColor::Hovered),
|
||||
std::make_pair(*wxWHITE, (int) StateColor::Normal));
|
||||
text_color = StateColor(
|
||||
@@ -36,23 +37,20 @@ Button::Button()
|
||||
std::make_pair(*wxBLACK, (int) StateColor::Normal));
|
||||
}
|
||||
|
||||
Button::Button(wxWindow* parent, wxString text, wxString icon, long style, int iconSize, wxWindowID btn_id)
|
||||
Button::Button(wxWindow* parent, wxString text, wxString icon, long style, wxSize iconSize/* = wxSize(16, 16)*/)
|
||||
: Button()
|
||||
{
|
||||
Create(parent, text, icon, style, iconSize, btn_id);
|
||||
Create(parent, text, icon, style, iconSize);
|
||||
}
|
||||
|
||||
bool Button::Create(wxWindow* parent, wxString text, wxString icon, long style, int iconSize, wxWindowID btn_id)
|
||||
bool Button::Create(wxWindow* parent, wxString text, wxString icon, long style, wxSize iconSize/* = wxSize(16, 16)*/)
|
||||
{
|
||||
StaticBox::Create(parent, btn_id, wxDefaultPosition, wxDefaultSize, style);
|
||||
StaticBox::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style);
|
||||
state_handler.attach({&text_color});
|
||||
state_handler.update_binds();
|
||||
//BBS set default font
|
||||
SetFont(Label::Body_14);
|
||||
wxWindow::SetLabel(text);
|
||||
if (!icon.IsEmpty()) {
|
||||
//BBS set button icon default size to 20
|
||||
this->active_icon = ScalableBitmap(this, icon.ToStdString(), iconSize > 0 ? iconSize : 20);
|
||||
this->active_icon = ScalableBitmap(this, icon.ToStdString(), iconSize);
|
||||
}
|
||||
messureSize();
|
||||
return true;
|
||||
@@ -65,19 +63,11 @@ void Button::SetLabel(const wxString& label)
|
||||
Refresh();
|
||||
}
|
||||
|
||||
bool Button::SetFont(const wxFont& font)
|
||||
{
|
||||
wxWindow::SetFont(font);
|
||||
messureSize();
|
||||
Refresh();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Button::SetIcon(const wxString& icon)
|
||||
{
|
||||
if (!icon.IsEmpty()) {
|
||||
//BBS set button icon default size to 20
|
||||
this->active_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_cnt());
|
||||
this->active_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_size());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -89,8 +79,7 @@ void Button::SetIcon(const wxString& icon)
|
||||
void Button::SetInactiveIcon(const wxString &icon)
|
||||
{
|
||||
if (!icon.IsEmpty()) {
|
||||
// BBS set button icon default size to 20
|
||||
this->inactive_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_cnt());
|
||||
this->inactive_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_size());
|
||||
} else {
|
||||
this->inactive_icon = ScalableBitmap();
|
||||
}
|
||||
@@ -135,22 +124,16 @@ bool Button::Enable(bool enable)
|
||||
|
||||
void Button::SetCanFocus(bool canFocus) { this->canFocus = canFocus; }
|
||||
|
||||
void Button::SetValue(bool state)
|
||||
{
|
||||
if (GetValue() == state) return;
|
||||
state_handler.set_state(state ? StateHandler::Checked : 0, StateHandler::Checked);
|
||||
}
|
||||
|
||||
bool Button::GetValue() const { return state_handler.states() & StateHandler::Checked; }
|
||||
|
||||
void Button::Rescale()
|
||||
{
|
||||
if (this->active_icon.get_bitmap().IsOk())
|
||||
/* if (this->active_icon.bmp().IsOk())
|
||||
this->active_icon.msw_rescale();
|
||||
|
||||
if (this->inactive_icon.get_bitmap().IsOk())
|
||||
if (this->inactive_icon.bmp().IsOk())
|
||||
this->inactive_icon.msw_rescale();
|
||||
|
||||
*/
|
||||
messureSize();
|
||||
}
|
||||
|
||||
@@ -174,15 +157,16 @@ void Button::render(wxDC& dc)
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
// calc content size
|
||||
wxSize szIcon;
|
||||
wxSize szContent = textSize.GetSize();
|
||||
wxSize szContent = textSize;
|
||||
|
||||
ScalableBitmap icon;
|
||||
if (m_selected || ((states & (int)StateColor::State::Hovered) != 0))
|
||||
// if (m_selected || (states & (int)StateColor::State::Hovered))
|
||||
icon = active_icon;
|
||||
else
|
||||
icon = inactive_icon;
|
||||
int padding = 5;
|
||||
if (icon.get_bitmap().IsOk()) {
|
||||
if (icon.bmp().IsOk()) {
|
||||
if (szContent.y > 0) {
|
||||
//BBS norrow size between text and icon
|
||||
szContent.x += padding;
|
||||
@@ -204,7 +188,7 @@ void Button::render(wxDC& dc)
|
||||
rcContent.Deflate(offset.x, offset.y);
|
||||
// start draw
|
||||
wxPoint pt = rcContent.GetLeftTop();
|
||||
if (icon.get_bitmap().IsOk()) {
|
||||
if (icon.bmp().IsOk()) {
|
||||
pt.y += (rcContent.height - szIcon.y) / 2;
|
||||
dc.DrawBitmap(icon.get_bitmap(), pt);
|
||||
//BBS norrow size between text and icon
|
||||
@@ -213,18 +197,11 @@ void Button::render(wxDC& dc)
|
||||
}
|
||||
auto text = GetLabel();
|
||||
if (!text.IsEmpty()) {
|
||||
if (pt.x + textSize.width > size.x)
|
||||
if (pt.x + textSize.x > size.x)
|
||||
text = wxControl::Ellipsize(text, dc, wxELLIPSIZE_END, size.x - pt.x);
|
||||
pt.y += (rcContent.height - textSize.height) / 2;
|
||||
pt.y += (rcContent.height - textSize.y) / 2;
|
||||
dc.SetFont(GetFont());
|
||||
dc.SetTextForeground(text_color.colorForStates(states));
|
||||
#if 0
|
||||
dc.SetBrush(*wxLIGHT_GREY);
|
||||
dc.SetPen(wxPen(*wxLIGHT_GREY));
|
||||
dc.DrawRectangle(pt, textSize.GetSize());
|
||||
#endif
|
||||
#ifdef __WXOSX__
|
||||
pt.y -= textSize.x / 2;
|
||||
#endif
|
||||
dc.DrawText(text, pt);
|
||||
}
|
||||
}
|
||||
@@ -232,9 +209,13 @@ void Button::render(wxDC& dc)
|
||||
void Button::messureSize()
|
||||
{
|
||||
wxClientDC dc(this);
|
||||
dc.GetTextExtent(GetLabel(), &textSize.width, &textSize.height, &textSize.x, &textSize.y);
|
||||
wxSize szContent = textSize.GetSize();
|
||||
if (this->active_icon.get_bitmap().IsOk()) {
|
||||
textSize = dc.GetTextExtent(GetLabel());
|
||||
if (minSize.GetWidth() > 0) {
|
||||
wxWindow::SetMinSize(minSize);
|
||||
return;
|
||||
}
|
||||
wxSize szContent = textSize;
|
||||
if (this->active_icon.bmp().IsOk()) {
|
||||
if (szContent.y > 0) {
|
||||
//BBS norrow size between text and icon
|
||||
szContent.x += 5;
|
||||
@@ -248,9 +229,6 @@ void Button::messureSize()
|
||||
if (minSize.GetHeight() > 0)
|
||||
size.SetHeight(minSize.GetHeight());
|
||||
|
||||
if (minSize.GetWidth() > size.GetWidth())
|
||||
wxWindow::SetMinSize(minSize);
|
||||
else
|
||||
wxWindow::SetMinSize(size);
|
||||
}
|
||||
|
||||
@@ -260,7 +238,6 @@ void Button::mouseDown(wxMouseEvent& event)
|
||||
pressedDown = true;
|
||||
if (canFocus)
|
||||
SetFocus();
|
||||
if (!HasCapture())
|
||||
CaptureMouse();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
class Button : public StaticBox
|
||||
{
|
||||
wxRect textSize;
|
||||
wxSize textSize;
|
||||
wxSize minSize; // set by outer
|
||||
wxSize paddingSize;
|
||||
ScalableBitmap active_icon;
|
||||
@@ -24,13 +24,12 @@ class Button : public StaticBox
|
||||
public:
|
||||
Button();
|
||||
|
||||
Button(wxWindow* parent, wxString text, wxString icon = "", long style = 0, int iconSize = 0, wxWindowID btn_id = wxID_ANY);
|
||||
Button(wxWindow* parent, wxString text, wxString icon = "", long style = 0, wxSize iconSize = wxSize(16, 16));
|
||||
|
||||
bool Create(wxWindow* parent, wxString text, wxString icon = "", long style = 0, int iconSize = 0, wxWindowID btn_id = wxID_ANY);
|
||||
bool Create(wxWindow* parent, wxString text, wxString icon = "", long style = 0, wxSize iconSize = wxSize(16, 16));
|
||||
|
||||
void SetLabel(const wxString& label) override;
|
||||
|
||||
bool SetFont(const wxFont& font) override;
|
||||
|
||||
void SetIcon(const wxString& icon);
|
||||
|
||||
@@ -50,9 +49,6 @@ public:
|
||||
|
||||
void SetCanFocus(bool canFocus) override;
|
||||
|
||||
void SetValue(bool state);
|
||||
|
||||
bool GetValue() const;
|
||||
|
||||
void Rescale();
|
||||
|
||||
|
||||
119
src/slic3r/GUI/Widgets/CheckBox.cpp
Normal file
119
src/slic3r/GUI/Widgets/CheckBox.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
#include "CheckBox.hpp"
|
||||
|
||||
//#include "../wxExtensions.hpp"
|
||||
|
||||
const int px_cnt = 16;
|
||||
|
||||
CheckBox::CheckBox(wxWindow* parent, const wxString& name)
|
||||
: BitmapToggleButton(parent, name, wxID_ANY)
|
||||
, m_on(this, "check_on", px_cnt)
|
||||
, m_off(this, "check_off", px_cnt)
|
||||
, m_on_disabled(this, "check_on_disabled", px_cnt)
|
||||
, m_off_disabled(this, "check_off_disabled", px_cnt)
|
||||
, m_on_focused(this, "check_on_focused", px_cnt)
|
||||
, m_off_focused(this, "check_off_focused", px_cnt)
|
||||
{
|
||||
#ifdef __WXOSX__ // State not fully implement on MacOS
|
||||
Bind(wxEVT_SET_FOCUS, &CheckBox::updateBitmap, this);
|
||||
Bind(wxEVT_KILL_FOCUS, &CheckBox::updateBitmap, this);
|
||||
Bind(wxEVT_ENTER_WINDOW, &CheckBox::updateBitmap, this);
|
||||
Bind(wxEVT_LEAVE_WINDOW, &CheckBox::updateBitmap, this);
|
||||
#endif
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void CheckBox::SetValue(bool value)
|
||||
{
|
||||
wxBitmapToggleButton::SetValue(value);
|
||||
update();
|
||||
}
|
||||
|
||||
void CheckBox::Update()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void CheckBox::Rescale()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void CheckBox::update()
|
||||
{
|
||||
const bool val = GetValue();
|
||||
const wxBitmapBundle& bmp = (val ? m_on : m_off).bmp();
|
||||
SetBitmap(bmp);
|
||||
SetBitmapCurrent(bmp);
|
||||
SetBitmapDisabled((val ? m_on_disabled : m_off_disabled).bmp());
|
||||
#ifdef __WXMSW__
|
||||
SetBitmapFocus((val ? m_on_focused : m_off_focused).bmp());
|
||||
#endif
|
||||
#ifdef __WXOSX__
|
||||
wxCommandEvent e(wxEVT_UPDATE_UI);
|
||||
updateBitmap(e);
|
||||
#endif
|
||||
|
||||
if (GetBitmapMargins().GetWidth() == 0 && !GetLabelText().IsEmpty())
|
||||
SetBitmapMargins(4, 0);
|
||||
update_size();
|
||||
}
|
||||
|
||||
#ifdef __WXMSW__
|
||||
|
||||
CheckBox::State CheckBox::GetNormalState() const
|
||||
{
|
||||
return State_Normal;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool CheckBox::Enable(bool enable)
|
||||
{
|
||||
bool result = wxBitmapToggleButton::Enable(enable);
|
||||
|
||||
#ifdef __WXOSX__
|
||||
if (result) {
|
||||
m_disable = !enable;
|
||||
wxCommandEvent e(wxEVT_ACTIVATE);
|
||||
updateBitmap(e);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef __WXOSX__
|
||||
|
||||
wxBitmap CheckBox::DoGetBitmap(State which) const
|
||||
{
|
||||
if (m_disable) {
|
||||
return wxBitmapToggleButton::DoGetBitmap(State_Disabled);
|
||||
}
|
||||
if (m_focus) {
|
||||
return wxBitmapToggleButton::DoGetBitmap(State_Current);
|
||||
}
|
||||
return wxBitmapToggleButton::DoGetBitmap(which);
|
||||
}
|
||||
|
||||
void CheckBox::updateBitmap(wxEvent & evt)
|
||||
{
|
||||
evt.Skip();
|
||||
if (evt.GetEventType() == wxEVT_ENTER_WINDOW) {
|
||||
m_hover = true;
|
||||
} else if (evt.GetEventType() == wxEVT_LEAVE_WINDOW) {
|
||||
m_hover = false;
|
||||
} else {
|
||||
if (evt.GetEventType() == wxEVT_SET_FOCUS) {
|
||||
m_focus = true;
|
||||
} else if (evt.GetEventType() == wxEVT_KILL_FOCUS) {
|
||||
m_focus = false;
|
||||
}
|
||||
wxMouseEvent e;
|
||||
if (m_hover)
|
||||
OnEnterWindow(e);
|
||||
else
|
||||
OnLeaveWindow(e);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
45
src/slic3r/GUI/Widgets/CheckBox.hpp
Normal file
45
src/slic3r/GUI/Widgets/CheckBox.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef slic3r_GUI_CheckBox_hpp_
|
||||
#define slic3r_GUI_CheckBox_hpp_
|
||||
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "BitmapToggleButton.hpp"
|
||||
|
||||
class CheckBox : public BitmapToggleButton
|
||||
{
|
||||
public:
|
||||
CheckBox(wxWindow* parent = NULL, const wxString& name = wxEmptyString);
|
||||
|
||||
public:
|
||||
void SetValue(bool value) override;
|
||||
void Update() override;
|
||||
bool Enable(bool enable = true) override;
|
||||
|
||||
void Rescale();
|
||||
|
||||
protected:
|
||||
#ifdef __WXMSW__
|
||||
virtual State GetNormalState() const wxOVERRIDE;
|
||||
#endif
|
||||
|
||||
#ifdef __WXOSX__
|
||||
virtual wxBitmap DoGetBitmap(State which) const wxOVERRIDE;
|
||||
|
||||
void updateBitmap(wxEvent & evt);
|
||||
|
||||
bool m_disable = false;
|
||||
bool m_hover = false;
|
||||
bool m_focus = false;
|
||||
#endif
|
||||
|
||||
private:
|
||||
void update() override;
|
||||
|
||||
ScalableBitmap m_on;
|
||||
ScalableBitmap m_off;
|
||||
ScalableBitmap m_on_disabled;
|
||||
ScalableBitmap m_off_disabled;
|
||||
ScalableBitmap m_on_focused;
|
||||
ScalableBitmap m_off_focused;
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_CheckBox_hpp_
|
||||
@@ -1,13 +1,13 @@
|
||||
#include "ComboBox.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "UIColors.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
#include "../GUI_App.hpp"
|
||||
BEGIN_EVENT_TABLE(ComboBox, TextInput)
|
||||
|
||||
EVT_LEFT_DOWN(ComboBox::mouseDown)
|
||||
EVT_LEFT_DCLICK(ComboBox::mouseDown)
|
||||
//EVT_MOUSEWHEEL(ComboBox::mouseWheelMoved)
|
||||
EVT_MOUSEWHEEL(ComboBox::mouseWheelMoved)
|
||||
EVT_KEY_DOWN(ComboBox::keyDown)
|
||||
|
||||
// catch paint events
|
||||
@@ -29,26 +29,20 @@ ComboBox::ComboBox(wxWindow * parent,
|
||||
long style)
|
||||
: drop(texts, icons)
|
||||
{
|
||||
if (style & wxCB_READONLY)
|
||||
style |= wxRIGHT;
|
||||
text_off = style & CB_NO_TEXT;
|
||||
TextInput::Create(parent, "", value, (style & CB_NO_DROP_ICON) ? "" : "drop_down", pos, size,
|
||||
style | wxTE_PROCESS_ENTER);
|
||||
drop.Create(this, style & DD_STYLE_MASK);
|
||||
drop.Create(this, style);
|
||||
|
||||
if (style & wxCB_READONLY) {
|
||||
SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
if (style & wxCB_READONLY)
|
||||
GetTextCtrl()->Hide();
|
||||
TextInput::SetFont(Label::Body_14);
|
||||
TextInput::SetBorderColor(StateColor(std::make_pair(0xDBDBDB, (int) StateColor::Disabled),
|
||||
std::make_pair(0x009688, (int) StateColor::Hovered),
|
||||
std::make_pair(0xDBDBDB, (int) StateColor::Normal)));
|
||||
TextInput::SetBackgroundColor(StateColor(std::make_pair(0xF0F0F1, (int) StateColor::Disabled),
|
||||
std::make_pair(0xEDFAF2, (int) StateColor::Focused),
|
||||
std::make_pair(*wxWHITE, (int) StateColor::Normal)));
|
||||
TextInput::SetLabelColor(StateColor(std::make_pair(0x909090, (int) StateColor::Disabled),
|
||||
std::make_pair(0x262E30, (int) StateColor::Normal)));
|
||||
} else {
|
||||
else
|
||||
GetTextCtrl()->Bind(wxEVT_KEY_DOWN, &ComboBox::keyDown, this);
|
||||
SetBorderColor(TextInput::GetBorderColor());
|
||||
if (parent) {
|
||||
SetBackgroundColour(parent->GetBackgroundColour());
|
||||
SetForegroundColour(parent->GetForegroundColour());
|
||||
}
|
||||
drop.Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &e) {
|
||||
SetSelection(e.GetInt());
|
||||
@@ -61,10 +55,20 @@ ComboBox::ComboBox(wxWindow * parent,
|
||||
wxCommandEvent e(wxEVT_COMBOBOX_CLOSEUP);
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
});
|
||||
#ifndef _WIN32
|
||||
this->Bind(wxEVT_SYS_COLOUR_CHANGED, [this, parent](wxSysColourChangedEvent& event) {
|
||||
event.Skip();
|
||||
SetBackgroundColour(parent->GetBackgroundColour());
|
||||
SetForegroundColour(parent->GetForegroundColour());
|
||||
});
|
||||
#endif
|
||||
for (int i = 0; i < n; ++i) Append(choices[i]);
|
||||
}
|
||||
|
||||
int ComboBox::GetSelection() const { return drop.GetSelection(); }
|
||||
int ComboBox::GetSelection() const
|
||||
{
|
||||
return drop.GetSelection();
|
||||
}
|
||||
|
||||
void ComboBox::SetSelection(int n)
|
||||
{
|
||||
@@ -74,14 +78,11 @@ void ComboBox::SetSelection(int n)
|
||||
SetIcon(icons[drop.selection]);
|
||||
}
|
||||
|
||||
void ComboBox::SelectAndNotify(int n) {
|
||||
SetSelection(n);
|
||||
sendComboBoxEvent();
|
||||
}
|
||||
|
||||
|
||||
void ComboBox::Rescale()
|
||||
{
|
||||
SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
TextInput::Rescale();
|
||||
drop.Rescale();
|
||||
}
|
||||
@@ -127,19 +128,52 @@ wxString ComboBox::GetTextLabel() const
|
||||
|
||||
bool ComboBox::SetFont(wxFont const& font)
|
||||
{
|
||||
const bool set_drop_font = drop.SetFont(font);
|
||||
if (GetTextCtrl() && GetTextCtrl()->IsShown())
|
||||
return GetTextCtrl()->SetFont(font);
|
||||
else
|
||||
return TextInput::SetFont(font);
|
||||
return GetTextCtrl()->SetFont(font) && set_drop_font;
|
||||
return TextInput::SetFont(font) && set_drop_font;
|
||||
}
|
||||
|
||||
int ComboBox::Append(const wxString &item, const wxBitmap &bitmap)
|
||||
bool ComboBox::SetBackgroundColour(const wxColour& colour)
|
||||
{
|
||||
TextInput::SetBackgroundColour(colour);
|
||||
|
||||
drop.SetBackgroundColour(colour);
|
||||
StateColor selector_colors( std::make_pair(clr_background_focused, (int)StateColor::Checked),
|
||||
Slic3r::GUI::wxGetApp().dark_mode() ?
|
||||
std::make_pair(clr_background_disabled_dark, (int)StateColor::Disabled) :
|
||||
std::make_pair(clr_background_disabled_light, (int)StateColor::Disabled),
|
||||
Slic3r::GUI::wxGetApp().dark_mode() ?
|
||||
std::make_pair(clr_background_normal_dark, (int)StateColor::Normal) :
|
||||
std::make_pair(clr_background_normal_light, (int)StateColor::Normal));
|
||||
drop.SetSelectorBackgroundColor(selector_colors);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ComboBox::SetForegroundColour(const wxColour& colour)
|
||||
{
|
||||
TextInput::SetForegroundColour(colour);
|
||||
|
||||
drop.SetTextColor(TextInput::GetTextColor());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ComboBox::SetBorderColor(StateColor const& color)
|
||||
{
|
||||
TextInput::SetBorderColor(color);
|
||||
drop.SetBorderColor(color);
|
||||
drop.SetSelectorBorderColor(color);
|
||||
}
|
||||
|
||||
int ComboBox::Append(const wxString &item, const wxBitmapBundle &bitmap)
|
||||
{
|
||||
return Append(item, bitmap, nullptr);
|
||||
}
|
||||
|
||||
int ComboBox::Append(const wxString &item,
|
||||
const wxBitmap &bitmap,
|
||||
const wxBitmapBundle &bitmap,
|
||||
void * clientData)
|
||||
{
|
||||
texts.push_back(item);
|
||||
@@ -147,7 +181,23 @@ int ComboBox::Append(const wxString &item,
|
||||
datas.push_back(clientData);
|
||||
types.push_back(wxClientData_None);
|
||||
drop.Invalidate();
|
||||
return texts.size() - 1;
|
||||
return int(texts.size()) - 1;
|
||||
}
|
||||
|
||||
int ComboBox::Insert(const wxString& item,
|
||||
const wxBitmapBundle& bitmap,
|
||||
unsigned int pos)
|
||||
{
|
||||
return Insert(item, bitmap, pos, nullptr);
|
||||
}
|
||||
|
||||
int ComboBox::Insert(const wxString& item, const wxBitmapBundle& bitmap,
|
||||
unsigned int pos, void* clientData)
|
||||
{
|
||||
const int n = wxItemContainer::Insert(item, pos, clientData);
|
||||
if (n != wxNOT_FOUND)
|
||||
icons[n] = bitmap;
|
||||
return n;
|
||||
}
|
||||
|
||||
void ComboBox::DoClear()
|
||||
@@ -157,6 +207,8 @@ void ComboBox::DoClear()
|
||||
datas.clear();
|
||||
types.clear();
|
||||
drop.Invalidate(true);
|
||||
if (GetTextCtrl()->IsShown() || text_off)
|
||||
GetTextCtrl()->Clear();
|
||||
}
|
||||
|
||||
void ComboBox::DoDeleteOneItem(unsigned int pos)
|
||||
@@ -166,7 +218,9 @@ void ComboBox::DoDeleteOneItem(unsigned int pos)
|
||||
icons.erase(icons.begin() + pos);
|
||||
datas.erase(datas.begin() + pos);
|
||||
types.erase(types.begin() + pos);
|
||||
const int selection = drop.GetSelection();
|
||||
drop.Invalidate(true);
|
||||
drop.SetSelection(selection);
|
||||
}
|
||||
|
||||
unsigned int ComboBox::GetCount() const { return texts.size(); }
|
||||
@@ -181,16 +235,17 @@ void ComboBox::SetString(unsigned int n, wxString const &value)
|
||||
if (n >= texts.size()) return;
|
||||
texts[n] = value;
|
||||
drop.Invalidate();
|
||||
if (n == drop.GetSelection()) SetLabel(value);
|
||||
if (int(n) == drop.GetSelection()) SetLabel(value);
|
||||
}
|
||||
|
||||
wxBitmap ComboBox::GetItemBitmap(unsigned int n) { return icons[n]; }
|
||||
|
||||
void ComboBox::SetItemBitmap(unsigned int n, wxBitmap const &bitmap)
|
||||
wxBitmap ComboBox::GetItemBitmap(unsigned int n)
|
||||
{
|
||||
if (n >= texts.size()) return;
|
||||
icons[n] = bitmap;
|
||||
drop.Invalidate();
|
||||
return icons[n].GetBitmapFor(m_parent);
|
||||
}
|
||||
|
||||
void ComboBox::OnKeyDown(wxKeyEvent &event)
|
||||
{
|
||||
keyDown(event);
|
||||
}
|
||||
|
||||
int ComboBox::DoInsertItems(const wxArrayStringsAdapter &items,
|
||||
@@ -199,15 +254,17 @@ int ComboBox::DoInsertItems(const wxArrayStringsAdapter &items,
|
||||
wxClientDataType type)
|
||||
{
|
||||
if (pos > texts.size()) return -1;
|
||||
for (int i = 0; i < items.GetCount(); ++i) {
|
||||
for (size_t i = 0; i < items.GetCount(); ++i) {
|
||||
texts.insert(texts.begin() + pos, items[i]);
|
||||
icons.insert(icons.begin() + pos, wxNullBitmap);
|
||||
datas.insert(datas.begin() + pos, clientData ? clientData[i] : NULL);
|
||||
types.insert(types.begin() + pos, type);
|
||||
++pos;
|
||||
}
|
||||
const int selection = drop.GetSelection();
|
||||
drop.Invalidate(true);
|
||||
return pos - 1;
|
||||
drop.SetSelection(selection);
|
||||
return int(pos) - 1;
|
||||
}
|
||||
|
||||
void *ComboBox::DoGetItemClientData(unsigned int n) const { return n < texts.size() ? datas[n] : NULL; }
|
||||
@@ -226,7 +283,7 @@ void ComboBox::mouseDown(wxMouseEvent &event)
|
||||
} else if (drop.HasDismissLongTime()) {
|
||||
drop.autoPosition();
|
||||
drop_down = true;
|
||||
drop.Popup(&drop);
|
||||
drop.Popup();
|
||||
wxCommandEvent e(wxEVT_COMBOBOX_DROPDOWN);
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
}
|
||||
@@ -236,7 +293,7 @@ void ComboBox::mouseWheelMoved(wxMouseEvent &event)
|
||||
{
|
||||
event.Skip();
|
||||
if (drop_down) return;
|
||||
auto delta = event.GetWheelRotation() < 0 ? 1 : -1;
|
||||
auto delta = ((event.GetWheelRotation() < 0) == event.IsWheelInverted()) ? -1 : 1;
|
||||
unsigned int n = GetSelection() + delta;
|
||||
if (n < GetCount()) {
|
||||
SetSelection((int) n);
|
||||
@@ -246,11 +303,16 @@ void ComboBox::mouseWheelMoved(wxMouseEvent &event)
|
||||
|
||||
void ComboBox::keyDown(wxKeyEvent& event)
|
||||
{
|
||||
switch (event.GetKeyCode()) {
|
||||
int key_code = event.GetKeyCode();
|
||||
switch (key_code) {
|
||||
case WXK_RETURN:
|
||||
case WXK_SPACE:
|
||||
if (drop_down) {
|
||||
drop.DismissAndNotify();
|
||||
wxCommandEvent e(wxEVT_COMBOBOX);
|
||||
e.SetEventObject(this);
|
||||
e.SetId(GetId());
|
||||
e.SetInt(GetSelection());
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
} else if (drop.HasDismissLongTime()) {
|
||||
drop.autoPosition();
|
||||
drop_down = true;
|
||||
@@ -259,27 +321,55 @@ void ComboBox::keyDown(wxKeyEvent& event)
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
}
|
||||
break;
|
||||
case WXK_UP:
|
||||
case WXK_DOWN:
|
||||
case WXK_LEFT:
|
||||
case WXK_RIGHT:
|
||||
if ((event.GetKeyCode() == WXK_UP || event.GetKeyCode() == WXK_LEFT) && GetSelection() > 0) {
|
||||
case WXK_UP: {
|
||||
if (GetSelection() > 0)
|
||||
SetSelection(GetSelection() - 1);
|
||||
} else if ((event.GetKeyCode() == WXK_DOWN || event.GetKeyCode() == WXK_RIGHT) && GetSelection() + 1 < texts.size()) {
|
||||
break;
|
||||
}
|
||||
case WXK_DOWN: {
|
||||
if (GetSelection() + 1 < int(texts.size()))
|
||||
SetSelection(GetSelection() + 1);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
case WXK_LEFT: {
|
||||
if (HasFlag(wxCB_READONLY)) {
|
||||
if(GetSelection() > 0)
|
||||
SetSelection(GetSelection() - 1);
|
||||
break;
|
||||
}
|
||||
sendComboBoxEvent();
|
||||
const auto pos = GetTextCtrl()->GetInsertionPoint();
|
||||
if(pos > 0)
|
||||
GetTextCtrl()->SetInsertionPoint(pos - 1);
|
||||
break;
|
||||
}
|
||||
case WXK_RIGHT: {
|
||||
if (HasFlag(wxCB_READONLY)) {
|
||||
if (GetSelection() + 1 < int(texts.size()))
|
||||
SetSelection(GetSelection() + 1);
|
||||
break;
|
||||
}
|
||||
const size_t pos = size_t(GetTextCtrl()->GetInsertionPoint());
|
||||
if (pos < GetLabel().Length())
|
||||
GetTextCtrl()->SetInsertionPoint(pos + 1);
|
||||
break;
|
||||
}
|
||||
case WXK_TAB:
|
||||
HandleAsNavigationKey(event);
|
||||
break;
|
||||
default:
|
||||
default: {
|
||||
if (drop.IsShown() && HasFlag(wxCB_READONLY)) {
|
||||
for (size_t n = 0; n < texts.size(); n++) {
|
||||
if (texts[n].StartsWith(wxString(static_cast<char>(key_code)))) {
|
||||
SetSelection(int(n));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
event.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ComboBox::OnEdit()
|
||||
{
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
#include "TextInput.hpp"
|
||||
#include "DropDown.hpp"
|
||||
|
||||
#define CB_NO_DROP_ICON DD_NO_CHECK_ICON
|
||||
#define CB_NO_DROP_ICON DD_NO_DROP_ICON
|
||||
#define CB_NO_TEXT DD_NO_TEXT
|
||||
|
||||
class ComboBox : public wxWindowWithItems<TextInput, wxItemContainer>
|
||||
{
|
||||
std::vector<wxString> texts;
|
||||
std::vector<wxBitmap> icons;
|
||||
std::vector<wxBitmapBundle> icons;
|
||||
std::vector<void *> datas;
|
||||
std::vector<wxClientDataType> types;
|
||||
|
||||
@@ -30,12 +30,19 @@ public:
|
||||
|
||||
DropDown & GetDropDown() { return drop; }
|
||||
|
||||
virtual bool SetFont(wxFont const & font) override;
|
||||
bool SetFont(wxFont const & font) override;
|
||||
|
||||
public:
|
||||
int Append(const wxString &item, const wxBitmap &bitmap = wxNullBitmap);
|
||||
bool SetBackgroundColour(const wxColour& colour) override;
|
||||
bool SetForegroundColour(const wxColour& colour) override;
|
||||
|
||||
int Append(const wxString &item, const wxBitmap &bitmap, void *clientData);
|
||||
void SetBorderColor(StateColor const& color);
|
||||
|
||||
int Append(const wxString &item, const wxBitmapBundle &bitmap = wxNullBitmap);
|
||||
int Append(const wxString &item, const wxBitmapBundle &bitmap, void *clientData);
|
||||
|
||||
int Insert(const wxString& item, const wxBitmapBundle& bitmap, unsigned int pos);
|
||||
int Insert(const wxString& item, const wxBitmapBundle& bitmap,
|
||||
unsigned int pos, void* clientData);
|
||||
|
||||
unsigned int GetCount() const override;
|
||||
|
||||
@@ -43,7 +50,6 @@ public:
|
||||
|
||||
void SetSelection(int n) override;
|
||||
|
||||
void SelectAndNotify(int n);
|
||||
|
||||
virtual void Rescale() override;
|
||||
|
||||
@@ -60,14 +66,14 @@ public:
|
||||
void SetString(unsigned int n, wxString const &value) override;
|
||||
|
||||
wxBitmap GetItemBitmap(unsigned int n);
|
||||
void SetItemBitmap(unsigned int n, wxBitmap const &bitmap);
|
||||
void OnKeyDown(wxKeyEvent& event);
|
||||
|
||||
protected:
|
||||
virtual int DoInsertItems(const wxArrayStringsAdapter &items,
|
||||
unsigned int pos,
|
||||
void ** clientData,
|
||||
wxClientDataType type) override;
|
||||
virtual void DoClear() override;
|
||||
void DoClear() override;
|
||||
|
||||
void DoDeleteOneItem(unsigned int pos) override;
|
||||
|
||||
@@ -76,7 +82,6 @@ protected:
|
||||
|
||||
void OnEdit() override;
|
||||
|
||||
void sendComboBoxEvent();
|
||||
|
||||
#ifdef __WIN32__
|
||||
WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) override;
|
||||
@@ -89,6 +94,7 @@ private:
|
||||
void mouseWheelMoved(wxMouseEvent &event);
|
||||
void keyDown(wxKeyEvent &event);
|
||||
|
||||
void sendComboBoxEvent();
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
#include "DropDown.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "ComboBox.hpp"
|
||||
#include "../GUI_App.hpp"
|
||||
#include "../OptionsGroup.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
#include <wx/dcbuffer.h>
|
||||
#include <wx/dcclient.h>
|
||||
#include <wx/dcscreen.h>
|
||||
#include <wx/dcmemory.h>
|
||||
#include <wx/bitmap.h>
|
||||
|
||||
#include <wx/display.h>
|
||||
|
||||
#ifdef __WXGTK__
|
||||
#include <gtk/gtk.h>
|
||||
@@ -9,7 +18,7 @@
|
||||
|
||||
wxDEFINE_EVENT(EVT_DISMISS, wxCommandEvent);
|
||||
|
||||
BEGIN_EVENT_TABLE(DropDown, PopupWindow)
|
||||
BEGIN_EVENT_TABLE(DropDown, wxPopupTransientWindow)
|
||||
|
||||
EVT_LEFT_DOWN(DropDown::mouseDown)
|
||||
EVT_LEFT_UP(DropDown::mouseReleased)
|
||||
@@ -29,13 +38,14 @@ END_EVENT_TABLE()
|
||||
*/
|
||||
|
||||
DropDown::DropDown(std::vector<wxString> &texts,
|
||||
std::vector<wxBitmap> &icons)
|
||||
std::vector<wxBitmapBundle> &icons)
|
||||
: texts(texts)
|
||||
, icons(icons)
|
||||
, radius(Slic3r::GUI::wxGetApp().suppress_round_corners() ? 0 : 5)
|
||||
, state_handler(this)
|
||||
, border_color(0xDBDBDB)
|
||||
, text_color(0x363636)
|
||||
, selector_border_color(std::make_pair(0x009688, (int) StateColor::Hovered),
|
||||
, border_color(0xDBDBDB)
|
||||
, selector_border_color(std::make_pair(0x00AE42, (int) StateColor::Hovered),
|
||||
std::make_pair(*wxWHITE, (int) StateColor::Normal))
|
||||
, selector_background_color(std::make_pair(0xEDFAF2, (int) StateColor::Checked),
|
||||
std::make_pair(*wxWHITE, (int) StateColor::Normal))
|
||||
@@ -44,29 +54,76 @@ DropDown::DropDown(std::vector<wxString> &texts,
|
||||
|
||||
DropDown::DropDown(wxWindow * parent,
|
||||
std::vector<wxString> &texts,
|
||||
std::vector<wxBitmap> &icons,
|
||||
std::vector<wxBitmapBundle> &icons,
|
||||
long style)
|
||||
: DropDown(texts, icons)
|
||||
{
|
||||
Create(parent, style);
|
||||
}
|
||||
|
||||
#ifdef __WXGTK__
|
||||
static gint gtk_popup_key_press (GtkWidget *widget, GdkEvent *gdk_event, wxPopupWindow* win )
|
||||
{
|
||||
// Ignore events sent out before we connected to the signal
|
||||
if (win->m_time >= ((GdkEventKey*)gdk_event)->time)
|
||||
return FALSE;
|
||||
|
||||
GtkWidget *child = gtk_get_event_widget (gdk_event);
|
||||
|
||||
/* We don't ask for button press events on the grab widget, so
|
||||
* if an event is reported directly to the grab widget, it must
|
||||
* be on a window outside the application (and thus we remove
|
||||
* the popup window). Otherwise, we check if the widget is a child
|
||||
* of the grab widget, and only remove the popup window if it
|
||||
* is not. */
|
||||
if (child != widget) {
|
||||
while (child) {
|
||||
if (child == widget)
|
||||
return FALSE;
|
||||
child = gtk_widget_get_parent(child);
|
||||
}
|
||||
}
|
||||
|
||||
gchar* keyval = gdk_keyval_name(((GdkEventKey*)gdk_event)->keyval);
|
||||
const long keyCode = strcmp(keyval, "Up") == 0 ? WXK_UP :
|
||||
strcmp(keyval, "Down") == 0 ? WXK_DOWN :
|
||||
strcmp(keyval, "Left") == 0 ? WXK_LEFT :
|
||||
strcmp(keyval, "Right") == 0 ? WXK_RIGHT :
|
||||
strcmp(keyval, "Return") == 0 ? WXK_RETURN : WXK_NONE;
|
||||
|
||||
if (keyCode != WXK_NONE) {
|
||||
wxKeyEvent event( wxEVT_KEY_DOWN, win->GetId());
|
||||
event.m_keyCode = keyCode;
|
||||
event.SetEventObject( win );
|
||||
(void)win->HandleWindowEvent( event );
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
void DropDown::Create(wxWindow * parent,
|
||||
long style)
|
||||
{
|
||||
PopupWindow::Create(parent, wxPU_CONTAINS_CONTROLS);
|
||||
SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
wxPopupTransientWindow::Create(parent);
|
||||
#ifdef __WXGTK__
|
||||
g_signal_connect (m_widget, "key_press_event", G_CALLBACK (gtk_popup_key_press), this);
|
||||
|
||||
Bind(wxEVT_KEY_DOWN, [parent](wxKeyEvent &e) {
|
||||
if (ComboBox* cb = dynamic_cast<ComboBox*>(parent))
|
||||
cb->OnKeyDown(e);
|
||||
});
|
||||
#endif
|
||||
|
||||
if (!wxOSX) SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
state_handler.attach({&border_color, &text_color, &selector_border_color, &selector_background_color});
|
||||
state_handler.update_binds();
|
||||
if ((style & DD_NO_CHECK_ICON) == 0)
|
||||
if (!(style & DD_NO_CHECK_ICON))
|
||||
check_bitmap = ScalableBitmap(this, "checked", 16);
|
||||
text_off = style & DD_NO_TEXT;
|
||||
|
||||
// BBS set default font
|
||||
SetFont(Label::Body_14);
|
||||
SetFont(parent->GetFont());
|
||||
#ifdef __WXOSX__
|
||||
// PopupWindow releases mouse on idle, which may cause various problems,
|
||||
// wxPopupTransientWindow releases mouse on idle, which may cause various problems,
|
||||
// such as losting mouse move, and dismissing soon on first LEFT_DOWN event.
|
||||
Bind(wxEVT_IDLE, [] (wxIdleEvent & evt) {});
|
||||
#endif
|
||||
@@ -84,11 +141,12 @@ void DropDown::Invalidate(bool clear)
|
||||
|
||||
void DropDown::SetSelection(int n)
|
||||
{
|
||||
assert(n < (int) texts.size());
|
||||
if (n >= (int) texts.size())
|
||||
n = -1;
|
||||
if (selection == n) return;
|
||||
selection = n;
|
||||
if (IsShown())
|
||||
autoPosition();
|
||||
paintNow();
|
||||
}
|
||||
|
||||
@@ -103,9 +161,9 @@ void DropDown::SetValue(const wxString &value)
|
||||
selection = i == texts.end() ? -1 : std::distance(texts.begin(), i);
|
||||
}
|
||||
|
||||
void DropDown::SetCornerRadius(double radius)
|
||||
void DropDown::SetCornerRadius(double radius_in)
|
||||
{
|
||||
this->radius = radius;
|
||||
radius = radius_in;
|
||||
paintNow();
|
||||
}
|
||||
|
||||
@@ -157,7 +215,7 @@ bool DropDown::HasDismissLongTime()
|
||||
{
|
||||
auto now = boost::posix_time::microsec_clock::universal_time();
|
||||
return !IsShown() &&
|
||||
(now - dismissTime).total_milliseconds() >= 20;
|
||||
(now - dismissTime).total_milliseconds() >= 200;
|
||||
}
|
||||
|
||||
void DropDown::paintEvent(wxPaintEvent& evt)
|
||||
@@ -183,15 +241,35 @@ void DropDown::paintNow()
|
||||
Refresh();
|
||||
}
|
||||
|
||||
static wxSize GetBmpSize(wxBitmap & bmp)
|
||||
void DropDown::SetTransparentBG(wxDC& dc, wxWindow* win)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return bmp.GetScaledSize();
|
||||
const wxSize size = win->GetSize();
|
||||
const wxPoint screen_pos = win->GetScreenPosition();
|
||||
wxScreenDC screen_dc;
|
||||
|
||||
#ifdef __WXMSW__
|
||||
// Draw screen_dc to dc for transparent background
|
||||
dc.Blit(0, 0, size.x, size.y, &screen_dc, screen_pos.x, screen_pos.y);
|
||||
#else
|
||||
return bmp.GetSize();
|
||||
#endif
|
||||
// See https://forums.wxwidgets.org/viewtopic.php?f=1&t=49318
|
||||
wxClientDC client_dc(win);
|
||||
client_dc.Blit(0, 0, size.x, size.y, &screen_dc, screen_pos.x, screen_pos.y);
|
||||
|
||||
wxBitmap bmp(size.x, size.y);
|
||||
wxMemoryDC mem_dc(bmp);
|
||||
mem_dc.Blit(0, 0, size.x, size.y, &client_dc, 0, 0);
|
||||
mem_dc.SelectObject(wxNullBitmap);
|
||||
dc.DrawBitmap(bmp, 0, 0);
|
||||
#endif //__WXMSW__
|
||||
}
|
||||
|
||||
constexpr int slider_width = 12;
|
||||
#ifdef __WXOSX__
|
||||
constexpr int slider_step = 1;
|
||||
#else
|
||||
constexpr int slider_step = 5;
|
||||
#endif
|
||||
constexpr int items_padding = 2;
|
||||
/*
|
||||
* Here we do the actual rendering. I put it in a separate
|
||||
* method so that it can work no matter what type of DC
|
||||
@@ -201,25 +279,38 @@ void DropDown::render(wxDC &dc)
|
||||
{
|
||||
if (texts.size() == 0) return;
|
||||
int states = state_handler.states();
|
||||
const wxSize size = GetSize();
|
||||
if (radius > 0. && !wxOSX)
|
||||
SetTransparentBG(dc, this);
|
||||
dc.SetPen(wxPen(border_color.colorForStates(states)));
|
||||
dc.SetBrush(wxBrush(StateColor::darkModeColorFor(GetBackgroundColour())));
|
||||
dc.SetBrush(wxBrush(GetBackgroundColour()));
|
||||
// if (GetWindowStyle() & wxBORDER_NONE)
|
||||
// dc.SetPen(wxNullPen);
|
||||
|
||||
const bool is_retina = wxOSX && dc.GetContentScaleFactor() > 1.0;
|
||||
|
||||
wxRect rc(0, 0, size.x, size.y);
|
||||
// On Retina displays all controls are cut on 1px
|
||||
if (is_retina)
|
||||
rc.x = rc.y = 1;
|
||||
// draw background
|
||||
wxSize size = GetSize();
|
||||
if (radius == 0)
|
||||
dc.DrawRectangle(0, 0, size.x, size.y);
|
||||
if (radius == 0.0 || wxOSX)
|
||||
dc.DrawRectangle(rc);
|
||||
else
|
||||
dc.DrawRoundedRectangle(0, 0, size.x, size.y, radius);
|
||||
dc.DrawRoundedRectangle(rc, radius);
|
||||
|
||||
// draw hover rectangle
|
||||
wxRect rcContent = {{0, offset.y}, rowSize};
|
||||
const int text_size = int(texts.size());
|
||||
|
||||
const bool has_bar = rowSize.y * text_size > size.y;
|
||||
if (has_bar)
|
||||
rcContent.width -= slider_width;
|
||||
if (hover_item >= 0 && (states & StateColor::Hovered)) {
|
||||
rcContent.y += rowSize.y * hover_item;
|
||||
if (rcContent.GetBottom() > 0 && rcContent.y < size.y) {
|
||||
if (selection == hover_item)
|
||||
dc.SetBrush(wxBrush(selector_background_color.colorForStates(states | StateColor::Checked)));
|
||||
dc.SetBrush(wxBrush(selector_background_color.colorForStates(StateColor::Disabled)));
|
||||
dc.SetPen(wxPen(selector_border_color.colorForStates(states)));
|
||||
rcContent.Deflate(4, 1);
|
||||
dc.DrawRectangle(rcContent);
|
||||
@@ -231,11 +322,15 @@ void DropDown::render(wxDC &dc)
|
||||
if (selection >= 0 && (selection != hover_item || (states & StateColor::Hovered) == 0)) {
|
||||
rcContent.y += rowSize.y * selection;
|
||||
if (rcContent.GetBottom() > 0 && rcContent.y < size.y) {
|
||||
dc.SetBrush(wxBrush(selector_background_color.colorForStates(states | StateColor::Checked)));
|
||||
dc.SetBrush(wxBrush(selector_background_color.colorForStates(StateColor::Disabled)));
|
||||
dc.SetPen(wxPen(selector_background_color.colorForStates(states)));
|
||||
rcContent.Deflate(4, 1);
|
||||
if (is_retina)
|
||||
rc.y += 1;
|
||||
dc.DrawRectangle(rcContent);
|
||||
rcContent.Inflate(4, 1);
|
||||
if (is_retina)
|
||||
rc.y -= 1;
|
||||
}
|
||||
rcContent.y = offset.y;
|
||||
}
|
||||
@@ -246,20 +341,19 @@ void DropDown::render(wxDC &dc)
|
||||
}
|
||||
|
||||
// draw position bar
|
||||
if (rowSize.y * texts.size() > size.y) {
|
||||
int height = rowSize.y * texts.size();
|
||||
wxRect rect = {size.x - 6, -offset.y * size.y / height, 4,
|
||||
size.y * size.y / height};
|
||||
if (has_bar) {
|
||||
int height = rowSize.y * text_size;
|
||||
wxRect rect = {size.x - slider_width - 2, -offset.y * size.y / height + 2, slider_width,
|
||||
size.y * size.y / height - 3};
|
||||
dc.SetPen(wxPen(border_color.defaultColor()));
|
||||
dc.SetBrush(wxBrush(*wxLIGHT_GREY));
|
||||
dc.SetBrush(wxBrush(selector_background_color.colorForStates(states | StateColor::Checked)));
|
||||
dc.DrawRoundedRectangle(rect, 2);
|
||||
rcContent.width -= 6;
|
||||
}
|
||||
|
||||
// draw check icon
|
||||
rcContent.x += 5;
|
||||
rcContent.width -= 5;
|
||||
if (check_bitmap.get_bitmap().IsOk()) {
|
||||
if (check_bitmap.bmp().IsOk()) {
|
||||
auto szBmp = check_bitmap.GetSize();
|
||||
if (selection >= 0) {
|
||||
wxPoint pt = rcContent.GetLeftTop();
|
||||
@@ -273,7 +367,7 @@ void DropDown::render(wxDC &dc)
|
||||
}
|
||||
// draw texts & icons
|
||||
dc.SetTextForeground(text_color.colorForStates(states));
|
||||
for (int i = 0; i < texts.size(); ++i) {
|
||||
for (size_t i = 0; i < texts.size(); ++i) {
|
||||
if (rcContent.GetBottom() < 0) {
|
||||
rcContent.y += rowSize.y;
|
||||
continue;
|
||||
@@ -281,18 +375,26 @@ void DropDown::render(wxDC &dc)
|
||||
if (rcContent.y > size.y) break;
|
||||
wxPoint pt = rcContent.GetLeftTop();
|
||||
auto & icon = icons[i];
|
||||
auto size2 = GetBmpSize(icon);
|
||||
const wxSize pref_icon_sz = get_preferred_size(icon, m_parent);
|
||||
if (iconSize.x > 0) {
|
||||
if (icon.IsOk()) {
|
||||
pt.y += (rcContent.height - size2.y) / 2;
|
||||
dc.DrawBitmap(icon, pt);
|
||||
pt.y += (rcContent.height - pref_icon_sz.y) / 2;
|
||||
#ifdef __WXGTK3__
|
||||
dc.DrawBitmap(icon.GetBitmap(pref_icon_sz), pt);
|
||||
#else
|
||||
dc.DrawBitmap(icon.GetBitmapFor(m_parent), pt);
|
||||
#endif
|
||||
}
|
||||
pt.x += iconSize.x + 5;
|
||||
pt.y = rcContent.y;
|
||||
} else if (icon.IsOk()) {
|
||||
pt.y += (rcContent.height - size2.y) / 2;
|
||||
dc.DrawBitmap(icon, pt);
|
||||
pt.x += size2.x + 5;
|
||||
pt.y += (rcContent.height - pref_icon_sz.y) / 2;
|
||||
#ifdef __WXGTK3__
|
||||
dc.DrawBitmap(icon.GetBitmap(pref_icon_sz), pt);
|
||||
#else
|
||||
dc.DrawBitmap(icon.GetBitmapFor(m_parent), pt);
|
||||
#endif
|
||||
pt.x += pref_icon_sz.GetWidth() + 5;
|
||||
pt.y = rcContent.y;
|
||||
}
|
||||
auto text = texts[i];
|
||||
@@ -319,7 +421,7 @@ void DropDown::messureSize()
|
||||
for (size_t i = 0; i < texts.size(); ++i) {
|
||||
wxSize size1 = text_off ? wxSize() : dc.GetMultiLineTextExtent(texts[i]);
|
||||
if (icons[i].IsOk()) {
|
||||
wxSize size2 = GetBmpSize(icons[i]);
|
||||
wxSize size2 = get_preferred_size(icons[i], m_parent);
|
||||
if (size2.x > iconSize.x) iconSize = size2;
|
||||
if (!align_icon) {
|
||||
size1.x += size2.x + (text_off ? 0 : 5);
|
||||
@@ -330,13 +432,13 @@ void DropDown::messureSize()
|
||||
if (!align_icon) iconSize.x = 0;
|
||||
wxSize szContent = textSize;
|
||||
szContent.x += 10;
|
||||
if (check_bitmap.get_bitmap().IsOk()) {
|
||||
if (check_bitmap.bmp().IsOk()) {
|
||||
auto szBmp = check_bitmap.GetSize();
|
||||
szContent.x += szBmp.x + 5;
|
||||
}
|
||||
if (iconSize.x > 0) szContent.x += iconSize.x + (text_off ? 0 : 5);
|
||||
if (iconSize.y > szContent.y) szContent.y = iconSize.y;
|
||||
szContent.y += 10;
|
||||
szContent.y += items_padding;
|
||||
if (texts.size() > 15) szContent.x += 6;
|
||||
if (GetParent()) {
|
||||
auto x = GetParent()->GetSize().x;
|
||||
@@ -378,15 +480,15 @@ void DropDown::autoPosition()
|
||||
if (use_content_width && texts.size() <= 15) size.x += 6;
|
||||
size.y = drect.GetBottom() - GetPosition().y - 10;
|
||||
wxWindow::SetSize(size);
|
||||
}
|
||||
}
|
||||
if (selection >= 0) {
|
||||
if (offset.y + rowSize.y * (selection + 1) > size.y)
|
||||
offset.y = size.y - rowSize.y * (selection + 1);
|
||||
offset.y = size.y - rowSize.y * (selection + 3);
|
||||
else if (offset.y + rowSize.y * selection < 0)
|
||||
offset.y = -rowSize.y * selection;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DropDown::mouseDown(wxMouseEvent& event)
|
||||
{
|
||||
@@ -395,6 +497,11 @@ void DropDown::mouseDown(wxMouseEvent& event)
|
||||
return;
|
||||
// force calc hover item again
|
||||
mouseMove(event);
|
||||
const wxSize size = GetSize();
|
||||
const int height = rowSize.y * int(texts.size());
|
||||
const wxRect rect = { size.x - slider_width, -offset.y * size.y / height, slider_width - 2,
|
||||
size.y * size.y / height };
|
||||
slider_grabbed = rect.Contains(event.GetPosition());
|
||||
pressedDown = true;
|
||||
CaptureMouse();
|
||||
dragStart = event.GetPosition();
|
||||
@@ -405,9 +512,14 @@ void DropDown::mouseReleased(wxMouseEvent& event)
|
||||
if (pressedDown) {
|
||||
dragStart = wxPoint();
|
||||
pressedDown = false;
|
||||
slider_grabbed = false;
|
||||
if (HasCapture())
|
||||
ReleaseMouse();
|
||||
if (hover_item >= 0) { // not moved
|
||||
#ifdef __WXOSX__
|
||||
// To avoid cases, when some dialog appears after item selection, but DropDown is still shown
|
||||
Hide();
|
||||
#endif
|
||||
sendDropDownEvent();
|
||||
DismissAndNotify();
|
||||
}
|
||||
@@ -423,14 +535,17 @@ void DropDown::mouseCaptureLost(wxMouseCaptureLostEvent &event)
|
||||
void DropDown::mouseMove(wxMouseEvent &event)
|
||||
{
|
||||
wxPoint pt = event.GetPosition();
|
||||
int text_size = int(texts.size());
|
||||
if (pressedDown) {
|
||||
wxPoint pt2 = offset + pt - dragStart;
|
||||
wxSize size = GetSize();
|
||||
const int height = rowSize.y * text_size;
|
||||
const int y_step = slider_grabbed ? -height / GetSize().y : 1;
|
||||
|
||||
wxPoint pt2 = offset + (pt - dragStart)*y_step;
|
||||
dragStart = pt;
|
||||
if (pt2.y > 0)
|
||||
pt2.y = 0;
|
||||
else if (pt2.y + rowSize.y * int(texts.size()) < size.y)
|
||||
pt2.y = size.y - rowSize.y * int(texts.size());
|
||||
else if (pt2.y + rowSize.y * text_size < GetSize().y)
|
||||
pt2.y = GetSize().y - rowSize.y * text_size;
|
||||
if (pt2.y != offset.y) {
|
||||
offset = pt2;
|
||||
hover_item = -1; // moved
|
||||
@@ -440,7 +555,7 @@ void DropDown::mouseMove(wxMouseEvent &event)
|
||||
}
|
||||
if (!pressedDown || hover_item >= 0) {
|
||||
int hover = (pt.y - offset.y) / rowSize.y;
|
||||
if (hover >= (int) texts.size()) hover = -1;
|
||||
if (hover >= text_size || slider_grabbed) hover = -1;
|
||||
if (hover == hover_item) return;
|
||||
hover_item = hover;
|
||||
if (hover >= 0)
|
||||
@@ -451,20 +566,22 @@ void DropDown::mouseMove(wxMouseEvent &event)
|
||||
|
||||
void DropDown::mouseWheelMoved(wxMouseEvent &event)
|
||||
{
|
||||
auto delta = event.GetWheelRotation();
|
||||
wxSize size = GetSize();
|
||||
wxPoint pt2 = offset + wxPoint{0, delta};
|
||||
if (event.GetWheelRotation() == 0)
|
||||
return;
|
||||
auto delta = event.GetWheelRotation() > 0 ? rowSize.y : -rowSize.y;
|
||||
wxPoint pt2 = offset + wxPoint{0, slider_step * delta};
|
||||
int text_size = int(texts.size());
|
||||
if (pt2.y > 0)
|
||||
pt2.y = 0;
|
||||
else if (pt2.y + rowSize.y * int(texts.size()) < size.y)
|
||||
pt2.y = size.y - rowSize.y * int(texts.size());
|
||||
else if (pt2.y + rowSize.y * text_size < GetSize().y)
|
||||
pt2.y = GetSize().y - rowSize.y * text_size;
|
||||
if (pt2.y != offset.y) {
|
||||
offset = pt2;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
int hover = (event.GetPosition().y - offset.y) / rowSize.y;
|
||||
if (hover >= (int) texts.size()) hover = -1;
|
||||
if (hover >= text_size) hover = -1;
|
||||
if (hover != hover_item) {
|
||||
hover_item = hover;
|
||||
if (hover >= 0) SetToolTip(texts[hover]);
|
||||
|
||||
@@ -2,31 +2,28 @@
|
||||
#define slic3r_GUI_DropDown_hpp_
|
||||
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/popupwin.h>
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "StateHandler.hpp"
|
||||
#include "PopupWindow.hpp"
|
||||
//B35
|
||||
#if defined __linux__
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include "wx/dcbuffer.h"
|
||||
#include "wx/display.h"
|
||||
#endif
|
||||
|
||||
#define DD_NO_CHECK_ICON 0x0001
|
||||
#define DD_NO_TEXT 0x0002
|
||||
#define DD_STYLE_MASK 0x0003
|
||||
#define DD_NO_DROP_ICON 0x0002
|
||||
#define DD_NO_TEXT 0x0004
|
||||
#define DD_STYLE_MASK 0x0008
|
||||
|
||||
wxDECLARE_EVENT(EVT_DISMISS, wxCommandEvent);
|
||||
|
||||
class DropDown : public PopupWindow
|
||||
class DropDown : public wxPopupTransientWindow
|
||||
{
|
||||
std::vector<wxString> & texts;
|
||||
std::vector<wxBitmap> & icons;
|
||||
std::vector<wxBitmapBundle> & icons;
|
||||
bool need_sync = false;
|
||||
int selection = -1;
|
||||
int hover_item = -1;
|
||||
|
||||
double radius = 0;
|
||||
double radius;
|
||||
bool use_content_width = false;
|
||||
bool align_icon = false;
|
||||
bool text_off = false;
|
||||
@@ -43,23 +40,23 @@ class DropDown : public PopupWindow
|
||||
ScalableBitmap check_bitmap;
|
||||
|
||||
bool pressedDown = false;
|
||||
bool slider_grabbed = false;
|
||||
boost::posix_time::ptime dismissTime;
|
||||
wxPoint offset; // x not used
|
||||
wxPoint dragStart;
|
||||
|
||||
public:
|
||||
DropDown(std::vector<wxString> &texts,
|
||||
std::vector<wxBitmap> &icons);
|
||||
std::vector<wxBitmapBundle> &icons);
|
||||
|
||||
DropDown(wxWindow * parent,
|
||||
std::vector<wxString> &texts,
|
||||
std::vector<wxBitmap> &icons,
|
||||
std::vector<wxBitmapBundle> &icons,
|
||||
long style = 0);
|
||||
|
||||
void Create(wxWindow * parent,
|
||||
long style = 0);
|
||||
|
||||
public:
|
||||
void Invalidate(bool clear = false);
|
||||
|
||||
int GetSelection() const { return selection; }
|
||||
@@ -69,7 +66,6 @@ public:
|
||||
wxString GetValue() const;
|
||||
void SetValue(const wxString &value);
|
||||
|
||||
public:
|
||||
void SetCornerRadius(double radius);
|
||||
|
||||
void SetBorderColor(StateColor const & color);
|
||||
@@ -84,11 +80,11 @@ public:
|
||||
|
||||
void SetAlignIcon(bool align);
|
||||
|
||||
public:
|
||||
void Rescale();
|
||||
|
||||
bool HasDismissLongTime();
|
||||
|
||||
static void SetTransparentBG(wxDC& dc, wxWindow* win);
|
||||
protected:
|
||||
void OnDismiss() override;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "StaticBox.hpp"
|
||||
|
||||
#include <wx/settings.h>
|
||||
wxFont Label::sysFont(int size, bool bold)
|
||||
{
|
||||
//#ifdef __linux__
|
||||
@@ -29,7 +29,6 @@ wxFont Label::Head_15;
|
||||
wxFont Label::Head_14;
|
||||
wxFont Label::Head_13;
|
||||
wxFont Label::Head_12;
|
||||
wxFont Label::Head_11;
|
||||
wxFont Label::Head_10;
|
||||
|
||||
wxFont Label::Body_16;
|
||||
@@ -43,17 +42,6 @@ wxFont Label::Body_9;
|
||||
|
||||
void Label::initSysFont()
|
||||
{
|
||||
#ifdef __linux__
|
||||
const std::string& resource_path = Slic3r::resources_dir();
|
||||
wxString font_path = wxString::FromUTF8(resource_path+"/fonts/HarmonyOS_Sans_SC_Bold.ttf");
|
||||
bool result = wxFont::AddPrivateFont(font_path);
|
||||
//BOOST_LOG_TRIVIAL(info) << boost::format("add font of HarmonyOS_Sans_SC_Bold returns %1%")%result;
|
||||
printf("add font of HarmonyOS_Sans_SC_Bold returns %d\n", result);
|
||||
font_path = wxString::FromUTF8(resource_path+"/fonts/HarmonyOS_Sans_SC_Regular.ttf");
|
||||
result = wxFont::AddPrivateFont(font_path);
|
||||
//BOOST_LOG_TRIVIAL(info) << boost::format("add font of HarmonyOS_Sans_SC_Regular returns %1%")%result;
|
||||
printf("add font of HarmonyOS_Sans_SC_Regular returns %d\n", result);
|
||||
#endif
|
||||
|
||||
Head_24 = Label::sysFont(24, true);
|
||||
Head_20 = Label::sysFont(20, true);
|
||||
@@ -63,7 +51,6 @@ void Label::initSysFont()
|
||||
Head_14 = Label::sysFont(14, true);
|
||||
Head_13 = Label::sysFont(13, true);
|
||||
Head_12 = Label::sysFont(12, true);
|
||||
Head_11 = Label::sysFont(11, true);
|
||||
Head_10 = Label::sysFont(10, true);
|
||||
|
||||
Body_16 = Label::sysFont(16, false);
|
||||
@@ -76,126 +63,6 @@ void Label::initSysFont()
|
||||
Body_9 = Label::sysFont(9, false);
|
||||
}
|
||||
|
||||
class WXDLLIMPEXP_CORE wxTextWrapper2
|
||||
{
|
||||
public:
|
||||
wxTextWrapper2() { m_eol = false; }
|
||||
|
||||
// win is used for getting the font, text is the text to wrap, width is the
|
||||
// max line width or -1 to disable wrapping
|
||||
void Wrap(wxWindow *win, const wxString &text, int widthMax)
|
||||
{
|
||||
const wxClientDC dc(win);
|
||||
|
||||
const wxArrayString ls = wxSplit(text, '\n', '\0');
|
||||
for (wxArrayString::const_iterator i = ls.begin(); i != ls.end(); ++i) {
|
||||
wxString line = *i;
|
||||
|
||||
if (i != ls.begin()) {
|
||||
// Do this even if the line is empty, except if it's the first one.
|
||||
OnNewLine();
|
||||
}
|
||||
|
||||
// Is this a special case when wrapping is disabled?
|
||||
if (widthMax < 0) {
|
||||
DoOutputLine(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (bool newLine = false; !line.empty(); newLine = true) {
|
||||
if (newLine) OnNewLine();
|
||||
|
||||
wxArrayInt widths;
|
||||
dc.GetPartialTextExtents(line, widths);
|
||||
|
||||
const size_t posEnd = std::lower_bound(widths.begin(), widths.end(), widthMax) - widths.begin();
|
||||
|
||||
// Does the entire remaining line fit?
|
||||
if (posEnd == line.length()) {
|
||||
DoOutputLine(line);
|
||||
break;
|
||||
}
|
||||
|
||||
// Find the last word to chop off.
|
||||
size_t lastSpace = posEnd;
|
||||
while (lastSpace > 0) {
|
||||
auto c = line[lastSpace];
|
||||
if (c == ' ')
|
||||
break;
|
||||
if (c > 0x4E00) {
|
||||
if (lastSpace != posEnd)
|
||||
++lastSpace;
|
||||
break;
|
||||
}
|
||||
--lastSpace;
|
||||
}
|
||||
if (lastSpace == 0) {
|
||||
// No spaces, so can't wrap.
|
||||
lastSpace = posEnd;
|
||||
}
|
||||
|
||||
// Output the part that fits.
|
||||
DoOutputLine(line.substr(0, lastSpace));
|
||||
|
||||
// And redo the layout with the rest.
|
||||
if (line[lastSpace] == ' ') ++lastSpace;
|
||||
line = line.substr(lastSpace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we don't need it, but just to avoid compiler warnings
|
||||
virtual ~wxTextWrapper2() {}
|
||||
|
||||
protected:
|
||||
// line may be empty
|
||||
virtual void OnOutputLine(const wxString &line) = 0;
|
||||
|
||||
// called at the start of every new line (except the very first one)
|
||||
virtual void OnNewLine() {}
|
||||
|
||||
private:
|
||||
// call OnOutputLine() and set m_eol to true
|
||||
void DoOutputLine(const wxString &line)
|
||||
{
|
||||
OnOutputLine(line);
|
||||
|
||||
m_eol = true;
|
||||
}
|
||||
|
||||
// this function is a destructive inspector: when it returns true it also
|
||||
// resets the flag to false so calling it again wouldn't return true any
|
||||
// more
|
||||
bool IsStartOfNewLine()
|
||||
{
|
||||
if (!m_eol) return false;
|
||||
|
||||
m_eol = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool m_eol;
|
||||
};
|
||||
|
||||
class wxLabelWrapper2 : public wxTextWrapper2
|
||||
{
|
||||
public:
|
||||
void WrapLabel(wxWindow *text, int widthMax)
|
||||
{
|
||||
m_text.clear();
|
||||
Wrap(text, text->GetLabel(), widthMax);
|
||||
text->SetLabel(m_text);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void OnOutputLine(const wxString &line) wxOVERRIDE { m_text += line; }
|
||||
|
||||
virtual void OnNewLine() wxOVERRIDE { m_text += wxT('\n'); }
|
||||
|
||||
private:
|
||||
wxString m_text;
|
||||
};
|
||||
|
||||
|
||||
wxSize Label::split_lines(wxDC &dc, int width, const wxString &text, wxString &multiline_text)
|
||||
@@ -231,27 +98,18 @@ Label::Label(wxWindow *parent, wxFont const &font, wxString const &text, long st
|
||||
{
|
||||
this->font = font;
|
||||
SetFont(font);
|
||||
SetForegroundColour(wxColour("#262E30"));
|
||||
SetBackgroundColour(StaticBox::GetParentBackgroundColor(parent));
|
||||
SetForegroundColour("#262E30");
|
||||
if (style & LB_PROPAGATE_MOUSE_EVENT) {
|
||||
for (auto evt : {
|
||||
wxEVT_LEFT_UP, wxEVT_LEFT_DOWN})
|
||||
Bind(evt, [this] (auto & e) { GetParent()->GetEventHandler()->ProcessEventLocally(e); });
|
||||
};
|
||||
Bind(wxEVT_ENTER_WINDOW, [this](auto &e) {
|
||||
if (GetWindowStyle() & LB_HYPERLINK) {
|
||||
SetFont(this->font.Underlined());
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void Label::SetLabel(const wxString& label)
|
||||
{
|
||||
if (GetLabel() == label)
|
||||
return;
|
||||
wxStaticText::SetLabel(label);
|
||||
#ifdef __WXOSX__
|
||||
if ((GetWindowStyle() & LB_HYPERLINK)) {
|
||||
SetLabelMarkup(label);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
});
|
||||
Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) {
|
||||
SetFont(this->font);
|
||||
Refresh();
|
||||
});
|
||||
}
|
||||
|
||||
void Label::SetWindowStyleFlag(long style)
|
||||
@@ -262,27 +120,12 @@ void Label::SetWindowStyleFlag(long style)
|
||||
if (style & LB_HYPERLINK) {
|
||||
this->color = GetForegroundColour();
|
||||
static wxColor clr_url("#00AE42");
|
||||
SetFont(this->font.Underlined());
|
||||
SetForegroundColour(clr_url);
|
||||
SetCursor(wxCURSOR_HAND);
|
||||
#ifdef __WXOSX__
|
||||
SetLabelMarkup(GetLabel());
|
||||
#endif
|
||||
} else {
|
||||
SetForegroundColour(this->color);
|
||||
SetFont(this->font);
|
||||
SetCursor(wxCURSOR_ARROW);
|
||||
#ifdef __WXOSX__
|
||||
auto label = GetLabel();
|
||||
wxStaticText::SetLabel({});
|
||||
wxStaticText::SetLabel(label);
|
||||
#endif
|
||||
}
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void Label::Wrap(int width)
|
||||
{
|
||||
wxLabelWrapper2 wrapper;
|
||||
wrapper.WrapLabel(this, width);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,15 +2,10 @@
|
||||
#define slic3r_GUI_Label_hpp_
|
||||
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/dcclient.h>
|
||||
|
||||
#define LB_HYPERLINK 0x0020
|
||||
#define LB_PROPAGATE_MOUSE_EVENT 0x0040
|
||||
#define LB_HYPERLINK 0x0001
|
||||
|
||||
//B35
|
||||
#if defined __linux__
|
||||
#include <wx/settings.h>
|
||||
#include "wx/dcclient.h"
|
||||
#endif
|
||||
|
||||
class Label : public wxStaticText
|
||||
{
|
||||
@@ -19,11 +14,9 @@ public:
|
||||
|
||||
Label(wxWindow *parent, wxFont const &font, wxString const &text = {}, long style = 0);
|
||||
|
||||
void SetLabel(const wxString& label) override;
|
||||
|
||||
void SetWindowStyleFlag(long style) override;
|
||||
|
||||
void Wrap(int width);
|
||||
|
||||
private:
|
||||
wxFont font;
|
||||
@@ -38,7 +31,6 @@ public:
|
||||
static wxFont Head_14;
|
||||
static wxFont Head_13;
|
||||
static wxFont Head_12;
|
||||
static wxFont Head_11;
|
||||
static wxFont Head_10;
|
||||
|
||||
static wxFont Body_16;
|
||||
|
||||
633
src/slic3r/GUI/Widgets/SpinInput.cpp
Normal file
633
src/slic3r/GUI/Widgets/SpinInput.cpp
Normal file
@@ -0,0 +1,633 @@
|
||||
#include "SpinInput.hpp"
|
||||
#include "Button.hpp"
|
||||
|
||||
#include "UIColors.hpp"
|
||||
|
||||
#include "../GUI_App.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/spinctrl.h>
|
||||
#include <wx/valtext.h>
|
||||
|
||||
BEGIN_EVENT_TABLE(SpinInputBase, wxPanel)
|
||||
|
||||
EVT_KEY_DOWN(SpinInputBase::keyPressed)
|
||||
EVT_MOUSEWHEEL(SpinInputBase::mouseWheelMoved)
|
||||
|
||||
EVT_PAINT(SpinInputBase::paintEvent)
|
||||
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
/*
|
||||
* Called by the system of by wxWidgets when the panel needs
|
||||
* to be redrawn. You can also trigger this call by
|
||||
* calling Refresh()/Update().
|
||||
*/
|
||||
|
||||
SpinInputBase::SpinInputBase()
|
||||
: label_color(std::make_pair(0x909090, (int) StateColor::Disabled), std::make_pair(0x6B6B6B, (int) StateColor::Normal))
|
||||
, text_color(std::make_pair(0x909090, (int) StateColor::Disabled), std::make_pair(0x262E30, (int) StateColor::Normal))
|
||||
{
|
||||
if (Slic3r::GUI::wxGetApp().suppress_round_corners())
|
||||
radius = 0;
|
||||
border_width = 1;
|
||||
}
|
||||
|
||||
Button * SpinInputBase::create_button(ButtonId id)
|
||||
{
|
||||
auto btn = new Button(this, "", id == ButtonId::btnIncrease ? "spin_inc_act" : "spin_dec_act", wxBORDER_NONE, wxSize(12, 7));
|
||||
btn->SetCornerRadius(0);
|
||||
btn->SetInactiveIcon(id == ButtonId::btnIncrease ? "spin_inc" : "spin_dec");
|
||||
btn->DisableFocusFromKeyboard();
|
||||
btn->SetSelected(false);
|
||||
|
||||
bind_inc_dec_button(btn, id);
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
void SpinInputBase::SetCornerRadius(double radius)
|
||||
{
|
||||
this->radius = radius;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SpinInputBase::SetLabel(const wxString &label)
|
||||
{
|
||||
wxWindow::SetLabel(label);
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SpinInputBase::SetLabelColor(StateColor const &color)
|
||||
{
|
||||
label_color = color;
|
||||
state_handler.update_binds();
|
||||
}
|
||||
|
||||
void SpinInputBase::SetTextColor(StateColor const &color)
|
||||
{
|
||||
text_color = color;
|
||||
state_handler.update_binds();
|
||||
}
|
||||
|
||||
void SpinInputBase::SetSize(wxSize const &size)
|
||||
{
|
||||
wxWindow::SetSize(size);
|
||||
Rescale();
|
||||
}
|
||||
|
||||
wxString SpinInputBase::GetTextValue() const
|
||||
{
|
||||
return text_ctrl->GetValue();
|
||||
}
|
||||
|
||||
void SpinInput::SetRange(int min, int max)
|
||||
{
|
||||
this->min = min;
|
||||
this->max = max;
|
||||
}
|
||||
|
||||
void SpinInputBase::SetSelection(long from, long to)
|
||||
{
|
||||
if (text_ctrl)
|
||||
text_ctrl->SetSelection(from, to);
|
||||
}
|
||||
|
||||
bool SpinInputBase::SetFont(wxFont const& font)
|
||||
{
|
||||
if (text_ctrl)
|
||||
return text_ctrl->SetFont(font);
|
||||
return StaticBox::SetFont(font);
|
||||
}
|
||||
|
||||
bool SpinInputBase::SetBackgroundColour(const wxColour& colour)
|
||||
{
|
||||
const int clr_background_disabled = Slic3r::GUI::wxGetApp().dark_mode() ? clr_background_disabled_dark : clr_background_disabled_light;
|
||||
StateColor clr_state(std::make_pair(clr_background_disabled, (int)StateColor::Disabled),
|
||||
std::make_pair(clr_background_focused, (int)StateColor::Checked),
|
||||
std::make_pair(colour, (int)StateColor::Focused),
|
||||
std::make_pair(colour, (int)StateColor::Normal));
|
||||
|
||||
StaticBox::SetBackgroundColor(clr_state);
|
||||
if (text_ctrl)
|
||||
text_ctrl->SetBackgroundColour(colour);
|
||||
if (button_inc)
|
||||
button_inc->SetBackgroundColor(clr_state);
|
||||
if (button_dec)
|
||||
button_dec->SetBackgroundColor(clr_state);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SpinInputBase::SetForegroundColour(const wxColour& colour)
|
||||
{
|
||||
StateColor clr_state(std::make_pair(clr_foreground_disabled, (int)StateColor::Disabled),
|
||||
std::make_pair(colour, (int)StateColor::Normal));
|
||||
|
||||
SetLabelColor(clr_state);
|
||||
SetTextColor(clr_state);
|
||||
|
||||
if (text_ctrl)
|
||||
text_ctrl->SetForegroundColour(colour);
|
||||
if (button_inc)
|
||||
button_inc->SetTextColor(clr_state);
|
||||
if (button_dec)
|
||||
button_dec->SetTextColor(clr_state);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpinInputBase::SetBorderColor(StateColor const &color)
|
||||
{
|
||||
StaticBox::SetBorderColor(color);
|
||||
if (button_inc)
|
||||
button_inc->SetBorderColor(color);
|
||||
if (button_dec)
|
||||
button_dec->SetBorderColor(color);
|
||||
}
|
||||
|
||||
void SpinInputBase::DoSetToolTipText(wxString const &tip)
|
||||
{
|
||||
wxWindow::DoSetToolTipText(tip);
|
||||
text_ctrl->SetToolTip(tip);
|
||||
}
|
||||
|
||||
void SpinInputBase::Rescale()
|
||||
{
|
||||
SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
|
||||
|
||||
button_inc->Rescale();
|
||||
button_dec->Rescale();
|
||||
messureSize();
|
||||
}
|
||||
|
||||
bool SpinInputBase::Enable(bool enable)
|
||||
{
|
||||
bool result = text_ctrl->Enable(enable) && wxWindow::Enable(enable);
|
||||
if (result) {
|
||||
wxCommandEvent e(EVT_ENABLE_CHANGED);
|
||||
e.SetEventObject(this);
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
text_ctrl->SetBackgroundColour(background_color.colorForStates(state_handler.states()));
|
||||
text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states()));
|
||||
button_inc->Enable(enable);
|
||||
button_dec->Enable(enable);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void SpinInputBase::paintEvent(wxPaintEvent& evt)
|
||||
{
|
||||
// depending on your system you may need to look at double-buffered dcs
|
||||
wxPaintDC dc(this);
|
||||
render(dc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we do the actual rendering. I put it in a separate
|
||||
* method so that it can work no matter what type of DC
|
||||
* (e.g. wxPaintDC or wxClientDC) is used.
|
||||
*/
|
||||
void SpinInputBase::render(wxDC& dc)
|
||||
{
|
||||
StaticBox::render(dc);
|
||||
int states = state_handler.states();
|
||||
wxSize size = GetSize();
|
||||
// draw seperator of buttons
|
||||
wxPoint pt = button_inc->GetPosition();
|
||||
pt.y = size.y / 2;
|
||||
dc.SetPen(wxPen(border_color.defaultColor()));
|
||||
|
||||
const double scale = dc.GetContentScaleFactor();
|
||||
const int btn_w = button_inc->GetSize().GetWidth();
|
||||
dc.DrawLine(pt, pt + wxSize{ btn_w - int(scale), 0});
|
||||
// draw label
|
||||
auto label = GetLabel();
|
||||
if (!label.IsEmpty()) {
|
||||
pt.x = size.x - labelSize.x - 5;
|
||||
pt.y = (size.y - labelSize.y) / 2;
|
||||
dc.SetFont(GetFont());
|
||||
dc.SetTextForeground(label_color.colorForStates(states));
|
||||
dc.DrawText(label, pt);
|
||||
}
|
||||
}
|
||||
|
||||
void SpinInputBase::messureSize()
|
||||
{
|
||||
wxSize size = GetSize();
|
||||
wxSize textSize = text_ctrl->GetSize();
|
||||
int h = textSize.y + 8;
|
||||
if (size.y != h) {
|
||||
size.y = h;
|
||||
SetSize(size);
|
||||
SetMinSize(size);
|
||||
}
|
||||
|
||||
wxSize btnSize = {14, (size.y - 4) / 2};
|
||||
btnSize.x = btnSize.x * btnSize.y / 10;
|
||||
|
||||
const double scale = this->GetContentScaleFactor();
|
||||
|
||||
wxClientDC dc(this);
|
||||
labelSize = dc.GetMultiLineTextExtent(GetLabel());
|
||||
textSize.x = size.x - labelSize.x - btnSize.x - 16;
|
||||
text_ctrl->SetSize(textSize);
|
||||
text_ctrl->SetPosition({int(3. * scale), (size.y - textSize.y) / 2});
|
||||
button_inc->SetSize(btnSize);
|
||||
button_dec->SetSize(btnSize);
|
||||
button_inc->SetPosition({size.x - btnSize.x - int(3. * scale), size.y / 2 - btnSize.y/* - 1*/});
|
||||
button_dec->SetPosition({size.x - btnSize.x - int(3. * scale), size.y / 2 + 1});
|
||||
}
|
||||
|
||||
void SpinInputBase::onText(wxCommandEvent &event)
|
||||
{
|
||||
sendSpinEvent();
|
||||
event.SetId(GetId());
|
||||
ProcessEventLocally(event);
|
||||
}
|
||||
|
||||
void SpinInputBase::sendSpinEvent()
|
||||
{
|
||||
wxCommandEvent event(wxEVT_SPINCTRL, GetId());
|
||||
event.SetEventObject(this);
|
||||
GetEventHandler()->ProcessEvent(event);
|
||||
}
|
||||
|
||||
|
||||
// SpinInput
|
||||
|
||||
SpinInput::SpinInput(wxWindow *parent,
|
||||
wxString text,
|
||||
wxString label,
|
||||
const wxPoint &pos,
|
||||
const wxSize & size,
|
||||
long style,
|
||||
int min, int max, int initial)
|
||||
: SpinInputBase()
|
||||
{
|
||||
Create(parent, text, label, pos, size, style, min, max, initial);
|
||||
}
|
||||
|
||||
void SpinInput::Create(wxWindow *parent,
|
||||
wxString text,
|
||||
wxString label,
|
||||
const wxPoint &pos,
|
||||
const wxSize & size,
|
||||
long style,
|
||||
int min, int max, int initial)
|
||||
{
|
||||
StaticBox::Create(parent, wxID_ANY, pos, size);
|
||||
wxWindow::SetLabel(label);
|
||||
|
||||
state_handler.attach({&label_color, &text_color});
|
||||
state_handler.update_binds();
|
||||
|
||||
text_ctrl = new wxTextCtrl(this, wxID_ANY, text, {20, 4}, wxDefaultSize, style | wxBORDER_NONE | wxTE_PROCESS_ENTER, wxTextValidator(wxFILTER_NUMERIC));
|
||||
#ifdef __WXOSX__
|
||||
text_ctrl->OSXDisableAllSmartSubstitutions();
|
||||
#endif // __WXOSX__
|
||||
text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
|
||||
state_handler.attach_child(text_ctrl);
|
||||
|
||||
text_ctrl->Bind(wxEVT_KILL_FOCUS, &SpinInput::onTextLostFocus, this);
|
||||
text_ctrl->Bind(wxEVT_TEXT, &SpinInput::onText, this);
|
||||
text_ctrl->Bind(wxEVT_TEXT_ENTER, &SpinInput::onTextEnter, this);
|
||||
text_ctrl->Bind(wxEVT_KEY_DOWN, &SpinInput::keyPressed, this);
|
||||
text_ctrl->Bind(wxEVT_RIGHT_DOWN, [](auto &e) {}); // disable context menu
|
||||
button_inc = create_button(ButtonId::btnIncrease);
|
||||
button_dec = create_button(ButtonId::btnDecrease);
|
||||
delta = 0;
|
||||
timer.Bind(wxEVT_TIMER, &SpinInput::onTimer, this);
|
||||
|
||||
SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
if (parent) {
|
||||
SetBackgroundColour(parent->GetBackgroundColour());
|
||||
SetForegroundColour(parent->GetForegroundColour());
|
||||
}
|
||||
|
||||
long initialFromText;
|
||||
if (text.ToLong(&initialFromText)) initial = initialFromText;
|
||||
SetRange(min, max);
|
||||
SetValue(initial);
|
||||
messureSize();
|
||||
}
|
||||
|
||||
void SpinInput::bind_inc_dec_button(Button *btn, ButtonId id)
|
||||
{
|
||||
btn->Bind(wxEVT_LEFT_DOWN, [this, btn, id](auto& e) {
|
||||
delta = id == ButtonId::btnIncrease ? 1 : -1;
|
||||
SetValue(val + delta);
|
||||
text_ctrl->SetFocus();
|
||||
btn->CaptureMouse();
|
||||
delta *= 8;
|
||||
timer.Start(100);
|
||||
sendSpinEvent();
|
||||
});
|
||||
btn->Bind(wxEVT_LEFT_DCLICK, [this, btn, id](auto& e) {
|
||||
delta = id == ButtonId::btnIncrease ? 1 : -1;
|
||||
btn->CaptureMouse();
|
||||
SetValue(val + delta);
|
||||
sendSpinEvent();
|
||||
});
|
||||
btn->Bind(wxEVT_LEFT_UP, [this, btn](auto& e) {
|
||||
btn->ReleaseMouse();
|
||||
timer.Stop();
|
||||
text_ctrl->SelectAll();
|
||||
delta = 0;
|
||||
});
|
||||
}
|
||||
|
||||
void SpinInput::SetValue(const wxString &text)
|
||||
{
|
||||
long value;
|
||||
if ( text.ToLong(&value) )
|
||||
SetValue(value);
|
||||
else
|
||||
text_ctrl->SetValue(text);
|
||||
}
|
||||
|
||||
void SpinInput::SetValue(int value)
|
||||
{
|
||||
if (value < min) value = min;
|
||||
else if (value > max) value = max;
|
||||
this->val = value;
|
||||
text_ctrl->SetValue(wxString::FromDouble(value));
|
||||
}
|
||||
|
||||
int SpinInput::GetValue()const
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
void SpinInput::onTimer(wxTimerEvent &evnet) {
|
||||
if (delta < -1 || delta > 1) {
|
||||
delta /= 2;
|
||||
return;
|
||||
}
|
||||
SetValue(val + delta);
|
||||
sendSpinEvent();
|
||||
}
|
||||
|
||||
void SpinInput::onTextLostFocus(wxEvent &event)
|
||||
{
|
||||
timer.Stop();
|
||||
for (auto * child : GetChildren())
|
||||
if (auto btn = dynamic_cast<Button*>(child))
|
||||
if (btn->HasCapture())
|
||||
btn->ReleaseMouse();
|
||||
wxCommandEvent e;
|
||||
onTextEnter(e);
|
||||
// pass to outer
|
||||
event.SetId(GetId());
|
||||
ProcessEventLocally(event);
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void SpinInput::onTextEnter(wxCommandEvent &event)
|
||||
{
|
||||
long value;
|
||||
if (!text_ctrl->GetValue().ToLong(&value))
|
||||
value = val;
|
||||
|
||||
if (value != val) {
|
||||
SetValue(value);
|
||||
sendSpinEvent();
|
||||
}
|
||||
event.SetId(GetId());
|
||||
ProcessEventLocally(event);
|
||||
}
|
||||
|
||||
void SpinInput::mouseWheelMoved(wxMouseEvent &event)
|
||||
{
|
||||
auto delta = ((event.GetWheelRotation() < 0) == event.IsWheelInverted()) ? 1 : -1;
|
||||
SetValue(val + delta);
|
||||
sendSpinEvent();
|
||||
text_ctrl->SetFocus();
|
||||
}
|
||||
|
||||
void SpinInput::keyPressed(wxKeyEvent &event)
|
||||
{
|
||||
switch (event.GetKeyCode()) {
|
||||
case WXK_UP:
|
||||
case WXK_DOWN:
|
||||
long value;
|
||||
if (!text_ctrl->GetValue().ToLong(&value)) { value = val; }
|
||||
if (event.GetKeyCode() == WXK_DOWN && value > min) {
|
||||
--value;
|
||||
} else if (event.GetKeyCode() == WXK_UP && value + 1 < max) {
|
||||
++value;
|
||||
}
|
||||
if (value != val) {
|
||||
SetValue(value);
|
||||
sendSpinEvent();
|
||||
}
|
||||
break;
|
||||
default: event.Skip(); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// SpinInputDouble
|
||||
|
||||
SpinInputDouble::SpinInputDouble(wxWindow * parent,
|
||||
wxString text,
|
||||
wxString label,
|
||||
const wxPoint &pos,
|
||||
const wxSize & size,
|
||||
long style,
|
||||
double min, double max, double initial,
|
||||
double inc)
|
||||
: SpinInputBase()
|
||||
{
|
||||
Create(parent, text, label, pos, size, style, min, max, initial, inc);
|
||||
}
|
||||
|
||||
void SpinInputDouble::Create(wxWindow *parent,
|
||||
wxString text,
|
||||
wxString label,
|
||||
const wxPoint &pos,
|
||||
const wxSize & size,
|
||||
long style,
|
||||
double min, double max, double initial,
|
||||
double inc)
|
||||
{
|
||||
StaticBox::Create(parent, wxID_ANY, pos, size);
|
||||
wxWindow::SetLabel(label);
|
||||
|
||||
state_handler.attach({&label_color, &text_color});
|
||||
state_handler.update_binds();
|
||||
|
||||
text_ctrl = new wxTextCtrl(this, wxID_ANY, text, {20, 4}, wxDefaultSize, style | wxBORDER_NONE | wxTE_PROCESS_ENTER, wxTextValidator(wxFILTER_NUMERIC));
|
||||
#ifdef __WXOSX__
|
||||
text_ctrl->OSXDisableAllSmartSubstitutions();
|
||||
#endif // __WXOSX__
|
||||
text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
|
||||
state_handler.attach_child(text_ctrl);
|
||||
|
||||
text_ctrl->Bind(wxEVT_KILL_FOCUS, &SpinInputDouble::onTextLostFocus, this);
|
||||
text_ctrl->Bind(wxEVT_TEXT, &SpinInputDouble::onText, this);
|
||||
text_ctrl->Bind(wxEVT_TEXT_ENTER, &SpinInputDouble::onTextEnter, this);
|
||||
text_ctrl->Bind(wxEVT_KEY_DOWN, &SpinInputDouble::keyPressed, this);
|
||||
text_ctrl->Bind(wxEVT_RIGHT_DOWN, [](auto &e) {}); // disable context menu
|
||||
button_inc = create_button(ButtonId::btnIncrease);
|
||||
button_dec = create_button(ButtonId::btnDecrease);
|
||||
delta = 0;
|
||||
timer.Bind(wxEVT_TIMER, &SpinInputDouble::onTimer, this);
|
||||
|
||||
SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
if (parent) {
|
||||
SetBackgroundColour(parent->GetBackgroundColour());
|
||||
SetForegroundColour(parent->GetForegroundColour());
|
||||
}
|
||||
|
||||
double initialFromText;
|
||||
if (text.ToDouble(&initialFromText)) initial = initialFromText;
|
||||
SetRange(min, max);
|
||||
SetIncrement(inc);
|
||||
SetValue(initial);
|
||||
messureSize();
|
||||
}
|
||||
|
||||
void SpinInputDouble::bind_inc_dec_button(Button *btn, ButtonId id)
|
||||
{
|
||||
btn->Bind(wxEVT_LEFT_DOWN, [this, btn, id](auto& e) {
|
||||
delta = id == ButtonId::btnIncrease ? inc : -inc;
|
||||
SetValue(val + delta);
|
||||
text_ctrl->SetFocus();
|
||||
btn->CaptureMouse();
|
||||
delta *= 8;
|
||||
timer.Start(100);
|
||||
sendSpinEvent();
|
||||
});
|
||||
btn->Bind(wxEVT_LEFT_DCLICK, [this, btn, id](auto& e) {
|
||||
delta = id == ButtonId::btnIncrease ? inc : -inc;
|
||||
btn->CaptureMouse();
|
||||
SetValue(val + delta);
|
||||
sendSpinEvent();
|
||||
});
|
||||
btn->Bind(wxEVT_LEFT_UP, [this, btn](auto& e) {
|
||||
btn->ReleaseMouse();
|
||||
timer.Stop();
|
||||
text_ctrl->SelectAll();
|
||||
delta = 0;
|
||||
});
|
||||
}
|
||||
|
||||
void SpinInputDouble::SetValue(const wxString &text)
|
||||
{
|
||||
double value;
|
||||
if ( text.ToDouble(&value) )
|
||||
SetValue(value);
|
||||
else
|
||||
text_ctrl->SetValue(text);
|
||||
}
|
||||
|
||||
void SpinInputDouble::SetValue(double value)
|
||||
{
|
||||
if (Slic3r::is_approx(value, val))
|
||||
return;
|
||||
|
||||
if (value < min) value = min;
|
||||
else if (value > max) value = max;
|
||||
this->val = value;
|
||||
wxString str_val = wxString::FromDouble(value, digits);
|
||||
text_ctrl->SetValue(str_val);
|
||||
}
|
||||
|
||||
double SpinInputDouble::GetValue()const
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
void SpinInputDouble::SetRange(double min, double max)
|
||||
{
|
||||
this->min = min;
|
||||
this->max = max;
|
||||
}
|
||||
|
||||
void SpinInputDouble::SetIncrement(double inc_in)
|
||||
{
|
||||
inc = inc_in;
|
||||
}
|
||||
|
||||
void SpinInputDouble::SetDigits(unsigned digits_in)
|
||||
{
|
||||
digits = int(digits_in);
|
||||
}
|
||||
|
||||
void SpinInputDouble::onTimer(wxTimerEvent &evnet) {
|
||||
if (delta < -inc || delta > inc) {
|
||||
delta /= 2;
|
||||
return;
|
||||
}
|
||||
SetValue(val + delta);
|
||||
sendSpinEvent();
|
||||
}
|
||||
|
||||
void SpinInputDouble::onTextLostFocus(wxEvent &event)
|
||||
{
|
||||
timer.Stop();
|
||||
for (auto * child : GetChildren())
|
||||
if (auto btn = dynamic_cast<Button*>(child))
|
||||
if (btn->HasCapture())
|
||||
btn->ReleaseMouse();
|
||||
wxCommandEvent e;
|
||||
onTextEnter(e);
|
||||
// pass to outer
|
||||
event.SetId(GetId());
|
||||
ProcessEventLocally(event);
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void SpinInputDouble::onTextEnter(wxCommandEvent &event)
|
||||
{
|
||||
double value;
|
||||
if (!text_ctrl->GetValue().ToDouble(&value))
|
||||
val = value;
|
||||
|
||||
if (!Slic3r::is_approx(value, val)) {
|
||||
SetValue(value);
|
||||
sendSpinEvent();
|
||||
}
|
||||
event.SetId(GetId());
|
||||
ProcessEventLocally(event);
|
||||
}
|
||||
|
||||
void SpinInputDouble::mouseWheelMoved(wxMouseEvent &event)
|
||||
{
|
||||
auto delta = ((event.GetWheelRotation() < 0) == event.IsWheelInverted()) ? inc : -inc;
|
||||
SetValue(val + delta);
|
||||
sendSpinEvent();
|
||||
text_ctrl->SetFocus();
|
||||
}
|
||||
|
||||
void SpinInputDouble::keyPressed(wxKeyEvent &event)
|
||||
{
|
||||
switch (event.GetKeyCode()) {
|
||||
case WXK_UP:
|
||||
case WXK_DOWN:
|
||||
double value;
|
||||
if (!text_ctrl->GetValue().ToDouble(&value))
|
||||
val = value;
|
||||
|
||||
if (event.GetKeyCode() == WXK_DOWN && value > min) {
|
||||
value -= inc;
|
||||
} else if (event.GetKeyCode() == WXK_UP && value + inc < max) {
|
||||
value += inc;
|
||||
}
|
||||
if (!Slic3r::is_approx(value, val)) {
|
||||
SetValue(value);
|
||||
sendSpinEvent();
|
||||
}
|
||||
break;
|
||||
default: event.Skip(); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
190
src/slic3r/GUI/Widgets/SpinInput.hpp
Normal file
190
src/slic3r/GUI/Widgets/SpinInput.hpp
Normal file
@@ -0,0 +1,190 @@
|
||||
#ifndef slic3r_GUI_SpinInput_hpp_
|
||||
#define slic3r_GUI_SpinInput_hpp_
|
||||
|
||||
#include <wx/textctrl.h>
|
||||
#include "StaticBox.hpp"
|
||||
|
||||
class Button;
|
||||
|
||||
class SpinInputBase : public wxNavigationEnabled<StaticBox>
|
||||
{
|
||||
protected:
|
||||
wxSize labelSize;
|
||||
StateColor label_color;
|
||||
StateColor text_color;
|
||||
wxTextCtrl * text_ctrl{nullptr};
|
||||
Button * button_inc {nullptr};
|
||||
Button * button_dec {nullptr};
|
||||
wxTimer timer;
|
||||
|
||||
static const int SpinInputWidth = 200;
|
||||
static const int SpinInputHeight = 50;
|
||||
|
||||
enum class ButtonId
|
||||
{
|
||||
btnIncrease,
|
||||
btnDecrease
|
||||
};
|
||||
|
||||
public:
|
||||
SpinInputBase();
|
||||
|
||||
void SetCornerRadius(double radius);
|
||||
|
||||
void SetLabel(const wxString &label) wxOVERRIDE;
|
||||
|
||||
void SetLabelColor(StateColor const &color);
|
||||
|
||||
void SetTextColor(StateColor const &color);
|
||||
|
||||
void SetSize(wxSize const &size);
|
||||
|
||||
void Rescale();
|
||||
|
||||
virtual bool Enable(bool enable = true) wxOVERRIDE;
|
||||
|
||||
wxTextCtrl * GetText() { return text_ctrl; }
|
||||
|
||||
virtual void SetValue(const wxString &text) = 0;
|
||||
|
||||
wxString GetTextValue() const;
|
||||
|
||||
bool SetFont(wxFont const& font) override;
|
||||
|
||||
bool SetBackgroundColour(const wxColour& colour) override;
|
||||
bool SetForegroundColour(const wxColour& colour) override;
|
||||
void SetBorderColor(StateColor const& color);
|
||||
void SetSelection(long from, long to);
|
||||
|
||||
protected:
|
||||
void DoSetToolTipText(wxString const &tip) override;
|
||||
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
|
||||
void render(wxDC& dc);
|
||||
|
||||
void messureSize();
|
||||
|
||||
Button *create_button(ButtonId id);
|
||||
virtual void bind_inc_dec_button(Button *btn, ButtonId id) = 0;
|
||||
|
||||
// some useful events
|
||||
virtual void mouseWheelMoved(wxMouseEvent& event) = 0;
|
||||
virtual void keyPressed(wxKeyEvent& event) = 0;
|
||||
virtual void onTimer(wxTimerEvent &evnet) = 0;
|
||||
virtual void onTextLostFocus(wxEvent &event) = 0;
|
||||
virtual void onTextEnter(wxCommandEvent &event) = 0;
|
||||
|
||||
void onText(wxCommandEvent &event);
|
||||
|
||||
void sendSpinEvent();
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
class SpinInput : public SpinInputBase
|
||||
{
|
||||
int val;
|
||||
int min;
|
||||
int max;
|
||||
int delta;
|
||||
|
||||
public:
|
||||
SpinInput(wxWindow * parent,
|
||||
wxString text,
|
||||
wxString label = "",
|
||||
const wxPoint &pos = wxDefaultPosition,
|
||||
const wxSize & size = wxDefaultSize,
|
||||
long style = 0,
|
||||
int min = 0, int max = 100, int initial = 0);
|
||||
|
||||
void Create(wxWindow * parent,
|
||||
wxString text,
|
||||
wxString label = "",
|
||||
const wxPoint &pos = wxDefaultPosition,
|
||||
const wxSize & size = wxDefaultSize,
|
||||
long style = 0,
|
||||
int min = 0,
|
||||
int max = 100,
|
||||
int initial = 0);
|
||||
|
||||
void SetValue(const wxString &text) override;
|
||||
|
||||
void SetValue (int value);
|
||||
int GetValue () const;
|
||||
|
||||
void SetRange(int min, int max);
|
||||
|
||||
int GetMin() const { return this->min; }
|
||||
int GetMax() const { return this->max; }
|
||||
|
||||
protected:
|
||||
void bind_inc_dec_button(Button* btn, ButtonId id) override;
|
||||
// some useful events
|
||||
void mouseWheelMoved(wxMouseEvent& event) override;
|
||||
void keyPressed(wxKeyEvent& event) override;
|
||||
void onTimer(wxTimerEvent& evnet) override;
|
||||
void onTextLostFocus(wxEvent& event) override;
|
||||
void onTextEnter(wxCommandEvent& event) override;
|
||||
};
|
||||
|
||||
class SpinInputDouble : public SpinInputBase
|
||||
{
|
||||
double val;
|
||||
double min;
|
||||
double max;
|
||||
double inc;
|
||||
double delta;
|
||||
int digits {-1};
|
||||
|
||||
public:
|
||||
|
||||
SpinInputDouble() : SpinInputBase() {}
|
||||
|
||||
SpinInputDouble(wxWindow* parent,
|
||||
wxString text,
|
||||
wxString label = "",
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = 0,
|
||||
double min = 0.,
|
||||
double max = 100.,
|
||||
double initial = 0.,
|
||||
double inc = 1.);
|
||||
|
||||
void Create(wxWindow* parent,
|
||||
wxString text,
|
||||
wxString label = "",
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = 0,
|
||||
double min = 0.,
|
||||
double max = 100.,
|
||||
double initial = 0.,
|
||||
double inc = 1.);
|
||||
|
||||
void SetValue(const wxString& text) override;
|
||||
|
||||
void SetValue(double value);
|
||||
double GetValue() const;
|
||||
|
||||
//wxString GetTextValue() const override;
|
||||
|
||||
void SetRange(double min, double max);
|
||||
void SetIncrement(double inc);
|
||||
void SetDigits(unsigned digits);
|
||||
|
||||
double GetMin() const { return this->min; }
|
||||
double GetMax() const { return this->max; }
|
||||
|
||||
protected:
|
||||
void bind_inc_dec_button(Button* btn, ButtonId id) override;
|
||||
// some useful events
|
||||
void mouseWheelMoved(wxMouseEvent& event) override;
|
||||
void keyPressed(wxKeyEvent& event) override;
|
||||
void onTimer(wxTimerEvent& evnet) override;
|
||||
void onTextLostFocus(wxEvent& event) override;
|
||||
void onTextEnter(wxCommandEvent& event) override;
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_SpinInput_hpp_
|
||||
@@ -1,80 +1,5 @@
|
||||
#include "StateColor.hpp"
|
||||
|
||||
static bool gDarkMode = false;
|
||||
|
||||
static bool operator<(wxColour const &l, wxColour const &r) { return l.GetRGBA() < r.GetRGBA(); }
|
||||
|
||||
static std::map<wxColour, wxColour> gDarkColors{
|
||||
{"#00AE42", "#21A452"},
|
||||
{"#1F8EEA", "#2778D2"},
|
||||
{"#FF6F00", "#D15B00"},
|
||||
{"#D01B1B", "#BB2A3A"},
|
||||
{"#262E30", "#EFEFF0"},
|
||||
{"#2C2C2E", "#B3B3B4"},
|
||||
{"#6B6B6B", "#818183"},
|
||||
{"#ACACAC", "#54545A"},
|
||||
{"#EEEEEE", "#4C4C55"},
|
||||
{"#E8E8E8", "#3E3E45"},
|
||||
{"#323A3D", "#E5E5E4"},
|
||||
{"#FFFFFF", "#2D2D31"},
|
||||
{"#F8F8F8", "#36363C"},
|
||||
{"#F1F1F1", "#36363B"},
|
||||
{"#3B4446", "#2D2D30"},
|
||||
{"#CECECE", "#54545B"},
|
||||
{"#DBFDD5", "#3B3B40"},
|
||||
{"#000000", "#FFFFFE"},
|
||||
{"#F4F4F4", "#36363D"},
|
||||
{"#DBDBDB", "#4A4A51"},
|
||||
{"#EDFAF2", "#283232"},
|
||||
{"#323A3C", "#E5E5E6"},
|
||||
{"#6B6B6A", "#B3B3B5"},
|
||||
{"#303A3C", "#E5E5E5"},
|
||||
{"#FEFFFF", "#242428"},
|
||||
{"#A6A9AA", "#2D2D29"},
|
||||
{"#363636", "#B2B3B5"},
|
||||
{"#F0F0F1", "#404040"},
|
||||
{"#9E9E9E", "#53545A"},
|
||||
{"#D7E8DE", "#1F2B27"},
|
||||
{"#2B3436", "#808080"},
|
||||
{"#ABABAB", "#ABABAB"},
|
||||
{"#D9D9D9", "#2D2D32"},
|
||||
//{"#F0F0F0", "#4C4C54"},
|
||||
};
|
||||
|
||||
std::map<wxColour, wxColour> const & StateColor::GetDarkMap()
|
||||
{
|
||||
return gDarkColors;
|
||||
}
|
||||
|
||||
void StateColor::SetDarkMode(bool dark) { gDarkMode = dark; }
|
||||
|
||||
inline wxColour darkModeColorFor2(wxColour const &color)
|
||||
{
|
||||
if (!gDarkMode)
|
||||
return color;
|
||||
auto iter = gDarkColors.find(color);
|
||||
wxFAIL(iter != gDarkColors.end());
|
||||
if (iter != gDarkColors.end()) return iter->second;
|
||||
return color;
|
||||
}
|
||||
|
||||
std::map<wxColour, wxColour> revert(std::map<wxColour, wxColour> const & map)
|
||||
{
|
||||
std::map<wxColour, wxColour> map2;
|
||||
for (auto &p : map) map2.emplace(p.second, p.first);
|
||||
return map2;
|
||||
}
|
||||
|
||||
wxColour StateColor::lightModeColorFor(wxColour const &color)
|
||||
{
|
||||
static std::map<wxColour, wxColour> gLightColors = revert(gDarkColors);
|
||||
auto iter = gLightColors.find(color);
|
||||
wxFAIL(iter != gLightColors.end());
|
||||
if (iter != gLightColors.end()) return iter->second;
|
||||
return color;
|
||||
}
|
||||
|
||||
wxColour StateColor::darkModeColorFor(wxColour const &color) { return darkModeColorFor2(color); }
|
||||
|
||||
StateColor::StateColor(wxColour const &color) { append(color, 0); }
|
||||
|
||||
@@ -98,7 +23,7 @@ void StateColor::append(unsigned long color, int states)
|
||||
{
|
||||
if ((color & 0xff000000) == 0)
|
||||
color |= 0xff000000;
|
||||
wxColour cl; cl.SetRGBA(color & 0xff00ff00 | ((color & 0xff) << 16) | ((color >> 16) & 0xff));
|
||||
wxColour cl; cl.SetRGBA((color & 0xff00ff00) | ((color & 0xff) << 16) | ((color >> 16) & 0xff));
|
||||
append(cl, states);
|
||||
}
|
||||
|
||||
@@ -125,28 +50,7 @@ wxColour StateColor::defaultColor() {
|
||||
wxColour StateColor::colorForStates(int states)
|
||||
{
|
||||
bool focused = takeFocusedAsHovered_ && (states & Focused);
|
||||
for (int i = 0; i < statesList_.size(); ++i) {
|
||||
int s = statesList_[i];
|
||||
int on = s & 0xffff;
|
||||
int off = s >> 16;
|
||||
if ((on & states) == on && (off & ~states) == off) {
|
||||
return darkModeColorFor2(colors_[i]);
|
||||
}
|
||||
if (focused && (on & Hovered)) {
|
||||
on |= Focused;
|
||||
on &= ~Hovered;
|
||||
if ((on & states) == on && (off & ~states) == off) {
|
||||
return darkModeColorFor2(colors_[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return wxColour(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
wxColour StateColor::colorForStatesNoDark(int states)
|
||||
{
|
||||
bool focused = takeFocusedAsHovered_ && (states & Focused);
|
||||
for (int i = 0; i < statesList_.size(); ++i) {
|
||||
for (size_t i = 0; i < statesList_.size(); ++i) {
|
||||
int s = statesList_[i];
|
||||
int on = s & 0xffff;
|
||||
int off = s >> 16;
|
||||
@@ -166,18 +70,18 @@ wxColour StateColor::colorForStatesNoDark(int states)
|
||||
|
||||
int StateColor::colorIndexForStates(int states)
|
||||
{
|
||||
for (int i = 0; i < statesList_.size(); ++i) {
|
||||
for (size_t i = 0; i < statesList_.size(); ++i) {
|
||||
int s = statesList_[i];
|
||||
int on = s & 0xffff;
|
||||
int off = s >> 16;
|
||||
if ((on & states) == on && (off & ~states) == off) { return i; }
|
||||
if ((on & states) == on && (off & ~states) == off) { return int(i); }
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool StateColor::setColorForStates(wxColour const &color, int states)
|
||||
{
|
||||
for (int i = 0; i < statesList_.size(); ++i) {
|
||||
for (size_t i = 0; i < statesList_.size(); ++i) {
|
||||
if (statesList_[i] == states) {
|
||||
colors_[i] = color;
|
||||
return true;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include <wx/colour.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
class StateColor
|
||||
{
|
||||
@@ -22,13 +21,6 @@ public:
|
||||
NotPressed = 16 << 16,
|
||||
};
|
||||
|
||||
public:
|
||||
static void SetDarkMode(bool dark);
|
||||
|
||||
static std::map<wxColour, wxColour> const & GetDarkMap();
|
||||
static wxColour darkModeColorFor(wxColour const &color);
|
||||
static wxColour lightModeColorFor(wxColour const &color);
|
||||
|
||||
public:
|
||||
template<typename ...Colors>
|
||||
StateColor(std::pair<Colors, int>... colors) {
|
||||
@@ -63,7 +55,6 @@ public:
|
||||
|
||||
wxColour colorForStates(int states);
|
||||
|
||||
wxColour colorForStatesNoDark(int states);
|
||||
|
||||
int colorIndexForStates(int states);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "StateHandler.hpp"
|
||||
|
||||
#include <wx/window.h>
|
||||
wxDEFINE_EVENT(EVT_ENABLE_CHANGED, wxCommandEvent);
|
||||
|
||||
StateHandler::StateHandler(wxWindow * owner)
|
||||
@@ -50,7 +51,7 @@ void StateHandler::update_binds()
|
||||
int diff = bind_states ^ bind_states_;
|
||||
State states[] = {Enabled, Checked, Focused, Hovered, Pressed};
|
||||
wxEventType events[] = {EVT_ENABLE_CHANGED, wxEVT_CHECKBOX, wxEVT_SET_FOCUS, wxEVT_ENTER_WINDOW, wxEVT_LEFT_DOWN};
|
||||
wxEventType events2[] = {{0}, {0}, wxEVT_KILL_FOCUS, wxEVT_LEAVE_WINDOW, wxEVT_LEFT_UP};
|
||||
wxEventType events2[] = {0, 0, wxEVT_KILL_FOCUS, wxEVT_LEAVE_WINDOW, wxEVT_LEFT_UP};
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
int s = states[i];
|
||||
if (diff & s) {
|
||||
@@ -69,18 +70,6 @@ void StateHandler::update_binds()
|
||||
for (auto &c : children_) c->update_binds();
|
||||
}
|
||||
|
||||
void StateHandler::set_state(int state, int mask)
|
||||
{
|
||||
if (states_ & mask == state & mask) return;
|
||||
int old = states_;
|
||||
states_ = states_ & ~mask | state & mask;
|
||||
if (old != states_ && (old | states2_) != (states_ | states2_)) {
|
||||
if (parent_)
|
||||
parent_->changed(states_ | states2_);
|
||||
else
|
||||
owner_->Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
StateHandler::StateHandler(StateHandler *parent, wxWindow *owner)
|
||||
: StateHandler(owner)
|
||||
@@ -93,7 +82,7 @@ void StateHandler::changed(wxEvent &event)
|
||||
{
|
||||
event.Skip();
|
||||
wxEventType events[] = {EVT_ENABLE_CHANGED, wxEVT_CHECKBOX, wxEVT_SET_FOCUS, wxEVT_ENTER_WINDOW, wxEVT_LEFT_DOWN};
|
||||
wxEventType events2[] = {{0}, {0}, wxEVT_KILL_FOCUS, wxEVT_LEAVE_WINDOW, wxEVT_LEFT_UP};
|
||||
wxEventType events2[] = { 0, 0, wxEVT_KILL_FOCUS, wxEVT_LEAVE_WINDOW, wxEVT_LEFT_UP};
|
||||
int old = states_;
|
||||
// some events are from another window (ex: text_ctrl of TextInput), save state in states2_ to avoid conflicts
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
|
||||
@@ -2,14 +2,10 @@
|
||||
#define slic3r_GUI_StateHandler_hpp_
|
||||
|
||||
#include <wx/event.h>
|
||||
#include <memory>
|
||||
|
||||
#include "StateColor.hpp"
|
||||
|
||||
//B35
|
||||
#if defined __linux__
|
||||
#include<memory>
|
||||
#include <wx/wx.h>
|
||||
#endif
|
||||
|
||||
|
||||
wxDECLARE_EVENT(EVT_ENABLE_CHANGED, wxCommandEvent);
|
||||
@@ -48,7 +44,6 @@ public:
|
||||
|
||||
int states() const { return states_ | states2_; }
|
||||
|
||||
void set_state(int state, int mask);
|
||||
|
||||
private:
|
||||
StateHandler(StateHandler * parent, wxWindow *owner);
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#include "StaticBox.hpp"
|
||||
#include "../GUI.hpp"
|
||||
#include <wx/dcgraph.h>
|
||||
#include <wx/dcbuffer.h>
|
||||
|
||||
#include "DropDown.hpp"
|
||||
#include "UIColors.hpp"
|
||||
|
||||
BEGIN_EVENT_TABLE(StaticBox, wxWindow)
|
||||
|
||||
// catch paint events
|
||||
//EVT_ERASE_BACKGROUND(StaticBox::eraseEvent)
|
||||
EVT_PAINT(StaticBox::paintEvent)
|
||||
|
||||
END_EVENT_TABLE()
|
||||
@@ -20,9 +22,15 @@ StaticBox::StaticBox()
|
||||
: state_handler(this)
|
||||
, radius(8)
|
||||
{
|
||||
border_color = StateColor(
|
||||
std::make_pair(0xF0F0F1, (int) StateColor::Disabled),
|
||||
std::make_pair(0x303A3C, (int) StateColor::Normal));
|
||||
border_color = StateColor(std::make_pair(clr_border_disabled, (int) StateColor::Disabled),
|
||||
#ifndef __WXMSW__
|
||||
std::make_pair(clr_border_normal, (int) StateColor::Focused),
|
||||
#endif
|
||||
std::make_pair(clr_border_hovered, (int) StateColor::Hovered),
|
||||
std::make_pair(clr_border_normal, (int) StateColor::Normal));
|
||||
#ifndef __WXMSW__
|
||||
border_color.setTakeFocusedAsHovered(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
StaticBox::StaticBox(wxWindow* parent,
|
||||
@@ -41,7 +49,8 @@ bool StaticBox::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos, cons
|
||||
wxWindow::Create(parent, id, pos, size, style);
|
||||
state_handler.attach({&border_color, &background_color, &background_color2});
|
||||
state_handler.update_binds();
|
||||
SetBackgroundColour(GetParentBackgroundColor(parent));
|
||||
// SetBackgroundColour(GetParentBackgroundColor(parent));
|
||||
// SetForegroundColour(parent->GetParent()->GetForegroundColour());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -109,21 +118,11 @@ wxColor StaticBox::GetParentBackgroundColor(wxWindow* parent)
|
||||
return *wxWHITE;
|
||||
}
|
||||
|
||||
void StaticBox::eraseEvent(wxEraseEvent& evt)
|
||||
{
|
||||
// for transparent background, but not work
|
||||
#ifdef __WXMSW__
|
||||
wxDC *dc = evt.GetDC();
|
||||
wxSize size = GetSize();
|
||||
wxClientDC dc2(GetParent());
|
||||
dc->Blit({0, 0}, size, &dc2, GetPosition());
|
||||
#endif
|
||||
}
|
||||
|
||||
void StaticBox::paintEvent(wxPaintEvent& evt)
|
||||
{
|
||||
// depending on your system you may need to look at double-buffered dcs
|
||||
wxPaintDC dc(this);
|
||||
wxBufferedPaintDC dc(this);//wxPaintDC dc(this);
|
||||
render(dc);
|
||||
}
|
||||
|
||||
@@ -134,31 +133,7 @@ void StaticBox::paintEvent(wxPaintEvent& evt)
|
||||
*/
|
||||
void StaticBox::render(wxDC& dc)
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
if (radius == 0) {
|
||||
doRender(dc);
|
||||
return;
|
||||
}
|
||||
|
||||
wxSize size = GetSize();
|
||||
if (size.x <= 0 || size.y <= 0)
|
||||
return;
|
||||
wxMemoryDC memdc;
|
||||
wxBitmap bmp(size.x, size.y);
|
||||
memdc.SelectObject(bmp);
|
||||
//memdc.Blit({0, 0}, size, &dc, {0, 0});
|
||||
memdc.SetBackground(wxBrush(GetBackgroundColour()));
|
||||
memdc.Clear();
|
||||
{
|
||||
wxGCDC dc2(memdc);
|
||||
doRender(dc2);
|
||||
}
|
||||
|
||||
memdc.SelectObject(wxNullBitmap);
|
||||
dc.DrawBitmap(bmp, 0, 0);
|
||||
#else
|
||||
doRender(dc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void StaticBox::doRender(wxDC& dc)
|
||||
@@ -168,37 +143,53 @@ void StaticBox::doRender(wxDC& dc)
|
||||
if (background_color2.count() == 0) {
|
||||
if ((border_width && border_color.count() > 0) || background_color.count() > 0) {
|
||||
wxRect rc(0, 0, size.x, size.y);
|
||||
if (border_width && border_color.count() > 0) {
|
||||
if (dc.GetContentScaleFactor() == 1.0) {
|
||||
int d = floor(border_width / 2.0);
|
||||
int d2 = floor(border_width - 1);
|
||||
rc.x += d;
|
||||
rc.width -= d2;
|
||||
rc.y += d;
|
||||
rc.height -= d2;
|
||||
} else {
|
||||
int d = 1;
|
||||
rc.x += d;
|
||||
rc.width -= d;
|
||||
rc.y += d;
|
||||
rc.height -= d;
|
||||
}
|
||||
dc.SetPen(wxPen(border_color.colorForStates(states), border_width));
|
||||
} else {
|
||||
dc.SetPen(wxPen(background_color.colorForStates(states)));
|
||||
#ifdef __WXOSX__
|
||||
// On Retina displays all controls are cut on 1px
|
||||
if (dc.GetContentScaleFactor() > 1.)
|
||||
rc.Deflate(1, 1);
|
||||
#endif //__WXOSX__
|
||||
|
||||
if (radius > 0.) {
|
||||
#if 0
|
||||
DropDown::SetTransparentBG(dc, this);
|
||||
#else
|
||||
#ifdef __WXMSW__
|
||||
wxColour bg_clr = GetParentBackgroundColor(m_parent);
|
||||
dc.SetBrush(wxBrush(bg_clr));
|
||||
dc.SetPen(wxPen(bg_clr));
|
||||
dc.DrawRectangle(rc);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
if (background_color.count() > 0)
|
||||
dc.SetBrush(wxBrush(background_color.colorForStates(states)));
|
||||
else
|
||||
dc.SetBrush(wxBrush(GetBackgroundColour()));
|
||||
if (radius == 0) {
|
||||
dc.DrawRectangle(rc);
|
||||
if (border_width && border_color.count() > 0) {
|
||||
#ifdef __WXOSX__
|
||||
const double bw = (double)border_width;
|
||||
#else
|
||||
const double bw = dc.GetContentScaleFactor() * (double)border_width;
|
||||
#endif //__WXOSX__
|
||||
{
|
||||
int d = floor(bw / 2.0);
|
||||
int d2 = floor(bw - 1);
|
||||
rc.x += d;
|
||||
rc.width -= d2;
|
||||
rc.y += d;
|
||||
rc.height -= d2;
|
||||
}
|
||||
dc.SetPen(wxPen(border_color.colorForStates(states), bw));
|
||||
} else {
|
||||
dc.SetPen(wxPen(background_color.colorForStates(states)));
|
||||
}
|
||||
else {
|
||||
if (radius == 0.)
|
||||
dc.DrawRectangle(rc);
|
||||
else
|
||||
dc.DrawRoundedRectangle(rc, radius - border_width);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
wxColor start = background_color.colorForStates(states);
|
||||
wxColor stop = background_color2.colorForStates(states);
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
|
||||
void SetBorderColorNormal(wxColor const &color);
|
||||
|
||||
void SetBackgroundColor(StateColor const &color);
|
||||
virtual void SetBackgroundColor(StateColor const &color);
|
||||
|
||||
void SetBackgroundColorNormal(wxColor const &color);
|
||||
|
||||
@@ -40,7 +40,6 @@ public:
|
||||
static wxColor GetParentBackgroundColor(wxWindow * parent);
|
||||
|
||||
protected:
|
||||
void eraseEvent(wxEraseEvent& evt);
|
||||
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
|
||||
@@ -48,7 +47,6 @@ protected:
|
||||
|
||||
virtual void doRender(wxDC& dc);
|
||||
|
||||
protected:
|
||||
double radius;
|
||||
int border_width = 1;
|
||||
StateHandler state_handler;
|
||||
|
||||
136
src/slic3r/GUI/Widgets/SwitchButton.cpp
Normal file
136
src/slic3r/GUI/Widgets/SwitchButton.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
#include "SwitchButton.hpp"
|
||||
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "../../Utils/MacDarkMode.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
#include <wx/dcmemory.h>
|
||||
#include <wx/dcclient.h>
|
||||
|
||||
SwitchButton::SwitchButton(wxWindow* parent, const wxString& name, wxWindowID id)
|
||||
: BitmapToggleButton(parent, name, id)
|
||||
, m_on(this, "toggle_on", 28, 16)
|
||||
, m_off(this, "toggle_off", 28, 16)
|
||||
, text_color(std::pair{*wxWHITE, (int) StateColor::Checked}, std::pair{0x6B6B6B, (int) StateColor::Normal})
|
||||
, track_color(0xD9D9D9)
|
||||
, thumb_color(std::pair{0x00AE42, (int) StateColor::Checked}, std::pair{0xD9D9D9, (int) StateColor::Normal})
|
||||
{
|
||||
Rescale();
|
||||
}
|
||||
|
||||
void SwitchButton::SetLabels(wxString const& lbl_on, wxString const& lbl_off)
|
||||
{
|
||||
labels[0] = lbl_on;
|
||||
labels[1] = lbl_off;
|
||||
Rescale();
|
||||
}
|
||||
|
||||
void SwitchButton::SetTextColor(StateColor const& color)
|
||||
{
|
||||
text_color = color;
|
||||
}
|
||||
|
||||
void SwitchButton::SetTrackColor(StateColor const& color)
|
||||
{
|
||||
track_color = color;
|
||||
}
|
||||
|
||||
void SwitchButton::SetThumbColor(StateColor const& color)
|
||||
{
|
||||
thumb_color = color;
|
||||
}
|
||||
|
||||
void SwitchButton::SetValue(bool value)
|
||||
{
|
||||
if (value != GetValue())
|
||||
wxBitmapToggleButton::SetValue(value);
|
||||
update();
|
||||
}
|
||||
|
||||
void SwitchButton::Rescale()
|
||||
{
|
||||
if (!labels[0].IsEmpty()) {
|
||||
#ifdef __WXOSX__
|
||||
auto scale = Slic3r::GUI::mac_max_scaling_factor();
|
||||
int BS = (int) scale;
|
||||
#else
|
||||
constexpr int BS = 1;
|
||||
#endif
|
||||
wxSize thumbSize;
|
||||
wxSize trackSize;
|
||||
wxClientDC dc(this);
|
||||
#ifdef __WXOSX__
|
||||
dc.SetFont(dc.GetFont().Scaled(scale));
|
||||
#endif
|
||||
wxSize textSize[2];
|
||||
{
|
||||
textSize[0] = dc.GetTextExtent(labels[0]);
|
||||
textSize[1] = dc.GetTextExtent(labels[1]);
|
||||
}
|
||||
{
|
||||
thumbSize = textSize[0];
|
||||
auto size = textSize[1];
|
||||
if (size.x > thumbSize.x) thumbSize.x = size.x;
|
||||
else size.x = thumbSize.x;
|
||||
thumbSize.x += BS * 12;
|
||||
thumbSize.y += BS * 6;
|
||||
trackSize.x = thumbSize.x + size.x + BS * 10;
|
||||
trackSize.y = thumbSize.y + BS * 2;
|
||||
auto maxWidth = GetMaxWidth();
|
||||
#ifdef __WXOSX__
|
||||
maxWidth *= scale;
|
||||
#endif
|
||||
if (trackSize.x > maxWidth) {
|
||||
thumbSize.x -= (trackSize.x - maxWidth) / 2;
|
||||
trackSize.x = maxWidth;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
wxMemoryDC memdc(&dc);
|
||||
wxBitmap bmp(trackSize.x, trackSize.y);
|
||||
memdc.SelectObject(bmp);
|
||||
memdc.SetBackground(wxBrush(GetBackgroundColour()));
|
||||
memdc.Clear();
|
||||
memdc.SetFont(dc.GetFont());
|
||||
auto state = i == 0 ? StateColor::Enabled : (StateColor::Checked | StateColor::Enabled);
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
wxGCDC dc2(memdc);
|
||||
#else
|
||||
wxDC &dc2(memdc);
|
||||
#endif
|
||||
dc2.SetBrush(wxBrush(track_color.colorForStates(state)));
|
||||
dc2.SetPen(wxPen(track_color.colorForStates(state)));
|
||||
dc2.DrawRoundedRectangle(wxRect({0, 0}, trackSize), trackSize.y / 2);
|
||||
dc2.SetBrush(wxBrush(thumb_color.colorForStates(StateColor::Checked | StateColor::Enabled)));
|
||||
dc2.SetPen(wxPen(thumb_color.colorForStates(StateColor::Checked | StateColor::Enabled)));
|
||||
dc2.DrawRoundedRectangle(wxRect({ i == 0 ? BS : (trackSize.x - thumbSize.x - BS), BS}, thumbSize), thumbSize.y / 2);
|
||||
}
|
||||
memdc.SetTextForeground(text_color.colorForStates(state ^ StateColor::Checked));
|
||||
memdc.DrawText(labels[0], {BS + (thumbSize.x - textSize[0].x) / 2, BS + (thumbSize.y - textSize[0].y) / 2});
|
||||
memdc.SetTextForeground(text_color.colorForStates(state));
|
||||
memdc.DrawText(labels[1], {trackSize.x - thumbSize.x - BS + (thumbSize.x - textSize[1].x) / 2, BS + (thumbSize.y - textSize[1].y) / 2});
|
||||
memdc.SelectObject(wxNullBitmap);
|
||||
#ifdef __WXOSX__
|
||||
bmp = wxBitmap(bmp.ConvertToImage(), -1, scale);
|
||||
#endif
|
||||
(i == 0 ? m_off : m_on).SetBitmap(bmp);
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void SwitchButton::SysColorChange()
|
||||
{
|
||||
m_on.sys_color_changed();
|
||||
m_off.sys_color_changed();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void SwitchButton::update()
|
||||
{
|
||||
SetBitmap((GetValue() ? m_on : m_off).bmp());
|
||||
update_size();
|
||||
}
|
||||
42
src/slic3r/GUI/Widgets/SwitchButton.hpp
Normal file
42
src/slic3r/GUI/Widgets/SwitchButton.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef slic3r_GUI_SwitchButton_hpp_
|
||||
#define slic3r_GUI_SwitchButton_hpp_
|
||||
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "StateColor.hpp"
|
||||
|
||||
#include "BitmapToggleButton.hpp"
|
||||
|
||||
class SwitchButton : public BitmapToggleButton
|
||||
{
|
||||
public:
|
||||
SwitchButton(wxWindow * parent = NULL, const wxString& name = wxEmptyString, wxWindowID id = wxID_ANY);
|
||||
|
||||
public:
|
||||
void SetLabels(wxString const & lbl_on, wxString const & lbl_off);
|
||||
|
||||
void SetTextColor(StateColor const &color);
|
||||
|
||||
void SetTrackColor(StateColor const &color);
|
||||
|
||||
void SetThumbColor(StateColor const &color);
|
||||
|
||||
void SetValue(bool value) override;
|
||||
|
||||
void Rescale();
|
||||
|
||||
void SysColorChange();
|
||||
|
||||
private:
|
||||
void update() override;
|
||||
|
||||
private:
|
||||
ScalableBitmap m_on;
|
||||
ScalableBitmap m_off;
|
||||
|
||||
wxString labels[2];
|
||||
StateColor text_color;
|
||||
StateColor track_color;
|
||||
StateColor thumb_color;
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_SwitchButton_hpp_
|
||||
@@ -1,9 +1,10 @@
|
||||
#include "TextInput.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "TextCtrl.h"
|
||||
#include "slic3r/GUI/Widgets/Label.hpp"
|
||||
#include "UIColors.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
|
||||
BEGIN_EVENT_TABLE(TextInput, wxPanel)
|
||||
|
||||
@@ -23,12 +24,9 @@ TextInput::TextInput()
|
||||
, text_color(std::make_pair(0x909090, (int) StateColor::Disabled),
|
||||
std::make_pair(0x262E30, (int) StateColor::Normal))
|
||||
{
|
||||
if (Slic3r::GUI::wxGetApp().suppress_round_corners())
|
||||
radius = 0;
|
||||
border_width = 1;
|
||||
border_color = StateColor(std::make_pair(0xDBDBDB, (int) StateColor::Disabled), std::make_pair(0x009688, (int) StateColor::Hovered),
|
||||
std::make_pair(0xDBDBDB, (int) StateColor::Normal));
|
||||
background_color = StateColor(std::make_pair(0xF0F0F1, (int) StateColor::Disabled), std::make_pair(*wxWHITE, (int) StateColor::Normal));
|
||||
SetFont(Label::Body_12);
|
||||
}
|
||||
|
||||
TextInput::TextInput(wxWindow * parent,
|
||||
@@ -54,14 +52,17 @@ void TextInput::Create(wxWindow * parent,
|
||||
text_ctrl = nullptr;
|
||||
StaticBox::Create(parent, wxID_ANY, pos, size, style);
|
||||
wxWindow::SetLabel(label);
|
||||
style &= ~wxRIGHT;
|
||||
state_handler.attach({&label_color, & text_color});
|
||||
state_handler.update_binds();
|
||||
text_ctrl = new TextCtrl(this, wxID_ANY, text, {4, 4}, wxDefaultSize, style | wxBORDER_NONE | wxTE_PROCESS_ENTER);
|
||||
text_ctrl->SetFont(Label::Body_14);
|
||||
text_ctrl = new wxTextCtrl(this, wxID_ANY, text, {4, 4}, size, style | wxBORDER_NONE);
|
||||
#ifdef __WXOSX__
|
||||
text_ctrl->OSXDisableAllSmartSubstitutions();
|
||||
#endif // __WXOSX__
|
||||
text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
|
||||
text_ctrl->SetBackgroundColour(background_color.colorForStates(state_handler.states()));
|
||||
text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states()));
|
||||
if (parent) {
|
||||
SetBackgroundColour(parent->GetBackgroundColour());
|
||||
SetForegroundColour(parent->GetForegroundColour());
|
||||
}
|
||||
state_handler.attach_child(text_ctrl);
|
||||
text_ctrl->Bind(wxEVT_KILL_FOCUS, [this](auto &e) {
|
||||
OnEdit();
|
||||
@@ -74,18 +75,17 @@ void TextInput::Create(wxWindow * parent,
|
||||
e.SetId(GetId());
|
||||
ProcessEventLocally(e);
|
||||
});
|
||||
text_ctrl->Bind(wxEVT_RIGHT_DOWN, [this](auto &e) {}); // disable context menu
|
||||
text_ctrl->Bind(wxEVT_TEXT, [this](auto &e) {
|
||||
e.SetId(GetId());
|
||||
ProcessEventLocally(e);
|
||||
});
|
||||
text_ctrl->Bind(wxEVT_RIGHT_DOWN, [](auto &e) {}); // disable context menu
|
||||
if (!icon.IsEmpty()) {
|
||||
this->icon = ScalableBitmap(this, icon.ToStdString(), 16);
|
||||
this->drop_down_icon = ScalableBitmap(this, icon.ToStdString(), 16);
|
||||
}
|
||||
messureSize();
|
||||
}
|
||||
|
||||
void TextInput::SetCornerRadius(double radius)
|
||||
{
|
||||
this->radius = radius;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void TextInput::SetLabel(const wxString& label)
|
||||
{
|
||||
@@ -94,10 +94,54 @@ void TextInput::SetLabel(const wxString& label)
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void TextInput::SetIcon(const wxBitmap &icon)
|
||||
bool TextInput::SetBackgroundColour(const wxColour& colour)
|
||||
{
|
||||
this->icon.get_bitmap() = icon;
|
||||
Rescale();
|
||||
const int clr_background_disabled = Slic3r::GUI::wxGetApp().dark_mode() ? clr_background_disabled_dark : clr_background_disabled_light;
|
||||
const StateColor clr_state( std::make_pair(clr_background_disabled, (int)StateColor::Disabled),
|
||||
std::make_pair(clr_background_focused, (int)StateColor::Checked),
|
||||
std::make_pair(colour, (int)StateColor::Focused),
|
||||
std::make_pair(colour, (int)StateColor::Normal));
|
||||
|
||||
SetBackgroundColor(clr_state);
|
||||
if (text_ctrl)
|
||||
text_ctrl->SetBackgroundColour(colour);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TextInput::SetForegroundColour(const wxColour& colour)
|
||||
{
|
||||
const StateColor clr_state( std::make_pair(clr_foreground_disabled, (int)StateColor::Disabled),
|
||||
std::make_pair(colour, (int)StateColor::Normal));
|
||||
|
||||
SetLabelColor(clr_state);
|
||||
SetTextColor (clr_state);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TextInput::SetValue(const wxString& value)
|
||||
{
|
||||
if (text_ctrl)
|
||||
text_ctrl->SetValue(value);
|
||||
}
|
||||
|
||||
wxString TextInput::GetValue()
|
||||
{
|
||||
if (text_ctrl)
|
||||
return text_ctrl->GetValue();
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
void TextInput::SetSelection(long from, long to)
|
||||
{
|
||||
if (text_ctrl)
|
||||
text_ctrl->SetSelection(from, to);
|
||||
}
|
||||
|
||||
void TextInput::SetIcon(const wxBitmapBundle& icon_in)
|
||||
{
|
||||
icon = icon_in;
|
||||
}
|
||||
|
||||
void TextInput::SetLabelColor(StateColor const &color)
|
||||
@@ -110,16 +154,37 @@ void TextInput::SetTextColor(StateColor const& color)
|
||||
{
|
||||
text_color= color;
|
||||
state_handler.update_binds();
|
||||
if (text_ctrl)
|
||||
text_ctrl->SetForegroundColour(text_color.colorForStates(state_handler.states()));
|
||||
}
|
||||
|
||||
void TextInput::SetBGColor(StateColor const& color)
|
||||
{
|
||||
background_color = color;
|
||||
state_handler.update_binds();
|
||||
}
|
||||
|
||||
void TextInput::SetCtrlSize(wxSize const& size)
|
||||
{
|
||||
StaticBox::SetInitialSize(size);
|
||||
Rescale();
|
||||
}
|
||||
|
||||
void TextInput::Rescale()
|
||||
{
|
||||
if (!this->icon.name().empty())
|
||||
this->icon.msw_rescale();
|
||||
if (text_ctrl)
|
||||
text_ctrl->SetInitialSize(text_ctrl->GetBestSize());
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
bool TextInput::SetFont(const wxFont& font)
|
||||
{
|
||||
bool ret = StaticBox::SetFont(font);
|
||||
if (text_ctrl)
|
||||
return ret && text_ctrl->SetFont(font);
|
||||
return ret;
|
||||
}
|
||||
bool TextInput::Enable(bool enable)
|
||||
{
|
||||
bool result = text_ctrl->Enable(enable) && wxWindow::Enable(enable);
|
||||
@@ -151,16 +216,21 @@ void TextInput::DoSetSize(int x, int y, int width, int height, int sizeFlags)
|
||||
if (sizeFlags & wxSIZE_USE_EXISTING) return;
|
||||
wxSize size = GetSize();
|
||||
wxPoint textPos = {5, 0};
|
||||
if (this->icon.get_bitmap().IsOk()) {
|
||||
wxSize szIcon = this->icon.GetSize();
|
||||
if (this->icon.IsOk()) {
|
||||
wxSize szIcon = get_preferred_size(icon, m_parent);
|
||||
textPos.x += szIcon.x;
|
||||
}
|
||||
wxSize dd_icon_size = wxSize(0,0);
|
||||
if (this->drop_down_icon.bmp().IsOk())
|
||||
dd_icon_size = this->drop_down_icon.GetSize();
|
||||
bool align_right = GetWindowStyle() & wxRIGHT;
|
||||
if (align_right)
|
||||
textPos.x += labelSize.x;
|
||||
if (text_ctrl) {
|
||||
wxSize textSize = text_ctrl->GetSize();
|
||||
textSize.x = size.x - textPos.x - labelSize.x - 10;
|
||||
wxClientDC dc(this);
|
||||
const int r_shift = int((dd_icon_size.x == 0 ? 3. : 2.) * dc.GetContentScaleFactor());
|
||||
textSize.x = size.x - textPos.x - labelSize.x - dd_icon_size.x - r_shift;
|
||||
text_ctrl->SetSize(textSize);
|
||||
text_ctrl->SetPosition({textPos.x, (size.y - textSize.y) / 2});
|
||||
}
|
||||
@@ -192,28 +262,38 @@ void TextInput::render(wxDC& dc)
|
||||
bool align_right = GetWindowStyle() & wxRIGHT;
|
||||
// start draw
|
||||
wxPoint pt = {5, 0};
|
||||
if (icon.get_bitmap().IsOk()) {
|
||||
wxSize szIcon = icon.GetSize();
|
||||
if (icon.IsOk()) {
|
||||
wxSize szIcon = get_preferred_size(icon, m_parent);
|
||||
pt.y = (size.y - szIcon.y) / 2;
|
||||
dc.DrawBitmap(icon.get_bitmap(), pt);
|
||||
pt.x += szIcon.x + 0;
|
||||
#ifdef __WXGTK3__
|
||||
dc.DrawBitmap(icon.GetBitmap(szIcon), pt);
|
||||
#else
|
||||
dc.DrawBitmap(icon.GetBitmapFor(m_parent), pt);
|
||||
#endif
|
||||
pt.x += szIcon.x + 5;
|
||||
}
|
||||
|
||||
// drop_down_icon draw
|
||||
wxPoint pt_r = {size.x, 0};
|
||||
if (drop_down_icon.bmp().IsOk()) {
|
||||
wxSize szIcon = drop_down_icon.GetSize();
|
||||
pt_r.x -= szIcon.x + 2;
|
||||
pt_r.y = (size.y - szIcon.y) / 2;
|
||||
dc.DrawBitmap(drop_down_icon.get_bitmap(), pt_r);
|
||||
}
|
||||
auto text = wxWindow::GetLabel();
|
||||
if (!text.IsEmpty()) {
|
||||
wxSize textSize = text_ctrl->GetSize();
|
||||
if (align_right) {
|
||||
if (pt.x + labelSize.x > size.x)
|
||||
text = wxControl::Ellipsize(text, dc, wxELLIPSIZE_END, size.x - pt.x);
|
||||
pt.y = (size.y - labelSize.y) / 2;
|
||||
} else {
|
||||
pt.x += textSize.x;
|
||||
pt.y = (size.y + textSize.y) / 2 - labelSize.y;
|
||||
} else {
|
||||
if (pt.x + labelSize.x > pt_r.x)
|
||||
text = wxControl::Ellipsize(text, dc, wxELLIPSIZE_END, pt_r.x - pt.x);
|
||||
pt.y = (size.y - labelSize.y) / 2;
|
||||
}
|
||||
dc.SetTextForeground(label_color.colorForStates(states));
|
||||
if(align_right)
|
||||
dc.SetFont(GetFont());
|
||||
else
|
||||
dc.SetFont(Label::Body_12);
|
||||
dc.DrawText(text, pt);
|
||||
}
|
||||
}
|
||||
@@ -222,17 +302,10 @@ void TextInput::messureSize()
|
||||
{
|
||||
wxSize size = GetSize();
|
||||
wxClientDC dc(this);
|
||||
bool align_right = GetWindowStyle() & wxRIGHT;
|
||||
if (align_right)
|
||||
dc.SetFont(GetFont());
|
||||
else
|
||||
dc.SetFont(Label::Body_12);
|
||||
labelSize = dc.GetTextExtent(wxWindow::GetLabel());
|
||||
wxSize textSize = text_ctrl->GetSize();
|
||||
int h = textSize.y + 8;
|
||||
if (size.y < h) {
|
||||
size.y = h;
|
||||
}
|
||||
const wxSize textSize = text_ctrl->GetSize();
|
||||
const wxSize iconSize = drop_down_icon.bmp().IsOk() ? drop_down_icon.GetSize() : wxSize(0, 0);
|
||||
size.y = ((textSize.y > iconSize.y) ? textSize.y : iconSize.y) + 8;
|
||||
wxSize minSize = size;
|
||||
minSize.x = GetMinWidth();
|
||||
SetMinSize(minSize);
|
||||
|
||||
@@ -8,10 +8,11 @@ class TextInput : public wxNavigationEnabled<StaticBox>
|
||||
{
|
||||
|
||||
wxSize labelSize;
|
||||
ScalableBitmap icon;
|
||||
wxBitmapBundle icon;
|
||||
ScalableBitmap drop_down_icon;
|
||||
StateColor label_color;
|
||||
StateColor text_color;
|
||||
wxTextCtrl * text_ctrl;
|
||||
wxTextCtrl* text_ctrl{nullptr};
|
||||
|
||||
static const int TextInputWidth = 200;
|
||||
static const int TextInputHeight = 50;
|
||||
@@ -36,34 +37,44 @@ public:
|
||||
const wxSize & size = wxDefaultSize,
|
||||
long style = 0);
|
||||
|
||||
void SetCornerRadius(double radius);
|
||||
void SetLabel(const wxString& label) wxOVERRIDE;
|
||||
|
||||
void SetLabel(const wxString& label);
|
||||
|
||||
void SetIcon(const wxBitmap &icon);
|
||||
void SetIcon(const wxBitmapBundle& icon);
|
||||
|
||||
void SetLabelColor(StateColor const &color);
|
||||
|
||||
void SetBGColor(StateColor const &color);
|
||||
void SetTextColor(StateColor const &color);
|
||||
|
||||
void SetCtrlSize(wxSize const& size);
|
||||
virtual void Rescale();
|
||||
|
||||
bool SetFont(const wxFont &font) override;
|
||||
virtual bool Enable(bool enable = true) override;
|
||||
|
||||
virtual void SetMinSize(const wxSize& size) override;
|
||||
|
||||
bool SetBackgroundColour(const wxColour &colour) override;
|
||||
|
||||
bool SetForegroundColour(const wxColour &colour) override;
|
||||
wxTextCtrl *GetTextCtrl() { return text_ctrl; }
|
||||
|
||||
wxTextCtrl const *GetTextCtrl() const { return text_ctrl; }
|
||||
|
||||
void SetValue(const wxString& value);
|
||||
|
||||
wxString GetValue();
|
||||
|
||||
void SetSelection(long from, long to);
|
||||
protected:
|
||||
virtual void OnEdit() {}
|
||||
|
||||
virtual void DoSetSize(
|
||||
int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
|
||||
void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO) wxOVERRIDE;
|
||||
|
||||
void DoSetToolTipText(wxString const &tip) override;
|
||||
|
||||
StateColor GetTextColor() const { return text_color; }
|
||||
StateColor GetBorderColor() const { return border_color; }
|
||||
private:
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
|
||||
|
||||
18
src/slic3r/GUI/Widgets/UIColors.hpp
Normal file
18
src/slic3r/GUI/Widgets/UIColors.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef slic3r_UI_Colors_hpp_
|
||||
#define slic3r_UI_Colors_hpp_
|
||||
|
||||
static const int clr_border_normal = 0x646464;//0xDBDBDB;
|
||||
static const int clr_border_hovered = 0xED6B21;//0x00AE42;
|
||||
static const int clr_border_disabled = 0x646464;//0xDBDBDB;
|
||||
|
||||
static const int clr_background_normal_light = 0xFFFFFF;
|
||||
static const int clr_background_normal_dark = 0x2B2B2B;//0x434343;
|
||||
static const int clr_background_focused = 0xED6B21;//0xEDFAF2;
|
||||
static const int clr_background_disabled_dark = 0x404040;//0xF0F0F0;
|
||||
static const int clr_background_disabled_light = 0xD9D9D9;//0xF0F0F0;
|
||||
|
||||
static const int clr_foreground_normal = 0x262E30;
|
||||
static const int clr_foreground_focused = 0x00AE42;
|
||||
static const int clr_foreground_disabled = 0x909090;
|
||||
|
||||
#endif // !slic3r_UI_Colors_hpp_
|
||||
Reference in New Issue
Block a user