2018-02-02 11:38:35 +00:00
|
|
|
#ifndef slic3r_GUI_wxExtensions_hpp_
|
|
|
|
#define slic3r_GUI_wxExtensions_hpp_
|
|
|
|
|
|
|
|
#include <wx/checklst.h>
|
|
|
|
#include <wx/combo.h>
|
2018-04-06 11:37:00 +00:00
|
|
|
#include <wx/dataview.h>
|
2018-05-04 16:32:20 +00:00
|
|
|
#include <wx/dc.h>
|
2018-05-10 14:36:12 +00:00
|
|
|
#include <wx/collpane.h>
|
|
|
|
#include <wx/wupdlock.h>
|
|
|
|
#include <wx/button.h>
|
2019-01-10 10:05:58 +00:00
|
|
|
#include <wx/sizer.h>
|
2018-08-21 00:03:10 +00:00
|
|
|
#include <wx/slider.h>
|
2019-01-25 16:21:45 +00:00
|
|
|
#include <wx/menu.h>
|
2018-05-10 14:36:12 +00:00
|
|
|
|
2018-05-04 16:32:20 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <set>
|
2018-10-22 13:18:05 +00:00
|
|
|
#include <functional>
|
2018-02-02 11:38:35 +00:00
|
|
|
|
2019-02-22 11:12:10 +00:00
|
|
|
namespace Slic3r {
|
|
|
|
enum class ModelVolumeType : int;
|
|
|
|
};
|
|
|
|
|
2018-12-06 13:49:14 +00:00
|
|
|
wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
|
|
|
|
std::function<void(wxCommandEvent& event)> cb, const wxBitmap& icon, wxEvtHandler* event_handler = nullptr);
|
2018-10-17 10:17:25 +00:00
|
|
|
wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
|
2018-10-18 12:42:21 +00:00
|
|
|
std::function<void(wxCommandEvent& event)> cb, const std::string& icon = "", wxEvtHandler* event_handler = nullptr);
|
|
|
|
|
2019-03-28 15:28:34 +00:00
|
|
|
wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description,
|
|
|
|
const std::string& icon = "");
|
|
|
|
|
|
|
|
wxMenuItem* append_menu_radio_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
|
|
|
|
std::function<void(wxCommandEvent& event)> cb, wxEvtHandler* event_handler);
|
2018-10-17 10:17:25 +00:00
|
|
|
|
2019-04-25 13:06:44 +00:00
|
|
|
void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector<int>& btn_ids);
|
|
|
|
int em_unit(wxWindow* win);
|
2019-04-17 19:35:53 +00:00
|
|
|
|
|
|
|
wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name, const int px_cnt = 16, const bool is_horizontal = false);
|
2019-02-06 14:29:13 +00:00
|
|
|
|
2018-02-02 11:38:35 +00:00
|
|
|
class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup
|
|
|
|
{
|
2018-02-20 13:25:40 +00:00
|
|
|
static const unsigned int DefaultWidth;
|
|
|
|
static const unsigned int DefaultHeight;
|
2018-02-20 13:44:00 +00:00
|
|
|
static const unsigned int DefaultItemHeight;
|
2018-02-02 11:38:35 +00:00
|
|
|
|
|
|
|
wxString m_text;
|
|
|
|
|
2018-05-17 08:23:02 +00:00
|
|
|
// Events sent on mouseclick are quite complex. Function OnListBoxSelection is supposed to pass the event to the checkbox, which works fine on
|
|
|
|
// Win. On OSX and Linux the events are generated differently - clicking on the checkbox square generates the event twice (and the square
|
|
|
|
// therefore seems not to respond).
|
|
|
|
// This enum is meant to save current state of affairs, i.e., if the event forwarding is ok to do or not. It is only used on Linux
|
|
|
|
// and OSX by some #ifdefs. It also stores information whether OnListBoxSelection is supposed to change the checkbox status,
|
|
|
|
// or if it changed status on its own already (which happens when the square is clicked). More comments in OnCheckListBox(...)
|
|
|
|
// There indeed is a better solution, maybe making a custom event used for the event passing to distinguish the original and passed message
|
|
|
|
// and blocking one of them on OSX and Linux. Feel free to refactor, but carefully test on all platforms.
|
|
|
|
enum class OnCheckListBoxFunction{
|
|
|
|
FreeToProceed,
|
|
|
|
RefuseToProceed,
|
|
|
|
WasRefusedLastTime
|
|
|
|
} m_check_box_events_status = OnCheckListBoxFunction::FreeToProceed;
|
|
|
|
|
|
|
|
|
2018-02-02 11:38:35 +00:00
|
|
|
public:
|
|
|
|
virtual bool Create(wxWindow* parent);
|
|
|
|
virtual wxWindow* GetControl();
|
|
|
|
virtual void SetStringValue(const wxString& value);
|
|
|
|
virtual wxString GetStringValue() const;
|
|
|
|
virtual wxSize GetAdjustedSize(int minWidth, int prefHeight, int maxHeight);
|
|
|
|
|
2018-02-20 13:25:40 +00:00
|
|
|
virtual void OnKeyEvent(wxKeyEvent& evt);
|
|
|
|
|
2018-02-02 11:38:35 +00:00
|
|
|
void OnCheckListBox(wxCommandEvent& evt);
|
|
|
|
void OnListBoxSelection(wxCommandEvent& evt);
|
|
|
|
};
|
|
|
|
|
2018-04-06 11:37:00 +00:00
|
|
|
|
|
|
|
// *** wxDataViewTreeCtrlComboBox ***
|
|
|
|
|
|
|
|
class wxDataViewTreeCtrlComboPopup: public wxDataViewTreeCtrl, public wxComboPopup
|
|
|
|
{
|
|
|
|
static const unsigned int DefaultWidth;
|
|
|
|
static const unsigned int DefaultHeight;
|
|
|
|
static const unsigned int DefaultItemHeight;
|
|
|
|
|
|
|
|
wxString m_text;
|
2018-04-06 13:42:52 +00:00
|
|
|
int m_cnt_open_items{0};
|
2018-04-06 11:37:00 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
virtual bool Create(wxWindow* parent);
|
|
|
|
virtual wxWindow* GetControl() { return this; }
|
|
|
|
virtual void SetStringValue(const wxString& value) { m_text = value; }
|
|
|
|
virtual wxString GetStringValue() const { return m_text; }
|
2018-04-09 10:41:25 +00:00
|
|
|
// virtual wxSize GetAdjustedSize(int minWidth, int prefHeight, int maxHeight);
|
2018-04-06 11:37:00 +00:00
|
|
|
|
|
|
|
virtual void OnKeyEvent(wxKeyEvent& evt);
|
|
|
|
void OnDataViewTreeCtrlSelection(wxCommandEvent& evt);
|
2018-04-06 13:42:52 +00:00
|
|
|
void SetItemsCnt(int cnt) { m_cnt_open_items = cnt; }
|
2018-04-06 11:37:00 +00:00
|
|
|
};
|
|
|
|
|
2018-05-10 14:36:12 +00:00
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2019-04-24 23:45:00 +00:00
|
|
|
// DataViewBitmapText: helper class used by PrusaBitmapTextRenderer
|
2018-06-08 10:43:39 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2018-09-17 13:12:13 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
class DataViewBitmapText : public wxObject
|
2018-09-17 13:12:13 +00:00
|
|
|
{
|
|
|
|
public:
|
2019-04-24 23:45:00 +00:00
|
|
|
DataViewBitmapText( const wxString &text = wxEmptyString,
|
|
|
|
const wxBitmap& bmp = wxNullBitmap) :
|
|
|
|
m_text(text),
|
|
|
|
m_bmp(bmp)
|
2018-09-17 13:12:13 +00:00
|
|
|
{ }
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
DataViewBitmapText(const DataViewBitmapText &other)
|
2018-09-17 13:12:13 +00:00
|
|
|
: wxObject(),
|
|
|
|
m_text(other.m_text),
|
|
|
|
m_bmp(other.m_bmp)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
void SetText(const wxString &text) { m_text = text; }
|
|
|
|
wxString GetText() const { return m_text; }
|
2019-04-24 23:45:00 +00:00
|
|
|
void SetBitmap(const wxBitmap &bmp) { m_bmp = bmp; }
|
2018-09-17 13:12:13 +00:00
|
|
|
const wxBitmap &GetBitmap() const { return m_bmp; }
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
bool IsSameAs(const DataViewBitmapText& other) const {
|
2018-09-17 13:12:13 +00:00
|
|
|
return m_text == other.m_text && m_bmp.IsSameAs(other.m_bmp);
|
|
|
|
}
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
bool operator==(const DataViewBitmapText& other) const {
|
2018-09-17 13:12:13 +00:00
|
|
|
return IsSameAs(other);
|
|
|
|
}
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
bool operator!=(const DataViewBitmapText& other) const {
|
2018-09-17 13:12:13 +00:00
|
|
|
return !IsSameAs(other);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
wxString m_text;
|
|
|
|
wxBitmap m_bmp;
|
2018-10-15 11:25:22 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
wxDECLARE_DYNAMIC_CLASS(DataViewBitmapText);
|
2018-09-17 13:12:13 +00:00
|
|
|
};
|
2019-04-24 23:45:00 +00:00
|
|
|
DECLARE_VARIANT_OBJECT(DataViewBitmapText)
|
2018-09-17 13:12:13 +00:00
|
|
|
|
|
|
|
|
2018-05-04 16:32:20 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2019-04-24 23:45:00 +00:00
|
|
|
// ObjectDataViewModelNode: a node inside PrusaObjectDataViewModel
|
2018-05-04 16:32:20 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2018-11-17 16:23:56 +00:00
|
|
|
enum ItemType {
|
2018-10-18 08:40:26 +00:00
|
|
|
itUndef = 0,
|
|
|
|
itObject = 1,
|
|
|
|
itVolume = 2,
|
|
|
|
itInstanceRoot = 4,
|
|
|
|
itInstance = 8,
|
|
|
|
itSettings = 16
|
2018-10-16 09:08:37 +00:00
|
|
|
};
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
class ObjectDataViewModelNode;
|
|
|
|
WX_DEFINE_ARRAY_PTR(ObjectDataViewModelNode*, MyObjectTreeModelNodePtrArray);
|
2018-05-04 16:32:20 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
class ObjectDataViewModelNode
|
2018-05-04 16:32:20 +00:00
|
|
|
{
|
2019-04-24 23:45:00 +00:00
|
|
|
ObjectDataViewModelNode* m_parent;
|
2018-05-04 16:32:20 +00:00
|
|
|
MyObjectTreeModelNodePtrArray m_children;
|
2018-09-17 13:12:13 +00:00
|
|
|
wxBitmap m_empty_bmp;
|
2018-10-18 08:40:26 +00:00
|
|
|
size_t m_volumes_cnt = 0;
|
2018-09-17 13:12:13 +00:00
|
|
|
std::vector< std::string > m_opt_categories;
|
2019-04-16 08:05:45 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
wxString m_name;
|
|
|
|
wxBitmap& m_bmp = m_empty_bmp;
|
|
|
|
ItemType m_type;
|
|
|
|
int m_idx = -1;
|
|
|
|
bool m_container = false;
|
|
|
|
wxString m_extruder = "default";
|
|
|
|
wxBitmap m_action_icon;
|
|
|
|
|
2019-04-16 08:05:45 +00:00
|
|
|
std::string m_action_icon_name = "";
|
|
|
|
Slic3r::ModelVolumeType m_volume_type;
|
|
|
|
|
2018-05-04 16:32:20 +00:00
|
|
|
public:
|
2019-04-24 23:45:00 +00:00
|
|
|
ObjectDataViewModelNode(const wxString &name,
|
|
|
|
const wxString& extruder):
|
|
|
|
m_parent(NULL),
|
|
|
|
m_name(name),
|
|
|
|
m_type(itObject),
|
|
|
|
m_extruder(extruder)
|
|
|
|
{
|
2018-07-30 12:25:09 +00:00
|
|
|
#ifdef __WXGTK__
|
|
|
|
// it's necessary on GTK because of control have to know if this item will be container
|
|
|
|
// in another case you couldn't to add subitem for this item
|
|
|
|
// it will be produce "segmentation fault"
|
|
|
|
m_container = true;
|
|
|
|
#endif //__WXGTK__
|
2019-04-16 08:05:45 +00:00
|
|
|
|
|
|
|
set_action_icon();
|
2018-05-04 16:32:20 +00:00
|
|
|
}
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
ObjectDataViewModelNode(ObjectDataViewModelNode* parent,
|
|
|
|
const wxString& sub_obj_name,
|
|
|
|
const wxBitmap& bmp,
|
|
|
|
const wxString& extruder,
|
|
|
|
const int idx = -1 ) :
|
|
|
|
m_parent (parent),
|
|
|
|
m_name (sub_obj_name),
|
|
|
|
m_type (itVolume),
|
|
|
|
m_idx (idx),
|
|
|
|
m_extruder (extruder)
|
|
|
|
{
|
|
|
|
m_bmp = bmp;
|
2018-09-17 13:12:13 +00:00
|
|
|
#ifdef __WXGTK__
|
|
|
|
// it's necessary on GTK because of control have to know if this item will be container
|
|
|
|
// in another case you couldn't to add subitem for this item
|
|
|
|
// it will be produce "segmentation fault"
|
|
|
|
m_container = true;
|
|
|
|
#endif //__WXGTK__
|
2019-04-16 08:05:45 +00:00
|
|
|
|
|
|
|
set_action_icon();
|
2018-09-17 13:12:13 +00:00
|
|
|
}
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
ObjectDataViewModelNode(ObjectDataViewModelNode* parent,
|
|
|
|
const ItemType type) :
|
|
|
|
m_parent(parent),
|
|
|
|
m_type(type),
|
|
|
|
m_extruder(wxEmptyString)
|
2018-10-16 09:08:37 +00:00
|
|
|
{
|
|
|
|
if (type == itSettings) {
|
|
|
|
m_name = "Settings to modified";
|
|
|
|
}
|
|
|
|
else if (type == itInstanceRoot) {
|
2018-10-19 11:55:29 +00:00
|
|
|
m_name = "Instances";
|
|
|
|
#ifdef __WXGTK__
|
|
|
|
m_container = true;
|
|
|
|
#endif //__WXGTK__
|
2018-10-16 09:08:37 +00:00
|
|
|
}
|
|
|
|
else if (type == itInstance) {
|
|
|
|
m_idx = parent->GetChildCount();
|
2018-10-18 08:40:26 +00:00
|
|
|
m_name = wxString::Format("Instance_%d", m_idx+1);
|
2019-04-24 23:45:00 +00:00
|
|
|
|
2019-04-16 08:05:45 +00:00
|
|
|
set_action_icon();
|
2018-10-16 09:08:37 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-15 20:42:51 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
~ObjectDataViewModelNode()
|
2018-05-04 16:32:20 +00:00
|
|
|
{
|
|
|
|
// free all our children nodes
|
|
|
|
size_t count = m_children.GetCount();
|
|
|
|
for (size_t i = 0; i < count; i++)
|
|
|
|
{
|
2019-04-24 23:45:00 +00:00
|
|
|
ObjectDataViewModelNode *child = m_children[i];
|
2018-05-04 16:32:20 +00:00
|
|
|
delete child;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsContainer() const
|
|
|
|
{
|
|
|
|
return m_container;
|
|
|
|
}
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
ObjectDataViewModelNode* GetParent()
|
2018-05-04 16:32:20 +00:00
|
|
|
{
|
|
|
|
return m_parent;
|
|
|
|
}
|
|
|
|
MyObjectTreeModelNodePtrArray& GetChildren()
|
|
|
|
{
|
|
|
|
return m_children;
|
|
|
|
}
|
2019-04-24 23:45:00 +00:00
|
|
|
ObjectDataViewModelNode* GetNthChild(unsigned int n)
|
2018-05-04 16:32:20 +00:00
|
|
|
{
|
|
|
|
return m_children.Item(n);
|
|
|
|
}
|
2019-04-24 23:45:00 +00:00
|
|
|
void Insert(ObjectDataViewModelNode* child, unsigned int n)
|
2018-05-04 16:32:20 +00:00
|
|
|
{
|
2018-09-17 13:12:13 +00:00
|
|
|
if (!m_container)
|
|
|
|
m_container = true;
|
2018-05-04 16:32:20 +00:00
|
|
|
m_children.Insert(child, n);
|
|
|
|
}
|
2019-04-24 23:45:00 +00:00
|
|
|
void Append(ObjectDataViewModelNode* child)
|
2018-05-04 16:32:20 +00:00
|
|
|
{
|
|
|
|
if (!m_container)
|
|
|
|
m_container = true;
|
|
|
|
m_children.Add(child);
|
|
|
|
}
|
2018-06-04 13:59:55 +00:00
|
|
|
void RemoveAllChildren()
|
|
|
|
{
|
|
|
|
if (GetChildCount() == 0)
|
|
|
|
return;
|
2019-01-09 15:05:36 +00:00
|
|
|
for (int id = int(GetChildCount()) - 1; id >= 0; --id)
|
2018-06-04 13:59:55 +00:00
|
|
|
{
|
|
|
|
if (m_children.Item(id)->GetChildCount() > 0)
|
|
|
|
m_children[id]->RemoveAllChildren();
|
|
|
|
auto node = m_children[id];
|
|
|
|
m_children.RemoveAt(id);
|
|
|
|
delete node;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-29 22:36:44 +00:00
|
|
|
size_t GetChildCount() const
|
2018-05-04 16:32:20 +00:00
|
|
|
{
|
|
|
|
return m_children.GetCount();
|
|
|
|
}
|
2018-06-05 08:41:20 +00:00
|
|
|
|
|
|
|
bool SetValue(const wxVariant &variant, unsigned int col)
|
|
|
|
{
|
|
|
|
switch (col)
|
|
|
|
{
|
2018-06-15 20:42:51 +00:00
|
|
|
case 0:{
|
2019-04-24 23:45:00 +00:00
|
|
|
DataViewBitmapText data;
|
2018-06-15 20:42:51 +00:00
|
|
|
data << variant;
|
2018-09-17 13:12:13 +00:00
|
|
|
m_bmp = data.GetBitmap();
|
2018-06-15 20:42:51 +00:00
|
|
|
m_name = data.GetText();
|
|
|
|
return true;}
|
2018-06-05 08:41:20 +00:00
|
|
|
case 1:
|
2018-07-04 06:54:30 +00:00
|
|
|
m_extruder = variant.GetString();
|
|
|
|
return true;
|
2018-10-18 09:28:31 +00:00
|
|
|
case 2:
|
2018-07-04 06:54:30 +00:00
|
|
|
m_action_icon << variant;
|
|
|
|
return true;
|
2018-06-05 08:41:20 +00:00
|
|
|
default:
|
|
|
|
printf("MyObjectTreeModel::SetValue: wrong column");
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2018-09-17 13:12:13 +00:00
|
|
|
|
|
|
|
void SetBitmap(const wxBitmap &icon)
|
|
|
|
{
|
|
|
|
m_bmp = icon;
|
|
|
|
}
|
2018-06-18 12:20:29 +00:00
|
|
|
|
2018-10-16 09:08:37 +00:00
|
|
|
ItemType GetType() const {
|
|
|
|
return m_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetIdx(const int& idx) {
|
|
|
|
m_idx = idx;
|
2018-10-18 08:40:26 +00:00
|
|
|
// update name if this node is instance
|
|
|
|
if (m_type == itInstance)
|
|
|
|
m_name = wxString::Format("Instance_%d", m_idx + 1);
|
2018-06-18 13:26:09 +00:00
|
|
|
}
|
2018-10-18 08:40:26 +00:00
|
|
|
|
2018-10-16 09:08:37 +00:00
|
|
|
int GetIdx() const {
|
|
|
|
return m_idx;
|
2018-06-18 12:20:29 +00:00
|
|
|
}
|
2018-06-19 10:24:16 +00:00
|
|
|
|
|
|
|
// use this function only for childrens
|
2019-04-24 23:45:00 +00:00
|
|
|
void AssignAllVal(ObjectDataViewModelNode& from_node)
|
2018-06-19 10:24:16 +00:00
|
|
|
{
|
|
|
|
// ! Don't overwrite other values because of equality of this values for all children --
|
|
|
|
m_name = from_node.m_name;
|
2018-10-16 09:08:37 +00:00
|
|
|
m_bmp = from_node.m_bmp;
|
|
|
|
m_idx = from_node.m_idx;
|
|
|
|
m_extruder = from_node.m_extruder;
|
|
|
|
m_type = from_node.m_type;
|
2018-06-19 10:24:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool SwapChildrens(int frst_id, int scnd_id) {
|
|
|
|
if (GetChildCount() < 2 ||
|
|
|
|
frst_id < 0 || frst_id >= GetChildCount() ||
|
|
|
|
scnd_id < 0 || scnd_id >= GetChildCount())
|
|
|
|
return false;
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
ObjectDataViewModelNode new_scnd = *GetNthChild(frst_id);
|
|
|
|
ObjectDataViewModelNode new_frst = *GetNthChild(scnd_id);
|
2018-06-19 10:24:16 +00:00
|
|
|
|
2018-10-16 09:08:37 +00:00
|
|
|
new_scnd.m_idx = m_children.Item(scnd_id)->m_idx;
|
|
|
|
new_frst.m_idx = m_children.Item(frst_id)->m_idx;
|
2018-06-19 10:24:16 +00:00
|
|
|
|
|
|
|
m_children.Item(frst_id)->AssignAllVal(new_frst);
|
|
|
|
m_children.Item(scnd_id)->AssignAllVal(new_scnd);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-07-04 06:54:30 +00:00
|
|
|
// Set action icons for node
|
2019-04-16 08:05:45 +00:00
|
|
|
void set_action_icon();
|
|
|
|
|
|
|
|
void update_settings_digest_bitmaps();
|
|
|
|
bool update_settings_digest(const std::vector<std::string>& categories);
|
|
|
|
int volume_type() const { return int(m_volume_type); }
|
2019-04-24 23:45:00 +00:00
|
|
|
void msw_rescale();
|
2018-10-18 08:40:26 +00:00
|
|
|
private:
|
2019-04-24 23:45:00 +00:00
|
|
|
friend class ObjectDataViewModel;
|
2018-05-04 16:32:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2019-04-24 23:45:00 +00:00
|
|
|
// ObjectDataViewModel
|
2018-05-04 16:32:20 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2018-11-12 12:47:24 +00:00
|
|
|
// custom message the model sends to associated control to notify a last volume deleted from the object:
|
|
|
|
wxDECLARE_EVENT(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED, wxCommandEvent);
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
class ObjectDataViewModel :public wxDataViewModel
|
2018-05-04 16:32:20 +00:00
|
|
|
{
|
2019-04-24 23:45:00 +00:00
|
|
|
std::vector<ObjectDataViewModelNode*> m_objects;
|
2018-11-02 22:27:31 +00:00
|
|
|
std::vector<wxBitmap*> m_volume_bmps;
|
|
|
|
|
2018-11-12 12:47:24 +00:00
|
|
|
wxDataViewCtrl* m_ctrl{ nullptr };
|
|
|
|
|
2018-05-04 16:32:20 +00:00
|
|
|
public:
|
2019-04-24 23:45:00 +00:00
|
|
|
ObjectDataViewModel();
|
|
|
|
~ObjectDataViewModel();
|
2018-05-04 16:32:20 +00:00
|
|
|
|
2018-12-11 07:53:18 +00:00
|
|
|
wxDataViewItem Add(const wxString &name, const int extruder);
|
2019-04-24 23:45:00 +00:00
|
|
|
wxDataViewItem AddVolumeChild( const wxDataViewItem &parent_item,
|
|
|
|
const wxString &name,
|
|
|
|
const Slic3r::ModelVolumeType volume_type,
|
|
|
|
const int extruder = 0,
|
|
|
|
const bool create_frst_child = true);
|
2019-04-10 07:27:42 +00:00
|
|
|
wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item);
|
2018-10-18 08:40:26 +00:00
|
|
|
wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num);
|
2018-05-30 15:52:28 +00:00
|
|
|
wxDataViewItem Delete(const wxDataViewItem &item);
|
2018-10-18 08:40:26 +00:00
|
|
|
wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num);
|
2018-06-04 13:59:55 +00:00
|
|
|
void DeleteAll();
|
2018-07-31 13:31:12 +00:00
|
|
|
void DeleteChildren(wxDataViewItem& parent);
|
2018-11-06 08:06:26 +00:00
|
|
|
void DeleteVolumeChildren(wxDataViewItem& parent);
|
2018-11-12 12:47:24 +00:00
|
|
|
void DeleteSettings(const wxDataViewItem& parent);
|
2018-06-04 13:59:55 +00:00
|
|
|
wxDataViewItem GetItemById(int obj_idx);
|
2018-09-17 13:12:13 +00:00
|
|
|
wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx);
|
2018-11-05 12:53:30 +00:00
|
|
|
wxDataViewItem GetItemByInstanceId(int obj_idx, int inst_idx);
|
2019-04-24 23:45:00 +00:00
|
|
|
int GetIdByItem(const wxDataViewItem& item) const;
|
|
|
|
int GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const;
|
|
|
|
int GetObjectIdByItem(const wxDataViewItem& item) const;
|
|
|
|
int GetVolumeIdByItem(const wxDataViewItem& item) const;
|
|
|
|
int GetInstanceIdByItem(const wxDataViewItem& item) const;
|
2018-10-16 09:08:37 +00:00
|
|
|
void GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx);
|
2019-04-24 23:45:00 +00:00
|
|
|
int GetRowByItem(const wxDataViewItem& item) const;
|
2018-10-12 10:00:37 +00:00
|
|
|
bool IsEmpty() { return m_objects.empty(); }
|
2018-05-29 20:45:35 +00:00
|
|
|
|
2018-05-04 16:32:20 +00:00
|
|
|
// helper method for wxLog
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
wxString GetName(const wxDataViewItem &item) const;
|
|
|
|
wxBitmap& GetBitmap(const wxDataViewItem &item) const;
|
2018-05-04 16:32:20 +00:00
|
|
|
|
|
|
|
// helper methods to change the model
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
virtual unsigned int GetColumnCount() const override { return 3;}
|
|
|
|
virtual wxString GetColumnType(unsigned int col) const override{ return wxT("string"); }
|
2018-05-04 16:32:20 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
virtual void GetValue( wxVariant &variant,
|
|
|
|
const wxDataViewItem &item,
|
|
|
|
unsigned int col) const override;
|
|
|
|
virtual bool SetValue( const wxVariant &variant,
|
|
|
|
const wxDataViewItem &item,
|
|
|
|
unsigned int col) override;
|
|
|
|
bool SetValue( const wxVariant &variant,
|
|
|
|
const int item_idx,
|
|
|
|
unsigned int col);
|
2018-05-04 16:32:20 +00:00
|
|
|
|
2018-08-13 12:15:43 +00:00
|
|
|
// For parent move child from cur_volume_id place to new_volume_id
|
|
|
|
// Remaining items will moved up/down accordingly
|
2019-04-24 23:45:00 +00:00
|
|
|
wxDataViewItem ReorganizeChildren( const int cur_volume_id,
|
|
|
|
const int new_volume_id,
|
|
|
|
const wxDataViewItem &parent);
|
2018-06-19 10:24:16 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override;
|
2018-05-04 16:32:20 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override;
|
2018-10-18 08:40:26 +00:00
|
|
|
// get object item
|
2019-04-24 23:45:00 +00:00
|
|
|
wxDataViewItem GetTopParent(const wxDataViewItem &item) const;
|
|
|
|
virtual bool IsContainer(const wxDataViewItem &item) const override;
|
|
|
|
virtual unsigned int GetChildren(const wxDataViewItem &parent,
|
|
|
|
wxDataViewItemArray &array) const override;
|
2019-03-29 13:36:09 +00:00
|
|
|
void GetAllChildren(const wxDataViewItem &parent,wxDataViewItemArray &array) const;
|
2018-05-09 12:36:20 +00:00
|
|
|
// Is the container just a header or an item with all columns
|
|
|
|
// In our case it is an item with all columns
|
2019-04-24 23:45:00 +00:00
|
|
|
virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; }
|
2018-09-17 13:12:13 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
ItemType GetItemType(const wxDataViewItem &item) const ;
|
|
|
|
wxDataViewItem GetItemByType( const wxDataViewItem &parent_item,
|
|
|
|
ItemType type) const;
|
|
|
|
wxDataViewItem GetSettingsItem(const wxDataViewItem &item) const;
|
|
|
|
wxDataViewItem GetInstanceRootItem(const wxDataViewItem &item) const;
|
2018-09-17 13:12:13 +00:00
|
|
|
bool IsSettingsItem(const wxDataViewItem &item) const;
|
2019-04-24 23:45:00 +00:00
|
|
|
void UpdateSettingsDigest( const wxDataViewItem &item,
|
|
|
|
const std::vector<std::string>& categories);
|
2018-11-02 22:27:31 +00:00
|
|
|
|
|
|
|
void SetVolumeBitmaps(const std::vector<wxBitmap*>& volume_bmps) { m_volume_bmps = volume_bmps; }
|
2019-02-22 11:12:10 +00:00
|
|
|
void SetVolumeType(const wxDataViewItem &item, const Slic3r::ModelVolumeType type);
|
2018-11-12 12:47:24 +00:00
|
|
|
|
|
|
|
void SetAssociatedControl(wxDataViewCtrl* ctrl) { m_ctrl = ctrl; }
|
2019-04-16 08:05:45 +00:00
|
|
|
// Rescale bitmaps for existing Items
|
|
|
|
void Rescale();
|
2018-05-04 16:32:20 +00:00
|
|
|
};
|
|
|
|
|
2018-09-17 13:12:13 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2019-04-24 23:45:00 +00:00
|
|
|
// BitmapTextRenderer
|
2018-09-17 13:12:13 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2018-12-17 07:37:50 +00:00
|
|
|
#if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
|
2019-04-24 23:45:00 +00:00
|
|
|
class BitmapTextRenderer : public wxDataViewRenderer
|
2018-12-17 07:37:50 +00:00
|
|
|
#else
|
2019-04-24 23:45:00 +00:00
|
|
|
class BitmapTextRenderer : public wxDataViewCustomRenderer
|
2018-12-17 07:37:50 +00:00
|
|
|
#endif //ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
|
2018-09-17 13:12:13 +00:00
|
|
|
{
|
|
|
|
public:
|
2019-04-24 23:45:00 +00:00
|
|
|
BitmapTextRenderer(wxDataViewCellMode mode =
|
2018-12-17 11:46:36 +00:00
|
|
|
#ifdef __WXOSX__
|
|
|
|
wxDATAVIEW_CELL_INERT
|
|
|
|
#else
|
|
|
|
wxDATAVIEW_CELL_EDITABLE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
,int align = wxDVR_DEFAULT_ALIGNMENT
|
2018-12-17 07:37:50 +00:00
|
|
|
#if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
|
|
|
|
);
|
|
|
|
#else
|
2019-04-24 23:45:00 +00:00
|
|
|
) : wxDataViewCustomRenderer(wxT("DataViewBitmapText"), mode, align) {}
|
2018-12-17 07:37:50 +00:00
|
|
|
#endif //ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
|
2018-09-17 13:12:13 +00:00
|
|
|
|
|
|
|
bool SetValue(const wxVariant &value);
|
|
|
|
bool GetValue(wxVariant &value) const;
|
2018-12-17 07:37:50 +00:00
|
|
|
#if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING && wxUSE_ACCESSIBILITY
|
2018-12-14 15:07:28 +00:00
|
|
|
virtual wxString GetAccessibleDescription() const override;
|
2018-12-17 07:37:50 +00:00
|
|
|
#endif // wxUSE_ACCESSIBILITY && ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
|
2018-09-17 13:12:13 +00:00
|
|
|
|
|
|
|
virtual bool Render(wxRect cell, wxDC *dc, int state);
|
|
|
|
virtual wxSize GetSize() const;
|
|
|
|
|
2018-12-17 11:46:36 +00:00
|
|
|
bool HasEditorCtrl() const override
|
|
|
|
{
|
|
|
|
#ifdef __WXOSX__
|
|
|
|
return false;
|
|
|
|
#else
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
}
|
2018-12-12 12:18:38 +00:00
|
|
|
wxWindow* CreateEditorCtrl(wxWindow* parent,
|
|
|
|
wxRect labelRect,
|
|
|
|
const wxVariant& value) override;
|
|
|
|
bool GetValueFromEditorCtrl( wxWindow* ctrl,
|
|
|
|
wxVariant& value) override;
|
2018-12-12 13:35:18 +00:00
|
|
|
bool WasCanceled() const { return m_was_unusable_symbol; }
|
2018-09-17 13:12:13 +00:00
|
|
|
|
|
|
|
private:
|
2019-04-24 23:45:00 +00:00
|
|
|
DataViewBitmapText m_value;
|
2018-12-14 15:07:28 +00:00
|
|
|
bool m_was_unusable_symbol {false};
|
2018-09-17 13:12:13 +00:00
|
|
|
};
|
2018-05-04 16:32:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// MyCustomRenderer
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class MyCustomRenderer : public wxDataViewCustomRenderer
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// This renderer can be either activatable or editable, for demonstration
|
|
|
|
// purposes. In real programs, you should select whether the user should be
|
|
|
|
// able to activate or edit the cell and it doesn't make sense to switch
|
|
|
|
// between the two -- but this is just an example, so it doesn't stop us.
|
|
|
|
explicit MyCustomRenderer(wxDataViewCellMode mode)
|
|
|
|
: wxDataViewCustomRenderer("string", mode, wxALIGN_CENTER)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual bool Render(wxRect rect, wxDC *dc, int state) override/*wxOVERRIDE*/
|
|
|
|
{
|
|
|
|
dc->SetBrush(*wxLIGHT_GREY_BRUSH);
|
|
|
|
dc->SetPen(*wxTRANSPARENT_PEN);
|
|
|
|
|
|
|
|
rect.Deflate(2);
|
|
|
|
dc->DrawRoundedRectangle(rect, 5);
|
|
|
|
|
|
|
|
RenderText(m_value,
|
|
|
|
0, // no offset
|
|
|
|
wxRect(dc->GetTextExtent(m_value)).CentreIn(rect),
|
|
|
|
dc,
|
|
|
|
state);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool ActivateCell(const wxRect& WXUNUSED(cell),
|
|
|
|
wxDataViewModel *WXUNUSED(model),
|
|
|
|
const wxDataViewItem &WXUNUSED(item),
|
|
|
|
unsigned int WXUNUSED(col),
|
|
|
|
const wxMouseEvent *mouseEvent) override/*wxOVERRIDE*/
|
|
|
|
{
|
|
|
|
wxString position;
|
|
|
|
if (mouseEvent)
|
|
|
|
position = wxString::Format("via mouse at %d, %d", mouseEvent->m_x, mouseEvent->m_y);
|
|
|
|
else
|
|
|
|
position = "from keyboard";
|
|
|
|
// wxLogMessage("MyCustomRenderer ActivateCell() %s", position);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual wxSize GetSize() const override/*wxOVERRIDE*/
|
|
|
|
{
|
|
|
|
return wxSize(60, 20);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool SetValue(const wxVariant &value) override/*wxOVERRIDE*/
|
|
|
|
{
|
|
|
|
m_value = value.GetString();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool GetValue(wxVariant &WXUNUSED(value)) const override/*wxOVERRIDE*/{ return true; }
|
|
|
|
|
|
|
|
virtual bool HasEditorCtrl() const override/*wxOVERRIDE*/{ return true; }
|
|
|
|
|
|
|
|
virtual wxWindow*
|
|
|
|
CreateEditorCtrl(wxWindow* parent,
|
|
|
|
wxRect labelRect,
|
|
|
|
const wxVariant& value) override/*wxOVERRIDE*/
|
|
|
|
{
|
|
|
|
wxTextCtrl* text = new wxTextCtrl(parent, wxID_ANY, value,
|
|
|
|
labelRect.GetPosition(),
|
|
|
|
labelRect.GetSize(),
|
|
|
|
wxTE_PROCESS_ENTER);
|
|
|
|
text->SetInsertionPointEnd();
|
|
|
|
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool
|
|
|
|
GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value) override/*wxOVERRIDE*/
|
|
|
|
{
|
|
|
|
wxTextCtrl* text = wxDynamicCast(ctrl, wxTextCtrl);
|
|
|
|
if (!text)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
value = text->GetValue();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
wxString m_value;
|
|
|
|
};
|
2018-08-29 09:21:22 +00:00
|
|
|
|
|
|
|
|
2019-04-16 08:05:45 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2019-04-24 23:45:00 +00:00
|
|
|
// ScalableBitmap
|
2019-04-16 08:05:45 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
class ScalableBitmap
|
2019-04-16 08:05:45 +00:00
|
|
|
{
|
|
|
|
public:
|
2019-04-24 23:45:00 +00:00
|
|
|
ScalableBitmap() {};
|
|
|
|
ScalableBitmap( wxWindow *parent,
|
|
|
|
const std::string& icon_name = "",
|
|
|
|
const int px_cnt = 16,
|
|
|
|
const bool is_horizontal = false);
|
2019-04-16 08:05:45 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
~ScalableBitmap() {}
|
2019-04-16 08:05:45 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
void msw_rescale();
|
2019-04-16 08:05:45 +00:00
|
|
|
|
|
|
|
const wxBitmap& bmp() const { return m_bmp; }
|
|
|
|
wxBitmap& bmp() { return m_bmp; }
|
|
|
|
const std::string& name() const{ return m_icon_name; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
wxWindow* m_parent{ nullptr };
|
|
|
|
wxBitmap m_bmp = wxBitmap();
|
|
|
|
std::string m_icon_name = "";
|
|
|
|
int m_px_cnt {16};
|
|
|
|
bool m_is_horizontal {false};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2018-08-29 09:21:22 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2019-04-24 23:45:00 +00:00
|
|
|
// DoubleSlider
|
2018-08-29 09:21:22 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2018-11-07 13:44:47 +00:00
|
|
|
// custom message the slider sends to its parent to notify a tick-change:
|
|
|
|
wxDECLARE_EVENT(wxCUSTOMEVT_TICKSCHANGED, wxEvent);
|
|
|
|
|
2018-08-21 00:03:10 +00:00
|
|
|
enum SelectedSlider {
|
|
|
|
ssUndef,
|
|
|
|
ssLower,
|
|
|
|
ssHigher
|
|
|
|
};
|
2018-08-23 11:01:18 +00:00
|
|
|
enum TicksAction{
|
2018-08-24 11:34:38 +00:00
|
|
|
taOnIcon,
|
2018-08-23 11:01:18 +00:00
|
|
|
taAdd,
|
|
|
|
taDel
|
|
|
|
};
|
2018-11-07 13:44:47 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
class DoubleSlider : public wxControl
|
2018-08-21 00:03:10 +00:00
|
|
|
{
|
|
|
|
public:
|
2019-04-24 23:45:00 +00:00
|
|
|
DoubleSlider(
|
2018-08-21 00:03:10 +00:00
|
|
|
wxWindow *parent,
|
|
|
|
wxWindowID id,
|
|
|
|
int lowerValue,
|
|
|
|
int higherValue,
|
|
|
|
int minValue,
|
|
|
|
int maxValue,
|
|
|
|
const wxPoint& pos = wxDefaultPosition,
|
|
|
|
const wxSize& size = wxDefaultSize,
|
2018-09-17 13:12:13 +00:00
|
|
|
long style = wxSL_VERTICAL,
|
2018-08-21 00:03:10 +00:00
|
|
|
const wxValidator& val = wxDefaultValidator,
|
|
|
|
const wxString& name = wxEmptyString);
|
2019-04-24 23:45:00 +00:00
|
|
|
~DoubleSlider() {}
|
2018-08-21 00:03:10 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
void msw_rescale();
|
2019-04-16 08:05:45 +00:00
|
|
|
|
2018-12-20 09:55:50 +00:00
|
|
|
int GetMinValue() const { return m_min_value; }
|
|
|
|
int GetMaxValue() const { return m_max_value; }
|
|
|
|
double GetMinValueD() { return m_values.empty() ? 0. : m_values[m_min_value].second; }
|
|
|
|
double GetMaxValueD() { return m_values.empty() ? 0. : m_values[m_max_value].second; }
|
|
|
|
int GetLowerValue() const { return m_lower_value; }
|
|
|
|
int GetHigherValue() const { return m_higher_value; }
|
2018-08-23 12:37:17 +00:00
|
|
|
int GetActiveValue() const;
|
2019-04-16 08:05:45 +00:00
|
|
|
wxSize get_min_size() const ;
|
2018-11-27 11:19:39 +00:00
|
|
|
double GetLowerValueD() { return get_double_value(ssLower); }
|
|
|
|
double GetHigherValueD() { return get_double_value(ssHigher); }
|
2018-08-22 12:24:30 +00:00
|
|
|
wxSize DoGetBestSize() const override;
|
2018-08-24 11:34:38 +00:00
|
|
|
void SetLowerValue(const int lower_val);
|
|
|
|
void SetHigherValue(const int higher_val);
|
2018-12-20 09:55:50 +00:00
|
|
|
// Set low and high slider position. If the span is non-empty, disable the "one layer" mode.
|
|
|
|
void SetSelectionSpan(const int lower_val, const int higher_val);
|
2018-08-24 11:34:38 +00:00
|
|
|
void SetMaxValue(const int max_value);
|
2018-08-23 12:37:17 +00:00
|
|
|
void SetKoefForLabels(const double koef) {
|
|
|
|
m_label_koef = koef;
|
|
|
|
}
|
2018-08-29 11:11:30 +00:00
|
|
|
void SetSliderValues(const std::vector<std::pair<int, double>>& values) {
|
2018-08-23 12:37:17 +00:00
|
|
|
m_values = values;
|
|
|
|
}
|
2018-09-17 13:12:13 +00:00
|
|
|
void ChangeOneLayerLock();
|
2018-11-07 13:44:47 +00:00
|
|
|
std::vector<double> GetTicksValues() const;
|
|
|
|
void SetTicksValues(const std::vector<double>& heights);
|
2018-11-28 15:02:29 +00:00
|
|
|
void EnableTickManipulation(bool enable = true) {
|
|
|
|
m_is_enabled_tick_manipulation = enable;
|
|
|
|
}
|
|
|
|
void DisableTickManipulation() {
|
|
|
|
EnableTickManipulation(false);
|
|
|
|
}
|
2018-08-21 00:03:10 +00:00
|
|
|
|
2018-12-20 09:55:50 +00:00
|
|
|
bool is_horizontal() const { return m_style == wxSL_HORIZONTAL; }
|
|
|
|
bool is_one_layer() const { return m_is_one_layer; }
|
|
|
|
bool is_lower_at_min() const { return m_lower_value == m_min_value; }
|
|
|
|
bool is_higher_at_max() const { return m_higher_value == m_max_value; }
|
|
|
|
bool is_full_span() const { return this->is_lower_at_min() && this->is_higher_at_max(); }
|
|
|
|
|
2018-10-31 11:56:08 +00:00
|
|
|
void OnPaint(wxPaintEvent& ) { render();}
|
2018-08-21 00:03:10 +00:00
|
|
|
void OnLeftDown(wxMouseEvent& event);
|
|
|
|
void OnMotion(wxMouseEvent& event);
|
|
|
|
void OnLeftUp(wxMouseEvent& event);
|
2018-10-31 11:56:08 +00:00
|
|
|
void OnEnterWin(wxMouseEvent& event) { enter_window(event, true); }
|
|
|
|
void OnLeaveWin(wxMouseEvent& event) { enter_window(event, false); }
|
2018-08-21 00:03:10 +00:00
|
|
|
void OnWheel(wxMouseEvent& event);
|
2018-08-21 15:47:05 +00:00
|
|
|
void OnKeyDown(wxKeyEvent &event);
|
2018-08-24 11:34:38 +00:00
|
|
|
void OnKeyUp(wxKeyEvent &event);
|
2018-08-22 16:00:48 +00:00
|
|
|
void OnRightDown(wxMouseEvent& event);
|
2018-08-24 11:34:38 +00:00
|
|
|
void OnRightUp(wxMouseEvent& event);
|
2018-08-21 00:03:10 +00:00
|
|
|
|
|
|
|
protected:
|
2018-08-21 15:47:05 +00:00
|
|
|
|
|
|
|
void render();
|
|
|
|
void draw_focus_rect();
|
2018-08-23 12:37:17 +00:00
|
|
|
void draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoint pt_end);
|
2018-08-22 12:24:30 +00:00
|
|
|
void draw_scroll_line(wxDC& dc, const int lower_pos, const int higher_pos);
|
|
|
|
void draw_thumb(wxDC& dc, const wxCoord& pos_coord, const SelectedSlider& selection);
|
2018-08-24 11:34:38 +00:00
|
|
|
void draw_thumbs(wxDC& dc, const wxCoord& lower_pos, const wxCoord& higher_pos);
|
2018-08-22 16:00:48 +00:00
|
|
|
void draw_ticks(wxDC& dc);
|
2019-01-10 16:24:23 +00:00
|
|
|
void draw_colored_band(wxDC& dc);
|
2018-08-24 11:34:38 +00:00
|
|
|
void draw_one_layer_icon(wxDC& dc);
|
2018-08-22 12:24:30 +00:00
|
|
|
void draw_thumb_item(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection);
|
2018-08-23 11:01:18 +00:00
|
|
|
void draw_info_line_with_icon(wxDC& dc, const wxPoint& pos, SelectedSlider selection);
|
2018-08-22 12:24:30 +00:00
|
|
|
void draw_thumb_text(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) const;
|
|
|
|
|
|
|
|
void update_thumb_rect(const wxCoord& begin_x, const wxCoord& begin_y, const SelectedSlider& selection);
|
2019-03-11 11:58:46 +00:00
|
|
|
void detect_selected_slider(const wxPoint& pt);
|
2018-08-22 12:24:30 +00:00
|
|
|
void correct_lower_value();
|
|
|
|
void correct_higher_value();
|
|
|
|
void move_current_thumb(const bool condition);
|
2018-08-23 11:01:18 +00:00
|
|
|
void action_tick(const TicksAction action);
|
2018-08-24 11:34:38 +00:00
|
|
|
void enter_window(wxMouseEvent& event, const bool enter);
|
2018-08-22 12:24:30 +00:00
|
|
|
|
2018-08-21 00:03:10 +00:00
|
|
|
bool is_point_in_rect(const wxPoint& pt, const wxRect& rect);
|
2018-11-27 10:08:34 +00:00
|
|
|
int is_point_near_tick(const wxPoint& pt);
|
2018-08-22 12:24:30 +00:00
|
|
|
|
|
|
|
double get_scroll_step();
|
|
|
|
wxString get_label(const SelectedSlider& selection) const;
|
|
|
|
void get_lower_and_higher_position(int& lower_pos, int& higher_pos);
|
2018-08-24 11:34:38 +00:00
|
|
|
int get_value_from_position(const wxCoord x, const wxCoord y);
|
2018-08-22 16:00:48 +00:00
|
|
|
wxCoord get_position_from_value(const int value);
|
2018-08-24 11:34:38 +00:00
|
|
|
wxSize get_size();
|
|
|
|
void get_size(int *w, int *h);
|
2018-11-27 11:19:39 +00:00
|
|
|
double get_double_value(const SelectedSlider& selection);
|
2018-05-04 16:32:20 +00:00
|
|
|
|
2018-08-21 00:03:10 +00:00
|
|
|
private:
|
2019-02-26 14:51:23 +00:00
|
|
|
bool is_osx { false };
|
|
|
|
wxFont m_font;
|
2018-08-21 00:03:10 +00:00
|
|
|
int m_min_value;
|
|
|
|
int m_max_value;
|
|
|
|
int m_lower_value;
|
|
|
|
int m_higher_value;
|
2019-04-24 23:45:00 +00:00
|
|
|
ScalableBitmap m_bmp_thumb_higher;
|
|
|
|
ScalableBitmap m_bmp_thumb_lower;
|
|
|
|
ScalableBitmap m_bmp_add_tick_on;
|
|
|
|
ScalableBitmap m_bmp_add_tick_off;
|
|
|
|
ScalableBitmap m_bmp_del_tick_on;
|
|
|
|
ScalableBitmap m_bmp_del_tick_off;
|
|
|
|
ScalableBitmap m_bmp_one_layer_lock_on;
|
|
|
|
ScalableBitmap m_bmp_one_layer_lock_off;
|
|
|
|
ScalableBitmap m_bmp_one_layer_unlock_on;
|
|
|
|
ScalableBitmap m_bmp_one_layer_unlock_off;
|
2018-08-21 00:03:10 +00:00
|
|
|
SelectedSlider m_selection;
|
|
|
|
bool m_is_left_down = false;
|
2018-08-24 11:34:38 +00:00
|
|
|
bool m_is_right_down = false;
|
|
|
|
bool m_is_one_layer = false;
|
2018-08-21 15:47:05 +00:00
|
|
|
bool m_is_focused = false;
|
2018-08-23 11:01:18 +00:00
|
|
|
bool m_is_action_icon_focesed = false;
|
2018-08-24 11:34:38 +00:00
|
|
|
bool m_is_one_layer_icon_focesed = false;
|
2018-11-28 15:02:29 +00:00
|
|
|
bool m_is_enabled_tick_manipulation = true;
|
2018-08-21 00:03:10 +00:00
|
|
|
|
|
|
|
wxRect m_rect_lower_thumb;
|
|
|
|
wxRect m_rect_higher_thumb;
|
2018-08-23 11:01:18 +00:00
|
|
|
wxRect m_rect_tick_action;
|
2018-08-24 11:34:38 +00:00
|
|
|
wxRect m_rect_one_layer_icon;
|
2018-08-22 12:24:30 +00:00
|
|
|
wxSize m_thumb_size;
|
2018-08-23 11:01:18 +00:00
|
|
|
int m_tick_icon_dim;
|
2018-08-28 13:51:53 +00:00
|
|
|
int m_lock_icon_dim;
|
2018-08-21 00:03:10 +00:00
|
|
|
long m_style;
|
2018-08-21 15:47:05 +00:00
|
|
|
float m_label_koef = 1.0;
|
2018-08-21 00:03:10 +00:00
|
|
|
|
|
|
|
// control's view variables
|
|
|
|
wxCoord SLIDER_MARGIN; // margin around slider
|
|
|
|
|
|
|
|
wxPen DARK_ORANGE_PEN;
|
|
|
|
wxPen ORANGE_PEN;
|
|
|
|
wxPen LIGHT_ORANGE_PEN;
|
|
|
|
|
|
|
|
wxPen DARK_GREY_PEN;
|
|
|
|
wxPen GREY_PEN;
|
|
|
|
wxPen LIGHT_GREY_PEN;
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
std::vector<wxPen*> m_line_pens;
|
|
|
|
std::vector<wxPen*> m_segm_pens;
|
2018-08-22 16:00:48 +00:00
|
|
|
std::set<int> m_ticks;
|
2018-08-29 11:11:30 +00:00
|
|
|
std::vector<std::pair<int,double>> m_values;
|
2018-08-21 00:03:10 +00:00
|
|
|
};
|
2018-08-28 13:51:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2019-04-24 23:45:00 +00:00
|
|
|
// LockButton
|
2018-08-28 13:51:53 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
class LockButton : public wxButton
|
2018-08-28 13:51:53 +00:00
|
|
|
{
|
|
|
|
public:
|
2019-04-24 23:45:00 +00:00
|
|
|
LockButton(
|
2018-08-28 13:51:53 +00:00
|
|
|
wxWindow *parent,
|
|
|
|
wxWindowID id,
|
|
|
|
const wxPoint& pos = wxDefaultPosition,
|
|
|
|
const wxSize& size = wxDefaultSize);
|
2019-04-24 23:45:00 +00:00
|
|
|
~LockButton() {}
|
2018-08-28 13:51:53 +00:00
|
|
|
|
|
|
|
void OnButton(wxCommandEvent& event);
|
2018-10-31 11:56:08 +00:00
|
|
|
void OnEnterBtn(wxMouseEvent& event) { enter_button(true); event.Skip(); }
|
|
|
|
void OnLeaveBtn(wxMouseEvent& event) { enter_button(false); event.Skip(); }
|
2018-08-28 13:51:53 +00:00
|
|
|
|
|
|
|
bool IsLocked() const { return m_is_pushed; }
|
2019-01-09 07:48:25 +00:00
|
|
|
void SetLock(bool lock);
|
2018-08-28 13:51:53 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
void msw_rescale();
|
2019-04-16 08:05:45 +00:00
|
|
|
|
2018-08-28 13:51:53 +00:00
|
|
|
protected:
|
|
|
|
void enter_button(const bool enter);
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool m_is_pushed = false;
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
ScalableBitmap m_bmp_lock_on;
|
|
|
|
ScalableBitmap m_bmp_lock_off;
|
|
|
|
ScalableBitmap m_bmp_unlock_on;
|
|
|
|
ScalableBitmap m_bmp_unlock_off;
|
2019-04-13 21:46:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2019-04-24 23:45:00 +00:00
|
|
|
// ScalableButton
|
2019-04-13 21:46:52 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
class ScalableButton : public wxButton
|
2019-04-13 21:46:52 +00:00
|
|
|
{
|
|
|
|
public:
|
2019-04-24 23:45:00 +00:00
|
|
|
ScalableButton(){}
|
|
|
|
ScalableButton(
|
|
|
|
wxWindow * parent,
|
|
|
|
wxWindowID id,
|
|
|
|
const std::string& icon_name = "",
|
|
|
|
const wxString& label = wxEmptyString,
|
|
|
|
const wxSize& size = wxDefaultSize,
|
|
|
|
const wxPoint& pos = wxDefaultPosition,
|
|
|
|
long style = wxBU_EXACTFIT | wxNO_BORDER);
|
2019-04-13 21:46:52 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
ScalableButton(
|
|
|
|
wxWindow * parent,
|
|
|
|
wxWindowID id,
|
|
|
|
const ScalableBitmap& bitmap,
|
|
|
|
const wxString& label = wxEmptyString,
|
|
|
|
long style = wxBU_EXACTFIT | wxNO_BORDER);
|
2019-04-13 21:46:52 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
~ScalableButton() {}
|
2019-04-13 21:46:52 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
void SetBitmap_(const ScalableBitmap& bmp);
|
2019-04-13 21:46:52 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
void msw_rescale();
|
2019-04-13 21:46:52 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
wxWindow* m_parent;
|
|
|
|
std::string m_current_icon_name = "";
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-01-10 10:05:58 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2019-04-24 23:45:00 +00:00
|
|
|
// ModeButton
|
2019-01-10 10:05:58 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
class ModeButton : public ScalableButton
|
2019-01-10 10:05:58 +00:00
|
|
|
{
|
|
|
|
public:
|
2019-04-24 23:45:00 +00:00
|
|
|
ModeButton(
|
|
|
|
wxWindow* parent,
|
|
|
|
wxWindowID id,
|
|
|
|
const std::string& icon_name = "",
|
|
|
|
const wxString& mode = wxEmptyString,
|
|
|
|
const wxSize& size = wxDefaultSize,
|
|
|
|
const wxPoint& pos = wxDefaultPosition);
|
|
|
|
~ModeButton() {}
|
2019-01-10 10:05:58 +00:00
|
|
|
|
|
|
|
void OnButton(wxCommandEvent& event);
|
|
|
|
void OnEnterBtn(wxMouseEvent& event) { focus_button(true); event.Skip(); }
|
|
|
|
void OnLeaveBtn(wxMouseEvent& event) { focus_button(m_is_selected); event.Skip(); }
|
|
|
|
|
|
|
|
void SetState(const bool state);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void focus_button(const bool focus);
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool m_is_selected = false;
|
|
|
|
|
2019-02-26 09:50:00 +00:00
|
|
|
wxString m_tt_selected;
|
|
|
|
wxString m_tt_focused;
|
2019-01-10 10:05:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2019-04-24 23:45:00 +00:00
|
|
|
// ModeSizer
|
2019-01-10 10:05:58 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
class ModeSizer : public wxFlexGridSizer
|
2019-01-10 10:05:58 +00:00
|
|
|
{
|
|
|
|
public:
|
2019-04-24 23:45:00 +00:00
|
|
|
ModeSizer( wxWindow *parent, int hgap = 10);
|
|
|
|
~ModeSizer() {}
|
2019-01-10 10:05:58 +00:00
|
|
|
|
2019-01-10 12:41:59 +00:00
|
|
|
void SetMode(const /*ConfigOptionMode*/int mode);
|
2019-01-10 10:05:58 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
void msw_rescale();
|
2019-04-13 21:46:52 +00:00
|
|
|
|
2019-01-10 10:05:58 +00:00
|
|
|
private:
|
2019-04-24 23:45:00 +00:00
|
|
|
std::vector<ModeButton*> m_mode_btns;
|
2018-08-28 13:51:53 +00:00
|
|
|
};
|
2018-08-29 09:21:22 +00:00
|
|
|
|
|
|
|
|
2019-01-25 12:16:32 +00:00
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2019-04-24 23:45:00 +00:00
|
|
|
// MenuWithSeparators
|
2019-01-25 12:16:32 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
class MenuWithSeparators : public wxMenu
|
2019-01-25 12:16:32 +00:00
|
|
|
{
|
|
|
|
public:
|
2019-04-24 23:45:00 +00:00
|
|
|
MenuWithSeparators(const wxString& title, long style = 0)
|
2019-01-25 12:16:32 +00:00
|
|
|
: wxMenu(title, style) {}
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
MenuWithSeparators(long style = 0)
|
2019-01-25 12:16:32 +00:00
|
|
|
: wxMenu(style) {}
|
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
~MenuWithSeparators() {}
|
2019-01-25 12:16:32 +00:00
|
|
|
|
|
|
|
void DestroySeparators();
|
2019-04-24 23:45:00 +00:00
|
|
|
void SetFirstSeparator();
|
|
|
|
void SetSecondSeparator();
|
2019-01-25 12:16:32 +00:00
|
|
|
|
2019-04-24 23:45:00 +00:00
|
|
|
private:
|
2019-01-25 12:16:32 +00:00
|
|
|
wxMenuItem* m_separator_frst { nullptr }; // use like separator before settings item
|
|
|
|
wxMenuItem* m_separator_scnd { nullptr }; // use like separator between settings items
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2018-05-04 16:32:20 +00:00
|
|
|
|
2018-02-02 11:38:35 +00:00
|
|
|
#endif // slic3r_GUI_wxExtensions_hpp_
|