mirror of
https://github.com/QIDITECH/QIDISlicer.git
synced 2026-01-30 23:48:44 +03:00
MAC
This commit is contained in:
@@ -71,9 +71,9 @@ typedef unsigned int UINT32;
|
||||
typedef int INT;
|
||||
#endif
|
||||
|
||||
#ifndef INT32
|
||||
typedef int INT32;
|
||||
#endif
|
||||
// #ifndef INT32
|
||||
// typedef int INT32;
|
||||
// #endif
|
||||
|
||||
typedef unsigned char INT8U; /* Unsigned 8 bit quantity */
|
||||
typedef signed char INT8S; /* Signed 8 bit quantity */
|
||||
|
||||
@@ -20,6 +20,12 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/Widgets/StateColor.hpp
|
||||
GUI/Widgets/WebView.cpp
|
||||
GUI/Widgets/WebView.hpp
|
||||
GUI/Widgets/Label.cpp
|
||||
GUI/Widgets/Label.hpp
|
||||
GUI/Widgets/StateHandler.cpp
|
||||
GUI/Widgets/StateHandler.hpp
|
||||
GUI/Widgets/StaticBox.cpp
|
||||
GUI/Widgets/StaticBox.hpp
|
||||
GUI/ConfigSnapshotDialog.cpp
|
||||
GUI/ConfigSnapshotDialog.hpp
|
||||
GUI/3DScene.cpp
|
||||
|
||||
@@ -286,8 +286,8 @@ private:
|
||||
// credits infornation
|
||||
credits = title + " " +
|
||||
// B11
|
||||
" ";
|
||||
// _L("is based on Slic3r by Alessandro Ranellucci and the RepRap community.") + "\n" +
|
||||
_L("is based on Slic3r by Alessandro Ranellucci and the RepRap community.") + "\n";
|
||||
//+
|
||||
// _L("Developed by QIDI Research.") + "\n\n" +
|
||||
// title + " " + _L("is licensed under the") + " " + _L("GNU Affero General Public License, version 3") + ".\n\n" +
|
||||
// _L("Contributions by Vojtech Bubnik, Enrico Turri, Oleksandra Iushchenko, Tamas Meszaros, Lukas Matena, Vojtech Kral, David Kocik and numerous others.") + "\n\n" +
|
||||
|
||||
288
src/slic3r/GUI/Widgets/Label.cpp
Normal file
288
src/slic3r/GUI/Widgets/Label.cpp
Normal file
@@ -0,0 +1,288 @@
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "StaticBox.hpp"
|
||||
|
||||
wxFont Label::sysFont(int size, bool bold)
|
||||
{
|
||||
//#ifdef __linux__
|
||||
// return wxFont{};
|
||||
//#endif
|
||||
#ifndef __APPLE__
|
||||
size = size * 4 / 5;
|
||||
#endif
|
||||
|
||||
auto face = wxString::FromUTF8("HarmonyOS Sans SC");
|
||||
wxFont font{size, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, bold ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL, false, face};
|
||||
font.SetFaceName(face);
|
||||
if (!font.IsOk()) {
|
||||
font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
||||
if (bold) font.MakeBold();
|
||||
font.SetPointSize(size);
|
||||
}
|
||||
return font;
|
||||
}
|
||||
wxFont Label::Head_24;
|
||||
wxFont Label::Head_20;
|
||||
wxFont Label::Head_18;
|
||||
wxFont Label::Head_16;
|
||||
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;
|
||||
wxFont Label::Body_15;
|
||||
wxFont Label::Body_14;
|
||||
wxFont Label::Body_13;
|
||||
wxFont Label::Body_12;
|
||||
wxFont Label::Body_11;
|
||||
wxFont Label::Body_10;
|
||||
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);
|
||||
Head_18 = Label::sysFont(18, true);
|
||||
Head_16 = Label::sysFont(16, true);
|
||||
Head_15 = Label::sysFont(15, true);
|
||||
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);
|
||||
Body_15 = Label::sysFont(15, false);
|
||||
Body_14 = Label::sysFont(14, false);
|
||||
Body_13 = Label::sysFont(13, false);
|
||||
Body_12 = Label::sysFont(12, false);
|
||||
Body_11 = Label::sysFont(11, false);
|
||||
Body_10 = Label::sysFont(10, false);
|
||||
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)
|
||||
{
|
||||
multiline_text = text;
|
||||
if (width > 0 && dc.GetTextExtent(text).x > width) {
|
||||
size_t start = 0;
|
||||
while (true) {
|
||||
size_t idx = size_t(-1);
|
||||
for (size_t i = start; i < multiline_text.Len(); i++) {
|
||||
if (multiline_text[i] == ' ') {
|
||||
if (dc.GetTextExtent(multiline_text.SubString(start, i)).x < width)
|
||||
idx = i;
|
||||
else {
|
||||
if (idx == size_t(-1)) idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (idx == size_t(-1)) break;
|
||||
multiline_text[idx] = '\n';
|
||||
start = idx + 1;
|
||||
if (dc.GetTextExtent(multiline_text.Mid(start)).x < width) break;
|
||||
}
|
||||
}
|
||||
return dc.GetMultiLineTextExtent(multiline_text);
|
||||
}
|
||||
|
||||
Label::Label(wxWindow *parent, wxString const &text, long style) : Label(parent, Body_14, text, style) {}
|
||||
|
||||
Label::Label(wxWindow *parent, wxFont const &font, wxString const &text, long style)
|
||||
: wxStaticText(parent, wxID_ANY, text, wxDefaultPosition, wxDefaultSize, style)
|
||||
{
|
||||
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); });
|
||||
};
|
||||
}
|
||||
|
||||
void Label::SetLabel(const wxString& label)
|
||||
{
|
||||
if (GetLabel() == label)
|
||||
return;
|
||||
wxStaticText::SetLabel(label);
|
||||
#ifdef __WXOSX__
|
||||
if ((GetWindowStyle() & LB_HYPERLINK)) {
|
||||
SetLabelMarkup(label);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Label::SetWindowStyleFlag(long style)
|
||||
{
|
||||
if (style == GetWindowStyle())
|
||||
return;
|
||||
wxStaticText::SetWindowStyleFlag(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);
|
||||
}
|
||||
55
src/slic3r/GUI/Widgets/Label.hpp
Normal file
55
src/slic3r/GUI/Widgets/Label.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef slic3r_GUI_Label_hpp_
|
||||
#define slic3r_GUI_Label_hpp_
|
||||
|
||||
#include <wx/stattext.h>
|
||||
|
||||
#define LB_HYPERLINK 0x0020
|
||||
#define LB_PROPAGATE_MOUSE_EVENT 0x0040
|
||||
|
||||
|
||||
class Label : public wxStaticText
|
||||
{
|
||||
public:
|
||||
Label(wxWindow *parent, wxString const &text = {}, long style = 0);
|
||||
|
||||
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;
|
||||
wxColour color;
|
||||
|
||||
public:
|
||||
static wxFont Head_24;
|
||||
static wxFont Head_20;
|
||||
static wxFont Head_18;
|
||||
static wxFont Head_16;
|
||||
static wxFont Head_15;
|
||||
static wxFont Head_14;
|
||||
static wxFont Head_13;
|
||||
static wxFont Head_12;
|
||||
static wxFont Head_11;
|
||||
static wxFont Head_10;
|
||||
|
||||
static wxFont Body_16;
|
||||
static wxFont Body_15;
|
||||
static wxFont Body_14;
|
||||
static wxFont Body_13;
|
||||
static wxFont Body_12;
|
||||
static wxFont Body_10;
|
||||
static wxFont Body_11;
|
||||
static wxFont Body_9;
|
||||
|
||||
static void initSysFont();
|
||||
|
||||
static wxFont sysFont(int size, bool bold = false);
|
||||
|
||||
static wxSize split_lines(wxDC &dc, int width, const wxString &text, wxString &multiline_text);
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_Label_hpp_
|
||||
135
src/slic3r/GUI/Widgets/StateHandler.cpp
Normal file
135
src/slic3r/GUI/Widgets/StateHandler.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
#include "StateHandler.hpp"
|
||||
|
||||
wxDEFINE_EVENT(EVT_ENABLE_CHANGED, wxCommandEvent);
|
||||
|
||||
StateHandler::StateHandler(wxWindow * owner)
|
||||
: owner_(owner)
|
||||
{
|
||||
owner_->PushEventHandler(this);
|
||||
if (owner->IsEnabled())
|
||||
states_ |= Enabled;
|
||||
if (owner->HasFocus())
|
||||
states_ |= Focused;
|
||||
}
|
||||
|
||||
StateHandler::~StateHandler() { owner_->RemoveEventHandler(this); }
|
||||
|
||||
void StateHandler::attach(StateColor const &color)
|
||||
{
|
||||
colors_.push_back(&color);
|
||||
}
|
||||
|
||||
void StateHandler::attach(std::vector<StateColor const *> const & colors)
|
||||
{
|
||||
colors_.insert(colors_.end(), colors.begin(), colors.end());
|
||||
}
|
||||
|
||||
void StateHandler::attach_child(wxWindow *child)
|
||||
{
|
||||
auto ch = new StateHandler(this, child);
|
||||
children_.emplace_back(ch);
|
||||
ch->update_binds();
|
||||
states2_ |= ch->states();
|
||||
}
|
||||
|
||||
void StateHandler::remove_child(wxWindow *child)
|
||||
{
|
||||
children_.erase(std::remove_if(children_.begin(), children_.end(),
|
||||
[child](auto &c) { return c->owner_ == child; }), children_.end());
|
||||
states2_ = 0;
|
||||
for (auto & c : children_) states2_ |= c->states();
|
||||
}
|
||||
|
||||
void StateHandler::update_binds()
|
||||
{
|
||||
int bind_states = parent_ ? (parent_->bind_states_ & ~Enabled) : 0;
|
||||
for (auto c : colors_) {
|
||||
bind_states |= c->states();
|
||||
}
|
||||
bind_states = bind_states | (bind_states >> 16);
|
||||
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};
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
int s = states[i];
|
||||
if (diff & s) {
|
||||
if (bind_states & s) {
|
||||
Bind(events[i], &StateHandler::changed, this);
|
||||
if (events2[i])
|
||||
Bind(events2[i], &StateHandler::changed, this);
|
||||
} else {
|
||||
Unbind(events[i], &StateHandler::changed, this);
|
||||
if (events2[i])
|
||||
owner_->Unbind(events2[i], &StateHandler::changed, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
bind_states_ = bind_states;
|
||||
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)
|
||||
{
|
||||
states_ &= ~Enabled;
|
||||
parent_ = parent;
|
||||
}
|
||||
|
||||
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};
|
||||
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) {
|
||||
if (events2[i]) {
|
||||
if (event.GetEventType() == events[i]) {
|
||||
states_ |= 1 << i;
|
||||
break;
|
||||
} else if (event.GetEventType() == events2[i]) {
|
||||
states_ &= ~(1 << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (event.GetEventType() == events[i]) {
|
||||
states_ ^= (1 << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (old != states_ && (old | states2_) != (states_ | states2_)) {
|
||||
if (parent_)
|
||||
parent_->changed(states_ | states2_);
|
||||
else
|
||||
owner_->Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void StateHandler::changed(int)
|
||||
{
|
||||
int old = states2_;
|
||||
states2_ = 0;
|
||||
for (auto &c : children_) states2_ |= c->states();
|
||||
if (old != states2_ && (old | states_) != (states_ | states2_)) {
|
||||
if (parent_)
|
||||
parent_->changed(states_ | states2_);
|
||||
else
|
||||
owner_->Refresh();
|
||||
}
|
||||
}
|
||||
63
src/slic3r/GUI/Widgets/StateHandler.hpp
Normal file
63
src/slic3r/GUI/Widgets/StateHandler.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef slic3r_GUI_StateHandler_hpp_
|
||||
#define slic3r_GUI_StateHandler_hpp_
|
||||
|
||||
#include <wx/event.h>
|
||||
|
||||
#include "StateColor.hpp"
|
||||
|
||||
wxDECLARE_EVENT(EVT_ENABLE_CHANGED, wxCommandEvent);
|
||||
|
||||
class StateHandler : public wxEvtHandler
|
||||
{
|
||||
public:
|
||||
enum State {
|
||||
Enabled = 1,
|
||||
Checked = 2,
|
||||
Focused = 4,
|
||||
Hovered = 8,
|
||||
Pressed = 16,
|
||||
Disabled = 1 << 16,
|
||||
NotChecked = 2 << 16,
|
||||
NotFocused = 4 << 16,
|
||||
NotHovered = 8 << 16,
|
||||
NotPressed = 16 << 16,
|
||||
};
|
||||
|
||||
public:
|
||||
StateHandler(wxWindow * owner);
|
||||
|
||||
~StateHandler();
|
||||
|
||||
public:
|
||||
void attach(StateColor const & color);
|
||||
|
||||
void attach(std::vector<StateColor const *> const & colors);
|
||||
|
||||
void attach_child(wxWindow *child);
|
||||
|
||||
void remove_child(wxWindow *child);
|
||||
|
||||
void update_binds();
|
||||
|
||||
int states() const { return states_ | states2_; }
|
||||
|
||||
void set_state(int state, int mask);
|
||||
|
||||
private:
|
||||
StateHandler(StateHandler * parent, wxWindow *owner);
|
||||
|
||||
void changed(wxEvent &event);
|
||||
|
||||
void changed(int state2);
|
||||
|
||||
private:
|
||||
wxWindow * owner_;
|
||||
std::vector<StateColor const *> colors_;
|
||||
int bind_states_ = 0;
|
||||
int states_ = 0;
|
||||
int states2_ = 0; // from children
|
||||
std::vector<std::unique_ptr<StateHandler>> children_;
|
||||
StateHandler * parent_ = nullptr;
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_StateHandler_hpp_
|
||||
216
src/slic3r/GUI/Widgets/StaticBox.cpp
Normal file
216
src/slic3r/GUI/Widgets/StaticBox.cpp
Normal file
@@ -0,0 +1,216 @@
|
||||
#include "StaticBox.hpp"
|
||||
#include "../GUI.hpp"
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
BEGIN_EVENT_TABLE(StaticBox, wxWindow)
|
||||
|
||||
// catch paint events
|
||||
//EVT_ERASE_BACKGROUND(StaticBox::eraseEvent)
|
||||
EVT_PAINT(StaticBox::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().
|
||||
*/
|
||||
|
||||
StaticBox::StaticBox()
|
||||
: state_handler(this)
|
||||
, radius(8)
|
||||
{
|
||||
border_color = StateColor(
|
||||
std::make_pair(0xF0F0F1, (int) StateColor::Disabled),
|
||||
std::make_pair(0x303A3C, (int) StateColor::Normal));
|
||||
}
|
||||
|
||||
StaticBox::StaticBox(wxWindow* parent,
|
||||
wxWindowID id,
|
||||
const wxPoint & pos,
|
||||
const wxSize & size, long style)
|
||||
: StaticBox()
|
||||
{
|
||||
Create(parent, id, pos, size, style);
|
||||
}
|
||||
|
||||
bool StaticBox::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
||||
{
|
||||
if (style & wxBORDER_NONE)
|
||||
border_width = 0;
|
||||
wxWindow::Create(parent, id, pos, size, style);
|
||||
state_handler.attach({&border_color, &background_color, &background_color2});
|
||||
state_handler.update_binds();
|
||||
SetBackgroundColour(GetParentBackgroundColor(parent));
|
||||
return true;
|
||||
}
|
||||
|
||||
void StaticBox::SetCornerRadius(double radius)
|
||||
{
|
||||
this->radius = radius;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void StaticBox::SetBorderWidth(int width)
|
||||
{
|
||||
border_width = width;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void StaticBox::SetBorderColor(StateColor const &color)
|
||||
{
|
||||
border_color = color;
|
||||
state_handler.update_binds();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void StaticBox::SetBorderColorNormal(wxColor const &color)
|
||||
{
|
||||
border_color.setColorForStates(color, 0);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void StaticBox::SetBackgroundColor(StateColor const &color)
|
||||
{
|
||||
background_color = color;
|
||||
state_handler.update_binds();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void StaticBox::SetBackgroundColorNormal(wxColor const &color)
|
||||
{
|
||||
background_color.setColorForStates(color, 0);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void StaticBox::SetBackgroundColor2(StateColor const &color)
|
||||
{
|
||||
background_color2 = color;
|
||||
state_handler.update_binds();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
wxColor StaticBox::GetParentBackgroundColor(wxWindow* parent)
|
||||
{
|
||||
if (auto box = dynamic_cast<StaticBox*>(parent)) {
|
||||
if (box->background_color.count() > 0) {
|
||||
if (box->background_color2.count() == 0)
|
||||
return box->background_color.defaultColor();
|
||||
auto s = box->background_color.defaultColor();
|
||||
auto e = box->background_color2.defaultColor();
|
||||
int r = (s.Red() + e.Red()) / 2;
|
||||
int g = (s.Green() + e.Green()) / 2;
|
||||
int b = (s.Blue() + e.Blue()) / 2;
|
||||
return wxColor(r, g, b);
|
||||
}
|
||||
}
|
||||
if (parent)
|
||||
return parent->GetBackgroundColour();
|
||||
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);
|
||||
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 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)
|
||||
{
|
||||
wxSize size = GetSize();
|
||||
int states = state_handler.states();
|
||||
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)));
|
||||
}
|
||||
if (background_color.count() > 0)
|
||||
dc.SetBrush(wxBrush(background_color.colorForStates(states)));
|
||||
else
|
||||
dc.SetBrush(wxBrush(GetBackgroundColour()));
|
||||
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);
|
||||
int r = start.Red(), g = start.Green(), b = start.Blue();
|
||||
int dr = (int) stop.Red() - r, dg = (int) stop.Green() - g, db = (int) stop.Blue() - b;
|
||||
int lr = 0, lg = 0, lb = 0;
|
||||
for (int y = 0; y < size.y; ++y) {
|
||||
dc.SetPen(wxPen(wxColor(r, g, b)));
|
||||
dc.DrawLine(0, y, size.x, y);
|
||||
lr += dr; while (lr >= size.y) { ++r, lr -= size.y; } while (lr <= -size.y) { --r, lr += size.y; }
|
||||
lg += dg; while (lg >= size.y) { ++g, lg -= size.y; } while (lg <= -size.y) { --g, lg += size.y; }
|
||||
lb += db; while (lb >= size.y) { ++b, lb -= size.y; } while (lb <= -size.y) { --b, lb += size.y; }
|
||||
}
|
||||
}
|
||||
}
|
||||
62
src/slic3r/GUI/Widgets/StaticBox.hpp
Normal file
62
src/slic3r/GUI/Widgets/StaticBox.hpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef slic3r_GUI_StaticBox_hpp_
|
||||
#define slic3r_GUI_StaticBox_hpp_
|
||||
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "StateHandler.hpp"
|
||||
|
||||
#include <wx/window.h>
|
||||
|
||||
class StaticBox : public wxWindow
|
||||
{
|
||||
public:
|
||||
StaticBox();
|
||||
|
||||
StaticBox(wxWindow* parent,
|
||||
wxWindowID id = wxID_ANY,
|
||||
const wxPoint & pos = wxDefaultPosition,
|
||||
const wxSize & size = wxDefaultSize,
|
||||
long style = 0);
|
||||
|
||||
bool Create(wxWindow* parent,
|
||||
wxWindowID id = wxID_ANY,
|
||||
const wxPoint & pos = wxDefaultPosition,
|
||||
const wxSize & size = wxDefaultSize,
|
||||
long style = 0);
|
||||
|
||||
void SetCornerRadius(double radius);
|
||||
|
||||
void SetBorderWidth(int width);
|
||||
|
||||
void SetBorderColor(StateColor const & color);
|
||||
|
||||
void SetBorderColorNormal(wxColor const &color);
|
||||
|
||||
void SetBackgroundColor(StateColor const &color);
|
||||
|
||||
void SetBackgroundColorNormal(wxColor const &color);
|
||||
|
||||
void SetBackgroundColor2(StateColor const &color);
|
||||
|
||||
static wxColor GetParentBackgroundColor(wxWindow * parent);
|
||||
|
||||
protected:
|
||||
void eraseEvent(wxEraseEvent& evt);
|
||||
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
|
||||
void render(wxDC& dc);
|
||||
|
||||
virtual void doRender(wxDC& dc);
|
||||
|
||||
protected:
|
||||
double radius;
|
||||
int border_width = 1;
|
||||
StateHandler state_handler;
|
||||
StateColor border_color;
|
||||
StateColor background_color;
|
||||
StateColor background_color2;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_StaticBox_hpp_
|
||||
@@ -259,7 +259,7 @@ bool WebView::RunScript(wxWebView *webView, wxString const &javascript)
|
||||
#elif defined __WXMAC__
|
||||
WKWebView * wkWebView = (WKWebView *) webView->GetNativeBackend();
|
||||
int count = 0;
|
||||
wxJSScriptWrapper wrapJS(javascript, &count);
|
||||
wxJSScriptWrapper wrapJS(javascript, wxJSScriptWrapper::OutputType::JS_OUTPUT_RAW);
|
||||
Slic3r::GUI::WKWebView_evaluateJavaScript(wkWebView, wrapJS.GetWrappedCode(), nullptr);
|
||||
return true;
|
||||
#else
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
#ifndef slic3r_MacDarkMode_hpp_
|
||||
#define slic3r_MacDarkMode_hpp_
|
||||
|
||||
#include <wx/event.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
#if __APPLE__
|
||||
extern bool mac_dark_mode();
|
||||
extern double mac_max_scaling_factor();
|
||||
extern void set_miniaturizable(void * window);
|
||||
void WKWebView_evaluateJavaScript(void * web, wxString const & script, void (*callback)(wxString const &));
|
||||
void WKWebView_setTransparentBackground(void * web);
|
||||
void set_tag_when_enter_full_screen(bool isfullscreen);
|
||||
void set_title_colour_after_set_title(void * window);
|
||||
void initGestures(void * view, wxEvtHandler * handler);
|
||||
void openFolderForFile(wxString const & file);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
#import "MacDarkMode.hpp"
|
||||
#include "../GUI/Widgets/Label.hpp"
|
||||
|
||||
#include "wx/osx/core/cfstring.h"
|
||||
|
||||
#import <algorithm>
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AppKit/NSScreen.h>
|
||||
#import <WebKit/WebKit.h>
|
||||
|
||||
#include <objc/runtime.h>
|
||||
|
||||
@interface MacDarkMode : NSObject {}
|
||||
@end
|
||||
@@ -14,6 +20,9 @@
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
NSTextField* mainframe_text_field = nil;
|
||||
bool is_in_full_screen_mode = false;
|
||||
|
||||
bool mac_dark_mode()
|
||||
{
|
||||
NSString *style = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
|
||||
@@ -33,7 +42,326 @@ double mac_max_scaling_factor()
|
||||
return scaling;
|
||||
}
|
||||
|
||||
void set_miniaturizable(void * window)
|
||||
{
|
||||
CGFloat rFloat = 34/255.0;
|
||||
CGFloat gFloat = 34/255.0;
|
||||
CGFloat bFloat = 36/255.0;
|
||||
[(NSView*) window window].titlebarAppearsTransparent = true;
|
||||
[(NSView*) window window].backgroundColor = [NSColor colorWithCalibratedRed:rFloat green:gFloat blue:bFloat alpha:1.0];
|
||||
[(NSView*) window window].styleMask |= NSMiniaturizableWindowMask;
|
||||
|
||||
NSEnumerator *viewEnum = [[[[[[[(NSView*) window window] contentView] superview] titlebarViewController] view] subviews] objectEnumerator];
|
||||
NSView *viewObject;
|
||||
|
||||
while(viewObject = (NSView *)[viewEnum nextObject]) {
|
||||
if([viewObject class] == [NSTextField self]) {
|
||||
//[(NSTextField*)viewObject setTextColor : NSColor.whiteColor];
|
||||
mainframe_text_field = viewObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_tag_when_enter_full_screen(bool isfullscreen)
|
||||
{
|
||||
is_in_full_screen_mode = isfullscreen;
|
||||
}
|
||||
|
||||
void set_title_colour_after_set_title(void * window)
|
||||
{
|
||||
NSEnumerator *viewEnum = [[[[[[[(NSView*) window window] contentView] superview] titlebarViewController] view] subviews] objectEnumerator];
|
||||
NSView *viewObject;
|
||||
while(viewObject = (NSView *)[viewEnum nextObject]) {
|
||||
if([viewObject class] == [NSTextField self]) {
|
||||
[(NSTextField*)viewObject setTextColor : NSColor.whiteColor];
|
||||
mainframe_text_field = viewObject;
|
||||
}
|
||||
}
|
||||
|
||||
if (mainframe_text_field) {
|
||||
[(NSTextField*)mainframe_text_field setTextColor : NSColor.whiteColor];
|
||||
}
|
||||
}
|
||||
|
||||
void WKWebView_evaluateJavaScript(void * web, wxString const & script, void (*callback)(wxString const &))
|
||||
{
|
||||
[(WKWebView*)web evaluateJavaScript:wxCFStringRef(script).AsNSString() completionHandler: ^(id result, NSError *error) {
|
||||
if (callback && error != nil) {
|
||||
wxString err = wxCFStringRef(error.localizedFailureReason).AsString();
|
||||
callback(err);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
void WKWebView_setTransparentBackground(void * web)
|
||||
{
|
||||
WKWebView * webView = (WKWebView*)web;
|
||||
[webView layer].backgroundColor = [NSColor clearColor].CGColor;
|
||||
}
|
||||
|
||||
void openFolderForFile(wxString const & file)
|
||||
{
|
||||
NSArray *fileURLs = [NSArray arrayWithObjects:wxCFStringRef(file).AsNSString(), /* ... */ nil];
|
||||
[[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs:fileURLs];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/* textColor for NSTextField */
|
||||
@implementation NSTextField (textColor)
|
||||
|
||||
- (void)setTextColor2:(NSColor *)textColor
|
||||
{
|
||||
if (Slic3r::GUI::mainframe_text_field != self){
|
||||
[self setTextColor2: textColor];
|
||||
}else{
|
||||
if(Slic3r::GUI::is_in_full_screen_mode){
|
||||
[self setTextColor2 : NSColor.darkGrayColor];
|
||||
}else{
|
||||
[self setTextColor2 : NSColor.whiteColor];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+ (void) load
|
||||
{
|
||||
Method setTextColor = class_getInstanceMethod([NSTextField class], @selector(setTextColor:));
|
||||
Method setTextColor2 = class_getInstanceMethod([NSTextField class], @selector(setTextColor2:));
|
||||
method_exchangeImplementations(setTextColor, setTextColor2);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/* drawsBackground for NSTextField */
|
||||
@implementation NSTextField (drawsBackground)
|
||||
|
||||
- (instancetype)initWithFrame2:(NSRect)frameRect
|
||||
{
|
||||
[self initWithFrame2:frameRect];
|
||||
self.drawsBackground = false;
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
+ (void) load
|
||||
{
|
||||
Method initWithFrame = class_getInstanceMethod([NSTextField class], @selector(initWithFrame:));
|
||||
Method initWithFrame2 = class_getInstanceMethod([NSTextField class], @selector(initWithFrame2:));
|
||||
method_exchangeImplementations(initWithFrame, initWithFrame2);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/* textColor for NSButton */
|
||||
|
||||
@implementation NSButton (NSButton_Extended)
|
||||
|
||||
- (NSColor *)textColor
|
||||
{
|
||||
NSAttributedString *attrTitle = [self attributedTitle];
|
||||
int len = [attrTitle length];
|
||||
NSRange range = NSMakeRange(0, MIN(len, 1)); // get the font attributes from the first character
|
||||
NSDictionary *attrs = [attrTitle fontAttributesInRange:range];
|
||||
NSColor *textColor = [NSColor controlTextColor];
|
||||
if (attrs)
|
||||
{
|
||||
textColor = [attrs objectForKey:NSForegroundColorAttributeName];
|
||||
}
|
||||
|
||||
return textColor;
|
||||
}
|
||||
|
||||
- (void)setTextColor:(NSColor *)textColor
|
||||
{
|
||||
NSMutableAttributedString *attrTitle =
|
||||
[[NSMutableAttributedString alloc] initWithAttributedString:[self attributedTitle]];
|
||||
int len = [attrTitle length];
|
||||
NSRange range = NSMakeRange(0, len);
|
||||
[attrTitle addAttribute:NSForegroundColorAttributeName value:textColor range:range];
|
||||
[attrTitle fixAttributesInRange:range];
|
||||
[self setAttributedTitle:attrTitle];
|
||||
[attrTitle release];
|
||||
}
|
||||
|
||||
- (void)setBezelStyle2:(NSBezelStyle)bezelStyle
|
||||
{
|
||||
if (bezelStyle != NSBezelStyleShadowlessSquare)
|
||||
[self setBordered: YES];
|
||||
[self setBezelStyle2: bezelStyle];
|
||||
}
|
||||
|
||||
+ (void) load
|
||||
{
|
||||
Method setBezelStyle = class_getInstanceMethod([NSButton class], @selector(setBezelStyle:));
|
||||
Method setBezelStyle2 = class_getInstanceMethod([NSButton class], @selector(setBezelStyle2:));
|
||||
method_exchangeImplementations(setBezelStyle, setBezelStyle2);
|
||||
}
|
||||
|
||||
- (NSFocusRingType) focusRingType
|
||||
{
|
||||
return NSFocusRingTypeNone;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/* edit column for wxCocoaOutlineView */
|
||||
|
||||
#include <wx/dataview.h>
|
||||
#include <wx/osx/cocoa/dataview.h>
|
||||
#include <wx/osx/dataview.h>
|
||||
|
||||
@implementation wxCocoaOutlineView (Edit)
|
||||
|
||||
bool addObserver = false;
|
||||
|
||||
- (BOOL)outlineView: (NSOutlineView*) view shouldEditTableColumn:(nullable NSTableColumn *)tableColumn item:(nonnull id)item
|
||||
{
|
||||
NSClipView * clipView = [[self enclosingScrollView] contentView];
|
||||
if (!addObserver) {
|
||||
addObserver = true;
|
||||
clipView.postsBoundsChangedNotifications = YES;
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(synchronizedViewContentBoundsDidChange:)
|
||||
name:NSViewBoundsDidChangeNotification
|
||||
object:clipView];
|
||||
}
|
||||
|
||||
wxDataViewColumn* const col((wxDataViewColumn *)[tableColumn getColumnPointer]);
|
||||
wxDataViewItem item2([static_cast<wxPointerObject *>(item) pointer]);
|
||||
|
||||
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
|
||||
// Before doing anything we send an event asking if editing of this item is really wanted.
|
||||
wxDataViewEvent event(wxEVT_DATAVIEW_ITEM_EDITING_STARTED, dvc, col, item2);
|
||||
dvc->GetEventHandler()->ProcessEvent( event );
|
||||
if( !event.IsAllowed() )
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)synchronizedViewContentBoundsDidChange:(NSNotification *)notification
|
||||
{
|
||||
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
|
||||
wxDataViewCustomRenderer * r = dvc->GetCustomRendererPtr();
|
||||
if (r)
|
||||
r->FinishEditing();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/* Font for wxTextCtrl */
|
||||
|
||||
@implementation NSTableHeaderCell (Font)
|
||||
|
||||
- (NSFont*) font
|
||||
{
|
||||
return Label::sysFont(13).OSXGetNSFont();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/* remove focused border for wxTextCtrl */
|
||||
|
||||
@implementation NSTextField (FocusRing)
|
||||
|
||||
- (NSFocusRingType) focusRingType
|
||||
{
|
||||
return NSFocusRingTypeNone;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/* gesture handle for Canvas3D */
|
||||
|
||||
@interface wxNSCustomOpenGLView : NSOpenGLView
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@implementation wxNSCustomOpenGLView (Gesture)
|
||||
|
||||
wxEvtHandler * _gestureHandler = nullptr;
|
||||
|
||||
- (void) onGestureMove: (NSPanGestureRecognizer*) gesture
|
||||
{
|
||||
wxPanGestureEvent evt;
|
||||
NSPoint tr = [gesture translationInView: self];
|
||||
evt.SetDelta({(int) tr.x, (int) tr.y});
|
||||
[self postEvent:evt withGesture:gesture];
|
||||
}
|
||||
|
||||
- (void) onGestureScale: (NSMagnificationGestureRecognizer*) gesture
|
||||
{
|
||||
wxZoomGestureEvent evt;
|
||||
evt.SetZoomFactor(gesture.magnification + 1.0);
|
||||
[self postEvent:evt withGesture:gesture];
|
||||
}
|
||||
|
||||
- (void) onGestureRotate: (NSRotationGestureRecognizer*) gesture
|
||||
{
|
||||
wxRotateGestureEvent evt;
|
||||
evt.SetRotationAngle(-gesture.rotation);
|
||||
[self postEvent:evt withGesture:gesture];
|
||||
}
|
||||
|
||||
- (void) postEvent: (wxGestureEvent &) evt withGesture: (NSGestureRecognizer* ) gesture
|
||||
{
|
||||
NSPoint pos = [gesture locationInView: self];
|
||||
evt.SetPosition({(int) pos.x, (int) pos.y});
|
||||
if (gesture.state == NSGestureRecognizerStateBegan)
|
||||
evt.SetGestureStart();
|
||||
else if (gesture.state == NSGestureRecognizerStateEnded)
|
||||
evt.SetGestureEnd();
|
||||
_gestureHandler->ProcessEvent(evt);
|
||||
}
|
||||
|
||||
- (void) scrollWheel2:(NSEvent *)event
|
||||
{
|
||||
bool shiftDown = [event modifierFlags] & NSShiftKeyMask;
|
||||
if (_gestureHandler && shiftDown && event.hasPreciseScrollingDeltas) {
|
||||
wxPanGestureEvent evt;
|
||||
evt.SetDelta({-(int)[event scrollingDeltaX], - (int)[event scrollingDeltaY]});
|
||||
_gestureHandler->ProcessEvent(evt);
|
||||
} else {
|
||||
[self scrollWheel2: event];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void) load
|
||||
{
|
||||
Method scrollWheel = class_getInstanceMethod([wxNSCustomOpenGLView class], @selector(scrollWheel:));
|
||||
Method scrollWheel2 = class_getInstanceMethod([wxNSCustomOpenGLView class], @selector(scrollWheel2:));
|
||||
method_exchangeImplementations(scrollWheel, scrollWheel2);
|
||||
}
|
||||
|
||||
- (void) initGesturesWithHandler: (wxEvtHandler*) handler
|
||||
{
|
||||
// NSPanGestureRecognizer * pan = [[NSPanGestureRecognizer alloc] initWithTarget: self action: @selector(onGestureMove:)];
|
||||
// pan.numberOfTouchesRequired = 2;
|
||||
// pan.allowedTouchTypes = 0;
|
||||
// NSMagnificationGestureRecognizer * magnification = [[NSMagnificationGestureRecognizer alloc] initWithTarget: self action: @selector(onGestureScale:)];
|
||||
// NSRotationGestureRecognizer * rotation = [[NSRotationGestureRecognizer alloc] initWithTarget: self action: @selector(onGestureRotate:)];
|
||||
// [self addGestureRecognizer:pan];
|
||||
// [self addGestureRecognizer:magnification];
|
||||
// [self addGestureRecognizer:rotation];
|
||||
_gestureHandler = handler;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
void initGestures(void * view, wxEvtHandler * handler)
|
||||
{
|
||||
wxNSCustomOpenGLView * glView = (wxNSCustomOpenGLView *) view;
|
||||
[glView initGesturesWithHandler: handler];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user