PrusaSlicer-NonPlainar/src/slic3r/GUI/wxExtensions.hpp
2020-01-31 21:03:17 +01:00

946 lines
34 KiB
C++

#ifndef slic3r_GUI_wxExtensions_hpp_
#define slic3r_GUI_wxExtensions_hpp_
#include <wx/checklst.h>
#include <wx/combo.h>
#include <wx/dataview.h>
#include <wx/dc.h>
#include <wx/wupdlock.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/menu.h>
#include <wx/bmpcbox.h>
#include <wx/wx.h>
#include <vector>
#include <set>
#include <functional>
namespace Slic3r {
enum class ModelVolumeType : int;
};
typedef double coordf_t;
typedef std::pair<coordf_t, coordf_t> t_layer_height_range;
#ifdef __WXMSW__
void msw_rescale_menu(wxMenu* menu);
#else /* __WXMSW__ */
inline void msw_rescale_menu(wxMenu* /* menu */) {}
#endif /* __WXMSW__ */
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,
std::function<bool()> const cb_condition = []() { return true;}, wxWindow* parent = nullptr);
wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
std::function<void(wxCommandEvent& event)> cb, const std::string& icon = "", wxEvtHandler* event_handler = nullptr,
std::function<bool()> const cb_condition = []() { return true; }, wxWindow* parent = nullptr);
wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description,
const std::string& icon = "",
std::function<bool()> const cb_condition = []() { return true; }, wxWindow* parent = nullptr);
wxMenuItem* append_menu_radio_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
std::function<void(wxCommandEvent& event)> cb, wxEvtHandler* event_handler);
wxMenuItem* append_menu_check_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
std::function<void(wxCommandEvent& event)> cb, wxEvtHandler* event_handler);
void enable_menu_item(wxUpdateUIEvent& evt, std::function<bool()> const cb_condition, wxMenuItem* item, wxWindow* win);
class wxDialog;
class wxBitmapComboBox;
void edit_tooltip(wxString& tooltip);
void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector<int>& btn_ids);
int em_unit(wxWindow* win);
wxBitmap create_scaled_bitmap(const std::string& bmp_name, wxWindow *win = nullptr,
const int px_cnt = 16, const bool grayscale = false);
std::vector<wxBitmap*> get_extruder_color_icons(bool thin_icon = false);
void apply_extruder_selector(wxBitmapComboBox** ctrl,
wxWindow* parent,
const std::string& first_item = "",
wxPoint pos = wxDefaultPosition,
wxSize size = wxDefaultSize,
bool use_thin_icon = false);
class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup
{
static const unsigned int DefaultWidth;
static const unsigned int DefaultHeight;
static const unsigned int DefaultItemHeight;
wxString m_text;
// 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;
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);
virtual void OnKeyEvent(wxKeyEvent& evt);
void OnCheckListBox(wxCommandEvent& evt);
void OnListBoxSelection(wxCommandEvent& evt);
};
namespace Slic3r {
namespace GUI {
// *** PresetBitmapComboBox ***
// BitmapComboBox used to presets list on Sidebar and Tabs
class PresetBitmapComboBox: public wxBitmapComboBox
{
public:
PresetBitmapComboBox(wxWindow* parent, const wxSize& size = wxDefaultSize);
~PresetBitmapComboBox() {}
#ifdef __APPLE__
protected:
/* For PresetBitmapComboBox we use bitmaps that are created from images that are already scaled appropriately for Retina
* (Contrary to the intuition, the `scale` argument for Bitmap's constructor doesn't mean
* "please scale this to such and such" but rather
* "the wxImage is already sized for backing scale such and such". )
* Unfortunately, the constructor changes the size of wxBitmap too.
* Thus We need to use unscaled size value for bitmaps that we use
* to avoid scaled size of control items.
* For this purpose control drawing methods and
* control size calculation methods (virtual) are overridden.
**/
virtual bool OnAddBitmap(const wxBitmap& bitmap) override;
virtual void OnDrawItem(wxDC& dc, const wxRect& rect, int item, int flags) const override;
#endif
};
}
}
// *** 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;
int m_cnt_open_items{0};
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; }
// virtual wxSize GetAdjustedSize(int minWidth, int prefHeight, int maxHeight);
virtual void OnKeyEvent(wxKeyEvent& evt);
void OnDataViewTreeCtrlSelection(wxCommandEvent& evt);
void SetItemsCnt(int cnt) { m_cnt_open_items = cnt; }
};
// ----------------------------------------------------------------------------
// DataViewBitmapText: helper class used by PrusaBitmapTextRenderer
// ----------------------------------------------------------------------------
class DataViewBitmapText : public wxObject
{
public:
DataViewBitmapText( const wxString &text = wxEmptyString,
const wxBitmap& bmp = wxNullBitmap) :
m_text(text),
m_bmp(bmp)
{ }
DataViewBitmapText(const DataViewBitmapText &other)
: 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; }
void SetBitmap(const wxBitmap &bmp) { m_bmp = bmp; }
const wxBitmap &GetBitmap() const { return m_bmp; }
bool IsSameAs(const DataViewBitmapText& other) const {
return m_text == other.m_text && m_bmp.IsSameAs(other.m_bmp);
}
bool operator==(const DataViewBitmapText& other) const {
return IsSameAs(other);
}
bool operator!=(const DataViewBitmapText& other) const {
return !IsSameAs(other);
}
private:
wxString m_text;
wxBitmap m_bmp;
wxDECLARE_DYNAMIC_CLASS(DataViewBitmapText);
};
DECLARE_VARIANT_OBJECT(DataViewBitmapText)
// ----------------------------------------------------------------------------
// ObjectDataViewModelNode: a node inside ObjectDataViewModel
// ----------------------------------------------------------------------------
enum ItemType {
itUndef = 0,
itObject = 1,
itVolume = 2,
itInstanceRoot = 4,
itInstance = 8,
itSettings = 16,
itLayerRoot = 32,
itLayer = 64,
};
enum ColumnNumber
{
colName = 0, // item name
colPrint , // printable property
colExtruder , // extruder selection
colEditing , // item editing
};
enum PrintIndicator
{
piUndef = 0, // no print indicator
piPrintable , // printable
piUnprintable , // unprintable
};
class ObjectDataViewModelNode;
WX_DEFINE_ARRAY_PTR(ObjectDataViewModelNode*, MyObjectTreeModelNodePtrArray);
class ObjectDataViewModelNode
{
ObjectDataViewModelNode* m_parent;
MyObjectTreeModelNodePtrArray m_children;
wxBitmap m_empty_bmp;
size_t m_volumes_cnt = 0;
std::vector< std::string > m_opt_categories;
t_layer_height_range m_layer_range = { 0.0f, 0.0f };
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_extruder_bmp;
wxBitmap m_action_icon;
PrintIndicator m_printable {piUndef};
wxBitmap m_printable_icon;
std::string m_action_icon_name = "";
Slic3r::ModelVolumeType m_volume_type;
public:
ObjectDataViewModelNode(const wxString& name,
const wxString& extruder):
m_parent(NULL),
m_name(name),
m_type(itObject),
m_extruder(extruder)
{
set_action_and_extruder_icons();
init_container();
}
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;
set_action_and_extruder_icons();
init_container();
}
ObjectDataViewModelNode(ObjectDataViewModelNode* parent,
const t_layer_height_range& layer_range,
const int idx = -1,
const wxString& extruder = wxEmptyString );
ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const ItemType type);
~ObjectDataViewModelNode()
{
// free all our children nodes
size_t count = m_children.GetCount();
for (size_t i = 0; i < count; i++)
{
ObjectDataViewModelNode *child = m_children[i];
delete child;
}
#ifndef NDEBUG
// Indicate that the object was deleted.
m_idx = -2;
#endif /* NDEBUG */
}
void init_container();
bool IsContainer() const
{
return m_container;
}
ObjectDataViewModelNode* GetParent()
{
assert(m_parent == nullptr || m_parent->valid());
return m_parent;
}
MyObjectTreeModelNodePtrArray& GetChildren()
{
return m_children;
}
ObjectDataViewModelNode* GetNthChild(unsigned int n)
{
return m_children.Item(n);
}
void Insert(ObjectDataViewModelNode* child, unsigned int n)
{
if (!m_container)
m_container = true;
m_children.Insert(child, n);
}
void Append(ObjectDataViewModelNode* child)
{
if (!m_container)
m_container = true;
m_children.Add(child);
}
void RemoveAllChildren()
{
if (GetChildCount() == 0)
return;
for (int id = int(GetChildCount()) - 1; id >= 0; --id)
{
if (m_children.Item(id)->GetChildCount() > 0)
m_children[id]->RemoveAllChildren();
auto node = m_children[id];
m_children.RemoveAt(id);
delete node;
}
}
size_t GetChildCount() const
{
return m_children.GetCount();
}
bool SetValue(const wxVariant &variant, unsigned int col);
void SetBitmap(const wxBitmap &icon) { m_bmp = icon; }
const wxBitmap& GetBitmap() const { return m_bmp; }
const wxString& GetName() const { return m_name; }
ItemType GetType() const { return m_type; }
void SetIdx(const int& idx);
int GetIdx() const { return m_idx; }
t_layer_height_range GetLayerRange() const { return m_layer_range; }
PrintIndicator IsPrintable() const { return m_printable; }
// use this function only for childrens
void AssignAllVal(ObjectDataViewModelNode& from_node)
{
// ! Don't overwrite other values because of equality of this values for all children --
m_name = from_node.m_name;
m_bmp = from_node.m_bmp;
m_idx = from_node.m_idx;
m_extruder = from_node.m_extruder;
m_type = from_node.m_type;
}
bool SwapChildrens(int frst_id, int scnd_id) {
if (GetChildCount() < 2 ||
frst_id < 0 || (size_t)frst_id >= GetChildCount() ||
scnd_id < 0 || (size_t)scnd_id >= GetChildCount())
return false;
ObjectDataViewModelNode new_scnd = *GetNthChild(frst_id);
ObjectDataViewModelNode new_frst = *GetNthChild(scnd_id);
new_scnd.m_idx = m_children.Item(scnd_id)->m_idx;
new_frst.m_idx = m_children.Item(frst_id)->m_idx;
m_children.Item(frst_id)->AssignAllVal(new_frst);
m_children.Item(scnd_id)->AssignAllVal(new_scnd);
return true;
}
// Set action icons for node
void set_action_and_extruder_icons();
// Set printable icon for node
void set_printable_icon(PrintIndicator printable);
void update_settings_digest_bitmaps();
bool update_settings_digest(const std::vector<std::string>& categories);
int volume_type() const { return int(m_volume_type); }
void msw_rescale();
#ifndef NDEBUG
bool valid();
#endif /* NDEBUG */
bool invalid() const { return m_idx < -1; }
private:
friend class ObjectDataViewModel;
};
// ----------------------------------------------------------------------------
// ObjectDataViewModel
// ----------------------------------------------------------------------------
// 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);
class ObjectDataViewModel :public wxDataViewModel
{
std::vector<ObjectDataViewModelNode*> m_objects;
std::vector<wxBitmap*> m_volume_bmps;
wxBitmap* m_warning_bmp { nullptr };
wxDataViewCtrl* m_ctrl { nullptr };
public:
ObjectDataViewModel();
~ObjectDataViewModel();
wxDataViewItem Add( const wxString &name,
const int extruder,
const bool has_errors = false);
wxDataViewItem AddVolumeChild( const wxDataViewItem &parent_item,
const wxString &name,
const Slic3r::ModelVolumeType volume_type,
const bool has_errors = false,
const int extruder = 0,
const bool create_frst_child = true);
wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item);
wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num);
wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, const std::vector<bool>& print_indicator);
wxDataViewItem AddLayersRoot(const wxDataViewItem &parent_item);
wxDataViewItem AddLayersChild( const wxDataViewItem &parent_item,
const t_layer_height_range& layer_range,
const int extruder = 0,
const int index = -1);
wxDataViewItem Delete(const wxDataViewItem &item);
wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num);
void DeleteAll();
void DeleteChildren(wxDataViewItem& parent);
void DeleteVolumeChildren(wxDataViewItem& parent);
void DeleteSettings(const wxDataViewItem& parent);
wxDataViewItem GetItemById(int obj_idx);
wxDataViewItem GetItemById(const int obj_idx, const int sub_obj_idx, const ItemType parent_type);
wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx);
wxDataViewItem GetItemByInstanceId(int obj_idx, int inst_idx);
wxDataViewItem GetItemByLayerId(int obj_idx, int layer_idx);
wxDataViewItem GetItemByLayerRange(const int obj_idx, const t_layer_height_range& layer_range);
int GetItemIdByLayerRange(const int obj_idx, const t_layer_height_range& layer_range);
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;
int GetLayerIdByItem(const wxDataViewItem& item) const;
void GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx);
int GetRowByItem(const wxDataViewItem& item) const;
bool IsEmpty() { return m_objects.empty(); }
bool InvalidItem(const wxDataViewItem& item);
// helper method for wxLog
wxString GetName(const wxDataViewItem &item) const;
wxBitmap& GetBitmap(const wxDataViewItem &item) const;
wxString GetExtruder(const wxDataViewItem &item) const;
int GetExtruderNumber(const wxDataViewItem &item) const;
// helper methods to change the model
virtual unsigned int GetColumnCount() const override { return 3;}
virtual wxString GetColumnType(unsigned int col) const override{ return wxT("string"); }
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);
void SetExtruder(const wxString& extruder, wxDataViewItem item);
// For parent move child from cur_volume_id place to new_volume_id
// Remaining items will moved up/down accordingly
wxDataViewItem ReorganizeChildren( const int cur_volume_id,
const int new_volume_id,
const wxDataViewItem &parent);
wxDataViewItem ReorganizeObjects( int current_id, int new_id);
virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override;
virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override;
// get object item
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;
void GetAllChildren(const wxDataViewItem &parent,wxDataViewItemArray &array) const;
// Is the container just a header or an item with all columns
// In our case it is an item with all columns
virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; }
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;
wxDataViewItem GetLayerRootItem(const wxDataViewItem &item) const;
bool IsSettingsItem(const wxDataViewItem &item) const;
void UpdateSettingsDigest( const wxDataViewItem &item,
const std::vector<std::string>& categories);
bool IsPrintable(const wxDataViewItem &item) const;
void UpdateObjectPrintable(wxDataViewItem parent_item);
void UpdateInstancesPrintable(wxDataViewItem parent_item);
void SetVolumeBitmaps(const std::vector<wxBitmap*>& volume_bmps) { m_volume_bmps = volume_bmps; }
void SetWarningBitmap(wxBitmap* bitmap) { m_warning_bmp = bitmap; }
void SetVolumeType(const wxDataViewItem &item, const Slic3r::ModelVolumeType type);
wxDataViewItem SetPrintableState( PrintIndicator printable, int obj_idx,
int subobj_idx = -1,
ItemType subobj_type = itInstance);
wxDataViewItem SetObjectPrintableState(PrintIndicator printable, wxDataViewItem obj_item);
void SetAssociatedControl(wxDataViewCtrl* ctrl) { m_ctrl = ctrl; }
// Rescale bitmaps for existing Items
void Rescale();
wxBitmap GetVolumeIcon(const Slic3r::ModelVolumeType vol_type,
const bool is_marked = false);
void DeleteWarningIcon(const wxDataViewItem& item, const bool unmark_object = false);
t_layer_height_range GetLayerRangeByItem(const wxDataViewItem& item) const;
bool UpdateColumValues(unsigned col);
void UpdateExtruderBitmap(wxDataViewItem item);
private:
wxDataViewItem AddRoot(const wxDataViewItem& parent_item, const ItemType root_type);
wxDataViewItem AddInstanceRoot(const wxDataViewItem& parent_item);
};
// ----------------------------------------------------------------------------
// BitmapTextRenderer
// ----------------------------------------------------------------------------
#if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
class BitmapTextRenderer : public wxDataViewRenderer
#else
class BitmapTextRenderer : public wxDataViewCustomRenderer
#endif //ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
{
public:
BitmapTextRenderer( wxWindow* parent,
wxDataViewCellMode mode =
#ifdef __WXOSX__
wxDATAVIEW_CELL_INERT
#else
wxDATAVIEW_CELL_EDITABLE
#endif
,int align = wxDVR_DEFAULT_ALIGNMENT
#if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
);
#else
) :
wxDataViewCustomRenderer(wxT("DataViewBitmapText"), mode, align),
m_parent(parent)
{}
#endif //ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
bool SetValue(const wxVariant &value);
bool GetValue(wxVariant &value) const;
#if ENABLE_NONCUSTOM_DATA_VIEW_RENDERING && wxUSE_ACCESSIBILITY
virtual wxString GetAccessibleDescription() const override;
#endif // wxUSE_ACCESSIBILITY && ENABLE_NONCUSTOM_DATA_VIEW_RENDERING
virtual bool Render(wxRect cell, wxDC *dc, int state);
virtual wxSize GetSize() const;
bool HasEditorCtrl() const override
{
#ifdef __WXOSX__
return false;
#else
return true;
#endif
}
wxWindow* CreateEditorCtrl(wxWindow* parent,
wxRect labelRect,
const wxVariant& value) override;
bool GetValueFromEditorCtrl( wxWindow* ctrl,
wxVariant& value) override;
bool WasCanceled() const { return m_was_unusable_symbol; }
private:
DataViewBitmapText m_value;
bool m_was_unusable_symbol {false};
wxWindow* m_parent {nullptr};
};
// ----------------------------------------------------------------------------
// BitmapChoiceRenderer
// ----------------------------------------------------------------------------
class BitmapChoiceRenderer : public wxDataViewCustomRenderer
{
public:
BitmapChoiceRenderer(wxDataViewCellMode mode =
#ifdef __WXOSX__
wxDATAVIEW_CELL_INERT
#else
wxDATAVIEW_CELL_EDITABLE
#endif
,int align = wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL
) : wxDataViewCustomRenderer(wxT("DataViewBitmapText"), mode, align) {}
bool SetValue(const wxVariant& value);
bool GetValue(wxVariant& value) const;
virtual bool Render(wxRect cell, wxDC* dc, int state);
virtual wxSize GetSize() const;
bool HasEditorCtrl() const override { return true; }
wxWindow* CreateEditorCtrl(wxWindow* parent,
wxRect labelRect,
const wxVariant& value) override;
bool GetValueFromEditorCtrl( wxWindow* ctrl,
wxVariant& value) override;
private:
DataViewBitmapText m_value;
};
// ----------------------------------------------------------------------------
// 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;
};
// ----------------------------------------------------------------------------
// ScalableBitmap
// ----------------------------------------------------------------------------
class ScalableBitmap
{
public:
ScalableBitmap() {};
ScalableBitmap( wxWindow *parent,
const std::string& icon_name = "",
const int px_cnt = 16);
~ScalableBitmap() {}
wxSize GetBmpSize() const;
int GetBmpWidth() const;
int GetBmpHeight() const;
void msw_rescale();
const wxBitmap& bmp() const { return m_bmp; }
wxBitmap& bmp() { return m_bmp; }
const std::string& name() const{ return m_icon_name; }
int px_cnt()const {return m_px_cnt;}
private:
wxWindow* m_parent{ nullptr };
wxBitmap m_bmp = wxBitmap();
std::string m_icon_name = "";
int m_px_cnt {16};
};
// ----------------------------------------------------------------------------
// LockButton
// ----------------------------------------------------------------------------
class LockButton : public wxButton
{
public:
LockButton(
wxWindow *parent,
wxWindowID id,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize);
~LockButton() {}
void OnButton(wxCommandEvent& event);
bool IsLocked() const { return m_is_pushed; }
void SetLock(bool lock);
// create its own Enable/Disable functions to not really disabled button because of tooltip enabling
void enable() { m_disabled = false; }
void disable() { m_disabled = true; }
void msw_rescale();
protected:
void update_button_bitmaps();
private:
bool m_is_pushed = false;
bool m_disabled = false;
ScalableBitmap m_bmp_lock_closed;
ScalableBitmap m_bmp_lock_closed_f;
ScalableBitmap m_bmp_lock_open;
ScalableBitmap m_bmp_lock_open_f;
};
// ----------------------------------------------------------------------------
// ScalableButton
// ----------------------------------------------------------------------------
class ScalableButton : public wxButton
{
public:
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);
ScalableButton(
wxWindow * parent,
wxWindowID id,
const ScalableBitmap& bitmap,
const wxString& label = wxEmptyString,
long style = wxBU_EXACTFIT | wxNO_BORDER);
~ScalableButton() {}
void SetBitmap_(const ScalableBitmap& bmp);
void SetBitmapDisabled_(const ScalableBitmap &bmp);
int GetBitmapHeight();
void msw_rescale();
private:
wxWindow* m_parent;
std::string m_current_icon_name = "";
std::string m_disabled_icon_name = "";
int m_width {-1}; // should be multiplied to em_unit
int m_height{-1}; // should be multiplied to em_unit
// bitmap dimensions
int m_px_cnt{ 16 };
};
// ----------------------------------------------------------------------------
// ModeButton
// ----------------------------------------------------------------------------
class ModeButton : public ScalableButton
{
public:
ModeButton(
wxWindow* parent,
wxWindowID id,
const std::string& icon_name = "",
const wxString& mode = wxEmptyString,
const wxSize& size = wxDefaultSize,
const wxPoint& pos = wxDefaultPosition);
~ModeButton() {}
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;
wxString m_tt_selected;
wxString m_tt_focused;
};
// ----------------------------------------------------------------------------
// ModeSizer
// ----------------------------------------------------------------------------
class ModeSizer : public wxFlexGridSizer
{
public:
ModeSizer( wxWindow *parent, int hgap = 0);
~ModeSizer() {}
void SetMode(const /*ConfigOptionMode*/int mode);
void msw_rescale();
private:
std::vector<ModeButton*> m_mode_btns;
};
// ----------------------------------------------------------------------------
// MenuWithSeparators
// ----------------------------------------------------------------------------
class MenuWithSeparators : public wxMenu
{
public:
MenuWithSeparators(const wxString& title, long style = 0)
: wxMenu(title, style) {}
MenuWithSeparators(long style = 0)
: wxMenu(style) {}
~MenuWithSeparators() {}
void DestroySeparators();
void SetFirstSeparator();
void SetSecondSeparator();
private:
wxMenuItem* m_separator_frst { nullptr }; // use like separator before settings item
wxMenuItem* m_separator_scnd { nullptr }; // use like separator between settings items
};
#endif // slic3r_GUI_wxExtensions_hpp_