#ifndef slic3r_GUI_wxExtensions_hpp_ #define slic3r_GUI_wxExtensions_hpp_ #include #include #include #include #include #include #include #include #include #include #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 cb, const wxBitmap& icon, wxEvtHandler* event_handler = nullptr, std::function const cb_condition = []() { return true;}, wxWindow* parent = nullptr); wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, std::function cb, const std::string& icon = "", wxEvtHandler* event_handler = nullptr, std::function 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 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 cb, wxEvtHandler* event_handler); wxMenuItem* append_menu_check_item(wxMenu* menu, int id, const wxString& string, const wxString& description, std::function cb, wxEvtHandler* event_handler, std::function const enable_condition = []() { return true; }, std::function const check_condition = []() { return true; }, wxWindow* parent = nullptr); void enable_menu_item(wxUpdateUIEvent& evt, std::function const cb_condition, wxMenuItem* item, wxWindow* win); class wxDialog; void edit_tooltip(wxString& tooltip); void msw_buttons_rescale(wxDialog* dlg, const int em_unit, const std::vector& btn_ids); int em_unit(wxWindow* win); int mode_icon_px_size(); wxBitmap create_scaled_bitmap(const std::string& bmp_name, wxWindow *win = nullptr, const int px_cnt = 16, const bool grayscale = false); std::vector 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; } }; // ---------------------------------------------------------------------------- // 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 { nullptr }; 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( wxWindow* parent, const wxString& mode = wxEmptyString, const std::string& icon_name = "", int px_cnt = 16); ~ModeButton() {} void Init(const wxString& mode); 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 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 }; // ---------------------------------------------------------------------------- // BlinkingBitmap // ---------------------------------------------------------------------------- class BlinkingBitmap : public wxStaticBitmap { public: BlinkingBitmap() {}; BlinkingBitmap(wxWindow* parent, const std::string& icon_name = "redo_toolbar"); ~BlinkingBitmap() {} void msw_rescale(); void invalidate(); void activate(); void blink(); private: ScalableBitmap bmp; bool show {false}; }; #endif // slic3r_GUI_wxExtensions_hpp_