mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-20 07:11:12 -06:00
Add the full source of BambuStudio
using version 1.0.10
This commit is contained in:
parent
30bcadab3e
commit
1555904bef
3771 changed files with 1251328 additions and 0 deletions
1963
src/slic3r/GUI/Widgets/AMSControl.cpp
Normal file
1963
src/slic3r/GUI/Widgets/AMSControl.cpp
Normal file
File diff suppressed because it is too large
Load diff
513
src/slic3r/GUI/Widgets/AMSControl.hpp
Normal file
513
src/slic3r/GUI/Widgets/AMSControl.hpp
Normal file
|
@ -0,0 +1,513 @@
|
|||
#ifndef slic3r_GUI_AMXCONTROL_hpp_
|
||||
#define slic3r_GUI_AMXCONTROL_hpp_
|
||||
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "StaticBox.hpp"
|
||||
#include "StepCtrl.hpp"
|
||||
#include "Button.hpp"
|
||||
#include "../DeviceManager.hpp"
|
||||
#include "slic3r/GUI/Event.hpp"
|
||||
#include <wx/simplebook.h>
|
||||
#include <wx/hyperlink.h>
|
||||
#include <wx/animate.h>
|
||||
#include <wx/dynarray.h>
|
||||
|
||||
#define AMS_CONTROL_BRAND_COLOUR wxColour(0, 174, 66)
|
||||
#define AMS_CONTROL_GRAY700 wxColour(107, 107, 107)
|
||||
#define AMS_CONTROL_GRAY800 wxColour(50, 58, 61)
|
||||
#define AMS_CONTROL_GRAY500 wxColour(172, 172, 172)
|
||||
#define AMS_CONTROL_DISABLE_COLOUR wxColour(206, 206, 206)
|
||||
#define AMS_CONTROL_DISABLE_TEXT_COLOUR wxColour(144, 144, 144)
|
||||
#define AMS_CONTROL_WHITE_COLOUR wxColour(255, 255, 255)
|
||||
#define AMS_CONTROL_BLACK_COLOUR wxColour(0, 0, 0)
|
||||
#define AMS_CONTROL_DEF_BLOCK_BK_COLOUR wxColour(238, 238, 238)
|
||||
#define AMS_EXTRUDER_DEF_COLOUR wxColour(234, 234, 234)
|
||||
#define AMS_CONTROL_MAX_COUNT 4
|
||||
#define AMS_CONTRO_CALIBRATION_BUTTON_SIZE wxSize(FromDIP(150), FromDIP(28))
|
||||
|
||||
// enum AMSRoadMode{
|
||||
// AMS_ROAD_MODE_LEFT,
|
||||
// AMS_ROAD_MODE_LEFT_RIGHT,
|
||||
// AMS_ROAD_MODE_END,
|
||||
//};
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
enum class AMSRoadMode : int {
|
||||
AMS_ROAD_MODE_LEFT,
|
||||
AMS_ROAD_MODE_LEFT_RIGHT,
|
||||
AMS_ROAD_MODE_END,
|
||||
AMS_ROAD_MODE_END_ONLY,
|
||||
AMS_ROAD_MODE_NONE,
|
||||
};
|
||||
|
||||
enum class AMSPassRoadMode : int {
|
||||
AMS_ROAD_MODE_NONE,
|
||||
AMS_ROAD_MODE_LEFT,
|
||||
AMS_ROAD_MODE_LEFT_RIGHT,
|
||||
AMS_ROAD_MODE_END_TOP,
|
||||
AMS_ROAD_MODE_END_RIGHT,
|
||||
AMS_ROAD_MODE_END_BOTTOM,
|
||||
};
|
||||
|
||||
enum class AMSAction : int {
|
||||
AMS_ACTION_NONE,
|
||||
AMS_ACTION_LOAD,
|
||||
AMS_ACTION_UNLOAD,
|
||||
AMS_ACTION_PRINTING,
|
||||
AMS_ACTION_NORMAL,
|
||||
};
|
||||
|
||||
enum class AMSPassRoadSTEP : int {
|
||||
AMS_ROAD_STEP_NONE,
|
||||
AMS_ROAD_STEP_1, // lib -> extrusion
|
||||
AMS_ROAD_STEP_2, // extrusion->buffer
|
||||
AMS_ROAD_STEP_3, // extrusion
|
||||
|
||||
AMS_ROAD_STEP_COMBO_LOAD_STEP1,
|
||||
AMS_ROAD_STEP_COMBO_LOAD_STEP2,
|
||||
AMS_ROAD_STEP_COMBO_LOAD_STEP3,
|
||||
};
|
||||
|
||||
enum class AMSPassRoadType : int {
|
||||
AMS_ROAD_TYPE_NONE,
|
||||
AMS_ROAD_TYPE_LOAD,
|
||||
AMS_ROAD_TYPE_UNLOAD,
|
||||
};
|
||||
|
||||
enum class AMSCanType : int {
|
||||
AMS_CAN_TYPE_NONE,
|
||||
AMS_CAN_TYPE_BRAND,
|
||||
AMS_CAN_TYPE_THIRDBRAND,
|
||||
AMS_CAN_TYPE_EMPTY,
|
||||
};
|
||||
|
||||
enum FilamentStep {
|
||||
STEP_IDLE,
|
||||
STEP_HEAT_NOZZLE,
|
||||
STEP_CUT_FILAMENT,
|
||||
STEP_PULL_CURR_FILAMENT,
|
||||
STEP_PUSH_NEW_FILAMENT,
|
||||
STEP_PURGE_OLD_FILAMENT,
|
||||
STEP_COUNT,
|
||||
};
|
||||
|
||||
#define AMS_ITEM_CUBE_SIZE wxSize(FromDIP(14), FromDIP(14))
|
||||
#define AMS_ITEM_SIZE wxSize(FromDIP(82), FromDIP(27))
|
||||
#define AMS_ITEM_HUMIDITY_SIZE wxSize(FromDIP(150), FromDIP(27))
|
||||
#define AMS_CAN_LIB_SIZE wxSize(FromDIP(58), FromDIP(84))
|
||||
#define AMS_CAN_ROAD_SIZE wxSize(FromDIP(66), FromDIP(60))
|
||||
#define AMS_CAN_ITEM_HEIGHT_SIZE FromDIP(27)
|
||||
#define AMS_CANS_SIZE wxSize(FromDIP(284), FromDIP(186))
|
||||
#define AMS_CANS_WINDOW_SIZE wxSize(FromDIP(264), FromDIP(186))
|
||||
#define AMS_STEP_SIZE wxSize(FromDIP(172), FromDIP(180))
|
||||
#define AMS_REFRESH_SIZE wxSize(FromDIP(26), FromDIP(26))
|
||||
#define AMS_EXTRUDER_SIZE wxSize(FromDIP(66), FromDIP(55))
|
||||
#define AMS_EXTRUDER_BITMAP_SIZE wxSize(FromDIP(36), FromDIP(55))
|
||||
|
||||
struct Caninfo
|
||||
{
|
||||
std::string can_id;
|
||||
wxString material_name;
|
||||
wxColour material_colour = {*wxWHITE};
|
||||
AMSCanType material_state;
|
||||
};
|
||||
|
||||
struct AMSinfo
|
||||
{
|
||||
public:
|
||||
std::string ams_id;
|
||||
std::vector<Caninfo> cans;
|
||||
|
||||
std::string current_can_id;
|
||||
AMSPassRoadSTEP current_step;
|
||||
AMSAction current_action;
|
||||
int curreent_filamentstep;
|
||||
|
||||
bool parse_ams_info(Ams *ams);
|
||||
};
|
||||
|
||||
/*************************************************
|
||||
Description:AMSrefresh
|
||||
**************************************************/
|
||||
#define AMS_REFRESH_PLAY_LOADING_TIMER 200
|
||||
class AMSrefresh : public wxWindow
|
||||
{
|
||||
public:
|
||||
AMSrefresh();
|
||||
AMSrefresh(wxWindow *parent, wxWindowID id, wxString number, Caninfo info, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
|
||||
AMSrefresh(wxWindow *parent, wxWindowID id, int number, Caninfo info, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
|
||||
~AMSrefresh();
|
||||
void PlayLoading();
|
||||
void StopLoading();
|
||||
void create(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size);
|
||||
void on_timer(wxTimerEvent &event);
|
||||
void OnEnterWindow(wxMouseEvent &evt);
|
||||
void OnLeaveWindow(wxMouseEvent &evt);
|
||||
void OnClick(wxMouseEvent &evt);
|
||||
void post_event(wxCommandEvent &&event);
|
||||
void paintEvent(wxPaintEvent &evt);
|
||||
void Update(Caninfo info);
|
||||
void msw_rescale();
|
||||
Caninfo m_info;
|
||||
|
||||
protected:
|
||||
wxTimer *m_playing_timer= {nullptr};
|
||||
int m_rotation_angle = {360};
|
||||
|
||||
wxAnimationCtrl *m_animationCtrl = {nullptr};
|
||||
|
||||
|
||||
bool m_play_loading = {false};
|
||||
bool m_selected = {false};
|
||||
wxBitmap m_bitmap_rotation;
|
||||
wxBitmap m_bitmap_normal;
|
||||
wxBitmap m_bitmap_selected;
|
||||
wxString m_text;
|
||||
wxBoxSizer * m_size_body;
|
||||
virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
|
||||
};
|
||||
|
||||
/*************************************************
|
||||
Description:AMSextruder
|
||||
**************************************************/
|
||||
class AMSextruderImage: public wxWindow
|
||||
{
|
||||
public:
|
||||
void TurnOn(wxColour col);
|
||||
void TurnOff();
|
||||
void msw_rescale();
|
||||
void paintEvent(wxPaintEvent &evt);
|
||||
|
||||
void render(wxDC &dc);
|
||||
bool m_turn_on = {false};
|
||||
wxColour m_colour;
|
||||
wxBitmap m_ams_extruder;
|
||||
void doRender(wxDC &dc);
|
||||
AMSextruderImage(wxWindow *parent, wxWindowID id, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
|
||||
~AMSextruderImage();
|
||||
};
|
||||
|
||||
|
||||
class AMSextruder : public wxWindow
|
||||
{
|
||||
public:
|
||||
void TurnOn(wxColour col);
|
||||
void TurnOff();
|
||||
void create(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size);
|
||||
void msw_rescale();
|
||||
|
||||
wxBoxSizer * m_bitmap_sizer{nullptr};
|
||||
wxPanel * m_bitmap_panel{nullptr};
|
||||
AMSextruderImage *m_amsSextruder{nullptr};
|
||||
wxBitmap monitor_ams_extruder;
|
||||
AMSextruder(wxWindow *parent, wxWindowID id, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
|
||||
~AMSextruder();
|
||||
};
|
||||
|
||||
/*************************************************
|
||||
Description:AMSLib
|
||||
**************************************************/
|
||||
class AMSLib : public wxWindow
|
||||
{
|
||||
public:
|
||||
AMSLib(wxWindow *parent, wxWindowID id, Caninfo info, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
|
||||
void create(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
|
||||
public:
|
||||
int m_can_index;
|
||||
void Update(Caninfo info, bool refresh = true);
|
||||
void UnableSelected() { m_unable_selected = true; };
|
||||
void EableSelected() { m_unable_selected = false; };
|
||||
wxColour GetLibColour();
|
||||
void OnSelected();
|
||||
void UnSelected();
|
||||
virtual bool Enable(bool enable = true);
|
||||
void post_event(wxCommandEvent &&event);
|
||||
Caninfo m_info;
|
||||
|
||||
protected:
|
||||
wxStaticBitmap *m_edit_bitmp = {nullptr};
|
||||
wxStaticBitmap *m_edit_bitmp_light = {nullptr};
|
||||
wxBitmap m_bitmap_editable;
|
||||
wxBitmap m_bitmap_editable_lifht;
|
||||
bool m_unable_selected = {false};
|
||||
bool m_enable = {false};
|
||||
bool m_selected = {false};
|
||||
bool m_hover = {false};
|
||||
|
||||
double m_radius = {4};
|
||||
wxColour m_border_color;
|
||||
wxColour m_road_def_color;
|
||||
wxColour m_lib_color;
|
||||
|
||||
void on_enter_window(wxMouseEvent &evt);
|
||||
void on_leave_window(wxMouseEvent &evt);
|
||||
void on_left_down(wxMouseEvent &evt);
|
||||
void paintEvent(wxPaintEvent &evt);
|
||||
void render(wxDC &dc);
|
||||
void doRender(wxDC &dc);
|
||||
};
|
||||
|
||||
/*************************************************
|
||||
Description:AMSRoad
|
||||
**************************************************/
|
||||
class AMSRoad : public wxWindow
|
||||
{
|
||||
public:
|
||||
AMSRoad();
|
||||
AMSRoad(wxWindow *parent, wxWindowID id, Caninfo info, int canindex, int maxcan, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
|
||||
void create(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
|
||||
|
||||
public:
|
||||
Caninfo m_info;
|
||||
int m_canindex = {0};
|
||||
AMSRoadMode m_rode_mode = {AMSRoadMode::AMS_ROAD_MODE_LEFT_RIGHT};
|
||||
std::vector<AMSPassRoadMode> m_pass_rode_mode = {AMSPassRoadMode::AMS_ROAD_MODE_NONE};
|
||||
bool m_selected = {false};
|
||||
int m_passroad_width = {6};
|
||||
double m_radius = {4};
|
||||
wxColour m_road_def_color;
|
||||
wxColour m_road_color;
|
||||
void Update(Caninfo info, int canindex, int maxcan);
|
||||
|
||||
void SetPassRoadColour(wxColour col);
|
||||
void SetMode(AMSRoadMode mode);
|
||||
void OnPassRoad(std::vector<AMSPassRoadMode> prord_list);
|
||||
void UpdatePassRoad(int tag_index, AMSPassRoadType type, AMSPassRoadSTEP step);
|
||||
|
||||
void paintEvent(wxPaintEvent &evt);
|
||||
void render(wxDC &dc);
|
||||
void doRender(wxDC &dc);
|
||||
};
|
||||
|
||||
/*************************************************
|
||||
Description:AMSItem
|
||||
**************************************************/
|
||||
|
||||
class AMSItem : public wxWindow
|
||||
{
|
||||
public:
|
||||
AMSItem();
|
||||
AMSItem(wxWindow *parent, wxWindowID id, AMSinfo amsinfo, const wxSize cube_size = wxSize(14, 14), const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
|
||||
|
||||
bool m_open = {false};
|
||||
void Open();
|
||||
void Close();
|
||||
|
||||
void Update(AMSinfo amsinfo);
|
||||
void create(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size);
|
||||
void OnEnterWindow(wxMouseEvent &evt);
|
||||
void OnLeaveWindow(wxMouseEvent &evt);
|
||||
void OnSelected();
|
||||
void UnSelected();
|
||||
void ShowHumidity();
|
||||
void HideHumidity();
|
||||
void SetHumidity(int humidity);
|
||||
virtual bool Enable(bool enable = true);
|
||||
AMSinfo m_amsinfo;
|
||||
|
||||
protected:
|
||||
wxSize m_cube_size;
|
||||
wxColour m_background_colour = {AMS_CONTROL_DEF_BLOCK_BK_COLOUR};
|
||||
int m_padding = {6};
|
||||
int m_space = {5};
|
||||
bool m_hover = {false};
|
||||
bool m_selected = {false};
|
||||
bool m_show_humidity = {false};
|
||||
int m_humidity = {0};
|
||||
|
||||
void paintEvent(wxPaintEvent &evt);
|
||||
void render(wxDC &dc);
|
||||
void doRender(wxDC &dc);
|
||||
virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
|
||||
};
|
||||
|
||||
/*************************************************
|
||||
Description:AmsCans
|
||||
**************************************************/
|
||||
class Canrefreshs
|
||||
{
|
||||
public:
|
||||
wxString canID;
|
||||
AMSrefresh *canrefresh;
|
||||
};
|
||||
|
||||
class CanLibs
|
||||
{
|
||||
public:
|
||||
wxString canID;
|
||||
AMSLib * canLib;
|
||||
};
|
||||
|
||||
class CanRoads
|
||||
{
|
||||
public:
|
||||
wxString canID;
|
||||
AMSRoad *canRoad;
|
||||
};
|
||||
|
||||
WX_DEFINE_ARRAY(Canrefreshs *, CanrefreshsHash);
|
||||
WX_DEFINE_ARRAY(CanLibs *, CanLibsHash);
|
||||
WX_DEFINE_ARRAY(CanRoads *, CansRoadsHash);
|
||||
|
||||
class AmsCans : public wxWindow
|
||||
{
|
||||
public:
|
||||
AmsCans();
|
||||
AmsCans(wxWindow *parent, wxWindowID id, AMSinfo info, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
|
||||
|
||||
void Update(AMSinfo info);
|
||||
void create(wxWindow *parent, wxWindowID id, AMSinfo info, const wxPoint &pos, const wxSize &size);
|
||||
void AddCan(Caninfo caninfo, int canindex, int maxcan);
|
||||
void SelectCan(std::string canid);
|
||||
void SetAmsStep(wxString canid, AMSPassRoadType type, AMSPassRoadSTEP step);
|
||||
//wxColour GetCanColour(wxString canid);
|
||||
void PlayRridLoading(wxString canid);
|
||||
void StopRridLoading(wxString canid);
|
||||
void msw_rescale();
|
||||
|
||||
std::string GetCurrentCan();
|
||||
|
||||
public:
|
||||
std::string m_canlib_id;
|
||||
int m_canlib_selection = {-1};
|
||||
int m_selection = {0};
|
||||
int m_can_count = {0};
|
||||
CanLibsHash m_can_lib_list;
|
||||
CansRoadsHash m_can_road_list;
|
||||
CanrefreshsHash m_can_refresh_list;
|
||||
AMSinfo m_info;
|
||||
wxBoxSizer * sizer_can = {nullptr};
|
||||
AMSPassRoadSTEP m_step = {AMSPassRoadSTEP ::AMS_ROAD_STEP_NONE};
|
||||
};
|
||||
|
||||
/*************************************************
|
||||
Description:AMSControl
|
||||
**************************************************/
|
||||
class AmsCansWindow
|
||||
{
|
||||
public:
|
||||
wxString amsIndex;
|
||||
AmsCans *amsCans;
|
||||
};
|
||||
|
||||
class AmsItems
|
||||
{
|
||||
public:
|
||||
wxString amsIndex;
|
||||
AMSItem *amsItem;
|
||||
};
|
||||
|
||||
class AMSextruders
|
||||
{
|
||||
public:
|
||||
wxString amsIndex;
|
||||
AMSextruder *amsextruder;
|
||||
};
|
||||
|
||||
WX_DEFINE_ARRAY(AmsCansWindow *, AmsCansHash);
|
||||
WX_DEFINE_ARRAY(AmsItems *, AmsItemsHash);
|
||||
WX_DEFINE_ARRAY(AMSextruders *, AMSextrudersHash);
|
||||
|
||||
class AMSControl : public wxSimplebook
|
||||
{
|
||||
public:
|
||||
AMSControl(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
|
||||
|
||||
void init_scaled_buttons();
|
||||
|
||||
protected:
|
||||
int m_ams_count = {0};
|
||||
|
||||
std::map<std::string, int> m_ams_selection;
|
||||
std::vector<AMSinfo> m_ams_info;
|
||||
|
||||
std::string m_current_ams;
|
||||
AmsItemsHash m_ams_item_list;
|
||||
AmsCansHash m_ams_cans_list;
|
||||
|
||||
AMSextruder *m_extruder = {nullptr};
|
||||
|
||||
wxSimplebook *m_simplebook_right = {nullptr};
|
||||
wxSimplebook *m_simplebook_calibration = {nullptr};
|
||||
wxSimplebook *m_simplebook_amsitems = {nullptr};
|
||||
wxSimplebook *m_simplebook_ams = {nullptr};
|
||||
wxSimplebook *m_simplebook_cans = {nullptr};
|
||||
wxSimplebook *m_simplebook_bottom = {nullptr};
|
||||
|
||||
wxStaticText *m_tip_right_top = {nullptr};
|
||||
wxStaticText *m_tip_load_info = {nullptr};
|
||||
wxStaticText *m_text_calibration_percent = {nullptr};
|
||||
wxWindow * m_none_ams_panel = {nullptr};
|
||||
wxWindow * m_panel_top = {nullptr};
|
||||
|
||||
StaticBox * m_panel_can = {nullptr};
|
||||
wxBoxSizer *m_sizer_top = {nullptr};
|
||||
wxBoxSizer *m_sizer_cans = {nullptr};
|
||||
wxBoxSizer *m_sizer_right_tip = {nullptr};
|
||||
|
||||
::StepIndicator *m_filament_load_step = {nullptr};
|
||||
::StepIndicator *m_filament_unload_step = {nullptr};
|
||||
|
||||
Button *m_button_extruder_feed = {nullptr};
|
||||
Button *m_button_extruder_back = {nullptr};
|
||||
Button *m_button_ams_setting = {nullptr};
|
||||
|
||||
wxHyperlinkCtrl *m_hyperlink = {nullptr};
|
||||
|
||||
public:
|
||||
std::string GetCurentAms();
|
||||
std::string GetCurrentCan(std::string amsid);
|
||||
wxColour GetCanColour(std::string amsid, std::string canid);
|
||||
|
||||
void SetActionState(AMSAction action);
|
||||
void EnterNoneAMSMode();
|
||||
void ExitNoneAMSMode();
|
||||
|
||||
void EnterCalibrationMode(bool read_to_calibration);
|
||||
void ExitcClibrationMode();
|
||||
|
||||
void SetClibrationpercent(int percent);
|
||||
void SetClibrationLink(wxString link);
|
||||
|
||||
void PlayRridLoading(wxString amsid, wxString canid);
|
||||
void StopRridLoading(wxString amsid, wxString canid);
|
||||
|
||||
void SetFilamentStep(int item_idx, bool isload = true);
|
||||
void ShowFilamentTip(bool hasams = true);
|
||||
|
||||
void SetHumidity(std::string amsid, int humidity);
|
||||
void UpdateStepCtrl();
|
||||
void CreateAms();
|
||||
void UpdateAms(std::vector<AMSinfo> info, bool keep_selection = true);
|
||||
void AddAms(AMSinfo info, bool refresh = true);
|
||||
void SetAmsStep(std::string ams_id, std::string canid, AMSPassRoadType type, AMSPassRoadSTEP step);
|
||||
void SwitchAms(std::string ams_id);
|
||||
|
||||
void msw_rescale();
|
||||
void on_filament_load(wxCommandEvent &event);
|
||||
void on_filament_unload(wxCommandEvent &event);
|
||||
void on_ams_setting_click(wxCommandEvent &event);
|
||||
void on_clibration_again_click(wxMouseEvent &event);
|
||||
void on_clibration_cancel_click(wxMouseEvent &event);
|
||||
|
||||
void post_event(wxEvent &&event);
|
||||
|
||||
virtual bool Enable(bool enable = true);
|
||||
|
||||
public:
|
||||
std::string m_current_senect;
|
||||
};
|
||||
|
||||
wxDECLARE_EVENT(EVT_AMS_LOAD, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_AMS_UNLOAD, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_AMS_SETTINGS, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_AMS_REFRESH_RFID, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_AMS_ON_SELECTED, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_AMS_ON_FILAMENT_EDIT, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_AMS_CLIBRATION_AGAIN, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_AMS_CLIBRATION_CANCEL, wxCommandEvent);
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
||||
#endif // !slic3r_GUI_amscontrol_hpp_
|
367
src/slic3r/GUI/Widgets/AxisCtrlButton.cpp
Normal file
367
src/slic3r/GUI/Widgets/AxisCtrlButton.cpp
Normal file
|
@ -0,0 +1,367 @@
|
|||
#include "AxisCtrlButton.hpp"
|
||||
#include "Label.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
static const wxColour bd = wxColour(0x00AE42);
|
||||
static const wxColour BUTTON_BG_COL = wxColour(238, 238, 238);
|
||||
static const wxColour BUTTON_IN_BG_COL = wxColour(206, 206, 206);
|
||||
static const wxColour blank_bg = wxColour(0xFFFFFF);
|
||||
static const wxColour text_num_color = wxColour(0x898989);
|
||||
static const wxColour BUTTON_PRESS_COL = wxColour(172, 172, 172);
|
||||
static const double sqrt2 = std::sqrt(2);
|
||||
|
||||
BEGIN_EVENT_TABLE(AxisCtrlButton, wxPanel)
|
||||
EVT_LEFT_DOWN(AxisCtrlButton::mouseDown)
|
||||
EVT_LEFT_UP(AxisCtrlButton::mouseReleased)
|
||||
EVT_MOTION(AxisCtrlButton::mouseMoving)
|
||||
EVT_PAINT(AxisCtrlButton::paintEvent)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
#define OUTER_SIZE FromDIP(105)
|
||||
#define INNER_SIZE FromDIP(58)
|
||||
#define HOME_SIZE FromDIP(23)
|
||||
#define BLANK_SIZE FromDIP(23)
|
||||
#define GAP_SIZE FromDIP(4)
|
||||
|
||||
AxisCtrlButton::AxisCtrlButton(wxWindow *parent, wxBitmap &icon, long stlye)
|
||||
: wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, stlye)
|
||||
, r_outer(OUTER_SIZE)
|
||||
, r_inner(INNER_SIZE)
|
||||
, r_home(HOME_SIZE)
|
||||
, r_blank(BLANK_SIZE)
|
||||
, gap(GAP_SIZE)
|
||||
, last_pos(UNDEFINED)
|
||||
, current_pos(UNDEFINED) // don't change init value
|
||||
, text_color(std::make_pair(0x6B6B6B, (int) StateColor::Disabled), std::make_pair(*wxBLACK, (int) StateColor::Normal))
|
||||
, state_handler(this)
|
||||
{
|
||||
m_icon = icon.GetSubBitmap(wxRect(0, 0, icon.GetWidth(), icon.GetHeight()));
|
||||
wxWindow::SetBackgroundColour(parent->GetBackgroundColour());
|
||||
|
||||
border_color.append(bd, StateColor::Hovered);
|
||||
|
||||
background_color.append(BUTTON_BG_COL, StateColor::Disabled);
|
||||
background_color.append(BUTTON_PRESS_COL, StateColor::Pressed);
|
||||
background_color.append(BUTTON_BG_COL, StateColor::Hovered);
|
||||
background_color.append(BUTTON_BG_COL, StateColor::Normal);
|
||||
background_color.append(BUTTON_BG_COL, StateColor::Enabled);
|
||||
|
||||
inner_background_color.append(BUTTON_IN_BG_COL, StateColor::Disabled);
|
||||
inner_background_color.append(BUTTON_PRESS_COL, StateColor::Pressed);
|
||||
inner_background_color.append(BUTTON_IN_BG_COL, StateColor::Hovered);
|
||||
inner_background_color.append(BUTTON_IN_BG_COL, StateColor::Normal);
|
||||
inner_background_color.append(BUTTON_IN_BG_COL, StateColor::Enabled);
|
||||
|
||||
state_handler.attach({ &border_color, &background_color });
|
||||
state_handler.update_binds();
|
||||
}
|
||||
|
||||
void AxisCtrlButton::updateParams() {
|
||||
r_outer = OUTER_SIZE;
|
||||
r_inner = INNER_SIZE;
|
||||
r_home = HOME_SIZE;
|
||||
r_blank = BLANK_SIZE;
|
||||
gap = GAP_SIZE;
|
||||
}
|
||||
|
||||
void AxisCtrlButton::SetMinSize(const wxSize& size)
|
||||
{
|
||||
wxSize cur_size = GetSize();
|
||||
if (size.GetWidth() > 0 && size.GetHeight() > 0) {
|
||||
stretch = std::min((double)size.GetWidth() / cur_size.x,(double)size.GetHeight() / cur_size.y);
|
||||
minSize = size;
|
||||
updateParams();
|
||||
}
|
||||
else if (size.GetWidth() > 0) {
|
||||
stretch = (double)size.GetWidth() / cur_size.x;
|
||||
minSize.x = size.x;
|
||||
updateParams();
|
||||
}
|
||||
else if (size.GetHeight() > 0) {
|
||||
stretch = (double)size.GetHeight() / cur_size.y;
|
||||
minSize.y = size.y;
|
||||
updateParams();
|
||||
}
|
||||
else {
|
||||
stretch = 1.0;
|
||||
minSize = wxSize(228, 228);
|
||||
}
|
||||
wxWindow::SetMinSize(minSize);
|
||||
center = wxPoint(minSize.x / 2, minSize.y / 2);
|
||||
}
|
||||
|
||||
void AxisCtrlButton::SetTextColor(StateColor const &color)
|
||||
{
|
||||
text_color = color;
|
||||
state_handler.update_binds();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void AxisCtrlButton::SetBorderColor(StateColor const& color)
|
||||
{
|
||||
border_color = color;
|
||||
state_handler.update_binds();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void AxisCtrlButton::SetBackgroundColor(StateColor const& color)
|
||||
{
|
||||
background_color = color;
|
||||
state_handler.update_binds();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void AxisCtrlButton::SetInnerBackgroundColor(StateColor const& color)
|
||||
{
|
||||
inner_background_color = color;
|
||||
state_handler.update_binds();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void AxisCtrlButton::SetBitmap(wxBitmap &bmp)
|
||||
{
|
||||
m_icon = bmp.GetSubBitmap(wxRect(0, 0, bmp.GetWidth(), bmp.GetHeight()));
|
||||
}
|
||||
|
||||
void AxisCtrlButton::Rescale() {
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void AxisCtrlButton::paintEvent(wxPaintEvent& evt)
|
||||
{
|
||||
// depending on your system you may need to look at double-buffered dcs
|
||||
wxPaintDC dc(this);
|
||||
wxGCDC gcdc(dc);
|
||||
render(gcdc);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 AxisCtrlButton::render(wxDC& dc)
|
||||
{
|
||||
wxGraphicsContext* gc = dc.GetGraphicsContext();
|
||||
|
||||
int states = state_handler.states();
|
||||
wxSize size = GetSize();
|
||||
|
||||
gc->PushState();
|
||||
gc->Translate(center.x, center.y);
|
||||
|
||||
//draw the outer ring
|
||||
wxGraphicsPath outer_path = gc->CreatePath();
|
||||
outer_path.AddCircle(0, 0, r_outer);
|
||||
outer_path.AddCircle(0, 0, r_inner);
|
||||
gc->SetPen(BUTTON_BG_COL);
|
||||
gc->SetBrush(BUTTON_BG_COL);
|
||||
gc->DrawPath(outer_path);
|
||||
|
||||
//draw the inner ring
|
||||
wxGraphicsPath inner_path = gc->CreatePath();
|
||||
inner_path.AddCircle(0, 0, r_inner);
|
||||
inner_path.AddCircle(0, 0, r_blank);
|
||||
gc->SetPen(BUTTON_IN_BG_COL);
|
||||
gc->SetBrush(BUTTON_IN_BG_COL);
|
||||
gc->DrawPath(inner_path);
|
||||
|
||||
//draw an arc in corresponding position
|
||||
if (current_pos != CurrentPos::UNDEFINED) {
|
||||
wxGraphicsPath path = gc->CreatePath();
|
||||
if (current_pos < 4) {
|
||||
path.AddArc(0, 0, r_outer, (5 - 2 * current_pos) * PI / 4, (7 - 2 * current_pos) * PI / 4, true);
|
||||
path.AddArc(0, 0, r_inner, (7 - 2 * current_pos) * PI / 4, (5 - 2 * current_pos) * PI / 4, false);
|
||||
path.CloseSubpath();
|
||||
gc->SetBrush(wxBrush(background_color.colorForStates(states)));
|
||||
}
|
||||
else if (current_pos < 8) {
|
||||
path.AddArc(0, 0, r_inner, (5 - 2 * current_pos) * PI / 4, (7 - 2 * current_pos) * PI / 4, true);
|
||||
path.AddArc(0, 0, r_blank, (7 - 2 * current_pos) * PI / 4, (5 - 2 * current_pos) * PI / 4, false);
|
||||
path.CloseSubpath();
|
||||
gc->SetBrush(wxBrush(inner_background_color.colorForStates(states)));
|
||||
}
|
||||
gc->SetPen(wxPen(border_color.colorForStates(states),2));
|
||||
gc->DrawPath(path);
|
||||
}
|
||||
|
||||
//draw rectangle gap
|
||||
gc->SetPen(blank_bg);
|
||||
gc->SetBrush(blank_bg);
|
||||
gc->PushState();
|
||||
gc->Rotate(-PI / 4);
|
||||
gc->DrawRectangle(-sqrt2 * size.x / 2, -sqrt2 * gap / 2, sqrt2 * size.x, sqrt2 * gap);
|
||||
gc->Rotate(-PI / 2);
|
||||
gc->DrawRectangle(-sqrt2 * size.x / 2, -sqrt2 * gap / 2, sqrt2 * size.x, sqrt2 * gap);
|
||||
gc->PopState();
|
||||
|
||||
// draw the home circle
|
||||
wxGraphicsPath home_path = gc->CreatePath();
|
||||
home_path.AddCircle(0, 0, r_home);
|
||||
home_path.CloseSubpath();
|
||||
gc->PushState();
|
||||
if (current_pos == 8) {
|
||||
gc->SetPen(wxPen(border_color.colorForStates(states), 2));
|
||||
gc->SetBrush(wxBrush(background_color.colorForStates(states)));
|
||||
} else {
|
||||
gc->SetPen(BUTTON_BG_COL);
|
||||
gc->SetBrush(BUTTON_BG_COL);
|
||||
}
|
||||
gc->DrawPath(home_path);
|
||||
|
||||
if (m_icon.IsOk()) {
|
||||
gc->DrawBitmap(m_icon, -1 * m_icon.GetWidth() / 2, -1 * m_icon.GetHeight() / 2, m_icon.GetWidth(), m_icon.GetHeight());
|
||||
}
|
||||
gc->PopState();
|
||||
|
||||
//draw linear border of the arc
|
||||
if (current_pos != CurrentPos::UNDEFINED) {
|
||||
gc->PushState();
|
||||
gc->SetPen(wxPen(border_color.colorForStates(states), 2));
|
||||
|
||||
if (current_pos == 8) {
|
||||
wxGraphicsPath line_path = gc->CreatePath();
|
||||
line_path.AddCircle(0, 0, r_home);
|
||||
gc->StrokePath(line_path);
|
||||
} else {
|
||||
wxGraphicsPath line_path1 = gc->CreatePath();
|
||||
wxGraphicsPath line_path2 = gc->CreatePath();
|
||||
if (current_pos < 4) {
|
||||
line_path1.MoveToPoint(r_inner, -sqrt2 * gap / 2);
|
||||
line_path1.AddLineToPoint(r_outer, -sqrt2 * gap / 2);
|
||||
line_path2.MoveToPoint(-r_inner, -sqrt2 * gap / 2);
|
||||
line_path2.AddLineToPoint(-r_outer, -sqrt2 * gap / 2);
|
||||
} else if (current_pos < 8) {
|
||||
line_path1.MoveToPoint(r_blank, -sqrt2 * gap / 2);
|
||||
line_path1.AddLineToPoint(r_inner, -sqrt2 * gap / 2);
|
||||
line_path2.MoveToPoint(-r_blank, -sqrt2 * gap / 2);
|
||||
line_path2.AddLineToPoint(-r_inner, -sqrt2 * gap / 2);
|
||||
}
|
||||
gc->Rotate(-(1 + 2 * current_pos) * PI / 4);
|
||||
gc->StrokePath(line_path1);
|
||||
gc->Rotate(PI / 2);
|
||||
gc->StrokePath(line_path2);
|
||||
}
|
||||
gc->PopState();
|
||||
}
|
||||
|
||||
//draw text
|
||||
if (!IsEnabled())
|
||||
gc->SetFont(Label::Body_12, text_color.colorForStates(StateColor::Disabled));
|
||||
else
|
||||
gc->SetFont(Label::Head_12, text_color.colorForStates(states));
|
||||
wxDouble w, h;
|
||||
gc->GetTextExtent("Y", &w, &h);
|
||||
gc->DrawText(wxT("Y"), -w / 2, -r_outer + (r_outer - r_inner) / 2 - h / 2);
|
||||
gc->GetTextExtent("-X", &w, &h);
|
||||
gc->DrawText(wxT("-X"), -r_outer + (r_outer - r_inner) / 2 - w / 2, - h / 2);
|
||||
gc->GetTextExtent("-Y", &w, &h);
|
||||
gc->DrawText(wxT("-Y"), -w / 2, r_outer - (r_outer - r_inner) / 2 - h / 2);
|
||||
gc->GetTextExtent("X", &w, &h);
|
||||
gc->DrawText(wxT("X"), r_outer - (r_outer - r_inner) / 2 - w / 2, -h / 2);
|
||||
|
||||
gc->SetFont(Label::Body_12, text_num_color);
|
||||
|
||||
gc->PushState();
|
||||
gc->Rotate(PI / 4);
|
||||
gc->GetTextExtent("+10", &w, &h);
|
||||
gc->DrawText(wxT("+10"), sqrt2 * gap, -r_outer + (r_outer - r_inner) / 2 - h / 2);
|
||||
gc->GetTextExtent("+1", &w, &h);
|
||||
gc->DrawText(wxT("+1"), sqrt2 * gap, -r_inner + (r_inner - r_blank) / 2 - h / 2);
|
||||
gc->GetTextExtent("-1", &w, &h);
|
||||
gc->DrawText(wxT("-1"), sqrt2 * gap, r_inner - (r_inner - r_blank) / 2 - h / 2);
|
||||
gc->GetTextExtent("-10", &w, &h);
|
||||
gc->DrawText(wxT("-10"), sqrt2 * gap, r_outer - (r_outer - r_inner) / 2 - h / 2);
|
||||
gc->PopState();
|
||||
|
||||
|
||||
gc->PopState();
|
||||
}
|
||||
|
||||
void AxisCtrlButton::mouseDown(wxMouseEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
pressedDown = true;
|
||||
SetFocus();
|
||||
CaptureMouse();
|
||||
}
|
||||
|
||||
void AxisCtrlButton::mouseReleased(wxMouseEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
if (pressedDown) {
|
||||
pressedDown = false;
|
||||
ReleaseMouse();
|
||||
if (wxRect({ 0, 0 }, GetSize()).Contains(event.GetPosition()))
|
||||
sendButtonEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void AxisCtrlButton::mouseMoving(wxMouseEvent& event)
|
||||
{
|
||||
if (pressedDown)
|
||||
return;
|
||||
wxPoint mouse_pos(event.GetX(), event.GetY());
|
||||
wxPoint transformed_mouse_pos = mouse_pos - center;
|
||||
double r_temp = transformed_mouse_pos.x * transformed_mouse_pos.x + transformed_mouse_pos.y * transformed_mouse_pos.y;
|
||||
if (r_temp > r_outer * r_outer) {
|
||||
current_pos = CurrentPos::UNDEFINED;
|
||||
}
|
||||
else if (r_temp > r_inner * r_inner) {
|
||||
if (transformed_mouse_pos.y < transformed_mouse_pos.x - gap && transformed_mouse_pos.y < -transformed_mouse_pos.x - gap)
|
||||
{
|
||||
current_pos = CurrentPos::OUTER_UP;
|
||||
}
|
||||
else if (transformed_mouse_pos.y > transformed_mouse_pos.x + gap && transformed_mouse_pos.y < -transformed_mouse_pos.x - gap)
|
||||
{
|
||||
current_pos = CurrentPos::OUTER_LEFT;
|
||||
}
|
||||
else if (transformed_mouse_pos.y > transformed_mouse_pos.x + gap && transformed_mouse_pos.y > -transformed_mouse_pos.x + gap)
|
||||
{
|
||||
current_pos = CurrentPos::OUTER_DOWN;
|
||||
}
|
||||
else if (transformed_mouse_pos.y < transformed_mouse_pos.x - gap && transformed_mouse_pos.y > -transformed_mouse_pos.x + gap)
|
||||
{
|
||||
current_pos = CurrentPos::OUTER_RIGHT;
|
||||
}
|
||||
else {
|
||||
current_pos = CurrentPos::UNDEFINED;
|
||||
}
|
||||
}
|
||||
else if (r_temp > r_blank * r_blank) {
|
||||
if (transformed_mouse_pos.y < transformed_mouse_pos.x - gap && transformed_mouse_pos.y < -transformed_mouse_pos.x - gap)
|
||||
{
|
||||
current_pos = CurrentPos::INNER_UP;
|
||||
}
|
||||
else if (transformed_mouse_pos.y > transformed_mouse_pos.x + gap && transformed_mouse_pos.y < -transformed_mouse_pos.x - gap)
|
||||
{
|
||||
current_pos = CurrentPos::INNER_LEFT;
|
||||
}
|
||||
else if (transformed_mouse_pos.y > transformed_mouse_pos.x + gap && transformed_mouse_pos.y > -transformed_mouse_pos.x + gap)
|
||||
{
|
||||
current_pos = CurrentPos::INNER_DOWN;
|
||||
}
|
||||
else if (transformed_mouse_pos.y < transformed_mouse_pos.x - gap && transformed_mouse_pos.y > -transformed_mouse_pos.x + gap)
|
||||
{
|
||||
current_pos = CurrentPos::INNER_RIGHT;
|
||||
}
|
||||
else {
|
||||
current_pos = CurrentPos::UNDEFINED;
|
||||
}
|
||||
} else if (r_temp <= r_home * r_home) {
|
||||
current_pos = INNER_HOME;
|
||||
}
|
||||
if (last_pos != current_pos) {
|
||||
last_pos = current_pos;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void AxisCtrlButton::sendButtonEvent()
|
||||
{
|
||||
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
|
||||
event.SetEventObject(this);
|
||||
event.SetInt(current_pos);
|
||||
GetEventHandler()->ProcessEvent(event);
|
||||
}
|
79
src/slic3r/GUI/Widgets/AxisCtrlButton.hpp
Normal file
79
src/slic3r/GUI/Widgets/AxisCtrlButton.hpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
#ifndef slic3r_GUI_AxisCtrlButton_hpp_
|
||||
#define slic3r_GUI_AxisCtrlButton_hpp_
|
||||
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/vlbox.h>
|
||||
#include <wx/combo.h>
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "StateHandler.hpp"
|
||||
|
||||
|
||||
class AxisCtrlButton : public wxWindow
|
||||
{
|
||||
wxSize minSize;
|
||||
double stretch;
|
||||
double r_outer;
|
||||
double r_inner;
|
||||
double r_home;
|
||||
double r_blank;
|
||||
double gap;
|
||||
wxPoint center;
|
||||
|
||||
StateHandler state_handler;
|
||||
StateColor text_color;
|
||||
StateColor border_color;
|
||||
StateColor background_color;
|
||||
StateColor inner_background_color;
|
||||
|
||||
wxBitmap m_icon;
|
||||
|
||||
bool pressedDown = false;
|
||||
|
||||
unsigned char last_pos;
|
||||
unsigned char current_pos;
|
||||
enum CurrentPos {
|
||||
OUTER_UP = 0,
|
||||
OUTER_LEFT = 1,
|
||||
OUTER_DOWN = 2,
|
||||
OUTER_RIGHT = 3,
|
||||
INNER_UP = 4,
|
||||
INNER_LEFT = 5,
|
||||
INNER_DOWN = 6,
|
||||
INNER_RIGHT = 7,
|
||||
INNER_HOME = 8,
|
||||
UNDEFINED = 9
|
||||
};
|
||||
|
||||
public:
|
||||
AxisCtrlButton(wxWindow *parent, wxBitmap &icon, long style = 0);
|
||||
|
||||
void SetMinSize(const wxSize& size) override;
|
||||
|
||||
void SetTextColor(StateColor const& color);
|
||||
|
||||
void SetBorderColor(StateColor const& color);
|
||||
|
||||
void SetBackgroundColor(StateColor const& color);
|
||||
|
||||
void SetInnerBackgroundColor(StateColor const& color);
|
||||
|
||||
void SetBitmap(wxBitmap &bmp);
|
||||
|
||||
void Rescale();
|
||||
|
||||
private:
|
||||
void updateParams();
|
||||
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
|
||||
void render(wxDC& dc);
|
||||
|
||||
void mouseDown(wxMouseEvent& event);
|
||||
void mouseReleased(wxMouseEvent& event);
|
||||
void mouseMoving(wxMouseEvent& event);
|
||||
|
||||
void sendButtonEvent();
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
#endif // !slic3r_GUI_Button_hpp_
|
247
src/slic3r/GUI/Widgets/Button.cpp
Normal file
247
src/slic3r/GUI/Widgets/Button.cpp
Normal file
|
@ -0,0 +1,247 @@
|
|||
#include "Button.hpp"
|
||||
#include "Label.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
BEGIN_EVENT_TABLE(Button, StaticBox)
|
||||
|
||||
EVT_LEFT_DOWN(Button::mouseDown)
|
||||
EVT_LEFT_UP(Button::mouseReleased)
|
||||
|
||||
// catch paint events
|
||||
EVT_PAINT(Button::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().
|
||||
*/
|
||||
|
||||
Button::Button()
|
||||
: paddingSize(10, 8)
|
||||
, text_color(*wxBLACK)
|
||||
{
|
||||
background_color = StateColor(
|
||||
std::make_pair(*wxLIGHT_GREY, (int) StateColor::Checked),
|
||||
std::make_pair(*wxLIGHT_GREY, (int) StateColor::Hovered),
|
||||
std::make_pair(*wxWHITE, (int) StateColor::Normal));
|
||||
}
|
||||
|
||||
Button::Button(wxWindow* parent, wxString text, wxString icon, long style, int iconSize)
|
||||
: Button()
|
||||
{
|
||||
Create(parent, text, icon, style, iconSize);
|
||||
}
|
||||
|
||||
bool Button::Create(wxWindow* parent, wxString text, wxString icon, long style, int iconSize)
|
||||
{
|
||||
StaticBox::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style);
|
||||
state_handler.attach({&text_color});
|
||||
state_handler.update_binds();
|
||||
//BBS set default font
|
||||
SetFont(Label::Body_14);
|
||||
wxWindow::SetLabel(text);
|
||||
if (!icon.IsEmpty()) {
|
||||
//BBS set button icon default size to 20
|
||||
this->active_icon = ScalableBitmap(this, icon.ToStdString(), iconSize > 0 ? iconSize : 20);
|
||||
}
|
||||
messureSize();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Button::SetLabel(const wxString& label)
|
||||
{
|
||||
wxWindow::SetLabel(label);
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void Button::SetIcon(const wxString& icon)
|
||||
{
|
||||
if (!icon.IsEmpty()) {
|
||||
//BBS set button icon default size to 20
|
||||
this->active_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_cnt());
|
||||
}
|
||||
else
|
||||
{
|
||||
this->active_icon = ScalableBitmap();
|
||||
}
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void Button::SetInactiveIcon(const wxString &icon)
|
||||
{
|
||||
if (!icon.IsEmpty()) {
|
||||
// BBS set button icon default size to 20
|
||||
this->inactive_icon = ScalableBitmap(this, icon.ToStdString(), this->active_icon.px_cnt());
|
||||
} else {
|
||||
this->inactive_icon = ScalableBitmap();
|
||||
}
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void Button::SetMinSize(const wxSize& size)
|
||||
{
|
||||
minSize = size;
|
||||
messureSize();
|
||||
}
|
||||
|
||||
void Button::SetPaddingSize(const wxSize& size)
|
||||
{
|
||||
paddingSize = size;
|
||||
messureSize();
|
||||
}
|
||||
|
||||
void Button::SetTextColor(StateColor const& color)
|
||||
{
|
||||
text_color = color;
|
||||
state_handler.update_binds();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void Button::SetTextColorNormal(wxColor const &color)
|
||||
{
|
||||
text_color.setColorForStates(color, 0);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
bool Button::Enable(bool enable)
|
||||
{
|
||||
bool result = wxWindow::Enable(enable);
|
||||
if (result) {
|
||||
wxCommandEvent e(EVT_ENABLE_CHANGED);
|
||||
e.SetEventObject(this);
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Button::Rescale()
|
||||
{
|
||||
if (this->active_icon.bmp().IsOk())
|
||||
this->active_icon.msw_rescale();
|
||||
|
||||
if (this->inactive_icon.bmp().IsOk())
|
||||
this->inactive_icon.msw_rescale();
|
||||
|
||||
messureSize();
|
||||
}
|
||||
|
||||
void Button::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 Button::render(wxDC& dc)
|
||||
{
|
||||
StaticBox::render(dc);
|
||||
int states = state_handler.states();
|
||||
wxSize size = GetSize();
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
// calc content size
|
||||
wxSize szIcon;
|
||||
wxSize szContent = textSize;
|
||||
|
||||
|
||||
ScalableBitmap icon;
|
||||
if (m_selected || ((states & (int)StateColor::State::Hovered) != 0))
|
||||
icon = active_icon;
|
||||
else
|
||||
icon = inactive_icon;
|
||||
int padding = 5;
|
||||
if (icon.bmp().IsOk()) {
|
||||
if (szContent.y > 0) {
|
||||
//BBS norrow size between text and icon
|
||||
szContent.x += padding;
|
||||
}
|
||||
szIcon = icon.bmp().GetSize();
|
||||
szContent.x += szIcon.x;
|
||||
if (szIcon.y > szContent.y)
|
||||
szContent.y = szIcon.y;
|
||||
if (szContent.x > size.x) {
|
||||
int d = std::min(padding, szContent.x - size.x);
|
||||
padding -= d;
|
||||
szContent.x -= d;
|
||||
}
|
||||
}
|
||||
// move to center
|
||||
wxRect rcContent = { {0, 0}, size };
|
||||
wxSize offset = (size - szContent) / 2;
|
||||
if (offset.x < 0) offset.x = 0;
|
||||
rcContent.Deflate(offset.x, offset.y);
|
||||
// start draw
|
||||
wxPoint pt = rcContent.GetLeftTop();
|
||||
if (icon.bmp().IsOk()) {
|
||||
pt.y += (rcContent.height - szIcon.y) / 2;
|
||||
dc.DrawBitmap(icon.bmp(), pt);
|
||||
//BBS norrow size between text and icon
|
||||
pt.x += szIcon.x + padding;
|
||||
pt.y = rcContent.y;
|
||||
}
|
||||
auto text = GetLabel();
|
||||
if (!text.IsEmpty()) {
|
||||
if (pt.x + textSize.x > size.x)
|
||||
text = wxControl::Ellipsize(text, dc, wxELLIPSIZE_END, size.x - pt.x);
|
||||
pt.y += (rcContent.height - textSize.y) / 2;
|
||||
dc.SetFont(GetFont());
|
||||
dc.SetTextForeground(text_color.colorForStates(states));
|
||||
dc.DrawText(text, pt);
|
||||
}
|
||||
}
|
||||
|
||||
void Button::messureSize()
|
||||
{
|
||||
wxClientDC dc(this);
|
||||
textSize = dc.GetTextExtent(GetLabel());
|
||||
if (minSize.GetWidth() > 0) {
|
||||
wxWindow::SetMinSize(minSize);
|
||||
return;
|
||||
}
|
||||
wxSize szContent = textSize;
|
||||
if (this->active_icon.bmp().IsOk()) {
|
||||
if (szContent.y > 0) {
|
||||
//BBS norrow size between text and icon
|
||||
szContent.x += 5;
|
||||
}
|
||||
wxSize szIcon = this->active_icon.bmp().GetSize();
|
||||
szContent.x += szIcon.x;
|
||||
if (szIcon.y > szContent.y)
|
||||
szContent.y = szIcon.y;
|
||||
}
|
||||
wxWindow::SetMinSize(szContent + paddingSize * 2);
|
||||
}
|
||||
|
||||
void Button::mouseDown(wxMouseEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
pressedDown = true;
|
||||
SetFocus();
|
||||
CaptureMouse();
|
||||
}
|
||||
|
||||
void Button::mouseReleased(wxMouseEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
if (pressedDown) {
|
||||
pressedDown = false;
|
||||
ReleaseMouse();
|
||||
if (wxRect({0, 0}, GetSize()).Contains(event.GetPosition()))
|
||||
sendButtonEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void Button::sendButtonEvent()
|
||||
{
|
||||
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
|
||||
event.SetEventObject(this);
|
||||
GetEventHandler()->ProcessEvent(event);
|
||||
}
|
66
src/slic3r/GUI/Widgets/Button.hpp
Normal file
66
src/slic3r/GUI/Widgets/Button.hpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
#ifndef slic3r_GUI_Button_hpp_
|
||||
#define slic3r_GUI_Button_hpp_
|
||||
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "StaticBox.hpp"
|
||||
|
||||
class Button : public StaticBox
|
||||
{
|
||||
wxSize textSize;
|
||||
wxSize minSize; // set by outer
|
||||
wxSize paddingSize;
|
||||
ScalableBitmap active_icon;
|
||||
ScalableBitmap inactive_icon;
|
||||
|
||||
StateColor text_color;
|
||||
|
||||
bool pressedDown = false;
|
||||
bool m_selected = true;
|
||||
|
||||
static const int buttonWidth = 200;
|
||||
static const int buttonHeight = 50;
|
||||
|
||||
public:
|
||||
Button();
|
||||
|
||||
Button(wxWindow* parent, wxString text, wxString icon = "", long style = 0, int iconSize = 0);
|
||||
|
||||
bool Create(wxWindow* parent, wxString text, wxString icon = "", long style = 0, int iconSize = 0);
|
||||
|
||||
void SetLabel(const wxString& label) override;
|
||||
|
||||
void SetIcon(const wxString& icon);
|
||||
|
||||
void SetInactiveIcon(const wxString& icon);
|
||||
|
||||
void SetMinSize(const wxSize& size) override;
|
||||
|
||||
void SetPaddingSize(const wxSize& size);
|
||||
|
||||
void SetTextColor(StateColor const &color);
|
||||
|
||||
void SetTextColorNormal(wxColor const &color);
|
||||
|
||||
void SetSelected(bool selected = true) { m_selected = selected; }
|
||||
|
||||
bool Enable(bool enable = true);
|
||||
|
||||
void Rescale();
|
||||
|
||||
private:
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
|
||||
void render(wxDC& dc);
|
||||
|
||||
void messureSize();
|
||||
|
||||
// some useful events
|
||||
void mouseDown(wxMouseEvent& event);
|
||||
void mouseReleased(wxMouseEvent& event);
|
||||
|
||||
void sendButtonEvent();
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_Button_hpp_
|
43
src/slic3r/GUI/Widgets/CheckBox.cpp
Normal file
43
src/slic3r/GUI/Widgets/CheckBox.cpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
#include "CheckBox.hpp"
|
||||
|
||||
#include "../wxExtensions.hpp"
|
||||
|
||||
CheckBox::CheckBox(wxWindow* parent)
|
||||
: wxBitmapToggleButton(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE)
|
||||
, m_on(this, "check_on", 16)
|
||||
, m_half(this, "check_half", 16)
|
||||
, m_off(this, "check_off", 16)
|
||||
{
|
||||
//SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
|
||||
if (parent)
|
||||
SetBackgroundColour(parent->GetBackgroundColour());
|
||||
Bind(wxEVT_TOGGLEBUTTON, [this](auto& e) { m_half_checked = false; update(); e.Skip(); });
|
||||
SetSize(m_on.GetBmpSize());
|
||||
SetMinSize(m_on.GetBmpSize());
|
||||
update();
|
||||
}
|
||||
|
||||
void CheckBox::SetValue(bool value)
|
||||
{
|
||||
wxBitmapToggleButton::SetValue(value);
|
||||
update();
|
||||
}
|
||||
|
||||
void CheckBox::SetHalfChecked(bool value)
|
||||
{
|
||||
m_half_checked = value;
|
||||
update();
|
||||
}
|
||||
|
||||
void CheckBox::Rescale()
|
||||
{
|
||||
m_on.msw_rescale();
|
||||
m_off.msw_rescale();
|
||||
SetSize(m_on.GetBmpSize());
|
||||
update();
|
||||
}
|
||||
|
||||
void CheckBox::update()
|
||||
{
|
||||
SetBitmap((m_half_checked ? m_half : GetValue() ? m_on : m_off).bmp());
|
||||
}
|
30
src/slic3r/GUI/Widgets/CheckBox.hpp
Normal file
30
src/slic3r/GUI/Widgets/CheckBox.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef slic3r_GUI_CheckBox_hpp_
|
||||
#define slic3r_GUI_CheckBox_hpp_
|
||||
|
||||
#include "../wxExtensions.hpp"
|
||||
|
||||
#include <wx/tglbtn.h>
|
||||
|
||||
class CheckBox : public wxBitmapToggleButton
|
||||
{
|
||||
public:
|
||||
CheckBox(wxWindow * parent = NULL);
|
||||
|
||||
public:
|
||||
void SetValue(bool value) override;
|
||||
|
||||
void SetHalfChecked(bool value = true);
|
||||
|
||||
void Rescale();
|
||||
|
||||
private:
|
||||
void update();
|
||||
|
||||
private:
|
||||
ScalableBitmap m_on;
|
||||
ScalableBitmap m_half;
|
||||
ScalableBitmap m_off;
|
||||
bool m_half_checked = false;
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_CheckBox_hpp_
|
247
src/slic3r/GUI/Widgets/ComboBox.cpp
Normal file
247
src/slic3r/GUI/Widgets/ComboBox.cpp
Normal file
|
@ -0,0 +1,247 @@
|
|||
#include "ComboBox.hpp"
|
||||
#include "Label.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
BEGIN_EVENT_TABLE(ComboBox, TextInput)
|
||||
|
||||
EVT_LEFT_DOWN(ComboBox::mouseDown)
|
||||
//EVT_MOUSEWHEEL(ComboBox::mouseWheelMoved)
|
||||
|
||||
// catch paint events
|
||||
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().
|
||||
*/
|
||||
|
||||
ComboBox::ComboBox(wxWindow * parent,
|
||||
wxWindowID id,
|
||||
const wxString &value,
|
||||
const wxPoint & pos,
|
||||
const wxSize & size,
|
||||
int n,
|
||||
const wxString choices[],
|
||||
long style)
|
||||
: drop(this, texts, icons, style & DD_STYLE_MASK)
|
||||
{
|
||||
if (style & wxCB_READONLY)
|
||||
style |= wxRIGHT;
|
||||
text_off = style & CB_NO_TEXT;
|
||||
TextInput::Create(parent, "", value, (style & CB_NO_DROP_ICON) ? "" : "drop_down", pos, size,
|
||||
style | wxTE_PROCESS_ENTER);
|
||||
|
||||
if (style & wxCB_READONLY)
|
||||
{
|
||||
GetTextCtrl()->Hide();
|
||||
TextInput::SetFont(Label::Body_14);
|
||||
TextInput::SetBorderColor(StateColor(std::make_pair(0xDBDBDB, (int) StateColor::Disabled),
|
||||
std::make_pair(0xEDFAF2, (int) StateColor::Focused),
|
||||
std::make_pair(0x00AE42, (int) StateColor::Hovered),
|
||||
std::make_pair(0xDBDBDB, (int) StateColor::Normal)));
|
||||
TextInput::SetBackgroundColor(StateColor(std::make_pair(0xF0F0F0, (int) StateColor::Disabled),
|
||||
std::make_pair(0xEDFAF2, (int) StateColor::Focused),
|
||||
std::make_pair(*wxWHITE, (int) StateColor::Normal)));
|
||||
}
|
||||
drop.Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &e) {
|
||||
SetSelection(e.GetInt());
|
||||
e.SetEventObject(this);
|
||||
e.SetId(GetId());
|
||||
wxMouseEvent e1;
|
||||
mouseDown(e1);
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
});
|
||||
drop.Bind(wxEVT_SHOW, [this](auto &e) {
|
||||
if (!e.IsShown()) {
|
||||
drop_down = false;
|
||||
wxCommandEvent e(wxEVT_COMBOBOX_DROPDOWN);
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
}
|
||||
});
|
||||
for (int i = 0; i < n; ++i) Append(choices[i]);
|
||||
}
|
||||
|
||||
int ComboBox::GetSelection() const { return drop.GetSelection(); }
|
||||
|
||||
void ComboBox::SetSelection(int n)
|
||||
{
|
||||
drop.SetSelection(n);
|
||||
SetLabel(drop.GetValue());
|
||||
if (drop.selection >= 0)
|
||||
SetIcon(icons[drop.selection]);
|
||||
}
|
||||
|
||||
void ComboBox::Rescale()
|
||||
{
|
||||
TextInput::Rescale();
|
||||
drop.Rescale();
|
||||
}
|
||||
|
||||
wxString ComboBox::GetValue() const
|
||||
{
|
||||
return drop.GetSelection() >= 0 ? drop.GetValue() : GetLabel();
|
||||
}
|
||||
|
||||
void ComboBox::SetValue(const wxString &value)
|
||||
{
|
||||
drop.SetValue(value);
|
||||
SetLabel(value);
|
||||
if (drop.selection >= 0)
|
||||
SetIcon(icons[drop.selection]);
|
||||
}
|
||||
|
||||
void ComboBox::SetLabel(const wxString &value)
|
||||
{
|
||||
if (GetTextCtrl()->IsShown() || text_off)
|
||||
GetTextCtrl()->SetValue(value);
|
||||
else
|
||||
TextInput::SetLabel(value);
|
||||
}
|
||||
|
||||
wxString ComboBox::GetLabel() const
|
||||
{
|
||||
if (GetTextCtrl()->IsShown() || text_off)
|
||||
return GetTextCtrl()->GetValue();
|
||||
else
|
||||
return TextInput::GetLabel();
|
||||
}
|
||||
|
||||
void ComboBox::SetTextLabel(const wxString& label)
|
||||
{
|
||||
TextInput::SetLabel(label);
|
||||
}
|
||||
|
||||
wxString ComboBox::GetTextLabel() const
|
||||
{
|
||||
return TextInput::GetLabel();
|
||||
}
|
||||
|
||||
bool ComboBox::SetFont(wxFont const& font)
|
||||
{
|
||||
if (GetTextCtrl()->IsShown())
|
||||
return GetTextCtrl()->SetFont(font);
|
||||
else
|
||||
return TextInput::SetFont(font);
|
||||
}
|
||||
|
||||
int ComboBox::Append(const wxString &item, const wxBitmap &bitmap)
|
||||
{
|
||||
return Append(item, bitmap, nullptr);
|
||||
}
|
||||
|
||||
int ComboBox::Append(const wxString &item,
|
||||
const wxBitmap &bitmap,
|
||||
void * clientData)
|
||||
{
|
||||
texts.push_back(item);
|
||||
icons.push_back(bitmap);
|
||||
datas.push_back(clientData);
|
||||
types.push_back(wxClientData_None);
|
||||
drop.Invalidate();
|
||||
return texts.size() - 1;
|
||||
}
|
||||
|
||||
void ComboBox::DoClear()
|
||||
{
|
||||
texts.clear();
|
||||
icons.clear();
|
||||
datas.clear();
|
||||
types.clear();
|
||||
drop.Invalidate(true);
|
||||
}
|
||||
|
||||
void ComboBox::DoDeleteOneItem(unsigned int pos)
|
||||
{
|
||||
if (pos >= texts.size()) return;
|
||||
texts.erase(texts.begin() + pos);
|
||||
icons.erase(icons.begin() + pos);
|
||||
datas.erase(datas.begin() + pos);
|
||||
types.erase(types.begin() + pos);
|
||||
drop.Invalidate(true);
|
||||
}
|
||||
|
||||
unsigned int ComboBox::GetCount() const { return texts.size(); }
|
||||
|
||||
wxString ComboBox::GetString(unsigned int n) const
|
||||
{
|
||||
return n < texts.size() ? texts[n] : wxString{};
|
||||
}
|
||||
|
||||
void ComboBox::SetString(unsigned int n, wxString const &value)
|
||||
{
|
||||
if (n >= texts.size()) return;
|
||||
texts[n] = value;
|
||||
drop.Invalidate();
|
||||
if (n == drop.GetSelection()) SetLabel(value);
|
||||
}
|
||||
|
||||
wxBitmap ComboBox::GetItemBitmap(unsigned int n) { return icons[n]; }
|
||||
|
||||
int ComboBox::DoInsertItems(const wxArrayStringsAdapter &items,
|
||||
unsigned int pos,
|
||||
void ** clientData,
|
||||
wxClientDataType type)
|
||||
{
|
||||
if (pos > texts.size()) return -1;
|
||||
for (int i = 0; i < items.GetCount(); ++i) {
|
||||
texts.insert(texts.begin() + pos, items[i]);
|
||||
icons.insert(icons.begin() + pos, wxNullBitmap);
|
||||
datas.insert(datas.begin() + pos, clientData ? clientData[i] : NULL);
|
||||
types.insert(types.begin() + pos, type);
|
||||
++pos;
|
||||
}
|
||||
drop.Invalidate(true);
|
||||
return pos - 1;
|
||||
}
|
||||
|
||||
void *ComboBox::DoGetItemClientData(unsigned int n) const { return n < texts.size() ? datas[n] : NULL; }
|
||||
|
||||
void ComboBox::DoSetItemClientData(unsigned int n, void *data)
|
||||
{
|
||||
if (n < texts.size())
|
||||
datas[n] = data;
|
||||
}
|
||||
|
||||
void ComboBox::mouseDown(wxMouseEvent &event)
|
||||
{
|
||||
SetFocus();
|
||||
if (drop_down) {
|
||||
drop.Hide();
|
||||
} else if (drop.HasDismissLongTime()) {
|
||||
drop.autoPosition();
|
||||
drop_down = true;
|
||||
drop.Show();
|
||||
drop.Raise();
|
||||
wxCommandEvent e(wxEVT_COMBOBOX_CLOSEUP);
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
void ComboBox::mouseWheelMoved(wxMouseEvent &event)
|
||||
{
|
||||
event.Skip();
|
||||
if (drop_down) return;
|
||||
auto delta = (event.GetWheelRotation() < 0 == event.IsWheelInverted()) ? -1 : 1;
|
||||
unsigned int n = GetSelection() + delta;
|
||||
if (n < GetCount()) {
|
||||
SetSelection((int) n);
|
||||
sendComboBoxEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void ComboBox::OnEdit()
|
||||
{
|
||||
auto value = GetTextCtrl()->GetValue();
|
||||
SetValue(value);
|
||||
}
|
||||
|
||||
void ComboBox::sendComboBoxEvent()
|
||||
{
|
||||
wxCommandEvent event(wxEVT_COMBOBOX, GetId());
|
||||
event.SetEventObject(this);
|
||||
event.SetInt(drop.GetSelection());
|
||||
event.SetString(drop.GetValue());
|
||||
GetEventHandler()->ProcessEvent(event);
|
||||
}
|
87
src/slic3r/GUI/Widgets/ComboBox.hpp
Normal file
87
src/slic3r/GUI/Widgets/ComboBox.hpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
#ifndef slic3r_GUI_ComboBox_hpp_
|
||||
#define slic3r_GUI_ComboBox_hpp_
|
||||
|
||||
#include "TextInput.hpp"
|
||||
#include "DropDown.hpp"
|
||||
|
||||
#define CB_NO_DROP_ICON 0x1000000
|
||||
#define CB_NO_TEXT 0x2000000
|
||||
|
||||
class ComboBox : public wxWindowWithItems<TextInput, wxItemContainer>
|
||||
{
|
||||
std::vector<wxString> texts;
|
||||
std::vector<wxBitmap> icons;
|
||||
std::vector<void *> datas;
|
||||
std::vector<wxClientDataType> types;
|
||||
|
||||
DropDown drop;
|
||||
bool drop_down = false;
|
||||
bool text_off = false;
|
||||
|
||||
public:
|
||||
ComboBox(wxWindow * parent,
|
||||
wxWindowID id,
|
||||
const wxString &value = wxEmptyString,
|
||||
const wxPoint & pos = wxDefaultPosition,
|
||||
const wxSize & size = wxDefaultSize,
|
||||
int n = 0,
|
||||
const wxString choices[] = NULL,
|
||||
long style = 0);
|
||||
|
||||
DropDown & GetDropDown() { return drop; }
|
||||
|
||||
virtual bool SetFont(wxFont const & font) override;
|
||||
|
||||
public:
|
||||
int Append(const wxString &item, const wxBitmap &bitmap = wxNullBitmap);
|
||||
|
||||
int Append(const wxString &item, const wxBitmap &bitmap, void *clientData);
|
||||
|
||||
unsigned int GetCount() const override;
|
||||
|
||||
int GetSelection() const override;
|
||||
|
||||
void SetSelection(int n) override;
|
||||
|
||||
virtual void Rescale() override;
|
||||
|
||||
wxString GetValue() const;
|
||||
void SetValue(const wxString &value);
|
||||
|
||||
void SetLabel(const wxString &label) override;
|
||||
wxString GetLabel() const override;
|
||||
|
||||
void SetTextLabel(const wxString &label);
|
||||
wxString GetTextLabel() const;
|
||||
|
||||
wxString GetString(unsigned int n) const override;
|
||||
void SetString(unsigned int n, wxString const &value) override;
|
||||
|
||||
wxBitmap GetItemBitmap(unsigned int n);
|
||||
|
||||
protected:
|
||||
virtual int DoInsertItems(const wxArrayStringsAdapter &items,
|
||||
unsigned int pos,
|
||||
void ** clientData,
|
||||
wxClientDataType type) override;
|
||||
virtual void DoClear() override;
|
||||
|
||||
void DoDeleteOneItem(unsigned int pos) override;
|
||||
|
||||
void *DoGetItemClientData(unsigned int n) const override;
|
||||
void DoSetItemClientData(unsigned int n, void *data) override;
|
||||
|
||||
void OnEdit() override;
|
||||
|
||||
private:
|
||||
|
||||
// some useful events
|
||||
void mouseDown(wxMouseEvent &event);
|
||||
void mouseWheelMoved(wxMouseEvent &event);
|
||||
|
||||
void sendComboBoxEvent();
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_ComboBox_hpp_
|
442
src/slic3r/GUI/Widgets/DropDown.cpp
Normal file
442
src/slic3r/GUI/Widgets/DropDown.cpp
Normal file
|
@ -0,0 +1,442 @@
|
|||
#include "DropDown.hpp"
|
||||
#include "Label.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
BEGIN_EVENT_TABLE(DropDown, wxPanel)
|
||||
|
||||
EVT_LEFT_DOWN(DropDown::mouseDown)
|
||||
EVT_LEFT_UP(DropDown::mouseReleased)
|
||||
EVT_MOTION(DropDown::mouseMove)
|
||||
EVT_MOUSEWHEEL(DropDown::mouseWheelMoved)
|
||||
|
||||
// catch paint events
|
||||
EVT_PAINT(DropDown::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().
|
||||
*/
|
||||
|
||||
DropDown::DropDown(wxWindow * parent,
|
||||
std::vector<wxString> &texts,
|
||||
std::vector<wxBitmap> &icons,
|
||||
long style)
|
||||
: wxPopupTransientWindow(parent)
|
||||
, texts(texts)
|
||||
, icons(icons)
|
||||
, state_handler(this)
|
||||
, border_color(0xDBDBDB)
|
||||
, text_color(0x363636)
|
||||
, selector_border_color(std::make_pair(0x00AE42, (int) StateColor::Hovered),
|
||||
std::make_pair(*wxWHITE, (int) StateColor::Normal))
|
||||
, selector_background_color(std::make_pair(0xEDFAF2, (int) StateColor::Checked),
|
||||
std::make_pair(*wxWHITE, (int) StateColor::Normal))
|
||||
{
|
||||
SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
state_handler.attach({&border_color, &text_color, &selector_border_color, &selector_background_color});
|
||||
state_handler.update_binds();
|
||||
if ((style & DD_NO_CHECK_ICON) == 0)
|
||||
check_bitmap = ScalableBitmap(this, "checked", 16);
|
||||
text_off = style & DD_NO_TEXT;
|
||||
|
||||
// BBS set default font
|
||||
SetFont(Label::Body_14);
|
||||
#ifdef __WXOSX__
|
||||
Bind(wxEVT_ACTIVATE, [this](auto & e) {
|
||||
if (!e.GetActive()) {
|
||||
Hide();
|
||||
OnDismiss();
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void DropDown::Invalidate(bool clear)
|
||||
{
|
||||
if (clear) {
|
||||
selection = hover_item = -1;
|
||||
offset = wxPoint();
|
||||
}
|
||||
assert(selection < (int) texts.size());
|
||||
need_sync = true;
|
||||
}
|
||||
|
||||
void DropDown::SetSelection(int n)
|
||||
{
|
||||
assert(n < (int) texts.size());
|
||||
if (n >= (int) texts.size())
|
||||
n = -1;
|
||||
selection = n;
|
||||
}
|
||||
|
||||
wxString DropDown::GetValue() const
|
||||
{
|
||||
return selection >= 0 ? texts[selection] : wxString();
|
||||
}
|
||||
|
||||
void DropDown::SetValue(const wxString &value)
|
||||
{
|
||||
auto i = std::find(texts.begin(), texts.end(), value);
|
||||
selection = i == texts.end() ? -1 : std::distance(texts.begin(), i);
|
||||
}
|
||||
|
||||
void DropDown::SetCornerRadius(double radius)
|
||||
{
|
||||
this->radius = radius;
|
||||
paintNow();
|
||||
}
|
||||
|
||||
void DropDown::SetBorderColor(StateColor const &color)
|
||||
{
|
||||
border_color = color;
|
||||
state_handler.update_binds();
|
||||
paintNow();
|
||||
}
|
||||
|
||||
void DropDown::SetSelectorBorderColor(StateColor const &color)
|
||||
{
|
||||
selector_border_color = color;
|
||||
state_handler.update_binds();
|
||||
paintNow();
|
||||
}
|
||||
|
||||
void DropDown::SetTextColor(StateColor const &color)
|
||||
{
|
||||
text_color = color;
|
||||
state_handler.update_binds();
|
||||
paintNow();
|
||||
}
|
||||
|
||||
void DropDown::SetSelectorBackgroundColor(StateColor const &color)
|
||||
{
|
||||
selector_background_color = color;
|
||||
state_handler.update_binds();
|
||||
paintNow();
|
||||
}
|
||||
|
||||
void DropDown::SetUseContentWidth(bool use)
|
||||
{
|
||||
if (use_content_width == use)
|
||||
return;
|
||||
use_content_width = use;
|
||||
need_sync = true;
|
||||
messureSize();
|
||||
}
|
||||
|
||||
void DropDown::SetAlignIcon(bool align) { align_icon = align; }
|
||||
|
||||
void DropDown::Rescale()
|
||||
{
|
||||
need_sync = true;
|
||||
}
|
||||
|
||||
bool DropDown::HasDismissLongTime()
|
||||
{
|
||||
auto now = boost::posix_time::microsec_clock::universal_time();
|
||||
return !IsShown() &&
|
||||
(now - dismissTime).total_milliseconds() >= 200;
|
||||
}
|
||||
|
||||
void DropDown::paintEvent(wxPaintEvent& evt)
|
||||
{
|
||||
// depending on your system you may need to look at double-buffered dcs
|
||||
wxBufferedPaintDC dc(this);
|
||||
render(dc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Alternatively, you can use a clientDC to paint on the panel
|
||||
* at any time. Using this generally does not free you from
|
||||
* catching paint events, since it is possible that e.g. the window
|
||||
* manager throws away your drawing when the window comes to the
|
||||
* background, and expects you will redraw it when the window comes
|
||||
* back (by sending a paint event).
|
||||
*/
|
||||
void DropDown::paintNow()
|
||||
{
|
||||
// depending on your system you may need to look at double-buffered dcs
|
||||
//wxClientDC dc(this);
|
||||
//render(dc);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 DropDown::render(wxDC &dc)
|
||||
{
|
||||
if (texts.size() == 0) return;
|
||||
int states = state_handler.states();
|
||||
dc.SetPen(wxPen(border_color.colorForStates(states)));
|
||||
dc.SetBrush(wxBrush(GetBackgroundColour()));
|
||||
// if (GetWindowStyle() & wxBORDER_NONE)
|
||||
// dc.SetPen(wxNullPen);
|
||||
|
||||
// draw background
|
||||
wxSize size = GetSize();
|
||||
if (radius == 0)
|
||||
dc.DrawRectangle(0, 0, size.x, size.y);
|
||||
else
|
||||
dc.DrawRoundedRectangle(0, 0, size.x, size.y, radius);
|
||||
|
||||
// draw hover rectangle
|
||||
wxRect rcContent = {{0, offset.y}, rowSize};
|
||||
if (hover_item >= 0 && (states & StateColor::Hovered)) {
|
||||
rcContent.y += rowSize.y * hover_item;
|
||||
if (rcContent.GetBottom() > 0 && rcContent.y < size.y) {
|
||||
if (selection == hover_item)
|
||||
dc.SetBrush(wxBrush(selector_background_color.colorForStates(states | StateColor::Checked)));
|
||||
dc.SetPen(wxPen(selector_border_color.colorForStates(states)));
|
||||
rcContent.Deflate(4, 1);
|
||||
dc.DrawRectangle(rcContent);
|
||||
rcContent.Inflate(4, 1);
|
||||
}
|
||||
rcContent.y = offset.y;
|
||||
}
|
||||
// draw checked rectangle
|
||||
if (selection >= 0 && (selection != hover_item || (states & StateColor::Hovered) == 0)) {
|
||||
rcContent.y += rowSize.y * selection;
|
||||
if (rcContent.GetBottom() > 0 && rcContent.y < size.y) {
|
||||
dc.SetBrush(wxBrush(selector_background_color.colorForStates(states | StateColor::Checked)));
|
||||
dc.SetPen(wxPen(selector_background_color.colorForStates(states)));
|
||||
rcContent.Deflate(4, 1);
|
||||
dc.DrawRectangle(rcContent);
|
||||
rcContent.Inflate(4, 1);
|
||||
}
|
||||
rcContent.y = offset.y;
|
||||
}
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
{
|
||||
wxSize offset = (rowSize - textSize) / 2;
|
||||
rcContent.Deflate(0, offset.y);
|
||||
}
|
||||
|
||||
// draw position bar
|
||||
if (rowSize.y * texts.size() > size.y) {
|
||||
int height = rowSize.y * texts.size();
|
||||
wxRect rect = {size.x - 6, -offset.y * size.y / height, 4,
|
||||
size.y * size.y / height};
|
||||
dc.SetPen(wxPen(border_color.defaultColor()));
|
||||
dc.SetBrush(wxBrush(*wxLIGHT_GREY));
|
||||
dc.DrawRoundedRectangle(rect, 2);
|
||||
rcContent.width -= 6;
|
||||
}
|
||||
|
||||
// draw check icon
|
||||
rcContent.x += 5;
|
||||
rcContent.width -= 5;
|
||||
if (check_bitmap.bmp().IsOk()) {
|
||||
auto szBmp = check_bitmap.bmp().GetSize();
|
||||
if (selection >= 0) {
|
||||
wxPoint pt = rcContent.GetLeftTop();
|
||||
pt.y += (rcContent.height - szBmp.y) / 2;
|
||||
pt.y += rowSize.y * selection;
|
||||
if (pt.y + szBmp.y > 0 && pt.y < size.y)
|
||||
dc.DrawBitmap(check_bitmap.bmp(), pt);
|
||||
}
|
||||
rcContent.x += szBmp.x + 5;
|
||||
rcContent.width -= szBmp.x + 5;
|
||||
}
|
||||
// draw texts & icons
|
||||
dc.SetTextForeground(text_color.colorForStates(states));
|
||||
for (int i = 0; i < texts.size(); ++i) {
|
||||
if (rcContent.GetBottom() < 0) {
|
||||
rcContent.y += rowSize.y;
|
||||
continue;
|
||||
}
|
||||
if (rcContent.y > size.y) break;
|
||||
wxPoint pt = rcContent.GetLeftTop();
|
||||
auto & icon = icons[i];
|
||||
if (iconSize.x > 0) {
|
||||
if (icon.IsOk()) {
|
||||
pt.y += (rcContent.height - icon.GetSize().y) / 2;
|
||||
dc.DrawBitmap(icon, pt);
|
||||
}
|
||||
pt.x += iconSize.x + 5;
|
||||
pt.y = rcContent.y;
|
||||
} else if (icon.IsOk()) {
|
||||
pt.y += (rcContent.height - icon.GetSize().y) / 2;
|
||||
dc.DrawBitmap(icon, pt);
|
||||
pt.x += icon.GetWidth() + 5;
|
||||
pt.y = rcContent.y;
|
||||
}
|
||||
auto text = texts[i];
|
||||
if (!text_off && !text.IsEmpty()) {
|
||||
wxSize tSize = dc.GetMultiLineTextExtent(text);
|
||||
if (pt.x + tSize.x > rcContent.GetRight()) {
|
||||
text = wxControl::Ellipsize(text, dc, wxELLIPSIZE_END,
|
||||
rcContent.GetRight() - pt.x);
|
||||
}
|
||||
pt.y += (rcContent.height - textSize.y) / 2;
|
||||
dc.SetFont(GetFont());
|
||||
dc.DrawText(text, pt);
|
||||
}
|
||||
rcContent.y += rowSize.y;
|
||||
}
|
||||
}
|
||||
|
||||
void DropDown::messureSize()
|
||||
{
|
||||
if (!need_sync) return;
|
||||
textSize = wxSize();
|
||||
iconSize = wxSize();
|
||||
wxClientDC dc(GetParent() ? GetParent() : this);
|
||||
for (size_t i = 0; i < texts.size(); ++i) {
|
||||
wxSize size1 = text_off ? wxSize() : dc.GetMultiLineTextExtent(texts[i]);
|
||||
if (icons[i].IsOk()) {
|
||||
wxSize size2 = icons[i].GetSize();
|
||||
if (size2.x > iconSize.x) iconSize = size2;
|
||||
if (!align_icon) {
|
||||
size1.x += size2.x + (text_off ? 0 : 5);
|
||||
}
|
||||
}
|
||||
if (size1.x > textSize.x) textSize = size1;
|
||||
}
|
||||
if (!align_icon) iconSize.x = 0;
|
||||
wxSize szContent = textSize;
|
||||
szContent.x += 10;
|
||||
if (check_bitmap.bmp().IsOk()) {
|
||||
auto szBmp = check_bitmap.bmp().GetSize();
|
||||
szContent.x += szBmp.x + 5;
|
||||
}
|
||||
if (iconSize.x > 0) szContent.x += iconSize.x + (text_off ? 0 : 5);
|
||||
if (iconSize.y > szContent.y) szContent.y = iconSize.y;
|
||||
szContent.y += 10;
|
||||
if (texts.size() > 15) szContent.x += 6;
|
||||
if (GetParent()) {
|
||||
auto x = GetParent()->GetSize().x;
|
||||
if (!use_content_width || x > szContent.x)
|
||||
szContent.x = x;
|
||||
}
|
||||
rowSize = szContent;
|
||||
szContent.y *= std::min((size_t)15, texts.size());
|
||||
szContent.y += texts.size() > 15 ? rowSize.y / 2 : 0;
|
||||
wxWindow::SetSize(szContent);
|
||||
need_sync = false;
|
||||
}
|
||||
|
||||
void DropDown::autoPosition()
|
||||
{
|
||||
messureSize();
|
||||
wxPoint pos = GetParent()->ClientToScreen(wxPoint(0, -6));
|
||||
wxPoint old = GetPosition();
|
||||
wxSize size = GetSize();
|
||||
Position(pos, {0, GetParent()->GetSize().y + 12});
|
||||
if (old != GetPosition()) {
|
||||
size = rowSize;
|
||||
size.y *= std::min((size_t)15, texts.size());
|
||||
size.y += texts.size() > 15 ? rowSize.y / 2 : 0;
|
||||
if (size != GetSize()) {
|
||||
wxWindow::SetSize(size);
|
||||
offset = wxPoint();
|
||||
Position(pos, {0, GetParent()->GetSize().y + 12});
|
||||
}
|
||||
}
|
||||
if (GetPosition().y > pos.y) {
|
||||
// may exceed
|
||||
auto drect = wxDisplay(wxDisplay::GetFromWindow(GetParent())).GetGeometry();
|
||||
if (GetPosition().y + size.y + 10 > drect.GetBottom()) {
|
||||
if (use_content_width && texts.size() <= 15) size.x += 6;
|
||||
size.y = drect.GetBottom() - GetPosition().y - 10;
|
||||
wxWindow::SetSize(size);
|
||||
if (selection >= 0) {
|
||||
if (offset.y + rowSize.y * (selection + 1) > size.y)
|
||||
offset.y = size.y - rowSize.y * (selection + 1);
|
||||
else if (offset.y + rowSize.y * selection < 0)
|
||||
offset.y = -rowSize.y * selection;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DropDown::mouseDown(wxMouseEvent& event)
|
||||
{
|
||||
pressedDown = true;
|
||||
CaptureMouse();
|
||||
dragStart = event.GetPosition();
|
||||
}
|
||||
|
||||
void DropDown::mouseReleased(wxMouseEvent& event)
|
||||
{
|
||||
if (pressedDown) {
|
||||
ReleaseMouse();
|
||||
dragStart = wxPoint();
|
||||
pressedDown = false;
|
||||
if (hover_item >= 0) // not moved
|
||||
sendDropDownEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void DropDown::mouseMove(wxMouseEvent &event)
|
||||
{
|
||||
if (pressedDown) {
|
||||
wxPoint pt = event.GetPosition();
|
||||
wxPoint pt2 = offset + pt - dragStart;
|
||||
dragStart = pt;
|
||||
if (pt2.y > 0)
|
||||
pt2.y = 0;
|
||||
else if (pt2.y + rowSize.y * texts.size() < GetSize().y)
|
||||
pt2.y = GetSize().y - rowSize.y * texts.size();
|
||||
if (pt2.y != offset.y) {
|
||||
offset = pt2;
|
||||
hover_item = -1; // moved
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!pressedDown || hover_item >= 0) {
|
||||
int hover = (event.GetPosition().y - offset.y) / rowSize.y;
|
||||
if (hover >= (int) texts.size()) hover = -1;
|
||||
if (hover == hover_item) return;
|
||||
hover_item = hover;
|
||||
if (hover >= 0)
|
||||
SetToolTip(texts[hover]);
|
||||
}
|
||||
paintNow();
|
||||
}
|
||||
|
||||
void DropDown::mouseWheelMoved(wxMouseEvent &event)
|
||||
{
|
||||
auto delta = (event.GetWheelRotation() < 0 == event.IsWheelInverted()) ? rowSize.y : -rowSize.y;
|
||||
wxPoint pt2 = offset + wxPoint{0, delta};
|
||||
if (pt2.y > 0)
|
||||
pt2.y = 0;
|
||||
else if (pt2.y + rowSize.y * texts.size() < GetSize().y)
|
||||
pt2.y = GetSize().y - rowSize.y * texts.size();
|
||||
if (pt2.y != offset.y) {
|
||||
offset = pt2;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
int hover = (event.GetPosition().y - offset.y) / rowSize.y;
|
||||
if (hover >= (int) texts.size()) hover = -1;
|
||||
if (hover != hover_item) {
|
||||
hover_item = hover;
|
||||
if (hover >= 0) SetToolTip(texts[hover]);
|
||||
}
|
||||
paintNow();
|
||||
}
|
||||
|
||||
// currently unused events
|
||||
void DropDown::sendDropDownEvent()
|
||||
{
|
||||
selection = hover_item;
|
||||
wxCommandEvent event(wxEVT_COMBOBOX, GetId());
|
||||
event.SetEventObject(this);
|
||||
event.SetInt(selection);
|
||||
event.SetString(GetValue());
|
||||
GetEventHandler()->ProcessEvent(event);
|
||||
}
|
||||
|
||||
void DropDown::OnDismiss()
|
||||
{
|
||||
dismissTime = boost::posix_time::microsec_clock::universal_time();
|
||||
hover_item = -1;
|
||||
}
|
100
src/slic3r/GUI/Widgets/DropDown.hpp
Normal file
100
src/slic3r/GUI/Widgets/DropDown.hpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
#ifndef slic3r_GUI_DropDown_hpp_
|
||||
#define slic3r_GUI_DropDown_hpp_
|
||||
|
||||
#include <wx/stattext.h>
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "StateHandler.hpp"
|
||||
|
||||
#define DD_NO_CHECK_ICON 0x1000000
|
||||
#define DD_NO_TEXT 0x2000000
|
||||
#define DD_STYLE_MASK 0x3000000
|
||||
|
||||
class DropDown : public wxPopupTransientWindow
|
||||
{
|
||||
std::vector<wxString> & texts;
|
||||
std::vector<wxBitmap> & icons;
|
||||
bool need_sync = false;
|
||||
int selection = -1;
|
||||
int hover_item = -1;
|
||||
|
||||
double radius = 0;
|
||||
bool use_content_width = false;
|
||||
bool align_icon = false;
|
||||
bool text_off = false;
|
||||
|
||||
wxSize textSize;
|
||||
wxSize iconSize;
|
||||
wxSize rowSize;
|
||||
|
||||
StateHandler state_handler;
|
||||
StateColor text_color;
|
||||
StateColor border_color;
|
||||
StateColor selector_border_color;
|
||||
StateColor selector_background_color;
|
||||
ScalableBitmap check_bitmap;
|
||||
|
||||
bool pressedDown = false;
|
||||
boost::posix_time::ptime dismissTime;
|
||||
wxPoint offset; // x not used
|
||||
wxPoint dragStart;
|
||||
|
||||
public:
|
||||
DropDown(wxWindow * parent,
|
||||
std::vector<wxString> &texts,
|
||||
std::vector<wxBitmap> &icons,
|
||||
long style = 0);
|
||||
|
||||
public:
|
||||
void Invalidate(bool clear = false);
|
||||
|
||||
int GetSelection() const { return selection; }
|
||||
|
||||
void SetSelection(int n);
|
||||
|
||||
wxString GetValue() const;
|
||||
void SetValue(const wxString &value);
|
||||
|
||||
public:
|
||||
void SetCornerRadius(double radius);
|
||||
|
||||
void SetBorderColor(StateColor const & color);
|
||||
|
||||
void SetSelectorBorderColor(StateColor const & color);
|
||||
|
||||
void SetTextColor(StateColor const &color);
|
||||
|
||||
void SetSelectorBackgroundColor(StateColor const &color);
|
||||
|
||||
void SetUseContentWidth(bool use);
|
||||
|
||||
void SetAlignIcon(bool align);
|
||||
|
||||
public:
|
||||
void Rescale();
|
||||
|
||||
bool HasDismissLongTime();
|
||||
|
||||
private:
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
void paintNow();
|
||||
|
||||
void render(wxDC& dc);
|
||||
|
||||
friend class ComboBox;
|
||||
void messureSize();
|
||||
void autoPosition();
|
||||
|
||||
// some useful events
|
||||
void mouseDown(wxMouseEvent& event);
|
||||
void mouseReleased(wxMouseEvent &event);
|
||||
void mouseMove(wxMouseEvent &event);
|
||||
void mouseWheelMoved(wxMouseEvent &event);
|
||||
|
||||
void sendDropDownEvent();
|
||||
|
||||
void OnDismiss() override;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_DropDown_hpp_
|
187
src/slic3r/GUI/Widgets/ImageSwitchButton.cpp
Normal file
187
src/slic3r/GUI/Widgets/ImageSwitchButton.cpp
Normal file
|
@ -0,0 +1,187 @@
|
|||
#include "ImageSwitchButton.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "StaticBox.hpp"
|
||||
#include "../wxExtensions.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
BEGIN_EVENT_TABLE(ImageSwitchButton, StaticBox)
|
||||
|
||||
EVT_LEFT_DOWN(ImageSwitchButton::mouseDown)
|
||||
EVT_ENTER_WINDOW(ImageSwitchButton::mouseEnterWindow)
|
||||
EVT_LEAVE_WINDOW(ImageSwitchButton::mouseLeaveWindow)
|
||||
EVT_LEFT_UP(ImageSwitchButton::mouseReleased)
|
||||
EVT_PAINT(ImageSwitchButton::paintEvent)
|
||||
|
||||
END_EVENT_TABLE()
|
||||
|
||||
static const wxColour DEFAULT_HOVER_COL = wxColour(0, 174, 66);
|
||||
static const wxColour DEFAULT_PRESS_COL = wxColour(238, 238, 238);
|
||||
|
||||
ImageSwitchButton::ImageSwitchButton(wxWindow *parent, wxBitmap &img_on, wxBitmap &img_off, long style)
|
||||
: text_color(std::make_pair(0x6B6B6B, (int) StateColor::Disabled), std::make_pair(*wxBLACK, (int) StateColor::Normal))
|
||||
, state_handler(this)
|
||||
{
|
||||
m_padding = 0;
|
||||
m_on = img_on.GetSubBitmap(wxRect(0, 0, img_on.GetWidth(), img_on.GetHeight()));
|
||||
m_off = img_off.GetSubBitmap(wxRect(0, 0, img_off.GetWidth(), img_off.GetHeight()));
|
||||
bg_color = StateColor(std::make_pair(DEFAULT_PRESS_COL, (int) StateColor::Pressed),
|
||||
std::make_pair(*wxWHITE, (int) StateColor::Normal));
|
||||
border_color = StateColor(std::make_pair(DEFAULT_HOVER_COL, (int) StateColor::Hovered));
|
||||
|
||||
StaticBox::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style);
|
||||
|
||||
state_handler.attach({&bg_color});
|
||||
state_handler.attach({&border_color});
|
||||
state_handler.update_binds();
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ImageSwitchButton::SetLabels(wxString const &lbl_on, wxString const &lbl_off)
|
||||
{
|
||||
labels[0] = lbl_on;
|
||||
labels[1] = lbl_off;
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ImageSwitchButton::SetImages(wxBitmap &img_on, wxBitmap &img_off)
|
||||
{
|
||||
m_on = img_on;
|
||||
m_off = img_off;
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ImageSwitchButton::SetTextColor(StateColor const &color)
|
||||
{
|
||||
text_color = color;
|
||||
state_handler.update_binds();
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ImageSwitchButton::SetBorderColor(StateColor const &color)
|
||||
{
|
||||
border_color = color;
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ImageSwitchButton::SetBgColor(StateColor const &color) {
|
||||
bg_color = color;
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ImageSwitchButton::SetValue(bool value)
|
||||
{
|
||||
m_on_off = value;
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ImageSwitchButton::SetPadding(int padding)
|
||||
{
|
||||
m_padding = padding;
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ImageSwitchButton::messureSize()
|
||||
{
|
||||
wxClientDC dc(this);
|
||||
dc.SetFont(GetFont());
|
||||
textSize = dc.GetTextExtent(GetValue() ? labels[0] : labels[1]);
|
||||
}
|
||||
|
||||
void ImageSwitchButton::paintEvent(wxPaintEvent &evt)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
render(dc);
|
||||
}
|
||||
|
||||
void ImageSwitchButton::render(wxDC& dc)
|
||||
{
|
||||
StaticBox::render(dc);
|
||||
int states = state_handler.states();
|
||||
wxSize size = GetSize();
|
||||
|
||||
if (pressedDown) {
|
||||
dc.SetBrush(bg_color.colorForStates(StateColor::Pressed));
|
||||
dc.DrawRectangle(wxRect(0, 0, size.x, size.y));
|
||||
}
|
||||
|
||||
if (hover) {
|
||||
dc.SetPen(border_color.colorForStates(StateColor::Hovered));
|
||||
dc.DrawRectangle(wxRect(0, 0, size.x, size.y));
|
||||
}
|
||||
|
||||
wxSize szIcon;
|
||||
wxSize szContent = textSize;
|
||||
wxBitmap &icon = GetValue() ? m_on: m_off;
|
||||
|
||||
int content_height = icon.GetHeight() + textSize.y + m_padding;
|
||||
|
||||
wxPoint pt = wxPoint((size.x - icon.GetWidth()) / 2, (size.y - content_height) / 2);
|
||||
if (icon.IsOk()) {
|
||||
dc.DrawBitmap(icon, pt);
|
||||
pt.y += m_padding + icon.GetHeight();
|
||||
}
|
||||
pt.x = (size.x - textSize.x) / 2;
|
||||
dc.SetFont(GetFont());
|
||||
if (!IsEnabled())
|
||||
dc.SetTextForeground(text_color.colorForStates(StateColor::Disabled));
|
||||
else
|
||||
dc.SetTextForeground(text_color.colorForStates(states));
|
||||
dc.DrawText(GetValue() ? labels[0] : labels[1], pt);
|
||||
}
|
||||
|
||||
void ImageSwitchButton::Rescale()
|
||||
{
|
||||
messureSize();
|
||||
}
|
||||
|
||||
void ImageSwitchButton::mouseDown(wxMouseEvent &event)
|
||||
{
|
||||
event.Skip();
|
||||
pressedDown = true;
|
||||
SetFocus();
|
||||
CaptureMouse();
|
||||
}
|
||||
|
||||
void ImageSwitchButton::mouseReleased(wxMouseEvent &event)
|
||||
{
|
||||
event.Skip();
|
||||
if (pressedDown) {
|
||||
pressedDown = false;
|
||||
ReleaseMouse();
|
||||
m_on_off = !m_on_off;
|
||||
Refresh();
|
||||
sendButtonEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void ImageSwitchButton::mouseEnterWindow(wxMouseEvent &event)
|
||||
{
|
||||
if (!hover) {
|
||||
hover = true;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void ImageSwitchButton::mouseLeaveWindow(wxMouseEvent &event)
|
||||
{
|
||||
if (hover) {
|
||||
hover = false;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void ImageSwitchButton::sendButtonEvent()
|
||||
{
|
||||
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
|
||||
event.SetEventObject(this);
|
||||
GetEventHandler()->ProcessEvent(event);
|
||||
}
|
58
src/slic3r/GUI/Widgets/ImageSwitchButton.hpp
Normal file
58
src/slic3r/GUI/Widgets/ImageSwitchButton.hpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
#ifndef slic3r_GUI_ImageSwitchButton_hpp_
|
||||
#define slic3r_GUI_ImageSwitchButton_hpp_
|
||||
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "StateColor.hpp"
|
||||
#include "StateHandler.hpp"
|
||||
#include "Button.hpp"
|
||||
|
||||
|
||||
#include <wx/tglbtn.h>
|
||||
|
||||
class ImageSwitchButton : public StaticBox
|
||||
{
|
||||
public:
|
||||
ImageSwitchButton(wxWindow *parent, wxBitmap &img_on, wxBitmap &img_off, long style = 0);
|
||||
|
||||
void SetLabels(wxString const & lbl_on, wxString const & lbl_off);
|
||||
void SetImages(wxBitmap &img_on, wxBitmap &img_off);
|
||||
void SetTextColor(StateColor const &color);
|
||||
void SetBorderColor(StateColor const &color);
|
||||
void SetBgColor(StateColor const &color);
|
||||
void SetValue(bool value);
|
||||
void SetPadding(int padding);
|
||||
|
||||
bool GetValue() { return m_on_off; }
|
||||
void Rescale();
|
||||
|
||||
private:
|
||||
void messureSize();
|
||||
void paintEvent(wxPaintEvent &evt);
|
||||
void render(wxDC& dc);
|
||||
void mouseDown(wxMouseEvent &event);
|
||||
void mouseReleased(wxMouseEvent &event);
|
||||
void mouseEnterWindow(wxMouseEvent &event);
|
||||
void mouseLeaveWindow(wxMouseEvent &event);
|
||||
void sendButtonEvent();
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
private:
|
||||
wxBitmap m_on;
|
||||
wxBitmap m_off;
|
||||
bool m_on_off;
|
||||
int m_padding; // size between icon and text
|
||||
bool pressedDown = false;
|
||||
bool hover = false;
|
||||
|
||||
wxSize textSize;
|
||||
wxSize minSize;
|
||||
|
||||
wxString labels[2];
|
||||
StateColor text_color;
|
||||
StateColor bg_color;
|
||||
StateColor border_color;
|
||||
StateHandler state_handler;
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_SwitchButton_hpp_
|
47
src/slic3r/GUI/Widgets/Label.cpp
Normal file
47
src/slic3r/GUI/Widgets/Label.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include "Label.hpp"
|
||||
#include "StaticBox.hpp"
|
||||
|
||||
wxFont Label::sysFont(int size, bool bold)
|
||||
{
|
||||
#ifdef __linux__
|
||||
return wxFont{};
|
||||
#endif
|
||||
#ifdef __WIN32__
|
||||
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 = Label::sysFont(24, true);
|
||||
wxFont Label::Head_20 = Label::sysFont(20, true);
|
||||
wxFont Label::Head_18 = Label::sysFont(18, true);
|
||||
wxFont Label::Head_16 = Label::sysFont(16, true);
|
||||
wxFont Label::Head_15 = Label::sysFont(15, true);
|
||||
wxFont Label::Head_14 = Label::sysFont(14, true);
|
||||
wxFont Label::Head_13 = Label::sysFont(13, true);
|
||||
wxFont Label::Head_12 = Label::sysFont(12, true);
|
||||
wxFont Label::Head_10 = Label::sysFont(10, true);
|
||||
|
||||
wxFont Label::Body_16 = Label::sysFont(16, false);
|
||||
wxFont Label::Body_15 = Label::sysFont(15, false);
|
||||
wxFont Label::Body_14 = Label::sysFont(14, false);
|
||||
wxFont Label::Body_13 = Label::sysFont(13, false);
|
||||
wxFont Label::Body_12 = Label::sysFont(12, false);
|
||||
wxFont Label::Body_10 = Label::sysFont(10, false);
|
||||
|
||||
Label::Label(wxString const &text, wxWindow *parent) : Label(Body_16, text, parent) {}
|
||||
|
||||
Label::Label(wxFont const &font, wxWindow *parent) : Label(font, "", parent) {}
|
||||
|
||||
Label::Label(wxFont const &font, wxString const &text, wxWindow *parent) : wxStaticText(parent, wxID_ANY, text, wxDefaultPosition, wxDefaultSize, 0)
|
||||
{
|
||||
SetBackgroundColour(StaticBox::GetParentBackgroundColor(parent));
|
||||
SetFont(font);
|
||||
}
|
36
src/slic3r/GUI/Widgets/Label.hpp
Normal file
36
src/slic3r/GUI/Widgets/Label.hpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef slic3r_GUI_Label_hpp_
|
||||
#define slic3r_GUI_Label_hpp_
|
||||
|
||||
#include <wx/stattext.h>
|
||||
|
||||
class Label : public wxStaticText
|
||||
{
|
||||
public:
|
||||
Label(wxString const& text, wxWindow* parent = NULL);
|
||||
|
||||
Label(wxFont const& font, wxWindow* parent = NULL);
|
||||
|
||||
Label(wxFont const& font, wxString const& text, wxWindow* parent = NULL);
|
||||
|
||||
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_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 sysFont(int size, bool bold = false);
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_Label_hpp_
|
237
src/slic3r/GUI/Widgets/ProgressBar.cpp
Normal file
237
src/slic3r/GUI/Widgets/ProgressBar.cpp
Normal file
|
@ -0,0 +1,237 @@
|
|||
#include "ProgressBar.hpp"
|
||||
#include "../I18N.hpp"
|
||||
#include <wx/dcgraph.h>
|
||||
#include "Label.hpp"
|
||||
|
||||
|
||||
|
||||
wxDEFINE_EVENT(wxCUSTOMEVT_SET_TEMP_FINISH, wxCommandEvent);
|
||||
BEGIN_EVENT_TABLE(ProgressBar, wxPanel)
|
||||
EVT_PAINT(ProgressBar::paintEvent)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
ProgressBar::ProgressBar(wxWindow *parent, wxWindowID id, int max, const wxPoint &pos, const wxSize &size, bool shown)
|
||||
{
|
||||
m_shownumber = shown;
|
||||
SetBackgroundColour(wxColour(255,255,255));
|
||||
|
||||
if (size.y >= miniHeight) {
|
||||
m_miniHeight = size.y;
|
||||
} else {
|
||||
m_miniHeight = miniHeight;
|
||||
}
|
||||
|
||||
m_max = max;
|
||||
m_radius = m_miniHeight / 2;
|
||||
wxSize temp_size(size.x, m_miniHeight);
|
||||
|
||||
SetFont(Label::Head_12);
|
||||
create(parent, id, pos, temp_size);
|
||||
}
|
||||
|
||||
|
||||
ProgressBar::~ProgressBar() {}
|
||||
|
||||
|
||||
void ProgressBar::create(wxWindow *parent, wxWindowID id, const wxPoint &pos, wxSize &size)
|
||||
{
|
||||
wxWindow::Create(parent, id, pos, size);
|
||||
// m_static_info = new wxStaticText(this, wxID_ANY,wxT(""),wxPoint(this->padding, 20), wxSize(GetSize().GetWidth() - this->padding * 3, -1), wxST_ELLIPSIZE_END);
|
||||
// m_static_info->Wrap(-1);
|
||||
|
||||
/* wxBoxSizer *m_sizer_body = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
auto m_progress_bk = new StaticBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
m_progress_bk->SetBackgroundColour(wxColour(238, 130, 238));
|
||||
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
|
||||
|
||||
wxBoxSizer *m_sizer_progress= new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
auto m_progress = new wxPanel(m_progress_bk, wxID_ANY, wxDefaultPosition, wxSize(50, -1), wxTAB_TRAVERSAL);
|
||||
m_progress->SetBackgroundColour(wxColour(128, 0, 255));
|
||||
|
||||
m_sizer_progress->Add(m_progress, 0, wxEXPAND, 0);
|
||||
|
||||
m_progress_bk->SetSizer(m_sizer_progress);
|
||||
m_progress_bk->Layout();
|
||||
m_sizer_progress->Fit(m_progress_bk);
|
||||
m_sizer_body->Add(m_progress_bk, 1, wxEXPAND, 0);
|
||||
|
||||
this->SetSizer(m_sizer_body);
|
||||
this->Layout();*/
|
||||
}
|
||||
|
||||
|
||||
void ProgressBar::SetRadius(double radius) {
|
||||
m_radius = radius;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ProgressBar::SetProgressForedColour(wxColour colour)
|
||||
{
|
||||
m_progress_background_colour = colour;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ProgressBar::SetProgressBackgroundColour(wxColour colour)
|
||||
{
|
||||
m_progress_colour = colour;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ProgressBar::Rescale()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void ProgressBar::ShowNumber(bool shown)
|
||||
{
|
||||
m_shownumber = shown;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ProgressBar::Disable(wxString text)
|
||||
{
|
||||
if (m_disable) return;
|
||||
m_disable_text = text;
|
||||
m_disable = true;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void ProgressBar::SetValue(int step)
|
||||
{
|
||||
m_disable = false;
|
||||
SetProgress(step);
|
||||
}
|
||||
|
||||
void ProgressBar::Reset()
|
||||
{
|
||||
m_step = 0;
|
||||
SetValue(0);
|
||||
}
|
||||
|
||||
void ProgressBar::SetProgress(int step)
|
||||
{
|
||||
m_disable = false;
|
||||
if (step < 0) return;
|
||||
//if (step == m_step) return;
|
||||
m_step = step;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void ProgressBar::SetMinSize(const wxSize &size)
|
||||
{
|
||||
if (size.y >= miniHeight) {
|
||||
m_miniHeight = size.y;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
m_radius = m_miniHeight / 2.4;
|
||||
wxWindow::SetMinSize({size.x, m_miniHeight});
|
||||
// SetSize(size);
|
||||
SetRadius(m_radius);
|
||||
}
|
||||
|
||||
|
||||
void ProgressBar::paintEvent(wxPaintEvent &evt)
|
||||
{
|
||||
|
||||
wxPaintDC dc(this);
|
||||
render(dc);
|
||||
}
|
||||
|
||||
void ProgressBar::render(wxDC &dc)
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
wxSize size = GetSize();
|
||||
wxMemoryDC memdc;
|
||||
wxBitmap bmp(size.x, size.y);
|
||||
memdc.SelectObject(bmp);
|
||||
memdc.Blit({0, 0}, size, &dc, {0, 0});
|
||||
|
||||
{
|
||||
wxGCDC dc2(memdc);
|
||||
doRender(dc2);
|
||||
}
|
||||
|
||||
memdc.SelectObject(wxNullBitmap);
|
||||
dc.DrawBitmap(bmp, 0, 0);
|
||||
#else
|
||||
doRender(dc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ProgressBar::doRender(wxDC &dc)
|
||||
{
|
||||
if (m_step >= m_max) m_step = m_max;
|
||||
wxSize size = GetSize();
|
||||
dc.SetPen(wxPen(m_progress_background_colour, 1));
|
||||
dc.SetBrush(wxBrush(m_progress_background_colour));
|
||||
if (m_radius == 0) {
|
||||
dc.DrawRectangle(0, 0, size.x, size.y);
|
||||
} else {
|
||||
dc.DrawRoundedRectangle(0, 0, size.x, size.y, m_radius);
|
||||
}
|
||||
|
||||
//draw progress
|
||||
if (m_disable) {
|
||||
m_proportion = float(size.x * float(this->m_step) / float(this->m_max));
|
||||
if (m_proportion < m_radius * 2 && m_proportion != 0) { m_proportion = m_radius * 2; }
|
||||
|
||||
dc.SetPen(wxPen(m_progress_colour_disable, 1));
|
||||
dc.SetBrush(wxBrush(m_progress_colour_disable));
|
||||
if (m_radius == 0) {
|
||||
dc.DrawRectangle(0, 0, m_proportion, size.y);
|
||||
} else {
|
||||
dc.DrawRoundedRectangle(0, 0, m_proportion, size.y, m_radius);
|
||||
}
|
||||
|
||||
dc.SetFont(::Label::Head_12);
|
||||
auto textSize = dc.GetMultiLineTextExtent(m_disable_text);
|
||||
dc.SetTextForeground(wxColour(144, 144, 144));
|
||||
auto pt = wxPoint();
|
||||
pt.x = (size.x - textSize.x) / 2;
|
||||
pt.y = (size.y - textSize.y) / 2;
|
||||
dc.DrawText(m_disable_text, pt);
|
||||
|
||||
} else {
|
||||
m_proportion = float(size.x * float(this->m_step) / float(this->m_max));
|
||||
if (m_proportion < m_radius * 2 && m_proportion != 0) { m_proportion = m_radius * 2; }
|
||||
|
||||
dc.SetPen(wxPen(m_progress_colour, 1));
|
||||
dc.SetBrush(wxBrush(m_progress_colour));
|
||||
if (m_radius == 0) {
|
||||
dc.DrawRectangle(0, 0, m_proportion, size.y);
|
||||
} else {
|
||||
dc.DrawRoundedRectangle(0, 0, m_proportion, size.y, m_radius);
|
||||
}
|
||||
|
||||
dc.SetFont(GetFont());
|
||||
auto textSize = dc.GetMultiLineTextExtent(wxString("000%"));
|
||||
dc.SetTextForeground(wxColour(144, 144, 144));
|
||||
auto pt = wxPoint();
|
||||
pt.x = (size.x - textSize.x) / 2;
|
||||
pt.y = (size.y - textSize.y) / 2;
|
||||
|
||||
auto text = wxString("");
|
||||
if (m_step < 10) {
|
||||
text = wxString::Format("%d", m_step);
|
||||
} else {
|
||||
text = wxString::Format("%d", m_step);
|
||||
}
|
||||
|
||||
if (m_shownumber) {
|
||||
dc.DrawText(text + wxString("%"), pt);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ProgressBar::DoSetSize(int x, int y, int width, int height, int sizeFlags)
|
||||
{
|
||||
wxWindow::DoSetSize(x, y, width, height, sizeFlags);
|
||||
}
|
66
src/slic3r/GUI/Widgets/ProgressBar.hpp
Normal file
66
src/slic3r/GUI/Widgets/ProgressBar.hpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
#ifndef slic3r_GUI_ProgressBar_hpp_
|
||||
#define slic3r_GUI_ProgressBar_hpp_
|
||||
|
||||
#include <wx/window.h>
|
||||
#include "../wxExtensions.hpp"
|
||||
|
||||
class ProgressBar : public wxWindow
|
||||
{
|
||||
public:
|
||||
ProgressBar();
|
||||
ProgressBar(wxWindow * parent,
|
||||
wxWindowID id = wxID_ANY,
|
||||
int max = 100,
|
||||
const wxPoint & pos = wxDefaultPosition,
|
||||
const wxSize & size = wxDefaultSize,
|
||||
bool shown = false);
|
||||
|
||||
|
||||
void create(wxWindow *parent, wxWindowID id, const wxPoint &pos, wxSize &size);
|
||||
|
||||
~ProgressBar();
|
||||
|
||||
public:
|
||||
bool m_shownumber = {false};
|
||||
int m_disable = {false};
|
||||
int m_max = {100};
|
||||
int m_step = {0};
|
||||
int m_miniHeight = {0};
|
||||
const int miniHeight = {14};
|
||||
double m_radius = {7};
|
||||
double m_proportion = {0};
|
||||
wxColour m_progress_background_colour = {233, 233, 233};
|
||||
wxColour m_progress_colour = {0, 174, 66};
|
||||
wxColour m_progress_colour_disable = {255, 111, 0};
|
||||
wxString m_disable_text;
|
||||
|
||||
|
||||
public:
|
||||
void ShowNumber(bool shown);
|
||||
void Disable(wxString text);
|
||||
void SetValue(int step);
|
||||
void Reset();
|
||||
void SetProgress(int step);
|
||||
void SetRadius(double radius);
|
||||
void SetProgressForedColour(wxColour colour);
|
||||
void SetProgressBackgroundColour(wxColour colour);
|
||||
void Rescale();
|
||||
void SetHeight(int height) {
|
||||
m_minHeight = height;
|
||||
m_radius = m_minHeight / 2;
|
||||
SetSize(GetSize().x, height);
|
||||
}
|
||||
virtual void SetMinSize(const wxSize &size) override;
|
||||
|
||||
protected:
|
||||
void paintEvent(wxPaintEvent &evt);
|
||||
void render(wxDC &dc);
|
||||
void doRender(wxDC &dc);
|
||||
virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
|
||||
|
||||
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_ProgressBar_hpp_
|
852
src/slic3r/GUI/Widgets/ProgressDialog.cpp
Normal file
852
src/slic3r/GUI/Widgets/ProgressDialog.cpp
Normal file
|
@ -0,0 +1,852 @@
|
|||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/utils.h"
|
||||
#include "wx/frame.h"
|
||||
#include "wx/button.h"
|
||||
#include "wx/stattext.h"
|
||||
#include "wx/sizer.h"
|
||||
#include "wx/event.h"
|
||||
#include "wx/gauge.h"
|
||||
#include "wx/intl.h"
|
||||
#include "wx/dcclient.h"
|
||||
#include "wx/timer.h"
|
||||
#include "wx/settings.h"
|
||||
#include "wx/app.h"
|
||||
#endif
|
||||
|
||||
#include "../GUI.hpp"
|
||||
#include "../GUI_App.hpp"
|
||||
#include "../I18N.hpp"
|
||||
#include "ProgressDialog.hpp"
|
||||
#include "wx/evtloop.h"
|
||||
#include "Label.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// constants
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#define LAYOUT_MARGIN 12
|
||||
|
||||
static const int wxID_SKIP = 32000;
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
void ProgressDialog::Init()
|
||||
{
|
||||
// we may disappear at any moment, let the others know about it
|
||||
SetExtraStyle(GetExtraStyle() | wxWS_EX_TRANSIENT);
|
||||
|
||||
// Initialize all our members that we always use (even when we don't
|
||||
// create a valid window in this class).
|
||||
|
||||
m_pdStyle = 0;
|
||||
m_parentTop = NULL;
|
||||
|
||||
m_gauge = NULL;
|
||||
m_msg = NULL;
|
||||
m_elapsed = m_estimated = m_remaining = NULL;
|
||||
|
||||
m_state = Uncancelable;
|
||||
m_maximum = 0;
|
||||
|
||||
m_timeStart = wxGetCurrentTime();
|
||||
m_timeStop = (unsigned long) -1;
|
||||
m_break = 0;
|
||||
|
||||
m_skip = false;
|
||||
|
||||
m_btnAbort = NULL;
|
||||
m_btnSkip = NULL;
|
||||
|
||||
m_display_estimated = m_last_timeupdate = m_ctdelay = 0;
|
||||
|
||||
m_delay = 3;
|
||||
|
||||
m_winDisabler = NULL;
|
||||
m_tempEventLoop = NULL;
|
||||
|
||||
SetWindowStyle(wxDEFAULT_DIALOG_STYLE);
|
||||
}
|
||||
|
||||
ProgressDialog::ProgressDialog() : wxDialog() { Init(); }
|
||||
|
||||
ProgressDialog::ProgressDialog(const wxString &title, const wxString &message, int maximum, wxWindow *parent, int style, bool adaptive) : wxDialog()
|
||||
{
|
||||
m_adaptive = adaptive;
|
||||
Init();
|
||||
Create(title, message, maximum, parent, style);
|
||||
Bind(wxEVT_PAINT, &ProgressDialog::OnPaint, this);
|
||||
Bind(wxEVT_CLOSE_WINDOW, &ProgressDialog::OnClose, this);
|
||||
}
|
||||
|
||||
void ProgressDialog::OnPaint(wxPaintEvent &evt) {}
|
||||
|
||||
void ProgressDialog::SetTopParent(wxWindow *parent)
|
||||
{
|
||||
m_parent = parent;
|
||||
m_parentTop = parent;
|
||||
}
|
||||
|
||||
wxString ProgressDialog::FormatString(wxString title)
|
||||
{
|
||||
if (!m_adaptive) {
|
||||
auto current_width = 0;
|
||||
m_mode = 0;
|
||||
for (int i = 0; i < title.length(); i++) {
|
||||
current_width = m_msg->GetTextExtent(title.SubString(0, i)).x;
|
||||
if (current_width > PROGRESSDIALOG_GAUGE_SIZE.x) {
|
||||
m_mode = 1;
|
||||
// title.insert(i - 1, "\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// set mode
|
||||
if (m_mode == 0) {
|
||||
m_simplebook->SetSelection(0);
|
||||
m_msg->SetLabel(title);
|
||||
} else {
|
||||
m_simplebook->SetSelection(1);
|
||||
m_msg_2line->SetLabel(title);
|
||||
}
|
||||
} else {
|
||||
m_msg->SetLabel(title);
|
||||
Layout();
|
||||
}
|
||||
|
||||
Fit();
|
||||
return title;
|
||||
}
|
||||
|
||||
bool ProgressDialog::Create(const wxString &title, const wxString &message, int maximum, wxWindow *parent, int style)
|
||||
{
|
||||
SetFont(wxGetApp().normal_font());
|
||||
SetTopParent(parent);
|
||||
|
||||
m_pdStyle = style;
|
||||
|
||||
if (!wxDialog::Create(m_parentTop, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, GetWindowStyle())) return false;
|
||||
SetBackgroundColour(PROGRESSDIALOG_DEF_BK);
|
||||
|
||||
/* SetSize(DESIGN_RESOUTION_PROGRESS_SIZE);
|
||||
SetMinSize(DESIGN_RESOUTION_PROGRESS_SIZE);
|
||||
SetMaxSize(DESIGN_RESOUTION_PROGRESS_SIZE);*/
|
||||
|
||||
SetMaximum(maximum);
|
||||
EnsureActiveEventLoopExists();
|
||||
|
||||
#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
|
||||
if (!HasPDFlag(wxPD_CAN_ABORT)) { EnableCloseButton(false); }
|
||||
#endif // wxMSW
|
||||
|
||||
m_state = HasPDFlag(wxPD_CAN_ABORT) ? Continue : Uncancelable;
|
||||
|
||||
wxBoxSizer *m_sizer_main = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_top_line = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_top_line->SetBackgroundColour(wxColour(166, 169, 170));
|
||||
|
||||
m_sizer_main->Add(m_top_line, 0, wxEXPAND, 0);
|
||||
m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(24));
|
||||
|
||||
if (!m_adaptive) {
|
||||
m_simplebook = new wxSimplebook(this, wxID_ANY, wxDefaultPosition, PROGRESSDIALOG_SIMPLEBOOK_SIZE, 0);
|
||||
|
||||
m_panel_1line = new wxPanel(m_simplebook, wxID_ANY, wxDefaultPosition, PROGRESSDIALOG_SIMPLEBOOK_SIZE, 0);
|
||||
m_panel_1line->SetMaxSize(PROGRESSDIALOG_SIMPLEBOOK_SIZE);
|
||||
m_panel_1line->SetBackgroundColour(PROGRESSDIALOG_DEF_BK);
|
||||
m_simplebook->AddPage(m_panel_1line, wxEmptyString, false);
|
||||
|
||||
m_panel_2line = new wxPanel(m_simplebook, wxID_ANY, wxDefaultPosition, PROGRESSDIALOG_SIMPLEBOOK_SIZE, 0);
|
||||
m_panel_2line->SetMaxSize(PROGRESSDIALOG_SIMPLEBOOK_SIZE);
|
||||
m_panel_2line->SetBackgroundColour(PROGRESSDIALOG_DEF_BK);
|
||||
m_simplebook->AddPage(m_panel_2line, wxEmptyString, false);
|
||||
|
||||
wxBoxSizer *sizer_1line = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_msg = new wxStaticText(m_panel_1line, wxID_ANY, wxEmptyString, wxDefaultPosition, PROGRESSDIALOG_SIMPLEBOOK_SIZE, 0);
|
||||
m_msg->Wrap(-1);
|
||||
m_msg->SetFont(::Label::Body_13);
|
||||
m_msg->SetForegroundColour(PROGRESSDIALOG_GREY_700);
|
||||
sizer_1line->Add(m_msg, 0, wxALIGN_CENTER, 0);
|
||||
m_panel_1line->SetSizer(sizer_1line);
|
||||
m_panel_1line->Layout();
|
||||
sizer_1line->Fit(m_panel_1line);
|
||||
|
||||
wxBoxSizer *sizer_2line = new wxBoxSizer(wxVERTICAL);
|
||||
m_msg_2line = new wxStaticText(m_panel_2line, wxID_ANY, wxEmptyString, wxDefaultPosition, PROGRESSDIALOG_SIMPLEBOOK_SIZE, 0);
|
||||
m_msg_2line->Wrap(PROGRESSDIALOG_SIMPLEBOOK_SIZE.x);
|
||||
m_msg_2line->SetFont(::Label::Body_13);
|
||||
m_msg_2line->SetForegroundColour(PROGRESSDIALOG_GREY_700);
|
||||
m_msg_2line->SetMaxSize(PROGRESSDIALOG_SIMPLEBOOK_SIZE);
|
||||
sizer_2line->Add(m_msg_2line, 1, wxALL, 0);
|
||||
m_panel_2line->SetSizer(sizer_2line);
|
||||
m_panel_2line->Layout();
|
||||
sizer_2line->Fit(m_panel_2line);
|
||||
|
||||
m_sizer_main->Add(m_simplebook, 1, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(28));
|
||||
} else {
|
||||
m_msg = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(PROGRESSDIALOG_SIMPLEBOOK_SIZE.x, -1), 0);
|
||||
m_msg->Wrap(PROGRESSDIALOG_SIMPLEBOOK_SIZE.x);
|
||||
m_msg->SetFont(::Label::Body_13);
|
||||
m_msg->SetForegroundColour(PROGRESSDIALOG_GREY_700);
|
||||
m_sizer_main->Add(m_msg, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(28));
|
||||
}
|
||||
|
||||
|
||||
m_sizer_main->Add(0, 0, 0, wxEXPAND | wxTOP, 0);
|
||||
|
||||
int gauge_style = wxGA_HORIZONTAL;
|
||||
if (style & wxPD_SMOOTH) gauge_style |= wxGA_SMOOTH;
|
||||
gauge_style |= wxGA_PROGRESS;
|
||||
|
||||
#ifdef __WXMSW__
|
||||
maximum /= m_factor;
|
||||
#endif
|
||||
|
||||
m_gauge = new wxGauge(this, wxID_ANY, maximum, wxDefaultPosition, PROGRESSDIALOG_GAUGE_SIZE, gauge_style);
|
||||
m_gauge->SetValue(0);
|
||||
m_sizer_main->Add(m_gauge, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(28));
|
||||
|
||||
m_block_left = new wxWindow(m_gauge, wxID_ANY, wxPoint(0, 0), wxSize(FromDIP(2), PROGRESSDIALOG_GAUGE_SIZE.y * 2));
|
||||
m_block_left->SetBackgroundColour(PROGRESSDIALOG_DEF_BK);
|
||||
m_block_right = new wxWindow(m_gauge, wxID_ANY, wxPoint(PROGRESSDIALOG_GAUGE_SIZE.x - 2, 0), wxSize(FromDIP(2), PROGRESSDIALOG_GAUGE_SIZE.y * 2));
|
||||
m_block_right->SetBackgroundColour(PROGRESSDIALOG_DEF_BK);
|
||||
|
||||
wxBoxSizer *m_sizer_bottom = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
m_sizer_bottom->Add(0, 0, 1, wxEXPAND, 0);
|
||||
|
||||
if (HasPDFlag(wxPD_CAN_ABORT)) {
|
||||
m_button_cancel = new Button(this, _L("Cancel"));
|
||||
m_button_cancel->SetTextColor(PROGRESSDIALOG_GREY_700);
|
||||
m_button_cancel->SetMinSize(PROGRESSDIALOG_CANCEL_BUTTON_SIZE);
|
||||
m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &event) {
|
||||
if (m_state == Finished) {
|
||||
event.Skip();
|
||||
} else {
|
||||
m_state = Canceled;
|
||||
DisableAbort();
|
||||
m_button_cancel->Enable(false);
|
||||
DisableSkip();
|
||||
m_timeStop = wxGetCurrentTime();
|
||||
}
|
||||
});
|
||||
m_sizer_bottom->Add(m_button_cancel, 0, wxALL, 0);
|
||||
}
|
||||
|
||||
m_sizer_main->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(16));
|
||||
m_sizer_main->Add(m_sizer_bottom, 1, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(28));
|
||||
m_sizer_main->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(10));
|
||||
|
||||
SetSizer(m_sizer_main);
|
||||
Layout();
|
||||
Fit();
|
||||
Centre(wxCENTER_FRAME | wxBOTH);
|
||||
DisableOtherWindows();
|
||||
FormatString(message);
|
||||
|
||||
Show();
|
||||
Enable();
|
||||
if (m_elapsed) { SetTimeLabel(0, m_elapsed); }
|
||||
|
||||
Update();
|
||||
return true;
|
||||
|
||||
//
|
||||
// sizerTop = new wxBoxSizer(wxVERTICAL);
|
||||
// auto def_size_width = wxMin(wxGetClientDisplayRect().width / 3, 305);
|
||||
//
|
||||
// wxStaticLine *m_staticline2 = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxSize(def_size_width, 1), wxLI_HORIZONTAL);
|
||||
// sizerTop->Add(m_staticline2, 0, wxEXPAND, 0);
|
||||
// auto m_block_top = new wxWindow(this, wxID_ANY, wxDefaultPosition, wxSize(def_size_width, 20));
|
||||
// m_block_top->SetBackgroundColour(wxColor(DESIGN_RESOUTION_DEF_BK_COLOR));
|
||||
// sizerTop->Add(m_block_top, 0, wxEXPAND);
|
||||
//
|
||||
// m_message_area = new wxWindow(this, wxID_ANY, wxDefaultPosition, wxSize(def_size_width, 38));
|
||||
// m_message_area->SetBackgroundColour(DESIGN_RESOUTION_DEF_BK_COLOR);
|
||||
// sizerTop->Add(m_message_area, 0, wxLEFT | wxRIGHT | wxBottom | wxEXPAND, 2 * LAYOUT_MARGIN);
|
||||
//
|
||||
// m_msg = new wxStaticText(m_message_area, wxID_ANY, wxString(""), wxPoint(0, 10), wxSize(def_size_width, 20), wxST_ELLIPSIZE_END);
|
||||
// m_msg->SetForegroundColour(wxColour(107, 107, 107));
|
||||
// m_msg->SetBackgroundColour(DESIGN_RESOUTION_DEF_BK_COLOR);
|
||||
// m_msg->SetMinSize(wxSize(def_size_width, 20));
|
||||
// m_msg->SetMaxSize(wxSize(def_size_width, 20));
|
||||
//
|
||||
// m_msg_2line = new wxStaticText(m_message_area, wxID_ANY, wxString(""), wxPoint(0, 0), wxSize(def_size_width, 40), wxST_ELLIPSIZE_END);
|
||||
// m_msg_2line->SetForegroundColour(wxColour(107, 107, 107));
|
||||
// m_msg_2line->SetBackgroundColour(DESIGN_RESOUTION_DEF_BK_COLOR);
|
||||
// m_msg_2line->SetMinSize(wxSize(def_size_width, 40));
|
||||
// m_msg_2line->SetMaxSize(wxSize(def_size_width, 40));
|
||||
//
|
||||
// auto block_left = new wxWindow(m_gauge, -1, wxPoint(0, 0), wxSize(2, m_gauge->GetSize().GetHeight()));
|
||||
// block_left->SetBackgroundColour(wxColor(255, 255, 255));
|
||||
//
|
||||
// auto block_right = new wxWindow(m_gauge, -1, wxPoint(m_gauge->GetSize().GetWidth() - 2, 0), wxSize(2, m_gauge->GetSize().GetHeight()));
|
||||
// block_right->SetBackgroundColour(wxColor(255, 255, 255));
|
||||
//
|
||||
// sizerTop->Add(m_gauge, 0, wxLEFT | wxRIGHT | wxBottom, 2 * LAYOUT_MARGIN);
|
||||
// m_gauge->SetValue(0);
|
||||
//
|
||||
// m_elapsed = m_estimated = m_remaining = NULL;
|
||||
// size_t nTimeLabels = 0;
|
||||
//
|
||||
// wxSizer *const sizerLabels = new wxFlexGridSizer(2);
|
||||
//
|
||||
// if (style & wxPD_ELAPSED_TIME) {
|
||||
// nTimeLabels++;
|
||||
//
|
||||
// m_elapsed = CreateLabel(GetElapsedLabel(), sizerLabels);
|
||||
// }
|
||||
//
|
||||
// if (style & wxPD_ESTIMATED_TIME) {
|
||||
// nTimeLabels++;
|
||||
//
|
||||
// m_estimated = CreateLabel(GetEstimatedLabel(), sizerLabels);
|
||||
// }
|
||||
//
|
||||
// if (style & wxPD_REMAINING_TIME) {
|
||||
// nTimeLabels++;
|
||||
//
|
||||
// m_remaining = CreateLabel(GetRemainingLabel(), sizerLabels);
|
||||
// }
|
||||
// sizerTop->Add(sizerLabels, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP | wxBottom, LAYOUT_MARGIN);
|
||||
//
|
||||
// wxStdDialogButtonSizer *buttonSizer = wxDialog::CreateStdDialogButtonSizer(0);
|
||||
//
|
||||
// const int borderFlags = wxALL;
|
||||
//
|
||||
// std::string icon_path = (boost::format("%1%/images/common_dialog_confirm.png") % resources_dir()).str();
|
||||
// /*m_btnAbort = new wxBitmapButton(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(52, 24), wxBU_AUTODRAW | wxBORDER_NONE);
|
||||
// m_btnAbort->SetBitmap(wxBitmap(icon_path, wxBITMAP_TYPE_ANY));
|
||||
// m_btnAbort->SetBitmapDisabled(wxBitmap(icon_path, wxBITMAP_TYPE_ANY));
|
||||
// m_btnAbort->SetBitmapPressed(wxBitmap(icon_path, wxBITMAP_TYPE_ANY));
|
||||
// m_btnAbort->SetBitmapFocus(wxBitmap(icon_path, wxBITMAP_TYPE_ANY));
|
||||
// m_btnAbort->SetBitmapCurrent(wxBitmap(icon_path, wxBITMAP_TYPE_ANY));*/
|
||||
//
|
||||
// m_btnAbort = new wxButton(this, wxID_CANCEL, wxString(""), wxDefaultPosition, wxSize(52,24));
|
||||
//
|
||||
// wxStaticBitmap *m_bitmatAbort = new wxStaticBitmap(m_btnAbort, wxID_ANY, wxBitmap(icon_path, wxBITMAP_TYPE_ANY), wxDefaultPosition, wxSize(52, 24), 0);
|
||||
// wxStaticText *textAbort = new wxStaticText(m_btnAbort, wxID_ANY, _T("Cancel"), wxPoint(5, 3), wxSize(42, 19));
|
||||
// textAbort->SetBa
|
||||
// ckgroundColour(wxColor(0, 174, 66));
|
||||
// textAbort->SetForegroundColour(DESIGN_RESOUTION_DEF_BK_COLOR);
|
||||
//
|
||||
// textAbort->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &event) {
|
||||
// if (m_state == Finished) {
|
||||
// event.Skip();
|
||||
// } else {
|
||||
// m_state = Canceled;
|
||||
// //DisableAbort();
|
||||
// DisableSkip();
|
||||
// m_timeStop = wxGetCurrentTime();
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// wxSizerFlags sizerFlags = wxSizerFlags().Border(borderFlags, LAYOUT_MARGIN);
|
||||
// wxWindow *m_button_sizer = new wxWindow(this, wxID_ANY, wxDefaultPosition, wxSize(def_size_width, 26));
|
||||
// m_button_sizer->SetBackgroundColour(DESIGN_RESOUTION_DEF_BK_COLOR);
|
||||
//
|
||||
// if (HasPDFlag(wxPD_CAN_SKIP)) {
|
||||
// m_btnSkip = new wxButton(this, wxID_SKIP, wxGetTranslation("&Skip"));
|
||||
// m_btnSkip->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &ProgressDialog::OnSkip, this);
|
||||
// buttonSizer->SetNegativeButton(m_btnSkip);
|
||||
// }
|
||||
//
|
||||
// if (HasPDFlag(wxPD_CAN_ABORT)) {
|
||||
// /*m_btnAbort = new wxButton(this, wxID_CANCEL);
|
||||
// buttonSizer->SetCancelButton(m_btnAbort);
|
||||
// m_btnAbort->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &ProgressDialog::OnCancel, this);*/
|
||||
//
|
||||
// m_button_calcel = new Button(m_button_sizer, _T("Cancel"));
|
||||
// m_button_calcel->SetTextColor(wxColour(107, 107, 107));
|
||||
// m_button_calcel->SetSize(60, 24);
|
||||
// m_button_calcel->SetPosition(wxPoint(m_button_sizer->GetSize().GetWidth() - m_button_calcel->GetSize().GetWidth(), 0));
|
||||
//
|
||||
// m_button_calcel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &event) {
|
||||
// if (m_state == Finished) {
|
||||
// event.Skip();
|
||||
// } else {
|
||||
// m_state = Canceled;
|
||||
// DisableAbort();
|
||||
// m_button_calcel->Enable(false);
|
||||
// DisableSkip();
|
||||
// m_timeStop = wxGetCurrentTime();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// if (!HasPDFlag(wxPD_CAN_SKIP | wxPD_CAN_ABORT)) buttonSizer->AddSpacer(LAYOUT_MARGIN);
|
||||
//
|
||||
// sizerTop->Add(m_button_sizer, 1, wxEXPAND, 0);
|
||||
//
|
||||
// auto m_block_bottom = new wxWindow(this, wxID_ANY, wxDefaultPosition, wxSize(def_size_width, 15));
|
||||
// m_block_bottom->SetBackgroundColour(DESIGN_RESOUTION_DEF_BK_COLOR);
|
||||
// sizerTop->Add(m_block_bottom, 0, wxEXPAND);
|
||||
//
|
||||
// SetSizerAndFit(sizerTop);
|
||||
// FormatString(message);
|
||||
//
|
||||
// Centre(wxCENTER_FRAME | wxBOTH);
|
||||
//
|
||||
// DisableOtherWindows();
|
||||
//
|
||||
// Show();
|
||||
// Enable();
|
||||
// if (m_elapsed) { SetTimeLabel(0, m_elapsed); }
|
||||
//
|
||||
// Update();
|
||||
// return true;
|
||||
}
|
||||
|
||||
void ProgressDialog::UpdateTimeEstimates(int value, unsigned long &elapsedTime, unsigned long &estimatedTime, unsigned long &remainingTime)
|
||||
{
|
||||
unsigned long elapsed = wxGetCurrentTime() - m_timeStart;
|
||||
if (value != 0 && (m_last_timeupdate < elapsed || value == m_maximum)) {
|
||||
m_last_timeupdate = elapsed;
|
||||
unsigned long estimated = m_break + (unsigned long) (((double) (elapsed - m_break) * m_maximum) / ((double) value));
|
||||
if (estimated > m_display_estimated && m_ctdelay >= 0) {
|
||||
++m_ctdelay;
|
||||
} else if (estimated < m_display_estimated && m_ctdelay <= 0) {
|
||||
--m_ctdelay;
|
||||
} else {
|
||||
m_ctdelay = 0;
|
||||
}
|
||||
if (m_ctdelay >= m_delay // enough confirmations for a higher value
|
||||
|| m_ctdelay <= (m_delay * -1) // enough confirmations for a lower value
|
||||
|| value == m_maximum // to stay consistent
|
||||
|| elapsed > m_display_estimated // to stay consistent
|
||||
|| (elapsed > 0 && elapsed < 4) // additional updates in the beginning
|
||||
) {
|
||||
m_display_estimated = estimated;
|
||||
m_ctdelay = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (value != 0) {
|
||||
long display_remaining = m_display_estimated - elapsed;
|
||||
if (display_remaining < 0) { display_remaining = 0; }
|
||||
|
||||
estimatedTime = m_display_estimated;
|
||||
remainingTime = display_remaining;
|
||||
}
|
||||
|
||||
elapsedTime = elapsed;
|
||||
}
|
||||
|
||||
// static
|
||||
wxString ProgressDialog::GetFormattedTime(unsigned long timeInSec)
|
||||
{
|
||||
wxString timeAsHMS;
|
||||
|
||||
if (timeInSec == (unsigned long) -1) {
|
||||
timeAsHMS = wxGetTranslation("Unknown");
|
||||
} else {
|
||||
unsigned hours = timeInSec / 3600;
|
||||
unsigned minutes = (timeInSec % 3600) / 60;
|
||||
unsigned seconds = timeInSec % 60;
|
||||
timeAsHMS.Printf("%u:%02u:%02u", hours, minutes, seconds);
|
||||
}
|
||||
|
||||
return timeAsHMS;
|
||||
}
|
||||
|
||||
void ProgressDialog::EnsureActiveEventLoopExists()
|
||||
{
|
||||
if (!wxEventLoopBase::GetActive()) {
|
||||
m_tempEventLoop = new wxEventLoop;
|
||||
wxEventLoop::SetActive(m_tempEventLoop);
|
||||
}
|
||||
}
|
||||
|
||||
wxStaticText *ProgressDialog::CreateLabel(const wxString &text, wxSizer *sizer)
|
||||
{
|
||||
wxStaticText *label = new wxStaticText(this, wxID_ANY, text);
|
||||
wxStaticText *value = new wxStaticText(this, wxID_ANY, wxGetTranslation("unknown"));
|
||||
|
||||
// select placement most native or nice on target GUI
|
||||
#if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXGTK20__)
|
||||
// value and time centered in one row
|
||||
sizer->Add(label, 1, wxALIGN_RIGHT | wxTOP | wxRIGHT, LAYOUT_MARGIN);
|
||||
sizer->Add(value, 1, wxALIGN_LEFT | wxTOP, LAYOUT_MARGIN);
|
||||
#else
|
||||
// value and time to the right in one row
|
||||
sizer->Add(label);
|
||||
sizer->Add(value, 0, wxLEFT, LAYOUT_MARGIN);
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ProgressDialog operations
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool ProgressDialog::Update(int value, const wxString &newmsg, bool *skip)
|
||||
{
|
||||
if (!DoBeforeUpdate(skip)) return false;
|
||||
|
||||
wxCHECK_MSG(m_gauge, false, "dialog should be fully created");
|
||||
|
||||
#ifdef __WXMSW__
|
||||
value /= m_factor;
|
||||
#endif // __WXMSW__
|
||||
|
||||
wxASSERT_MSG(value <= m_maximum, wxT("invalid progress value"));
|
||||
m_gauge->SetValue(value);
|
||||
|
||||
UpdateMessage(newmsg);
|
||||
|
||||
if ((m_elapsed || m_remaining || m_estimated) && (value != 0)) {
|
||||
unsigned long elapsed;
|
||||
unsigned long display_remaining;
|
||||
|
||||
UpdateTimeEstimates(value, elapsed, m_display_estimated, display_remaining);
|
||||
|
||||
SetTimeLabel(elapsed, m_elapsed);
|
||||
SetTimeLabel(m_display_estimated, m_estimated);
|
||||
SetTimeLabel(display_remaining, m_remaining);
|
||||
}
|
||||
|
||||
if (value == m_maximum) {
|
||||
if (m_state == Finished) {
|
||||
// ignore multiple calls to Update(m_maximum): it may sometimes be
|
||||
// troublesome to ensure that Update() is not called twice with the
|
||||
// same value (e.g. because of the rounding errors) and if we don't
|
||||
// return now we're going to generate asserts below
|
||||
return true;
|
||||
}
|
||||
|
||||
// so that we return true below and that out [Cancel] handler knew what
|
||||
// to do
|
||||
m_state = Finished;
|
||||
if (!HasPDFlag(wxPD_AUTO_HIDE)) {
|
||||
EnableClose();
|
||||
DisableSkip();
|
||||
#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
|
||||
EnableCloseButton();
|
||||
#endif // __WXMSW__
|
||||
|
||||
if (newmsg.empty()) {
|
||||
// also provide the finishing message if the application didn't
|
||||
m_msg->SetLabel(wxGetTranslation("Done."));
|
||||
}
|
||||
|
||||
// allow the window to repaint:
|
||||
// NOTE: since we yield only for UI events with this call, there
|
||||
// should be no side-effects
|
||||
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI | wxEVT_CATEGORY_USER_INPUT);
|
||||
|
||||
// NOTE: this call results in a new event loop being created
|
||||
// and to a call to ProcessPendingEvents() (which may generate
|
||||
// unwanted re-entrancies).
|
||||
(void) ShowModal();
|
||||
} else // auto hide
|
||||
{
|
||||
// reenable other windows before hiding this one because otherwise
|
||||
// Windows wouldn't give the focus back to the window which had
|
||||
// been previously focused because it would still be disabled
|
||||
ReenableOtherWindows();
|
||||
|
||||
Hide();
|
||||
}
|
||||
} else // not at maximum yet
|
||||
{
|
||||
DoAfterUpdate();
|
||||
}
|
||||
|
||||
// update the display in case yielding above didn't do it
|
||||
Update();
|
||||
|
||||
return m_state != Canceled;
|
||||
}
|
||||
|
||||
bool ProgressDialog::Pulse(const wxString &newmsg, bool *skip)
|
||||
{
|
||||
if (!DoBeforeUpdate(skip)) return false;
|
||||
|
||||
wxCHECK_MSG(m_gauge, false, "dialog should be fully created");
|
||||
|
||||
// show a bit of progress
|
||||
m_gauge->Pulse();
|
||||
|
||||
UpdateMessage(newmsg);
|
||||
|
||||
if (m_elapsed || m_remaining || m_estimated) {
|
||||
unsigned long elapsed = wxGetCurrentTime() - m_timeStart;
|
||||
|
||||
SetTimeLabel(elapsed, m_elapsed);
|
||||
SetTimeLabel((unsigned long) -1, m_estimated);
|
||||
SetTimeLabel((unsigned long) -1, m_remaining);
|
||||
}
|
||||
|
||||
DoAfterUpdate();
|
||||
|
||||
return m_state != Canceled;
|
||||
}
|
||||
|
||||
bool ProgressDialog::DoBeforeUpdate(bool *skip)
|
||||
{
|
||||
// we have to yield because not only we want to update the display but
|
||||
// also to process the clicks on the cancel and skip buttons
|
||||
// NOTE: using YieldFor() this call shouldn't give re-entrancy problems
|
||||
// for event handlers not interested to UI/user-input events.
|
||||
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI | wxEVT_CATEGORY_USER_INPUT);
|
||||
|
||||
Update();
|
||||
|
||||
if (m_skip && skip && !*skip) {
|
||||
*skip = true;
|
||||
m_skip = false;
|
||||
EnableSkip();
|
||||
}
|
||||
|
||||
return m_state != Canceled;
|
||||
}
|
||||
|
||||
void ProgressDialog::DoAfterUpdate()
|
||||
{
|
||||
// allow the window to repaint:
|
||||
// NOTE: since we yield only for UI events with this call, there
|
||||
// should be no side-effects
|
||||
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI | wxEVT_CATEGORY_USER_INPUT);
|
||||
}
|
||||
|
||||
void ProgressDialog::Resume()
|
||||
{
|
||||
m_state = Continue;
|
||||
m_ctdelay = m_delay; // force an update of the elapsed/estimated/remaining time
|
||||
m_break += wxGetCurrentTime() - m_timeStop;
|
||||
|
||||
EnableAbort();
|
||||
m_button_cancel->Enable(true);
|
||||
EnableSkip();
|
||||
m_skip = false;
|
||||
}
|
||||
|
||||
bool ProgressDialog::Show(bool show)
|
||||
{
|
||||
// reenable other windows before hiding this one because otherwise
|
||||
// Windows wouldn't give the focus back to the window which had
|
||||
// been previously focused because it would still be disabled
|
||||
if (!show) ReenableOtherWindows();
|
||||
return wxDialog::Show(show);
|
||||
}
|
||||
|
||||
int ProgressDialog::GetValue() const
|
||||
{
|
||||
wxCHECK_MSG(m_gauge, -1, "dialog should be fully created");
|
||||
|
||||
return m_gauge->GetValue();
|
||||
}
|
||||
|
||||
int ProgressDialog::GetRange() const { return m_maximum; }
|
||||
|
||||
wxString ProgressDialog::GetMessage() const { return m_msg->GetLabel(); }
|
||||
|
||||
void ProgressDialog::SetRange(int maximum)
|
||||
{
|
||||
wxCHECK_RET(m_gauge, "dialog should be fully created");
|
||||
|
||||
wxCHECK_RET(maximum > 0, "Invalid range");
|
||||
|
||||
m_gauge->SetRange(maximum);
|
||||
|
||||
SetMaximum(maximum);
|
||||
}
|
||||
|
||||
void ProgressDialog::SetMaximum(int maximum)
|
||||
{
|
||||
m_maximum = maximum;
|
||||
|
||||
#if defined(__WXMSW__)
|
||||
// we can't have values > 65,536 in the progress control under Windows, so
|
||||
// scale everything down
|
||||
m_factor = m_maximum / 65536 + 1;
|
||||
m_maximum /= m_factor;
|
||||
#endif // __WXMSW__
|
||||
}
|
||||
|
||||
bool ProgressDialog::WasCancelled() const { return HasPDFlag(wxPD_CAN_ABORT) && m_state == Canceled; }
|
||||
|
||||
bool ProgressDialog::WasSkipped() const { return HasPDFlag(wxPD_CAN_SKIP) && m_skip; }
|
||||
|
||||
// static
|
||||
void ProgressDialog::SetTimeLabel(unsigned long val, wxStaticText *label)
|
||||
{
|
||||
if (label) {
|
||||
wxString s;
|
||||
|
||||
if (val != (unsigned long) -1) {
|
||||
s = GetFormattedTime(val);
|
||||
} else {
|
||||
s = wxGetTranslation("Unknown");
|
||||
}
|
||||
|
||||
if (s != label->GetLabel()) label->SetLabel(s);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// event handlers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ProgressDialog::OnCancel(wxCommandEvent &event)
|
||||
{
|
||||
if (m_state == Finished) {
|
||||
// this means that the count down is already finished and we're being
|
||||
// shown as a modal dialog - so just let the default handler do the job
|
||||
event.Skip();
|
||||
} else {
|
||||
// request to cancel was received, the next time Update() is called we
|
||||
// will handle it
|
||||
m_state = Canceled;
|
||||
|
||||
// update the buttons state immediately so that the user knows that the
|
||||
// request has been noticed
|
||||
DisableAbort();
|
||||
DisableSkip();
|
||||
|
||||
// save the time when the dialog was stopped
|
||||
m_timeStop = wxGetCurrentTime();
|
||||
}
|
||||
}
|
||||
|
||||
void ProgressDialog::OnSkip(wxCommandEvent &WXUNUSED(event))
|
||||
{
|
||||
DisableSkip();
|
||||
m_skip = true;
|
||||
}
|
||||
|
||||
void ProgressDialog::OnClose(wxCloseEvent &event)
|
||||
{
|
||||
if (m_state == Uncancelable) {
|
||||
// can't close this dialog
|
||||
event.Veto();
|
||||
} else if (m_state == Finished) {
|
||||
// let the default handler close the window as we already terminated
|
||||
event.Skip();
|
||||
} else {
|
||||
// next Update() will notice it
|
||||
m_state = Canceled;
|
||||
DisableAbort();
|
||||
DisableSkip();
|
||||
|
||||
m_timeStop = wxGetCurrentTime();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// destruction
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ProgressDialog::~ProgressDialog()
|
||||
{
|
||||
// normally this should have been already done, but just in case
|
||||
ReenableOtherWindows();
|
||||
|
||||
if (m_tempEventLoop) {
|
||||
// If another event loop has been installed as active during the life
|
||||
// time of this object, we shouldn't deactivate it, but we also can't
|
||||
// delete our m_tempEventLoop in this case because it risks leaving the
|
||||
// new event loop with a dangling pointer, which it will set back as
|
||||
// the active loop when it exits, resulting in a crash. So we have no
|
||||
// choice but to just leak this pointer then, which is, of course, bad
|
||||
// and usually easily avoidable by just destroying the progress dialog
|
||||
// sooner, so warn the programmer about it.
|
||||
wxCHECK_RET(wxEventLoopBase::GetActive() == m_tempEventLoop, "current event loop must not be changed during "
|
||||
"ProgressDialog lifetime");
|
||||
|
||||
wxEventLoopBase::SetActive(NULL);
|
||||
delete m_tempEventLoop;
|
||||
}
|
||||
}
|
||||
|
||||
void ProgressDialog::DoSetSize(int x, int y, int width, int height, int sizeFlags /*= wxSIZE_AUTO*/)
|
||||
{
|
||||
if (m_button_cancel != nullptr) { m_button_cancel->SetMinSize(PROGRESSDIALOG_CANCEL_BUTTON_SIZE); }
|
||||
if (m_block_left != nullptr && m_block_right != nullptr) {
|
||||
m_block_left->SetPosition(wxPoint(0, 0));
|
||||
m_block_right->SetPosition(wxPoint(PROGRESSDIALOG_GAUGE_SIZE.x - 2, 0));
|
||||
}
|
||||
wxWindow::DoSetSize(x, y, width, height, sizeFlags);
|
||||
}
|
||||
|
||||
void ProgressDialog::DisableOtherWindows()
|
||||
{
|
||||
if (HasPDFlag(wxPD_APP_MODAL)) {
|
||||
#if defined(__WXOSX__)
|
||||
if (m_parentTop) m_parentTop->Disable();
|
||||
m_winDisabler = NULL;
|
||||
#else
|
||||
m_winDisabler = new wxWindowDisabler(this);
|
||||
#endif
|
||||
} else {
|
||||
if (m_parentTop) m_parentTop->Disable();
|
||||
m_winDisabler = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ProgressDialog::ReenableOtherWindows()
|
||||
{
|
||||
if (HasPDFlag(wxPD_APP_MODAL)) {
|
||||
#if defined(__WXOSX__)
|
||||
if (m_parentTop) m_parentTop->Enable();
|
||||
#else
|
||||
wxDELETE(m_winDisabler);
|
||||
#endif
|
||||
} else {
|
||||
if (m_parentTop) m_parentTop->Enable();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ProgressDialog::EnableSkip(bool enable)
|
||||
{
|
||||
if (HasPDFlag(wxPD_CAN_SKIP)) {
|
||||
if (m_btnSkip) m_btnSkip->Enable(enable);
|
||||
}
|
||||
}
|
||||
|
||||
void ProgressDialog::EnableAbort(bool enable)
|
||||
{
|
||||
if (HasPDFlag(wxPD_CAN_ABORT)) {
|
||||
if (m_btnAbort) m_btnAbort->Enable(enable);
|
||||
}
|
||||
}
|
||||
|
||||
void ProgressDialog::EnableClose()
|
||||
{
|
||||
if (HasPDFlag(wxPD_CAN_ABORT)) {
|
||||
if (m_btnAbort) {
|
||||
m_btnAbort->Enable();
|
||||
m_btnAbort->SetLabel(wxGetTranslation("Close"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProgressDialog::UpdateMessage(const wxString &newmsg)
|
||||
{
|
||||
if (!newmsg.empty() && newmsg != m_msg->GetLabel()) {
|
||||
const wxSize sizeOld = m_msg->GetSize();
|
||||
|
||||
FormatString(newmsg);
|
||||
Fit();
|
||||
// m_msg->SetLabel(newmsg);
|
||||
|
||||
if (m_msg->GetSize().x > sizeOld.x) {
|
||||
// Resize the dialog to fit its new, longer contents instead of
|
||||
// just truncating it.
|
||||
Fit();
|
||||
}
|
||||
|
||||
// allow the window to repaint:
|
||||
// NOTE: since we yield only for UI events with this call, there
|
||||
// should be no side-effects
|
||||
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI | wxEVT_CATEGORY_USER_INPUT);
|
||||
}
|
||||
}
|
||||
}} // namespace Slic3r::GUI
|
231
src/slic3r/GUI/Widgets/ProgressDialog.hpp
Normal file
231
src/slic3r/GUI/Widgets/ProgressDialog.hpp
Normal file
|
@ -0,0 +1,231 @@
|
|||
#ifndef slic3r_GUI_PROGRESSDIALOG_hpp_
|
||||
#define slic3r_GUI_PROGRESSDIALOG_hpp_
|
||||
|
||||
#include "wx/dialog.h"
|
||||
#include "wx/weakref.h"
|
||||
#include "wx/simplebook.h"
|
||||
#include "Button.hpp"
|
||||
#include "../wxExtensions.hpp"
|
||||
|
||||
class WXDLLIMPEXP_FWD_CORE wxButton;
|
||||
class WXDLLIMPEXP_FWD_CORE wxEventLoop;
|
||||
class WXDLLIMPEXP_FWD_CORE wxGauge;
|
||||
class WXDLLIMPEXP_FWD_CORE wxStaticText;
|
||||
class WXDLLIMPEXP_FWD_CORE wxWindowDisabler;
|
||||
|
||||
#define PROGRESSDIALOG_SIMPLEBOOK_SIZE wxSize(FromDIP(320), FromDIP(38))
|
||||
#define PROGRESSDIALOG_GAUGE_SIZE wxSize(FromDIP(320), FromDIP(6))
|
||||
#define PROGRESSDIALOG_CANCEL_BUTTON_SIZE wxSize(FromDIP(60), FromDIP(24))
|
||||
#define PROGRESSDIALOG_DEF_BK wxColour(255,255,255)
|
||||
#define PROGRESSDIALOG_GREY_700 wxColour(107,107,107)
|
||||
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
class WXDLLIMPEXP_CORE ProgressDialog : public wxDialog
|
||||
{
|
||||
public:
|
||||
ProgressDialog();
|
||||
ProgressDialog(const wxString &title, const wxString &message, int maximum = 100, wxWindow *parent = NULL, int style = wxPD_APP_MODAL | wxPD_AUTO_HIDE, bool adaptive = false);
|
||||
|
||||
void OnPaint(wxPaintEvent &evt);
|
||||
virtual ~ProgressDialog();
|
||||
|
||||
virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
|
||||
bool Create(const wxString &title, const wxString &message, int maximum = 100, wxWindow *parent = NULL, int style = wxPD_APP_MODAL | wxPD_AUTO_HIDE);
|
||||
|
||||
virtual bool Update(int value, const wxString &newmsg = wxEmptyString, bool *skip = NULL);
|
||||
virtual bool Pulse(const wxString &newmsg = wxEmptyString, bool *skip = NULL);
|
||||
|
||||
virtual void Resume();
|
||||
|
||||
virtual int GetValue() const;
|
||||
virtual int GetRange() const;
|
||||
virtual wxString GetMessage() const;
|
||||
|
||||
virtual void SetRange(int maximum);
|
||||
|
||||
// Return whether "Cancel" or "Skip" button was pressed, always return
|
||||
// false if the corresponding button is not shown.
|
||||
virtual bool WasCancelled() const;
|
||||
virtual bool WasSkipped() const;
|
||||
|
||||
// Must provide overload to avoid hiding it (and warnings about it)
|
||||
virtual void Update() wxOVERRIDE { wxDialog::Update(); }
|
||||
|
||||
virtual bool Show(bool show = true) wxOVERRIDE;
|
||||
|
||||
// This enum is an implementation detail and should not be used
|
||||
// by user code.
|
||||
enum State {
|
||||
Uncancelable = -1, // dialog can't be canceled
|
||||
Canceled, // can be cancelled and, in fact, was
|
||||
Continue, // can be cancelled but wasn't
|
||||
Finished, // finished, waiting to be removed from screen
|
||||
Dismissed // was closed by user after finishing
|
||||
};
|
||||
|
||||
int m_mode = 0; // 0 is 1line mode 1 is 2line mode
|
||||
|
||||
bool m_adaptive = {false};
|
||||
wxSizer * m_sizer_main = {nullptr};
|
||||
wxPanel * m_top_line= {nullptr};
|
||||
wxSimplebook * m_simplebook= {nullptr};
|
||||
wxPanel * m_panel_2line= {nullptr};
|
||||
wxPanel * m_panel_1line= {nullptr};
|
||||
Button* m_button_cancel = {nullptr};
|
||||
wxWindow * m_block_left = {nullptr};
|
||||
wxWindow * m_block_right = {nullptr};
|
||||
|
||||
protected:
|
||||
// Update just the m_maximum field, this is used by public SetRange() but,
|
||||
// unlike it, doesn't update the controls state. This makes it useful for
|
||||
// both this class and its derived classes that don't use m_gauge to
|
||||
// display progress.
|
||||
void SetMaximum(int maximum);
|
||||
|
||||
// Return the labels to use for showing the elapsed/estimated/remaining
|
||||
// times respectively.
|
||||
static wxString GetElapsedLabel() { return wxGetTranslation("Elapsed time:"); }
|
||||
static wxString GetEstimatedLabel() { return wxGetTranslation("Estimated time:"); }
|
||||
static wxString GetRemainingLabel() { return wxGetTranslation("Remaining time:"); }
|
||||
|
||||
// Similar to wxWindow::HasFlag() but tests for a presence of a wxPD_XXX
|
||||
// flag in our (separate) flags instead of using m_windowStyle.
|
||||
bool HasPDFlag(int flag) const { return (m_pdStyle & flag) != 0; }
|
||||
|
||||
// Return the progress dialog style. Prefer to use HasPDFlag() if possible.
|
||||
int GetPDStyle() const { return m_pdStyle; }
|
||||
void SetPDStyle(int pdStyle) { m_pdStyle = pdStyle; }
|
||||
|
||||
// Updates estimated times from a given progress bar value and stores the
|
||||
// results in provided arguments.
|
||||
void UpdateTimeEstimates(int value, unsigned long &elapsedTime, unsigned long &estimatedTime, unsigned long &remainingTime);
|
||||
|
||||
// Converts seconds to HH:mm:ss format.
|
||||
static wxString GetFormattedTime(unsigned long timeInSec);
|
||||
|
||||
// Create a new event loop if there is no currently running one.
|
||||
void EnsureActiveEventLoopExists();
|
||||
|
||||
// callback for optional abort button
|
||||
void OnCancel(wxCommandEvent &);
|
||||
|
||||
// callback for optional skip button
|
||||
void OnSkip(wxCommandEvent &);
|
||||
|
||||
// callback to disable "hard" window closing
|
||||
void OnClose(wxCloseEvent &);
|
||||
|
||||
// called to disable the other windows while this dialog is shown
|
||||
void DisableOtherWindows();
|
||||
|
||||
// must be called to re-enable the other windows temporarily disabled while
|
||||
// the dialog was shown
|
||||
void ReenableOtherWindows();
|
||||
|
||||
// Store the parent window as wxWindow::m_parent and also set the top level
|
||||
// parent reference we store in this class itself.
|
||||
void SetTopParent(wxWindow *parent);
|
||||
|
||||
wxString FormatString(wxString title);
|
||||
// return the top level parent window of this dialog (may be NULL)
|
||||
wxWindow *GetTopParent() const { return m_parentTop; }
|
||||
|
||||
// continue processing or not (return value for Update())
|
||||
State m_state;
|
||||
|
||||
// the maximum value
|
||||
int m_maximum;
|
||||
|
||||
#if defined(__WXMSW__)
|
||||
// the factor we use to always keep the value in 16 bit range as the native
|
||||
// control only supports ranges from 0 to 65,535
|
||||
size_t m_factor;
|
||||
#endif // __WXMSW__
|
||||
|
||||
// time when the dialog was created
|
||||
unsigned long m_timeStart;
|
||||
// time when the dialog was closed or cancelled
|
||||
unsigned long m_timeStop;
|
||||
// time between the moment the dialog was closed/cancelled and resume
|
||||
unsigned long m_break;
|
||||
|
||||
private:
|
||||
// update the label to show the given time (in seconds)
|
||||
static void SetTimeLabel(unsigned long val, wxStaticText *label);
|
||||
|
||||
// common part of all ctors
|
||||
void Init();
|
||||
|
||||
// create the label with given text and another one to show the time nearby
|
||||
// as the next windows in the sizer, returns the created control
|
||||
wxStaticText *CreateLabel(const wxString &text, wxSizer *sizer);
|
||||
|
||||
// updates the label message
|
||||
void UpdateMessage(const wxString &newmsg);
|
||||
|
||||
// common part of Update() and Pulse(), returns true if not cancelled
|
||||
bool DoBeforeUpdate(bool *skip);
|
||||
|
||||
// common part of Update() and Pulse()
|
||||
void DoAfterUpdate();
|
||||
|
||||
// shortcuts for enabling buttons
|
||||
void EnableClose();
|
||||
void EnableSkip(bool enable = true);
|
||||
void EnableAbort(bool enable = true);
|
||||
void DisableSkip() { EnableSkip(false); }
|
||||
void DisableAbort() { EnableAbort(false); }
|
||||
|
||||
// the widget displaying current status (may be NULL)
|
||||
wxGauge *m_gauge;
|
||||
// the message displayed
|
||||
wxStaticText *m_msg;
|
||||
wxStaticText *m_msg_2line;
|
||||
// displayed elapsed, estimated, remaining time
|
||||
wxStaticText *m_elapsed, *m_estimated, *m_remaining;
|
||||
|
||||
// Reference to the parent top level window, automatically becomes NULL if
|
||||
// it it is destroyed and could be always NULL if it's not given at all.
|
||||
wxWindowRef m_parentTop;
|
||||
|
||||
// Progress dialog styles: this is not the same as m_windowStyle because
|
||||
// wxPD_XXX constants clash with the existing TLW styles so to be sure we
|
||||
// don't have any conflicts we just use a separate variable for storing
|
||||
// them.
|
||||
int m_pdStyle;
|
||||
|
||||
// skip some portion
|
||||
bool m_skip;
|
||||
|
||||
// the abort and skip buttons (or NULL if none)
|
||||
wxButton *m_btnAbort;
|
||||
wxButton *m_btnSkip;
|
||||
|
||||
// saves the time when elapsed time was updated so there is only one
|
||||
// update per second
|
||||
unsigned long m_last_timeupdate;
|
||||
|
||||
// tells how often a change of the estimated time has to be confirmed
|
||||
// before it is actually displayed - this reduces the frequency of updates
|
||||
// of estimated and remaining time
|
||||
int m_delay;
|
||||
|
||||
// counts the confirmations
|
||||
int m_ctdelay;
|
||||
unsigned long m_display_estimated;
|
||||
|
||||
// for wxPD_APP_MODAL case
|
||||
wxWindowDisabler *m_winDisabler;
|
||||
|
||||
// Temporary event loop created by the dialog itself if there is no
|
||||
// currently active loop when it is created.
|
||||
wxEventLoop *m_tempEventLoop;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(ProgressDialog);
|
||||
};
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
||||
#endif // slic3r_GUI_PROGRESSDIALOG_hpp_
|
42
src/slic3r/GUI/Widgets/RadioBox.cpp
Normal file
42
src/slic3r/GUI/Widgets/RadioBox.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include "RadioBox.hpp"
|
||||
|
||||
#include "../wxExtensions.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
RadioBox::RadioBox(wxWindow *parent)
|
||||
: wxBitmapToggleButton(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE), m_on(this, "radio_on", 18), m_off(this, "radio_off", 18)
|
||||
{
|
||||
// SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
|
||||
if (parent) SetBackgroundColour(parent->GetBackgroundColour());
|
||||
// Bind(wxEVT_TOGGLEBUTTON, [this](auto& e) { update(); e.Skip(); });
|
||||
SetSize(m_on.GetBmpSize());
|
||||
SetMinSize(m_on.GetBmpSize());
|
||||
update();
|
||||
}
|
||||
|
||||
void RadioBox::SetValue(bool value)
|
||||
{
|
||||
wxBitmapToggleButton::SetValue(value);
|
||||
update();
|
||||
}
|
||||
|
||||
bool RadioBox::GetValue()
|
||||
{
|
||||
return wxBitmapToggleButton::GetValue();
|
||||
}
|
||||
|
||||
|
||||
void RadioBox::Rescale()
|
||||
{
|
||||
m_on.msw_rescale();
|
||||
m_off.msw_rescale();
|
||||
SetSize(m_on.GetBmpSize());
|
||||
update();
|
||||
}
|
||||
|
||||
void RadioBox::update() { SetBitmap((GetValue() ? m_on : m_off).bmp()); }
|
||||
|
||||
}
|
||||
}
|
||||
|
39
src/slic3r/GUI/Widgets/RadioBox.hpp
Normal file
39
src/slic3r/GUI/Widgets/RadioBox.hpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef slic3r_GUI_RADIOBOX_hpp_
|
||||
#define slic3r_GUI_RADIOBOX_hpp_
|
||||
|
||||
#include "../wxExtensions.hpp"
|
||||
|
||||
#include <wx/tglbtn.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class RadioBox : public wxBitmapToggleButton
|
||||
{
|
||||
public:
|
||||
RadioBox(wxWindow *parent);
|
||||
|
||||
public:
|
||||
void SetValue(bool value) override;
|
||||
bool GetValue();
|
||||
void Rescale();
|
||||
bool Disable() {
|
||||
return wxBitmapToggleButton::Disable();
|
||||
}
|
||||
bool Enable() {
|
||||
return wxBitmapToggleButton::Enable();
|
||||
}
|
||||
|
||||
private:
|
||||
void update();
|
||||
|
||||
private:
|
||||
ScalableBitmap m_on;
|
||||
ScalableBitmap m_off;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
|
||||
|
||||
#endif // !slic3r_GUI_CheckBox_hpp_
|
34
src/slic3r/GUI/Widgets/RoundedRectangle.cpp
Normal file
34
src/slic3r/GUI/Widgets/RoundedRectangle.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include "RoundedRectangle.hpp"
|
||||
#include "../wxExtensions.hpp"
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
BEGIN_EVENT_TABLE(RoundedRectangle, wxPanel)
|
||||
EVT_PAINT(RoundedRectangle::OnPaint)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
RoundedRectangle::RoundedRectangle(wxWindow *parent, wxColour col, wxPoint pos, wxSize size, double radius, int type)
|
||||
: wxWindow(parent, wxID_ANY, pos, size, wxBORDER_NONE)
|
||||
{
|
||||
SetBackgroundColour(wxColour(255,255,255));
|
||||
m_type = type;
|
||||
m_color = col;
|
||||
m_radius = radius;
|
||||
}
|
||||
|
||||
void RoundedRectangle::OnPaint(wxPaintEvent &evt)
|
||||
{
|
||||
//draw RoundedRectangle
|
||||
if (m_type == 0) {
|
||||
wxPaintDC dc(this);
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(wxBrush(m_color));
|
||||
dc.DrawRoundedRectangle(0, 0, GetSize().GetWidth(), GetSize().GetHeight(), m_radius);
|
||||
}
|
||||
|
||||
//draw RoundedRectangle only board
|
||||
if (m_type == 1) {
|
||||
wxPaintDC dc(this);
|
||||
dc.SetPen(m_color);
|
||||
dc.DrawRoundedRectangle(0, 0, GetSize().GetWidth(), GetSize().GetHeight(), m_radius);
|
||||
}
|
||||
}
|
21
src/slic3r/GUI/Widgets/RoundedRectangle.hpp
Normal file
21
src/slic3r/GUI/Widgets/RoundedRectangle.hpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef slic3r_GUI_ROUNDEDRECTANGLE_hpp_
|
||||
#define slic3r_GUI_ROUNDEDRECTANGLE_hpp_
|
||||
|
||||
#include "../wxExtensions.hpp"
|
||||
|
||||
class RoundedRectangle : public wxWindow
|
||||
{
|
||||
public:
|
||||
RoundedRectangle(wxWindow *parent, wxColour col, wxPoint pos, wxSize size, double radius, int type = 0);
|
||||
~RoundedRectangle(){};
|
||||
|
||||
private:
|
||||
double m_radius;
|
||||
int m_type;
|
||||
wxColour m_color;
|
||||
|
||||
public:
|
||||
void OnPaint(wxPaintEvent &evt);
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
#endif // !slic3r_GUI_RoundedRectangle_hpp_
|
311
src/slic3r/GUI/Widgets/Scrollbar.cpp
Normal file
311
src/slic3r/GUI/Widgets/Scrollbar.cpp
Normal file
|
@ -0,0 +1,311 @@
|
|||
#pragma once
|
||||
#include <wx/wxprec.h>
|
||||
#ifndef WX_PRECOMP
|
||||
#include <wx/wx.h>
|
||||
#endif
|
||||
|
||||
#include "Scrollbar.hpp"
|
||||
#include "ScrolledWindow.hpp"
|
||||
|
||||
MyScrollbar::MyScrollbar(wxWindow *parent, wxWindowID id, wxPoint position, wxSize size, ScrolledWindow* scrolledWindow, long direction, int scrollbarWidth, int tipLength) : wxPanel(parent, id, position, size)
|
||||
{
|
||||
m_parent = parent;
|
||||
m_direction = direction;
|
||||
m_tipLength = tipLength;
|
||||
if (m_direction == wxVSCROLL)
|
||||
m_virtualDim = size.GetHeight();
|
||||
else
|
||||
m_virtualDim = size.GetWidth(); // default values
|
||||
|
||||
m_actualDim = GetSize().GetHeight();
|
||||
|
||||
m_viewStartInScrollUnits = 0;
|
||||
m_viewStartInPixels = 0;
|
||||
m_minSliderSize = 30;
|
||||
|
||||
m_scrollbarWidth = scrollbarWidth;
|
||||
m_marginWidth = scrollbarWidth;
|
||||
|
||||
m_tipColor = m_parent->GetBackgroundColour(); // default value. Can be changed with SetTipColour
|
||||
m_marginColor = m_parent->GetBackgroundColour(); // default value. Can be changed with SetMarginColour
|
||||
m_scrollbarColor = wxColour(255,255,255); // default value. Can be changed with SetScrollbarColour
|
||||
m_scrolledWindow = scrolledWindow;
|
||||
|
||||
Bind(wxEVT_PAINT, &MyScrollbar::OnPaint, this);
|
||||
Bind(wxEVT_SIZE, &MyScrollbar::OnSize, this);
|
||||
Bind(wxEVT_ERASE_BACKGROUND, &MyScrollbar::OnEraseBackground, this);
|
||||
Bind(wxEVT_LEFT_DOWN, &MyScrollbar::OnMouseLeftDown, this);
|
||||
Bind(wxEVT_LEFT_UP, &MyScrollbar::OnMouseLeftUp, this);
|
||||
Bind(wxEVT_MOTION, &MyScrollbar::OnMouseMove, this);
|
||||
Bind(wxEVT_MOUSEWHEEL, &MyScrollbar::OnMouseWheel, this);
|
||||
}
|
||||
|
||||
void MyScrollbar::SetViewStart(int start)
|
||||
{
|
||||
m_viewStartInScrollUnits = start;
|
||||
m_viewStartInPixels = start;
|
||||
}
|
||||
|
||||
void MyScrollbar::SetTipColor(wxColour color)
|
||||
{
|
||||
m_tipColor = color;
|
||||
}
|
||||
|
||||
void MyScrollbar::SetMarginColor(wxColour color)
|
||||
{
|
||||
m_marginColor = color;
|
||||
}
|
||||
|
||||
void MyScrollbar::SetScrollbarColor(wxColour color)
|
||||
{
|
||||
m_scrollbarColor = color;
|
||||
}
|
||||
|
||||
void MyScrollbar::SetScrollbarTip(int len)
|
||||
{
|
||||
m_tipLength = len ;
|
||||
}
|
||||
|
||||
void MyScrollbar::SetVirtualDim(int pixelsPerUnit, int noUnits)
|
||||
{
|
||||
m_virtualDim = pixelsPerUnit* noUnits;
|
||||
m_pixelsPerUnit = pixelsPerUnit;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void MyScrollbar::OnSize(wxSizeEvent& WXUNUSED(event))
|
||||
{
|
||||
if (m_direction == wxVSCROLL)
|
||||
{
|
||||
m_actualDim = GetSize().GetHeight();
|
||||
if (m_actualDim < m_virtualDim)
|
||||
m_marginWidth = GetSize().GetWidth();
|
||||
else
|
||||
m_marginWidth = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_actualDim = GetSize().GetWidth();
|
||||
if (m_actualDim < m_virtualDim)
|
||||
m_marginWidth = GetSize().GetHeight();
|
||||
else
|
||||
m_marginWidth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MyScrollbar::OnPaint(wxPaintEvent& event)
|
||||
// This scrollbar is either a vertical one or an horizontal one
|
||||
{
|
||||
int scrollbarStart, scrollbarLength, scrollbarSide;
|
||||
//wxBufferedPaintDC dc(this);
|
||||
wxClientDC dc(this);
|
||||
PrepareDC(dc);
|
||||
int actualDim = m_actualDim;
|
||||
|
||||
//m_marginWidth = 10;
|
||||
//m_scrollbarWidth = 10;
|
||||
|
||||
if (m_direction == wxVSCROLL && actualDim < m_virtualDim) // if actualDim >= m_virtualDim, the scrollbar is hidden, no need to paint it
|
||||
{
|
||||
scrollbarSide = (m_marginWidth - m_scrollbarWidth) / 2;
|
||||
scrollbarStart = (m_pixelsPerUnit*actualDim*m_viewStartInScrollUnits) / (float)m_virtualDim + 0.5; // + 0.5 is a cheap way to round the float value
|
||||
scrollbarLength = (actualDim*actualDim) / (float)m_virtualDim + 0.5;
|
||||
|
||||
if (scrollbarLength < m_minSliderSize)
|
||||
{
|
||||
scrollbarStart = (actualDim - m_minSliderSize)*(m_viewStartInScrollUnits*m_pixelsPerUnit / (float)(m_virtualDim - actualDim)) + 0.5;
|
||||
scrollbarLength = m_minSliderSize;
|
||||
}
|
||||
|
||||
if (scrollbarStart < 0) // the mouse is out of the panel
|
||||
scrollbarStart = 0;
|
||||
else if (scrollbarStart + scrollbarLength >= actualDim)
|
||||
scrollbarStart = actualDim - scrollbarLength;
|
||||
|
||||
// draw the upper and lower tips
|
||||
dc.SetPen(m_tipColor);
|
||||
dc.SetBrush(m_tipColor);
|
||||
dc.DrawRectangle(scrollbarSide, 0, m_scrollbarWidth, m_tipLength); // upper tip
|
||||
dc.DrawRectangle(scrollbarSide, actualDim - m_tipLength, m_scrollbarWidth, m_tipLength); // lower tip
|
||||
|
||||
// draw the margins
|
||||
dc.SetPen(m_marginColor);
|
||||
dc.SetBrush(m_marginColor);
|
||||
dc.DrawRectangle(scrollbarSide, m_tipLength, m_scrollbarWidth, scrollbarStart + m_tipLength); // above the scrollbar
|
||||
dc.DrawRectangle(scrollbarSide, scrollbarStart + scrollbarLength - m_tipLength, m_scrollbarWidth, actualDim - scrollbarLength - scrollbarStart); // below the scrollbar
|
||||
dc.DrawRectangle(0, 0, scrollbarSide, actualDim); // left side of the scrollbar
|
||||
dc.DrawRectangle(m_marginWidth - scrollbarSide, 0, scrollbarSide, actualDim); // right side of the scrollbar
|
||||
|
||||
// draw the scrollbar
|
||||
dc.SetPen(m_scrollbarColor);
|
||||
dc.SetBrush(m_scrollbarColor);
|
||||
dc.DrawRectangle(scrollbarSide, scrollbarStart + m_tipLength, m_scrollbarWidth, scrollbarLength - 2 * m_tipLength);
|
||||
}
|
||||
else if (m_direction == wxHSCROLL && actualDim < m_virtualDim) // if actualDim >= m_virtualDim, the scrollbar is hidden, no need to paint it
|
||||
{
|
||||
if (m_scrolledWindow->IsBothDirections())
|
||||
actualDim -= m_marginWidth; // must take into account the right margin
|
||||
|
||||
scrollbarSide = (m_marginWidth - m_scrollbarWidth) / 2;
|
||||
scrollbarStart = (m_pixelsPerUnit*actualDim*m_viewStartInScrollUnits) / (float)m_virtualDim + 0.5; // + 0.5 is a cheap way round the float value
|
||||
scrollbarLength = (actualDim*actualDim) / (float)m_virtualDim + 0.5;
|
||||
|
||||
if (scrollbarLength < m_minSliderSize)
|
||||
{
|
||||
scrollbarStart = (actualDim - m_minSliderSize)*(m_viewStartInScrollUnits*m_pixelsPerUnit / (float)(m_virtualDim - actualDim)) + 0.5;
|
||||
scrollbarLength = m_minSliderSize;
|
||||
}
|
||||
|
||||
if (scrollbarStart < 0) // the mouse is out of the panel
|
||||
scrollbarStart = 0;
|
||||
else if (scrollbarStart + scrollbarLength >= actualDim)
|
||||
scrollbarStart = actualDim - scrollbarLength;
|
||||
|
||||
// draw the left and right tips
|
||||
dc.SetPen(m_tipColor);
|
||||
dc.SetBrush(m_tipColor);
|
||||
dc.DrawRectangle(0, scrollbarSide, m_tipLength, m_scrollbarWidth); // left tip
|
||||
dc.DrawRectangle(actualDim - m_tipLength, scrollbarSide, m_tipLength, m_scrollbarWidth); // right tip
|
||||
|
||||
// draw the margins
|
||||
dc.SetPen(m_marginColor);
|
||||
dc.SetBrush(m_marginColor);
|
||||
dc.DrawRectangle(m_tipLength, scrollbarSide, scrollbarStart + m_tipLength, m_scrollbarWidth); // left of the scrollbar
|
||||
dc.DrawRectangle(scrollbarStart + scrollbarLength - m_tipLength, scrollbarSide, actualDim - scrollbarLength - scrollbarStart, m_scrollbarWidth); // right of the scrollbar
|
||||
dc.DrawRectangle(0, 0, actualDim, scrollbarSide); // above the scrollbar
|
||||
dc.DrawRectangle(0, m_marginWidth - scrollbarSide, actualDim, scrollbarSide); // below the scrollbar
|
||||
dc.DrawRectangle(actualDim, 0, m_marginWidth, m_marginWidth); // lower right corner of the scrolled window
|
||||
|
||||
// draw the scrollbar
|
||||
dc.SetPen(m_scrollbarColor);
|
||||
dc.SetBrush(m_scrollbarColor);
|
||||
dc.DrawRectangle(scrollbarStart + m_tipLength, scrollbarSide, scrollbarLength - 2 * m_tipLength, m_scrollbarWidth);
|
||||
}
|
||||
}
|
||||
|
||||
void MyScrollbar::OnEraseBackground(wxEraseEvent & event)
|
||||
{
|
||||
// necessary to avoid automatic background erasing
|
||||
SetBackgroundColour(wxColor(255,255,255));
|
||||
}
|
||||
|
||||
void MyScrollbar::OnMouseLeftDown(wxMouseEvent &event)
|
||||
{
|
||||
int scrollbarStart, scrollbarLength, eventPos ;
|
||||
|
||||
if (m_direction == wxVSCROLL)
|
||||
eventPos = event.m_y;
|
||||
else
|
||||
eventPos = event.m_x;
|
||||
|
||||
int actualDim = m_actualDim;
|
||||
scrollbarStart = (m_pixelsPerUnit*actualDim*m_viewStartInScrollUnits) / (float)m_virtualDim + 0.5; // + 0.5 is a cheap way to round the float value
|
||||
scrollbarLength = MAX((actualDim*actualDim) / (float)m_virtualDim + 0.5, m_minSliderSize);
|
||||
|
||||
m_previousMouse = eventPos;
|
||||
/*eventPos >= scrollbarStart &&*/
|
||||
if (eventPos < scrollbarStart + scrollbarLength)
|
||||
m_mouseLocation = ON_SCROLLBAR;
|
||||
else
|
||||
m_mouseLocation = BEFORE_SCROLLBAR;
|
||||
|
||||
CaptureMouse();
|
||||
}
|
||||
|
||||
void MyScrollbar::OnMouseLeftUp(wxMouseEvent &event)
|
||||
{
|
||||
if (HasCapture())
|
||||
{
|
||||
ReleaseMouse();
|
||||
}
|
||||
m_mouseLocation = NOWHERE;
|
||||
}
|
||||
|
||||
void MyScrollbar::OnMouseMove(wxMouseEvent &event)
|
||||
{
|
||||
int dMotion, actualDim;
|
||||
if (!event.Dragging())
|
||||
return; // button is not pressed, the user doesn't scroll
|
||||
|
||||
actualDim = m_actualDim;
|
||||
|
||||
if (m_direction == wxVSCROLL && m_mouseLocation == ON_SCROLLBAR)
|
||||
{
|
||||
dMotion = event.m_y - m_previousMouse;
|
||||
m_viewStartInPixels += (dMotion*m_virtualDim) / (float)actualDim + 0.5; // in pixels
|
||||
|
||||
if (m_viewStartInPixels < 0)
|
||||
m_viewStartInPixels = 0;
|
||||
else if (m_viewStartInPixels + actualDim >= m_virtualDim)
|
||||
m_viewStartInPixels = m_virtualDim - actualDim;
|
||||
|
||||
m_viewStartInScrollUnits = m_viewStartInPixels / (float)m_pixelsPerUnit + 0.5; // in scroll units
|
||||
m_scrolledWindow->Scroll(-1, m_viewStartInScrollUnits); // -1 means no change in this direction
|
||||
SetViewStart(m_viewStartInScrollUnits);
|
||||
m_previousMouse = event.m_y;
|
||||
}
|
||||
else if (m_direction == wxHSCROLL && m_mouseLocation == ON_SCROLLBAR)
|
||||
{
|
||||
if (m_scrolledWindow->IsBothDirections())
|
||||
actualDim -= m_marginWidth; // must take into account the right margin
|
||||
|
||||
dMotion = event.m_x - m_previousMouse;
|
||||
m_viewStartInPixels += (dMotion*m_virtualDim) / (float)actualDim + 0.5; // in pixels
|
||||
|
||||
if (m_viewStartInPixels < 0)
|
||||
m_viewStartInPixels = 0;
|
||||
else if (m_viewStartInPixels + actualDim >= m_virtualDim)
|
||||
m_viewStartInPixels = m_virtualDim - actualDim;
|
||||
|
||||
m_viewStartInScrollUnits = m_viewStartInPixels / (float)m_pixelsPerUnit + 0.5; // in scroll units
|
||||
m_scrolledWindow->Scroll(m_viewStartInScrollUnits, -1); // -1 means no change in this direction
|
||||
SetViewStart(m_viewStartInScrollUnits);
|
||||
m_previousMouse = event.m_x;
|
||||
}
|
||||
Refresh();
|
||||
Update();
|
||||
}
|
||||
|
||||
void MyScrollbar::OnMouseWheel(wxMouseEvent &event)
|
||||
{
|
||||
int dMotion, actualDim;
|
||||
if (event.GetWheelRotation() > 0)
|
||||
dMotion = -m_pixelsPerUnit;
|
||||
else
|
||||
dMotion = m_pixelsPerUnit;
|
||||
m_previousMouse += dMotion;
|
||||
actualDim = m_actualDim;
|
||||
|
||||
if (m_direction == wxVSCROLL)
|
||||
{
|
||||
m_viewStartInPixels += (dMotion*m_virtualDim) / (float)actualDim + 0.5; // in pixels
|
||||
|
||||
if (m_viewStartInPixels < 0)
|
||||
m_viewStartInPixels = 0;
|
||||
else if (m_viewStartInPixels + actualDim >= m_virtualDim)
|
||||
m_viewStartInPixels = m_virtualDim - actualDim;
|
||||
|
||||
m_viewStartInScrollUnits = m_viewStartInPixels / (float)m_pixelsPerUnit + 0.5; // in scroll units
|
||||
m_scrolledWindow->Scroll(-1, m_viewStartInScrollUnits); // -1 means no change in this direction
|
||||
SetViewStart(m_viewStartInScrollUnits);
|
||||
}
|
||||
else
|
||||
{
|
||||
dMotion = -dMotion;
|
||||
if (m_scrolledWindow->IsBothDirections())
|
||||
actualDim -= m_marginWidth; // must take into account the right margin
|
||||
|
||||
m_viewStartInPixels += (dMotion*m_virtualDim) / (float)actualDim + 0.5; // in pixels
|
||||
|
||||
if (m_viewStartInPixels < 0)
|
||||
m_viewStartInPixels = 0;
|
||||
else if (m_viewStartInPixels + actualDim >= m_virtualDim)
|
||||
m_viewStartInPixels = m_virtualDim - actualDim;
|
||||
|
||||
m_viewStartInScrollUnits = m_viewStartInPixels / (float)m_pixelsPerUnit + 0.5; // in scroll units
|
||||
m_scrolledWindow->Scroll(m_viewStartInScrollUnits, -1); // -1 means no change in this direction
|
||||
SetViewStart(m_viewStartInScrollUnits);
|
||||
}
|
||||
Refresh();
|
||||
Update();
|
||||
}
|
51
src/slic3r/GUI/Widgets/Scrollbar.hpp
Normal file
51
src/slic3r/GUI/Widgets/Scrollbar.hpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
#pragma once
|
||||
#include <wx/wxprec.h>
|
||||
#ifndef WX_PRECOMP
|
||||
#include <wx/wx.h>
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
enum {BEFORE_SCROLLBAR, ON_SCROLLBAR, AFTER_SCROLLBAR, NOWHERE};
|
||||
|
||||
class ScrolledWindow;
|
||||
|
||||
class MyScrollbar : public wxPanel
|
||||
{
|
||||
public:
|
||||
MyScrollbar(wxWindow *parent, wxWindowID id, wxPoint position, wxSize size, ScrolledWindow* scrolledWindow, long direction, int scrollbarWidth, int tipLength = 0);
|
||||
void SetViewStart(int start);
|
||||
void SetTipColor(wxColour color);
|
||||
void SetMarginColor(wxColour color);
|
||||
void SetScrollbarColor(wxColour color);
|
||||
void SetScrollbarTip(int len);
|
||||
void SetVirtualDim(int pixelsPerUnit, int noUnits);
|
||||
|
||||
private:
|
||||
long m_direction;
|
||||
int m_virtualDim;
|
||||
int m_actualDim;
|
||||
int m_pixelsPerUnit;
|
||||
int m_viewStartInPixels;
|
||||
int m_viewStartInScrollUnits;
|
||||
int m_scrollbarWidth;
|
||||
int m_marginWidth;
|
||||
int m_previousMouse;
|
||||
int m_mouseLocation;
|
||||
int m_tipLength;
|
||||
int m_minSliderSize;
|
||||
wxColour m_tipColor;
|
||||
wxColour m_marginColor;
|
||||
wxColour m_scrollbarColor;
|
||||
ScrolledWindow* m_scrolledWindow; // the scrolledWindow whose the scrollbar is controlling
|
||||
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
void OnSize(wxSizeEvent& WXUNUSED(event));
|
||||
void OnEraseBackground(wxEraseEvent & event);
|
||||
void OnMouseLeftDown(wxMouseEvent &event);
|
||||
void OnMouseLeftUp(wxMouseEvent &event);
|
||||
void OnMouseMove(wxMouseEvent &event);
|
||||
void OnMouseWheel(wxMouseEvent &event);
|
||||
};
|
231
src/slic3r/GUI/Widgets/ScrolledWindow.cpp
Normal file
231
src/slic3r/GUI/Widgets/ScrolledWindow.cpp
Normal file
|
@ -0,0 +1,231 @@
|
|||
// for scroll
|
||||
#pragma once
|
||||
#include <wx/wxprec.h>
|
||||
#ifndef WX_PRECOMP
|
||||
#include <wx/wx.h>
|
||||
#endif
|
||||
|
||||
#include <wx/splitter.h>
|
||||
#include "ScrolledWindow.hpp"
|
||||
#include "Scrollbar.hpp"
|
||||
|
||||
ScrolledWindow::ScrolledWindow(wxWindow *parent, wxWindowID id, wxPoint position, wxSize size, long style, int marginWidth, int scrollbarWidth, int tipLength)
|
||||
: wxScrolled<wxWindow>(parent, id, position, size, style)
|
||||
{
|
||||
bool bVertical = (style & wxVSCROLL) != 0;
|
||||
bool bHorizontal = (style & wxHSCROLL) != 0;
|
||||
m_bothDirections = bVertical & bHorizontal;
|
||||
EnableScrolling(bHorizontal, bVertical);
|
||||
ShowScrollbars(wxSHOW_SB_NEVER, wxSHOW_SB_NEVER);
|
||||
|
||||
m_rightScrollbar = NULL;
|
||||
m_bottomScrollbar = NULL;
|
||||
m_verticalSplitter = NULL;
|
||||
m_horizontalSplitter = NULL;
|
||||
|
||||
m_marginWidth = marginWidth;
|
||||
|
||||
wxSize hsSize = size;
|
||||
hsSize.SetWidth(hsSize.GetWidth() - marginWidth);
|
||||
hsSize.SetHeight(hsSize.GetHeight() - marginWidth);
|
||||
|
||||
wxSize vsSize = size;
|
||||
vsSize.SetWidth(vsSize.GetWidth() - marginWidth);
|
||||
|
||||
|
||||
if (bVertical) {
|
||||
m_verticalSplitter = new wxWindow(this, -1, position, vsSize);
|
||||
m_userPanel = new wxPanel(m_verticalSplitter, -1, wxPoint(0, 0), wxSize(size.GetWidth() - marginWidth, size.GetHeight()));
|
||||
m_scroll_win = new wxWindow(m_verticalSplitter, -1, wxPoint(size.GetWidth() - marginWidth, 0), wxSize(marginWidth, size.GetHeight()));
|
||||
m_rightScrollbar = new MyScrollbar(m_scroll_win, -1, wxPoint(0, 0), wxSize(scrollbarWidth, size.GetHeight()), this, wxVSCROLL, scrollbarWidth, tipLength);
|
||||
} else if (bHorizontal) {
|
||||
m_horizontalSplitter = new wxSplitterWindow(this, -1, position, hsSize);
|
||||
m_userPanel = new wxPanel(m_horizontalSplitter, -1, wxPoint(0, 0), wxSize(size.GetWidth() - marginWidth, size.GetHeight() - marginWidth));
|
||||
m_userPanel->SetBackgroundColour(parent->GetBackgroundColour());
|
||||
|
||||
m_bottomScrollbar = new MyScrollbar(m_horizontalSplitter, -1, wxPoint(0, 0), wxSize(size.GetWidth() - marginWidth, marginWidth), this, wxHSCROLL, scrollbarWidth,
|
||||
tipLength);
|
||||
m_horizontalSplitter->SplitHorizontally(m_userPanel, m_bottomScrollbar, -marginWidth);
|
||||
m_horizontalSplitter->SetSashInvisible();
|
||||
}
|
||||
|
||||
SetTargetWindow(m_userPanel); // very very important line
|
||||
|
||||
Bind(wxEVT_SIZE, &ScrolledWindow::OnSize, this);
|
||||
Bind(wxEVT_SCROLLWIN_TOP, &ScrolledWindow::OnScroll, this);
|
||||
Bind(wxEVT_SCROLLWIN_BOTTOM, &ScrolledWindow::OnScroll, this);
|
||||
Bind(wxEVT_SCROLLWIN_LINEUP, &ScrolledWindow::OnScroll, this);
|
||||
Bind(wxEVT_SCROLLWIN_LINEDOWN, &ScrolledWindow::OnScroll, this);
|
||||
Bind(wxEVT_SCROLLWIN_PAGEUP, &ScrolledWindow::OnScroll, this);
|
||||
Bind(wxEVT_SCROLLWIN_PAGEDOWN, &ScrolledWindow::OnScroll, this);
|
||||
Bind(wxEVT_SCROLLWIN_THUMBTRACK, &ScrolledWindow::OnScroll, this);
|
||||
Bind(wxEVT_SCROLLWIN_THUMBRELEASE, &ScrolledWindow::OnScroll, this);
|
||||
Bind(wxEVT_MOUSEWHEEL, &ScrolledWindow::OnMouseWheel, this);
|
||||
}
|
||||
|
||||
void ScrolledWindow::OnMouseWheel(wxMouseEvent &event)
|
||||
{
|
||||
m_rightScrollbar->GetEventHandler()->ProcessEvent(event);
|
||||
|
||||
// int dMotion, actualDim;
|
||||
// if (event.GetWheelRotation() > 0)
|
||||
// dMotion = -m_pixelsPerUnit;
|
||||
// else
|
||||
// dMotion = m_pixelsPerUnit;
|
||||
// m_previousMouse += dMotion;
|
||||
// actualDim = m_actualDim;
|
||||
|
||||
// if (m_direction == wxVSCROLL) {
|
||||
// m_viewStartInPixels += (dMotion * m_virtualDim) / (float) actualDim + 0.5; // in pixels
|
||||
|
||||
// if (m_viewStartInPixels < 0)
|
||||
// m_viewStartInPixels = 0;
|
||||
// else if (m_viewStartInPixels + actualDim >= m_virtualDim)
|
||||
// m_viewStartInPixels = m_virtualDim - actualDim;
|
||||
|
||||
// m_viewStartInScrollUnits = m_viewStartInPixels / (float) m_pixelsPerUnit + 0.5; // in scroll units
|
||||
// m_scrolledWindow->Scroll(-1, m_viewStartInScrollUnits); // -1 means no change in this direction
|
||||
// SetViewStart(m_viewStartInScrollUnits);
|
||||
//} else {
|
||||
// dMotion = -dMotion;
|
||||
// if (m_scrolledWindow->IsBothDirections()) actualDim -= m_marginWidth; // must take into account the right margin
|
||||
|
||||
// m_viewStartInPixels += (dMotion * m_virtualDim) / (float) actualDim + 0.5; // in pixels
|
||||
|
||||
// if (m_viewStartInPixels < 0)
|
||||
// m_viewStartInPixels = 0;
|
||||
// else if (m_viewStartInPixels + actualDim >= m_virtualDim)
|
||||
// m_viewStartInPixels = m_virtualDim - actualDim;
|
||||
|
||||
// m_viewStartInScrollUnits = m_viewStartInPixels / (float) m_pixelsPerUnit + 0.5; // in scroll units
|
||||
// m_scrolledWindow->Scroll(m_viewStartInScrollUnits, -1); // -1 means no change in this direction
|
||||
// SetViewStart(m_viewStartInScrollUnits);
|
||||
//}
|
||||
// Refresh();
|
||||
// Update();
|
||||
}
|
||||
|
||||
void ScrolledWindow::SetTipColor(wxColour color)
|
||||
{
|
||||
if (m_rightScrollbar) m_rightScrollbar->SetTipColor(color);
|
||||
if (m_bottomScrollbar) m_bottomScrollbar->SetTipColor(color);
|
||||
}
|
||||
|
||||
void ScrolledWindow::Refresh()
|
||||
{
|
||||
// m_rightScrollbar->SetViewStart(0);
|
||||
// m_rightScrollbar->Refresh();
|
||||
// m_rightScrollbar->Update();
|
||||
// m_userPanel->Refresh();
|
||||
// m_bottomScrollbar->SetViewStart(0);
|
||||
// m_rightScrollbar->Refresh();
|
||||
// m_bottomScrollbar->Refresh();
|
||||
}
|
||||
|
||||
void ScrolledWindow::SetBackgroundColour(wxColour color)
|
||||
{
|
||||
wxWindow::SetBackgroundColour(color);
|
||||
m_verticalSplitter->SetBackgroundColour(color);
|
||||
m_userPanel->SetBackgroundColour(color);
|
||||
m_scroll_win->SetBackgroundColour(color);
|
||||
}
|
||||
|
||||
void ScrolledWindow::SetMarginColor(wxColour color)
|
||||
{
|
||||
if (m_rightScrollbar) m_rightScrollbar->SetMarginColor(color);
|
||||
if (m_bottomScrollbar) m_bottomScrollbar->SetMarginColor(color);
|
||||
}
|
||||
|
||||
void ScrolledWindow::SetScrollbarColor(wxColour color)
|
||||
{
|
||||
if (m_rightScrollbar) m_rightScrollbar->SetScrollbarColor(color);
|
||||
if (m_bottomScrollbar) m_bottomScrollbar->SetScrollbarColor(color);
|
||||
}
|
||||
|
||||
void ScrolledWindow::SetScrollbarTip(int len)
|
||||
{
|
||||
if (m_rightScrollbar) m_rightScrollbar->SetScrollbarTip(len);
|
||||
if (m_bottomScrollbar) m_bottomScrollbar->SetScrollbarTip(len);
|
||||
}
|
||||
|
||||
void ScrolledWindow::SetVirtualSize(int x, int y) { SetScrollbars(1, 1, x, y); }
|
||||
|
||||
void ScrolledWindow::SetVirtualSize(wxSize &size) { SetScrollbars(1, 1, size.GetWidth(), size.GetHeight()); }
|
||||
|
||||
void ScrolledWindow::SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY, int noUnitsX, int noUnitsY, int xPos, int yPos, bool noRefresh)
|
||||
{
|
||||
wxScrolled<wxWindow>::SetScrollbars(pixelsPerUnitX, pixelsPerUnitY, noUnitsX, noUnitsY, xPos, yPos, noRefresh);
|
||||
wxScrolled<wxWindow>::SetVirtualSize(pixelsPerUnitX * noUnitsX, pixelsPerUnitY * noUnitsY); // So that GetVirtualSize gives good values
|
||||
if (m_rightScrollbar) m_rightScrollbar->SetVirtualDim(pixelsPerUnitY, noUnitsY);
|
||||
if (m_bottomScrollbar) m_bottomScrollbar->SetVirtualDim(pixelsPerUnitX, noUnitsX);
|
||||
}
|
||||
|
||||
void ScrolledWindow::OnSize(wxSizeEvent &event)
|
||||
{
|
||||
int startX, startY, virtX, virtY, clientW, clientH;
|
||||
|
||||
if (!m_verticalSplitter && !m_horizontalSplitter) return;
|
||||
|
||||
GetViewStart(&startX, &startY);
|
||||
GetVirtualSize(&virtX, &virtY);
|
||||
GetClientSize(&clientW, &clientH);
|
||||
|
||||
// trace / log in the output / console window
|
||||
// wxString str; str.sprintf("Actual=(%d,%d). Virtual=(%d,%d)\n", clientW, clientH, virtX, virtY); OutputDebugString(str);
|
||||
if (m_verticalSplitter) m_verticalSplitter->SetSize(clientW, clientH);
|
||||
if (m_horizontalSplitter) m_horizontalSplitter->SetSize(clientW, clientH);
|
||||
|
||||
if (m_rightScrollbar) {
|
||||
if (clientH >= virtY) // hide the scrollbar by enlarging the user panel
|
||||
{
|
||||
// m_verticalSplitter->SetSashPosition(clientW);
|
||||
m_userPanel->SetSize(GetClientSize());
|
||||
m_rightScrollbar->SetSize(0, clientH);
|
||||
m_userPanel->Refresh();
|
||||
m_userPanel->Update();
|
||||
} else {
|
||||
// m_verticalSplitter->SetSashPosition(clientW - m_marginWidth); // resize the splitter panes
|
||||
}
|
||||
m_rightScrollbar->SetViewStart(startY);
|
||||
m_rightScrollbar->Refresh();
|
||||
m_rightScrollbar->Update(); // we want to repaint
|
||||
}
|
||||
if (m_bottomScrollbar) {
|
||||
if (clientW >= virtX) // hide the scrollbar by enlarging the user panel
|
||||
{
|
||||
m_horizontalSplitter->SetSashPosition(clientH); // we don't need horizontal scrollbar
|
||||
if (m_rightScrollbar)
|
||||
m_userPanel->SetSize(clientW - m_marginWidth, clientH); // don't hide the vertical scrollbar
|
||||
else
|
||||
m_userPanel->SetSize(GetClientSize());
|
||||
|
||||
m_bottomScrollbar->SetSize(clientW, 0);
|
||||
m_userPanel->Refresh();
|
||||
m_userPanel->Update();
|
||||
} else {
|
||||
m_horizontalSplitter->SetSashPosition(clientH - m_marginWidth); // resize the splitter panes
|
||||
}
|
||||
m_bottomScrollbar->SetViewStart(startX);
|
||||
m_bottomScrollbar->Refresh();
|
||||
m_bottomScrollbar->Update(); // we want to repaint even if the panel gets smaller
|
||||
}
|
||||
Layout();
|
||||
AdjustScrollbars();
|
||||
}
|
||||
|
||||
void ScrolledWindow::OnScroll(wxScrollWinEvent &event)
|
||||
{
|
||||
int startX, startY;
|
||||
GetViewStart(&startX, &startY);
|
||||
if (m_rightScrollbar) {
|
||||
m_rightScrollbar->SetViewStart(startY);
|
||||
m_rightScrollbar->Refresh();
|
||||
m_rightScrollbar->Update();
|
||||
}
|
||||
if (m_bottomScrollbar) {
|
||||
m_bottomScrollbar->SetViewStart(startX);
|
||||
m_bottomScrollbar->Refresh();
|
||||
m_bottomScrollbar->Update();
|
||||
}
|
||||
// event.Skip(); // then do the regular process // uncomment if you want to use the mouse and the trackpad in the scrolled panel
|
||||
}
|
45
src/slic3r/GUI/Widgets/ScrolledWindow.hpp
Normal file
45
src/slic3r/GUI/Widgets/ScrolledWindow.hpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
#include <wx/wxprec.h>
|
||||
#ifndef WX_PRECOMP
|
||||
#include <wx/wx.h>
|
||||
#endif
|
||||
|
||||
#include <wx/splitter.h>
|
||||
#include "Scrollbar.hpp"
|
||||
|
||||
class MyScrollbar;
|
||||
|
||||
class ScrolledWindow : public wxScrolled<wxWindow>
|
||||
{
|
||||
public:
|
||||
ScrolledWindow(wxWindow *parent, wxWindowID id, wxPoint position, wxSize size, long style, int marginWidth = 0, int scrollbarWidth = 4, int tipLength = 0);
|
||||
void OnMouseWheel(wxMouseEvent &event);
|
||||
void SetTipColor(wxColour color);
|
||||
void Refresh();
|
||||
void SetBackgroundColour(wxColour color);
|
||||
|
||||
void SetMarginColor(wxColour color);
|
||||
void SetScrollbarColor(wxColour color);
|
||||
void SetScrollbarTip(int len);
|
||||
virtual void SetVirtualSize(int x, int y);
|
||||
virtual void SetVirtualSize(wxSize &size);
|
||||
wxPanel * GetPanel() { return m_userPanel; }
|
||||
// wxSplitterWindow* GetVerticalSplitter() { return m_verticalSplitter; }
|
||||
// wxSplitterWindow* GetHorizontalSplitter() { return m_horizontalSplitter; }
|
||||
bool IsBothDirections() { return m_bothDirections; }
|
||||
virtual void SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY, int noUnitsX, int noUnitsY, int xPos = 0, int yPos = 0, bool noRefresh = false);
|
||||
|
||||
private:
|
||||
wxPanel * m_userPanel; // the panel targeted by the scrolled window
|
||||
wxWindow * m_scroll_win;
|
||||
MyScrollbar *m_rightScrollbar;
|
||||
MyScrollbar *m_bottomScrollbar;
|
||||
// wxSplitterWindow* m_verticalSplitter;
|
||||
wxWindow * m_verticalSplitter;
|
||||
wxSplitterWindow *m_horizontalSplitter;
|
||||
int m_marginWidth;
|
||||
bool m_bothDirections;
|
||||
|
||||
void OnSize(wxSizeEvent &WXUNUSED(event));
|
||||
void OnScroll(wxScrollWinEvent &event);
|
||||
};
|
325
src/slic3r/GUI/Widgets/SideButton.cpp
Normal file
325
src/slic3r/GUI/Widgets/SideButton.cpp
Normal file
|
@ -0,0 +1,325 @@
|
|||
#include "SideButton.hpp"
|
||||
#include "Label.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
BEGIN_EVENT_TABLE(SideButton, wxPanel)
|
||||
EVT_LEFT_DOWN(SideButton::mouseDown)
|
||||
EVT_LEFT_UP(SideButton::mouseReleased)
|
||||
EVT_PAINT(SideButton::paintEvent)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
SideButton::SideButton(wxWindow* parent, wxString text, wxString icon, long stlye, int iconSize)
|
||||
: wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, stlye)
|
||||
, state_handler(this)
|
||||
{
|
||||
radius = 12;
|
||||
extra_size = wxSize(38, 10);
|
||||
icon_offset = 0;
|
||||
text_orientation = HO_Left;
|
||||
text_margin = 15;
|
||||
|
||||
border_color.append(0x6B6B6B, StateColor::Disabled);
|
||||
border_color.append(0x1B8844, StateColor::Pressed);
|
||||
border_color.append(0xFFFFF, StateColor::Hovered);
|
||||
border_color.append(0x00AE42, StateColor::Normal);
|
||||
|
||||
text_color.append(0xACACAC, StateColor::Disabled);
|
||||
text_color.append(0xFFFFFF, StateColor::Pressed);
|
||||
text_color.append(0xFFFFFF, StateColor::Hovered);
|
||||
text_color.append(0xFFFFFF, StateColor::Normal);
|
||||
|
||||
background_color.append(0x6B6B6B, StateColor::Disabled);
|
||||
background_color.append(0x1B8844, StateColor::Pressed);
|
||||
background_color.append(0x00AE42, StateColor::Hovered);
|
||||
background_color.append(0x00AE42, StateColor::Normal);
|
||||
|
||||
state_handler.attach({ &border_color, &text_color, &background_color });
|
||||
state_handler.update_binds();
|
||||
|
||||
// icon only
|
||||
if (!icon.IsEmpty()) {
|
||||
this->icon = ScalableBitmap(this, icon.ToStdString(), iconSize > 0 ? iconSize : 14);
|
||||
}
|
||||
|
||||
SetFont(Label::Body_14);
|
||||
wxWindow::SetLabel(text);
|
||||
|
||||
messureSize();
|
||||
}
|
||||
|
||||
void SideButton::SetCornerRadius(double radius)
|
||||
{
|
||||
this->radius = radius;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SideButton::SetCornerEnable(const std::vector<bool>& enable)
|
||||
{
|
||||
radius_enable.clear();
|
||||
for (auto en : enable) {
|
||||
radius_enable.push_back(en);
|
||||
}
|
||||
}
|
||||
|
||||
void SideButton::SetTextLayout(EHorizontalOrientation orient, int margin)
|
||||
{
|
||||
text_orientation = orient;
|
||||
text_margin = margin;
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SideButton::SetLayoutStyle(int style)
|
||||
{
|
||||
layout_style = style;
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SideButton::SetLabel(const wxString& label)
|
||||
{
|
||||
wxWindow::SetLabel(label);
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
bool SideButton::SetForegroundColour(wxColour const &color)
|
||||
{
|
||||
text_color = StateColor(color);
|
||||
state_handler.update_binds();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SideButton::SetBackgroundColour(wxColour const& color)
|
||||
{
|
||||
background_color = StateColor(color);
|
||||
state_handler.update_binds();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SideButton::SetBottomColour(wxColour const& color)
|
||||
{
|
||||
bottom_color = color;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SideButton::SetMinSize(const wxSize& size)
|
||||
{
|
||||
minSize = size;
|
||||
messureSize();
|
||||
}
|
||||
|
||||
void SideButton::SetBorderColor(StateColor const &color)
|
||||
{
|
||||
border_color = color;
|
||||
state_handler.update_binds();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SideButton::SetForegroundColor(StateColor const &color)
|
||||
{
|
||||
text_color = color;
|
||||
state_handler.update_binds();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SideButton::SetBackgroundColor(StateColor const &color)
|
||||
{
|
||||
background_color = color;
|
||||
state_handler.update_binds();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
bool SideButton::Enable(bool enable)
|
||||
{
|
||||
bool result = wxWindow::Enable(enable);
|
||||
if (result) {
|
||||
wxCommandEvent e(EVT_ENABLE_CHANGED);
|
||||
e.SetEventObject(this);
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void SideButton::Rescale()
|
||||
{
|
||||
if (this->icon.bmp().IsOk())
|
||||
this->icon.msw_rescale();
|
||||
messureSize();
|
||||
}
|
||||
|
||||
void SideButton::SetExtraSize(const wxSize& size)
|
||||
{
|
||||
extra_size = size;
|
||||
messureSize();
|
||||
}
|
||||
|
||||
void SideButton::SetIconOffset(const int offset)
|
||||
{
|
||||
icon_offset = offset;
|
||||
messureSize();
|
||||
}
|
||||
|
||||
void SideButton::paintEvent(wxPaintEvent& evt)
|
||||
{
|
||||
// depending on your system you may need to look at double-buffered dcs
|
||||
wxPaintDC dc(this);
|
||||
wxGCDC dc2(dc);
|
||||
render(dc2);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 SideButton::render(wxDC& dc)
|
||||
{
|
||||
wxSize size = GetSize();
|
||||
|
||||
// draw background
|
||||
dc.SetPen(wxNullPen);
|
||||
dc.SetBrush(bottom_color);
|
||||
dc.DrawRectangle(0, 0, size.x, size.y);
|
||||
|
||||
int states = state_handler.states();
|
||||
dc.SetBrush(wxBrush(background_color.colorForStates(states)));
|
||||
|
||||
dc.SetPen(wxPen(border_color.colorForStates(states)));
|
||||
int pen_width = dc.GetPen().GetWidth();
|
||||
|
||||
|
||||
// draw icon style
|
||||
if (icon.bmp().IsOk()) {
|
||||
if (radius > 1e-5) {
|
||||
dc.DrawRoundedRectangle(0, 0, size.x, size.y, radius);
|
||||
dc.DrawRectangle(radius, 0, size.x - radius, size.y);
|
||||
dc.SetPen(wxNullPen);
|
||||
dc.DrawRectangle(radius - pen_width, pen_width, radius, size.y - 2 * pen_width);
|
||||
}
|
||||
else {
|
||||
dc.DrawRectangle(0, 0, size.x, size.y);
|
||||
}
|
||||
}
|
||||
// draw text style
|
||||
else {
|
||||
if (radius > 1e-5) {
|
||||
if (layout_style == 1) {
|
||||
dc.DrawRoundedRectangle(0, 0, size.x, size.y, radius);
|
||||
dc.SetPen(wxNullPen);
|
||||
} else {
|
||||
dc.DrawRoundedRectangle(0, 0, size.x, size.y, radius);
|
||||
dc.DrawRectangle(0, 0, size.x - radius, size.y);
|
||||
dc.SetPen(wxNullPen);
|
||||
dc.DrawRectangle(size.x - radius - pen_width, pen_width, 2 * pen_width, size.y - 2 * pen_width);
|
||||
}
|
||||
} else {
|
||||
dc.DrawRectangle(0, 0, size.x, size.y);
|
||||
}
|
||||
}
|
||||
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
// calc content size
|
||||
wxSize szIcon;
|
||||
wxSize szContent = textSize;
|
||||
if (icon.bmp().IsOk()) {
|
||||
if (szContent.y > 0) {
|
||||
//BBS norrow size between text and icon
|
||||
szContent.x += 5;
|
||||
}
|
||||
szIcon = icon.bmp().GetSize();
|
||||
szContent.x += szIcon.x;
|
||||
if (szIcon.y > szContent.y)
|
||||
szContent.y = szIcon.y;
|
||||
}
|
||||
// move to center
|
||||
wxRect rcContent = { {0, 0}, size };
|
||||
if (text_orientation == EHorizontalOrientation::HO_Center) {
|
||||
wxSize offset = (size - szContent) / 2;
|
||||
rcContent.Deflate(offset.x, offset.y);
|
||||
} else if (text_orientation == EHorizontalOrientation::HO_Left) {
|
||||
wxSize offset = (size - szContent) / 2;
|
||||
rcContent.Deflate(text_margin, offset.y);
|
||||
} else if (text_orientation == EHorizontalOrientation::HO_Right) {
|
||||
wxSize offset = (size - szContent) / 2;
|
||||
rcContent.Deflate(size.x - text_margin, offset.y);
|
||||
}
|
||||
|
||||
// start draw
|
||||
wxPoint pt = rcContent.GetLeftTop();
|
||||
if (icon.bmp().IsOk()) {
|
||||
//BBS extra pixels for icon
|
||||
pt.x += icon_offset;
|
||||
pt.y += (rcContent.height - szIcon.y) / 2;
|
||||
dc.DrawBitmap(icon.bmp(), pt);
|
||||
//BBS norrow size between text and icon
|
||||
pt.x += szIcon.x + 5;
|
||||
pt.y = rcContent.y;
|
||||
}
|
||||
|
||||
auto text = GetLabel();
|
||||
if (!text.IsEmpty()) {
|
||||
pt.y += (rcContent.height - textSize.y) / 2;
|
||||
dc.SetFont(GetFont());
|
||||
dc.SetTextForeground(text_color.colorForStates(states));
|
||||
dc.DrawText(text, pt);
|
||||
}
|
||||
}
|
||||
|
||||
void SideButton::messureSize()
|
||||
{
|
||||
textSize = GetTextExtent(GetLabel());
|
||||
if (minSize.GetWidth() > 0) {
|
||||
wxWindow::SetMinSize(minSize);
|
||||
return;
|
||||
}
|
||||
|
||||
wxSize szContent = textSize;
|
||||
if (this->icon.bmp().IsOk()) {
|
||||
if (szContent.y > 0) {
|
||||
szContent.x += 5;
|
||||
}
|
||||
wxSize szIcon = this->icon.bmp().GetSize();
|
||||
szContent.x += szIcon.x;
|
||||
if (szIcon.y > szContent.y)
|
||||
szContent.y = szIcon.y;
|
||||
//BBS icon only
|
||||
wxWindow::SetMinSize(szContent + wxSize(szContent.GetX() + extra_size.GetX(), minSize.GetHeight()));
|
||||
}
|
||||
else {
|
||||
if (minSize.GetHeight() > 0) {
|
||||
//BBS with text size
|
||||
wxWindow::SetMinSize(wxSize(szContent.GetX() + extra_size.GetX(), minSize.GetHeight()));
|
||||
} else {
|
||||
//BBS with text size
|
||||
wxWindow::SetMinSize(szContent + extra_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SideButton::mouseDown(wxMouseEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
pressedDown = true;
|
||||
SetFocus();
|
||||
CaptureMouse();
|
||||
}
|
||||
|
||||
void SideButton::mouseReleased(wxMouseEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
if (pressedDown) {
|
||||
pressedDown = false;
|
||||
ReleaseMouse();
|
||||
if (wxRect({0, 0}, GetSize()).Contains(event.GetPosition()))
|
||||
sendButtonEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void SideButton::sendButtonEvent()
|
||||
{
|
||||
wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
|
||||
event.SetEventObject(this);
|
||||
GetEventHandler()->ProcessEvent(event);
|
||||
}
|
93
src/slic3r/GUI/Widgets/SideButton.hpp
Normal file
93
src/slic3r/GUI/Widgets/SideButton.hpp
Normal file
|
@ -0,0 +1,93 @@
|
|||
#ifndef slic3r_GUI_SideButton_hpp_
|
||||
#define slic3r_GUI_SideButton_hpp_
|
||||
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/vlbox.h>
|
||||
#include <wx/combo.h>
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "StateHandler.hpp"
|
||||
|
||||
|
||||
class SideButton : public wxWindow
|
||||
{
|
||||
public:
|
||||
|
||||
enum EHorizontalOrientation : unsigned char
|
||||
{
|
||||
HO_Left,
|
||||
HO_Center,
|
||||
HO_Right,
|
||||
Num_Horizontal_Orientations
|
||||
};
|
||||
|
||||
SideButton(wxWindow* parent, wxString text, wxString icon = "", long style = 0, int iconSize = 0);
|
||||
|
||||
void SetCornerRadius(double radius);
|
||||
|
||||
//BBS set enable array
|
||||
void SetCornerEnable(const std::vector<bool>& enable);
|
||||
|
||||
void SetTextLayout(EHorizontalOrientation orient, int margin = 15);
|
||||
|
||||
void SetLayoutStyle(int style);
|
||||
|
||||
void SetLabel(const wxString& label);
|
||||
|
||||
bool SetForegroundColour(wxColour const & colour) override;
|
||||
|
||||
bool SetBackgroundColour(wxColour const & color) override;
|
||||
|
||||
bool SetBottomColour(wxColour const &color);
|
||||
|
||||
void SetMinSize(const wxSize& size) override;
|
||||
|
||||
void SetBorderColor(StateColor const & color);
|
||||
|
||||
void SetForegroundColor(StateColor const &color);
|
||||
|
||||
void SetBackgroundColor(StateColor const &color);
|
||||
|
||||
bool Enable(bool enable = true);
|
||||
|
||||
void Rescale();
|
||||
|
||||
void SetExtraSize(const wxSize& size);
|
||||
|
||||
void SetIconOffset(const int offset);
|
||||
|
||||
private:
|
||||
wxSize textSize;
|
||||
wxSize minSize;
|
||||
ScalableBitmap icon;
|
||||
double radius;
|
||||
wxSize extra_size;
|
||||
int icon_offset;
|
||||
std::vector<bool> radius_enable;
|
||||
|
||||
StateHandler state_handler;
|
||||
StateColor text_color;
|
||||
StateColor border_color;
|
||||
StateColor background_color;
|
||||
wxColour bottom_color;
|
||||
|
||||
bool pressedDown = false;
|
||||
int layout_style = 0;
|
||||
|
||||
EHorizontalOrientation text_orientation;
|
||||
int text_margin;
|
||||
|
||||
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
|
||||
void render(wxDC& dc);
|
||||
|
||||
void messureSize();
|
||||
|
||||
void mouseDown(wxMouseEvent& event);
|
||||
void mouseReleased(wxMouseEvent& event);
|
||||
|
||||
void sendButtonEvent();
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
#endif // !slic3r_GUI_Button_hpp_
|
92
src/slic3r/GUI/Widgets/SideMenuPopup.cpp
Normal file
92
src/slic3r/GUI/Widgets/SideMenuPopup.cpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
#include "SideMenuPopup.hpp"
|
||||
#include "Label.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
|
||||
|
||||
wxBEGIN_EVENT_TABLE(SidePopup,wxPopupTransientWindow)
|
||||
EVT_PAINT(SidePopup::paintEvent)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
SidePopup::SidePopup(wxWindow* parent)
|
||||
:wxPopupTransientWindow(parent,
|
||||
wxBORDER_NONE |
|
||||
wxPU_CONTAINS_CONTROLS)
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
SetDoubleBuffered(true);
|
||||
#endif //__WINDOWS__
|
||||
|
||||
}
|
||||
|
||||
SidePopup::~SidePopup()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void SidePopup::OnDismiss()
|
||||
{
|
||||
wxPopupTransientWindow::OnDismiss();
|
||||
}
|
||||
|
||||
bool SidePopup::ProcessLeftDown(wxMouseEvent& event)
|
||||
{
|
||||
return wxPopupTransientWindow::ProcessLeftDown(event);
|
||||
}
|
||||
bool SidePopup::Show( bool show )
|
||||
{
|
||||
return wxPopupTransientWindow::Show(show);
|
||||
}
|
||||
|
||||
void SidePopup::Popup(wxWindow* focus)
|
||||
{
|
||||
Create();
|
||||
if (focus) {
|
||||
wxPoint pos = focus->ClientToScreen(wxPoint(0, -6));
|
||||
Position(pos, {0, focus->GetSize().y + 12});
|
||||
}
|
||||
wxPopupTransientWindow::Popup();
|
||||
}
|
||||
|
||||
void SidePopup::Create()
|
||||
{
|
||||
wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
int max_width = 0;
|
||||
int height = 0;
|
||||
for (auto btn : btn_list)
|
||||
{
|
||||
max_width = std::max(btn->GetMinSize().x, max_width);
|
||||
}
|
||||
|
||||
for (auto btn : btn_list)
|
||||
{
|
||||
wxSize size = btn->GetMinSize();
|
||||
height += size.y;
|
||||
size.x = max_width;
|
||||
btn->SetMinSize(size);
|
||||
btn->SetSize(size);
|
||||
sizer->Add(btn, 0, 0, 0);
|
||||
}
|
||||
|
||||
SetSize(wxSize(max_width, height));
|
||||
|
||||
SetSizer(sizer, true);
|
||||
|
||||
Layout();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SidePopup::paintEvent(wxPaintEvent& evt)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
wxSize size = GetSize();
|
||||
dc.SetBrush(wxTransparentColour);
|
||||
dc.DrawRectangle(0, 0, size.x, size.y);
|
||||
}
|
||||
|
||||
void SidePopup::append_button(SideButton* btn)
|
||||
{
|
||||
btn_list.push_back(btn);
|
||||
}
|
35
src/slic3r/GUI/Widgets/SideMenuPopup.hpp
Normal file
35
src/slic3r/GUI/Widgets/SideMenuPopup.hpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef slic3r_GUI_SideMenuPopup_hpp_
|
||||
#define slic3r_GUI_SideMenuPopup_hpp_
|
||||
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/vlbox.h>
|
||||
#include <wx/combo.h>
|
||||
#include <wx/htmllbox.h>
|
||||
#include <wx/frame.h>
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "StateHandler.hpp"
|
||||
#include "SideButton.hpp"
|
||||
|
||||
class SidePopup : public wxPopupTransientWindow
|
||||
{
|
||||
private:
|
||||
std::vector<SideButton*> btn_list;
|
||||
public:
|
||||
SidePopup(wxWindow* parent);
|
||||
~SidePopup();
|
||||
|
||||
void Create();
|
||||
|
||||
virtual void Popup(wxWindow *focus = NULL) wxOVERRIDE;
|
||||
virtual void OnDismiss() wxOVERRIDE;
|
||||
virtual bool ProcessLeftDown(wxMouseEvent& event) wxOVERRIDE;
|
||||
virtual bool Show(bool show = true) wxOVERRIDE;
|
||||
|
||||
void append_button(SideButton* btn);
|
||||
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_Button_hpp_
|
215
src/slic3r/GUI/Widgets/SideTools.cpp
Normal file
215
src/slic3r/GUI/Widgets/SideTools.cpp
Normal file
|
@ -0,0 +1,215 @@
|
|||
#include "SideTools.hpp"
|
||||
#include <wx/dcmemory.h>
|
||||
#include <wx/dcgraph.h>
|
||||
#include "Label.hpp"
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "../I18N.hpp"
|
||||
#include "../GUI.hpp"
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
SideTools::SideTools(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size)
|
||||
{
|
||||
wxPanel::Create(parent, id, pos, wxSize(0, FromDIP(50)));
|
||||
Bind(wxEVT_PAINT, &SideTools::OnPaint, this);
|
||||
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
|
||||
m_printing_img = create_scaled_bitmap("printer", nullptr, 16);
|
||||
m_arrow_img = create_scaled_bitmap("monitor_arrow", nullptr, 14);
|
||||
|
||||
m_none_printing_img = create_scaled_bitmap("tab_monitor_active", nullptr, 24);
|
||||
m_none_arrow_img = create_scaled_bitmap("monitor_none_arrow", nullptr, 14);
|
||||
m_none_add_img = create_scaled_bitmap("monitor_none_add", nullptr, 14);
|
||||
|
||||
m_wifi_none_img = create_scaled_bitmap("monitor_signal_no", nullptr, 18);
|
||||
m_wifi_weak_img = create_scaled_bitmap("monitor_signal_weak", nullptr, 18);
|
||||
m_wifi_middle_img = create_scaled_bitmap("monitor_signal_middle", nullptr, 18);
|
||||
m_wifi_strong_img = create_scaled_bitmap("monitor_signal_strong", nullptr, 18);
|
||||
|
||||
m_intetval_timer = new wxTimer();
|
||||
m_intetval_timer->SetOwner(this);
|
||||
|
||||
this->Bind(wxEVT_TIMER, &SideTools::stop_interval, this);
|
||||
this->Bind(wxEVT_ENTER_WINDOW, &SideTools::on_mouse_enter, this);
|
||||
this->Bind(wxEVT_LEAVE_WINDOW, &SideTools::on_mouse_leave, this);
|
||||
this->Bind(wxEVT_LEFT_DOWN, &SideTools::on_mouse_left_down, this);
|
||||
this->Bind(wxEVT_LEFT_UP, &SideTools::on_mouse_left_up, this);
|
||||
}
|
||||
|
||||
SideTools::~SideTools() {}
|
||||
|
||||
void SideTools::set_none_printer_mode()
|
||||
{
|
||||
m_none_printer = true;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SideTools::on_timer(wxTimerEvent &event)
|
||||
{
|
||||
}
|
||||
|
||||
void SideTools::set_current_printer_name(std::string dev_name)
|
||||
{
|
||||
m_none_printer = false;
|
||||
m_dev_name = from_u8(dev_name);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SideTools::set_current_printer_signal(WifiSignal sign)
|
||||
{
|
||||
if (last_printer_signal == sign) return;
|
||||
|
||||
last_printer_signal = sign;
|
||||
m_none_printer = false;
|
||||
m_wifi_type = sign;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SideTools::start_interval()
|
||||
{
|
||||
m_intetval_timer->Start(SIDE_TOOL_CLICK_INTERVAL);
|
||||
m_is_in_interval = true;
|
||||
}
|
||||
|
||||
void SideTools::stop_interval(wxTimerEvent& event)
|
||||
{
|
||||
m_is_in_interval = false;
|
||||
m_intetval_timer->Stop();
|
||||
}
|
||||
|
||||
|
||||
bool SideTools::is_in_interval()
|
||||
{
|
||||
return m_is_in_interval;
|
||||
}
|
||||
|
||||
void SideTools::msw_rescale()
|
||||
{
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SideTools::OnPaint(wxPaintEvent &event)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
doRender(dc);
|
||||
}
|
||||
|
||||
void SideTools::render(wxDC &dc)
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
wxSize size = GetSize();
|
||||
wxMemoryDC memdc;
|
||||
wxBitmap bmp(size.x, size.y);
|
||||
memdc.SelectObject(bmp);
|
||||
memdc.Blit({0, 0}, size, &dc, {0, 0});
|
||||
|
||||
{
|
||||
wxGCDC dc2(memdc);
|
||||
doRender(dc2);
|
||||
}
|
||||
|
||||
memdc.SelectObject(wxNullBitmap);
|
||||
dc.DrawBitmap(bmp, 0, 0);
|
||||
#else
|
||||
doRender(dc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SideTools::doRender(wxDC &dc)
|
||||
{
|
||||
auto left = FromDIP(15);
|
||||
wxSize size = GetSize();
|
||||
|
||||
//if (m_none_printer) {
|
||||
// dc.SetPen(SIDE_TOOLS_LIGHT_GREEN);
|
||||
// dc.SetBrush(SIDE_TOOLS_LIGHT_GREEN);
|
||||
// dc.DrawRectangle(0, 0, size.x, size.y);
|
||||
//}
|
||||
|
||||
if (m_none_printer) {
|
||||
dc.SetPen(SIDE_TOOLS_BRAND);
|
||||
dc.SetBrush(SIDE_TOOLS_BRAND);
|
||||
dc.DrawRectangle(0, 0, size.x, size.y);
|
||||
|
||||
dc.DrawBitmap(m_none_printing_img, left, (size.y - m_none_printing_img.GetSize().y) / 2);
|
||||
|
||||
left += (m_none_printing_img.GetSize().x + FromDIP(15));
|
||||
dc.DrawBitmap(m_none_arrow_img, left, (size.y - m_none_arrow_img.GetSize().y) / 2);
|
||||
|
||||
left += (m_none_arrow_img.GetSize().x + FromDIP(6));
|
||||
dc.SetFont(::Label::Body_14);
|
||||
dc.SetBackgroundMode(wxTRANSPARENT);
|
||||
dc.SetTextForeground(*wxWHITE);
|
||||
|
||||
auto sizet = dc.GetTextExtent(_L("No printer"));
|
||||
dc.DrawText(_L("No printer"), wxPoint(left, (size.y - sizet.y) / 2));
|
||||
|
||||
left = size.x - FromDIP(30) - m_wifi_none_img.GetSize().x;
|
||||
dc.DrawBitmap(m_none_add_img, left, (size.y - m_none_add_img.GetSize().y) / 2);
|
||||
} else {
|
||||
dc.DrawBitmap(m_printing_img, left, (size.y - m_printing_img.GetSize().y) / 2);
|
||||
|
||||
left += (m_printing_img.GetSize().x + FromDIP(5));
|
||||
dc.DrawBitmap(m_arrow_img, left, (size.y - m_arrow_img.GetSize().y) / 2);
|
||||
|
||||
left += (m_arrow_img.GetSize().x + FromDIP(6));
|
||||
dc.SetFont(::Label::Body_14);
|
||||
dc.SetBackgroundMode(wxTRANSPARENT);
|
||||
dc.SetTextForeground(SIDE_TOOLS_GREY900);
|
||||
|
||||
auto sizet = dc.GetTextExtent(m_dev_name);
|
||||
auto text_end = size.x - m_wifi_none_img.GetSize().x - 20;
|
||||
|
||||
std::string finally_name = m_dev_name.ToStdString();
|
||||
if (sizet.x > (text_end - left)) {
|
||||
auto limit_width = text_end - left - dc.GetTextExtent("...").x - 20;
|
||||
for (auto i = 0; i < m_dev_name.length(); i++) {
|
||||
auto curr_width = dc.GetTextExtent(m_dev_name.substr(0, i));
|
||||
if (curr_width.x >= limit_width) {
|
||||
finally_name = (m_dev_name.substr(0, i) + wxString("...")).ToStdString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dc.DrawText(finally_name, wxPoint(left, (size.y - sizet.y) / 2));
|
||||
|
||||
left = size.x - FromDIP(18) - m_wifi_none_img.GetSize().x;
|
||||
if (m_wifi_type == WifiSignal::NONE) dc.DrawBitmap(m_wifi_none_img, left, (size.y - m_wifi_none_img.GetSize().y) / 2);
|
||||
if (m_wifi_type == WifiSignal::WEAK) dc.DrawBitmap(m_wifi_weak_img, left, (size.y - m_wifi_weak_img.GetSize().y) / 2);
|
||||
if (m_wifi_type == WifiSignal::MIDDLE) dc.DrawBitmap(m_wifi_middle_img, left, (size.y - m_wifi_middle_img.GetSize().y) / 2);
|
||||
if (m_wifi_type == WifiSignal::STRONG) dc.DrawBitmap(m_wifi_strong_img, left, (size.y - m_wifi_strong_img.GetSize().y) / 2);
|
||||
}
|
||||
|
||||
if (m_hover) {
|
||||
dc.SetPen(SIDE_TOOLS_BRAND);
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRectangle(0, 0, size.x, size.y);
|
||||
}
|
||||
}
|
||||
|
||||
void SideTools::on_mouse_left_down(wxMouseEvent &evt)
|
||||
{
|
||||
m_click = true;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SideTools::on_mouse_left_up(wxMouseEvent &evt)
|
||||
{
|
||||
m_click = false;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SideTools::on_mouse_enter(wxMouseEvent &evt)
|
||||
{
|
||||
m_hover = true;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SideTools::on_mouse_leave(wxMouseEvent &evt)
|
||||
{
|
||||
m_hover = false;
|
||||
Refresh();
|
||||
}
|
||||
}}
|
79
src/slic3r/GUI/Widgets/SideTools.hpp
Normal file
79
src/slic3r/GUI/Widgets/SideTools.hpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
#ifndef slic3r_GUI_SIDETOOLS_hpp_
|
||||
#define slic3r_GUI_SIDETOOLS_hpp_
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/dcclient.h>
|
||||
#include "../wxExtensions.hpp"
|
||||
|
||||
#define SIDE_TOOLS_GREY900 wxColour(38, 46, 48)
|
||||
#define SIDE_TOOLS_GREY600 wxColour(144, 144, 144)
|
||||
#define SIDE_TOOLS_GREY400 wxColour(206, 206, 206)
|
||||
#define SIDE_TOOLS_BRAND wxColour(0, 174, 66)
|
||||
#define SIDE_TOOLS_LIGHT_GREEN wxColour(219, 253, 231)
|
||||
|
||||
enum WifiSignal {
|
||||
NONE,
|
||||
WEAK,
|
||||
MIDDLE,
|
||||
STRONG,
|
||||
};
|
||||
|
||||
#define SIDE_TOOL_CLICK_INTERVAL 20
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
class SideTools : public wxPanel
|
||||
{
|
||||
private:
|
||||
WifiSignal m_wifi_type{WifiSignal::NONE};
|
||||
wxString m_dev_name;
|
||||
bool m_hover{false};
|
||||
bool m_click{false};
|
||||
bool m_none_printer{true};
|
||||
int last_printer_signal = 0;
|
||||
|
||||
wxBitmap m_printing_img;
|
||||
wxBitmap m_arrow_img;
|
||||
|
||||
wxBitmap m_none_printing_img;
|
||||
wxBitmap m_none_arrow_img;
|
||||
wxBitmap m_none_add_img;
|
||||
|
||||
wxBitmap m_wifi_none_img;
|
||||
wxBitmap m_wifi_weak_img;
|
||||
wxBitmap m_wifi_middle_img;
|
||||
wxBitmap m_wifi_strong_img;
|
||||
|
||||
protected:
|
||||
wxBitmap m_bitmap_type;
|
||||
wxStaticBitmap *m_bitmap_info;
|
||||
wxStaticBitmap *m_bitmap_bind;
|
||||
wxTimer * m_intetval_timer{nullptr};
|
||||
bool m_is_in_interval {false};
|
||||
|
||||
public:
|
||||
SideTools(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
|
||||
~SideTools();
|
||||
|
||||
void set_none_printer_mode();
|
||||
void on_timer(wxTimerEvent &event);
|
||||
void set_current_printer_name(std::string dev_name);
|
||||
void set_current_printer_signal(WifiSignal sign);;
|
||||
void start_interval();
|
||||
void stop_interval(wxTimerEvent &event);
|
||||
bool is_in_interval();
|
||||
void msw_rescale();
|
||||
|
||||
protected:
|
||||
void OnPaint(wxPaintEvent &event);
|
||||
void render(wxDC &dc);
|
||||
void doRender(wxDC &dc);
|
||||
void on_mouse_enter(wxMouseEvent &evt);
|
||||
void on_mouse_leave(wxMouseEvent &evt);
|
||||
void on_mouse_left_down(wxMouseEvent &evt);
|
||||
void on_mouse_left_up(wxMouseEvent &evt);
|
||||
};
|
||||
}} // namespace Slic3r::GUI
|
||||
|
||||
#endif // !slic3r_GUI_SIDETOOLS_hpp_
|
325
src/slic3r/GUI/Widgets/SpinInput.cpp
Normal file
325
src/slic3r/GUI/Widgets/SpinInput.cpp
Normal file
|
@ -0,0 +1,325 @@
|
|||
#include "SpinInput.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "Button.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
BEGIN_EVENT_TABLE(SpinInput, wxPanel)
|
||||
|
||||
EVT_MOTION(SpinInput::mouseMoved)
|
||||
EVT_ENTER_WINDOW(SpinInput::mouseEnterWindow)
|
||||
EVT_LEAVE_WINDOW(SpinInput::mouseLeaveWindow)
|
||||
EVT_KEY_DOWN(SpinInput::keyPressed)
|
||||
EVT_KEY_UP(SpinInput::keyReleased)
|
||||
EVT_MOUSEWHEEL(SpinInput::mouseWheelMoved)
|
||||
|
||||
// catch paint events
|
||||
EVT_PAINT(SpinInput::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().
|
||||
*/
|
||||
|
||||
SpinInput::SpinInput(wxWindow * parent,
|
||||
wxString text,
|
||||
wxString label,
|
||||
const wxPoint &pos,
|
||||
const wxSize & size,
|
||||
long style,
|
||||
int min, int max, int initial)
|
||||
: wxWindow(parent, wxID_ANY, pos, size)
|
||||
, state_handler(this)
|
||||
, border_color(std::make_pair(0xDBDBDB, (int) StateColor::Disabled),
|
||||
std::make_pair(0x00AE42, (int) StateColor::Focused),
|
||||
std::make_pair(0x00AE42, (int) StateColor::Hovered),
|
||||
std::make_pair(0xDBDBDB, (int) StateColor::Normal))
|
||||
, text_color(std::make_pair(0xACACAC, (int) StateColor::Disabled),
|
||||
std::make_pair(*wxBLACK, (int) StateColor::Normal))
|
||||
, background_color(std::make_pair(0xF0F0F0, (int) StateColor::Disabled),
|
||||
std::make_pair(*wxWHITE, (int) StateColor::Normal))
|
||||
{
|
||||
hover = false;
|
||||
radius = 0;
|
||||
SetFont(Label::Body_12);
|
||||
wxWindow::SetLabel(label);
|
||||
state_handler.attach({&border_color, &text_color, &background_color});
|
||||
state_handler.update_binds();
|
||||
text_ctrl = new wxTextCtrl(this, wxID_ANY, text, {20, 5}, wxDefaultSize,
|
||||
style | wxBORDER_NONE | wxTE_PROCESS_ENTER, wxTextValidator(wxFILTER_DIGITS));
|
||||
text_ctrl->SetFont(Label::Body_14);
|
||||
text_ctrl->Bind(wxEVT_SET_FOCUS, [this](auto &e) {
|
||||
e.SetId(GetId());
|
||||
ProcessEventLocally(e);
|
||||
});
|
||||
text_ctrl->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) {
|
||||
e.SetId(GetId());
|
||||
ProcessEventLocally(e);
|
||||
});
|
||||
text_ctrl->Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) {
|
||||
e.SetId(GetId());
|
||||
ProcessEventLocally(e);
|
||||
});
|
||||
text_ctrl->Bind(wxEVT_KILL_FOCUS, &SpinInput::onTextLostFocus, this);
|
||||
text_ctrl->Bind(wxEVT_TEXT_ENTER, &SpinInput::onTextEnter, this);
|
||||
text_ctrl->Bind(wxEVT_RIGHT_DOWN, [this](auto &e) {}); // disable context menu
|
||||
button_inc = createButton(true);
|
||||
button_dec = createButton(false);
|
||||
delta = 0;
|
||||
timer.Bind(wxEVT_TIMER, &SpinInput::onTimer, this);
|
||||
|
||||
long initialFromText;
|
||||
if ( text.ToLong(&initialFromText) )
|
||||
initial = initialFromText;
|
||||
SetRange(min, max);
|
||||
SetValue(initial);
|
||||
messureSize();
|
||||
}
|
||||
|
||||
void SpinInput::SetCornerRadius(double radius)
|
||||
{
|
||||
this->radius = radius;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SpinInput::SetLabel(const wxString &label)
|
||||
{
|
||||
wxWindow::SetLabel(label);
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SpinInput::SetTextColor(StateColor const &color)
|
||||
{
|
||||
text_color = color;
|
||||
state_handler.update_binds();
|
||||
}
|
||||
|
||||
void SpinInput::SetBackgroundColor(StateColor const& color)
|
||||
{
|
||||
background_color = color;
|
||||
state_handler.update_binds();
|
||||
}
|
||||
|
||||
void SpinInput::SetSize(wxSize const &size)
|
||||
{
|
||||
wxWindow::SetSize(size);
|
||||
Rescale();
|
||||
}
|
||||
|
||||
void SpinInput::SetValue(const wxString &text)
|
||||
{
|
||||
long value;
|
||||
if ( text.ToLong(&value) )
|
||||
SetValue(value);
|
||||
}
|
||||
|
||||
void SpinInput::SetValue(int value)
|
||||
{
|
||||
if (value < min) value = min;
|
||||
else if (value > max) value = max;
|
||||
this->val = value;
|
||||
text_ctrl->SetValue(wxString::FromDouble(value));
|
||||
}
|
||||
|
||||
int SpinInput::GetValue()const
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
void SpinInput::SetRange(int min, int max)
|
||||
{
|
||||
this->min = min;
|
||||
this->max = max;
|
||||
}
|
||||
|
||||
void SpinInput::DoSetToolTipText(wxString const &tip)
|
||||
{
|
||||
wxWindow::DoSetToolTipText(tip);
|
||||
text_ctrl->SetToolTip(tip);
|
||||
}
|
||||
|
||||
void SpinInput::Rescale()
|
||||
{
|
||||
button_inc->Rescale();
|
||||
button_dec->Rescale();
|
||||
messureSize();
|
||||
}
|
||||
|
||||
bool SpinInput::Enable(bool enable)
|
||||
{
|
||||
bool result = text_ctrl->Enable(enable) && wxWindow::Enable(enable);
|
||||
if (result) {
|
||||
wxCommandEvent e(EVT_ENABLE_CHANGED);
|
||||
e.SetEventObject(this);
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void SpinInput::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 SpinInput::render(wxDC& dc)
|
||||
{
|
||||
int states = state_handler.states();
|
||||
wxSize size = GetSize();
|
||||
dc.SetPen(wxPen(border_color.colorForStates(states)));
|
||||
dc.SetBrush(wxBrush(background_color.colorForStates(states)));
|
||||
dc.DrawRoundedRectangle(0, 0, size.x, size.y, radius);
|
||||
wxPoint pt = button_inc->GetPosition();
|
||||
pt.y = size.y / 2;
|
||||
dc.SetPen(wxPen(border_color.defaultColor()));
|
||||
dc.DrawLine(pt, pt + wxSize{button_inc->GetSize().x - 2, 0});
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
// start draw
|
||||
auto text = GetLabel();
|
||||
if (!text.IsEmpty()) {
|
||||
pt.x = size.x - labelSize.x - 5;
|
||||
pt.y = (size.y - labelSize.y) / 2;
|
||||
dc.SetFont(GetFont());
|
||||
dc.SetTextForeground(text_color.colorForStates(states));
|
||||
dc.DrawText(text, pt);
|
||||
}
|
||||
}
|
||||
|
||||
void SpinInput::messureSize()
|
||||
{
|
||||
wxSize size = GetSize();
|
||||
wxSize textSize = text_ctrl->GetSize();
|
||||
#ifdef __WXOSX__
|
||||
textSize.y -= 3; // TODO:
|
||||
#endif
|
||||
int h = textSize.y * 24 / 14;
|
||||
if (size.y < h) {
|
||||
size.y = h;
|
||||
SetSize(size);
|
||||
SetMinSize(size);
|
||||
} else {
|
||||
textSize.y = size.y * 14 / 24;
|
||||
}
|
||||
wxSize btnSize = {14, (size.y - 4) / 2};
|
||||
btnSize.x = btnSize.x * btnSize.y / 10;
|
||||
wxClientDC dc(this);
|
||||
labelSize = dc.GetMultiLineTextExtent(GetLabel());
|
||||
textSize.x = size.x - labelSize.x - btnSize.x - 16;
|
||||
text_ctrl->SetSize(textSize);
|
||||
text_ctrl->SetPosition({6 + btnSize.x, (size.y - textSize.y) / 2});
|
||||
button_inc->SetSize(btnSize);
|
||||
button_dec->SetSize(btnSize);
|
||||
button_inc->SetPosition({3, size.y / 2 - btnSize.y - 1});
|
||||
button_dec->SetPosition({3, size.y / 2 + 1});
|
||||
}
|
||||
|
||||
Button *SpinInput::createButton(bool inc)
|
||||
{
|
||||
auto btn = new Button(this, "", inc ? "spin_inc" : "spin_dec", wxBORDER_NONE, 6);
|
||||
btn->SetCornerRadius(0);
|
||||
btn->SetCanFocus(false);
|
||||
btn->Bind(wxEVT_LEFT_DOWN, [=](auto &e) {
|
||||
delta = inc ? 1 : -1;
|
||||
SetValue(val + delta);
|
||||
text_ctrl->SetFocus();
|
||||
btn->CaptureMouse();
|
||||
delta *= 8;
|
||||
timer.Start(100);
|
||||
sendSpinEvent();
|
||||
});
|
||||
btn->Bind(wxEVT_LEFT_DCLICK, [=](auto &e) {
|
||||
delta = inc ? 1 : -1;
|
||||
SetValue(val + delta);
|
||||
sendSpinEvent();
|
||||
});
|
||||
btn->Bind(wxEVT_LEFT_UP, [=](auto &e) {
|
||||
btn->ReleaseMouse();
|
||||
timer.Stop();
|
||||
text_ctrl->SelectAll();
|
||||
delta = 0;
|
||||
});
|
||||
return btn;
|
||||
}
|
||||
|
||||
void SpinInput::mouseEnterWindow(wxMouseEvent& event)
|
||||
{
|
||||
if (!hover)
|
||||
{
|
||||
hover = true;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void SpinInput::mouseLeaveWindow(wxMouseEvent& event)
|
||||
{
|
||||
if (hover)
|
||||
{
|
||||
hover = false;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void SpinInput::onTimer(wxTimerEvent &evnet) {
|
||||
if (delta < -1 || delta > 1) {
|
||||
delta /= 2;
|
||||
return;
|
||||
}
|
||||
SetValue(val + delta);
|
||||
sendSpinEvent();
|
||||
}
|
||||
|
||||
void SpinInput::onTextLostFocus(wxEvent &event)
|
||||
{
|
||||
timer.Stop();
|
||||
for (auto * child : GetChildren())
|
||||
if (auto btn = dynamic_cast<Button*>(child))
|
||||
if (btn->HasCapture())
|
||||
btn->ReleaseMouse();
|
||||
wxCommandEvent e;
|
||||
onTextEnter(e);
|
||||
// pass to outer
|
||||
event.SetId(GetId());
|
||||
ProcessEventLocally(event);
|
||||
}
|
||||
|
||||
void SpinInput::onTextEnter(wxCommandEvent &event)
|
||||
{
|
||||
long value;
|
||||
if (!text_ctrl->GetValue().ToLong(&value)) { value = val; }
|
||||
if (value != val) {
|
||||
SetValue(value);
|
||||
sendSpinEvent();
|
||||
}
|
||||
event.SetId(GetId());
|
||||
ProcessEventLocally(event);
|
||||
}
|
||||
|
||||
void SpinInput::mouseWheelMoved(wxMouseEvent &event)
|
||||
{
|
||||
auto delta = (event.GetWheelRotation() < 0 == event.IsWheelInverted()) ? 1 : -1;
|
||||
SetValue(val + delta);
|
||||
sendSpinEvent();
|
||||
text_ctrl->SetFocus();
|
||||
}
|
||||
|
||||
// currently unused events
|
||||
void SpinInput::mouseMoved(wxMouseEvent& event) {}
|
||||
void SpinInput::keyPressed(wxKeyEvent& event) {}
|
||||
void SpinInput::keyReleased(wxKeyEvent &event) {}
|
||||
|
||||
void SpinInput::sendSpinEvent()
|
||||
{
|
||||
wxCommandEvent event(wxEVT_SPINCTRL, GetId());
|
||||
event.SetEventObject(this);
|
||||
GetEventHandler()->ProcessEvent(event);
|
||||
}
|
94
src/slic3r/GUI/Widgets/SpinInput.hpp
Normal file
94
src/slic3r/GUI/Widgets/SpinInput.hpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
#ifndef slic3r_GUI_SpinInput_hpp_
|
||||
#define slic3r_GUI_SpinInput_hpp_
|
||||
|
||||
#include <wx/textctrl.h>
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "StateHandler.hpp"
|
||||
|
||||
class Button;
|
||||
|
||||
class SpinInput : public wxWindow
|
||||
{
|
||||
|
||||
bool hover;
|
||||
wxSize labelSize;
|
||||
double radius;
|
||||
StateHandler state_handler;
|
||||
StateColor text_color;
|
||||
StateColor border_color;
|
||||
StateColor background_color;
|
||||
wxTextCtrl * text_ctrl;
|
||||
Button * button_inc;
|
||||
Button * button_dec;
|
||||
wxTimer timer;
|
||||
|
||||
int val;
|
||||
int min;
|
||||
int max;
|
||||
int delta;
|
||||
|
||||
static const int SpinInputWidth = 200;
|
||||
static const int SpinInputHeight = 50;
|
||||
|
||||
public:
|
||||
SpinInput(wxWindow * parent,
|
||||
wxString text,
|
||||
wxString label = "",
|
||||
const wxPoint &pos = wxDefaultPosition,
|
||||
const wxSize & size = wxDefaultSize,
|
||||
long style = 0,
|
||||
int min = 0, int max = 100, int initial = 0);
|
||||
|
||||
void SetCornerRadius(double radius);
|
||||
|
||||
void SetLabel(const wxString &label) wxOVERRIDE;
|
||||
|
||||
void SetTextColor(StateColor const & color);
|
||||
|
||||
void SetBackgroundColor(StateColor const & color);
|
||||
|
||||
void SetSize(wxSize const &size);
|
||||
|
||||
void Rescale();
|
||||
|
||||
virtual bool Enable(bool enable = true) wxOVERRIDE;
|
||||
|
||||
wxTextCtrl * GetTextCtrl() { return text_ctrl; }
|
||||
|
||||
void SetValue(const wxString &text);
|
||||
|
||||
void SetValue (int value);
|
||||
|
||||
int GetValue () const;
|
||||
|
||||
void SetRange(int min, int max);
|
||||
|
||||
protected:
|
||||
void DoSetToolTipText(wxString const &tip) override;
|
||||
|
||||
private:
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
|
||||
void render(wxDC& dc);
|
||||
|
||||
void messureSize();
|
||||
|
||||
Button *createButton(bool inc);
|
||||
|
||||
// some useful events
|
||||
void mouseMoved(wxMouseEvent& event);
|
||||
void mouseWheelMoved(wxMouseEvent& event);
|
||||
void mouseEnterWindow(wxMouseEvent& event);
|
||||
void mouseLeaveWindow(wxMouseEvent& event);
|
||||
void keyPressed(wxKeyEvent& event);
|
||||
void keyReleased(wxKeyEvent& event);
|
||||
void onTimer(wxTimerEvent &evnet);
|
||||
void onTextLostFocus(wxEvent &event);
|
||||
void onTextEnter(wxCommandEvent &event);
|
||||
|
||||
void sendSpinEvent();
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_SpinInput_hpp_
|
80
src/slic3r/GUI/Widgets/StateColor.cpp
Normal file
80
src/slic3r/GUI/Widgets/StateColor.cpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
#include "StateColor.hpp"
|
||||
|
||||
StateColor::StateColor(wxColour const &color) { append(color, 0); }
|
||||
|
||||
StateColor::StateColor(wxString const &color) { append(color, 0); }
|
||||
|
||||
StateColor::StateColor(unsigned long color) { append(color, 0); }
|
||||
|
||||
void StateColor::append(wxColour const & color, int states)
|
||||
{
|
||||
statesList_.push_back(states);
|
||||
colors_.push_back(color);
|
||||
}
|
||||
|
||||
void StateColor::append(wxString const & color, int states)
|
||||
{
|
||||
wxColour c1(color);
|
||||
append(c1, states);
|
||||
}
|
||||
|
||||
void StateColor::append(unsigned long color, int states)
|
||||
{
|
||||
if ((color & 0xff000000) == 0)
|
||||
color |= 0xff000000;
|
||||
wxColour cl; cl.SetRGBA(color & 0xff00ff00 | ((color & 0xff) << 16) | ((color >> 16) & 0xff));
|
||||
append(cl, states);
|
||||
}
|
||||
|
||||
void StateColor::clear()
|
||||
{
|
||||
statesList_.clear();
|
||||
colors_.clear();
|
||||
}
|
||||
|
||||
int StateColor::states() const
|
||||
{
|
||||
int states = 0;
|
||||
for (auto s : statesList_) states |= s;
|
||||
return states;
|
||||
}
|
||||
|
||||
wxColour StateColor::defaultColor() {
|
||||
return colorForStates(0);
|
||||
}
|
||||
|
||||
wxColour StateColor::colorForStates(int states)
|
||||
{
|
||||
for (int i = 0; i < statesList_.size(); ++i) {
|
||||
int s = statesList_[i];
|
||||
int on = s & 0xffff;
|
||||
int off = s >> 16;
|
||||
if ((on & states) == on && (off & ~states) == off) {
|
||||
return colors_[i];
|
||||
}
|
||||
}
|
||||
return wxColour(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
int StateColor::colorIndexForStates(int states)
|
||||
{
|
||||
for (int i = 0; i < statesList_.size(); ++i) {
|
||||
int s = statesList_[i];
|
||||
int on = s & 0xffff;
|
||||
int off = s >> 16;
|
||||
if ((on & states) == on && (off & ~states) == off) { return i; }
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool StateColor::setColorForStates(wxColour const &color, int states)
|
||||
{
|
||||
for (int i = 0; i < statesList_.size(); ++i) {
|
||||
if (statesList_[i] == states) {
|
||||
colors_[i] = color;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
81
src/slic3r/GUI/Widgets/StateColor.hpp
Normal file
81
src/slic3r/GUI/Widgets/StateColor.hpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
#ifndef slic3r_GUI_StateColor_hpp_
|
||||
#define slic3r_GUI_StateColor_hpp_
|
||||
|
||||
#include <wx/colour.h>
|
||||
|
||||
class StateColor
|
||||
{
|
||||
public:
|
||||
enum State {
|
||||
Normal = 0,
|
||||
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:
|
||||
template<typename ...Colors>
|
||||
StateColor(std::pair<Colors, int>... colors) {
|
||||
fill(colors...);
|
||||
}
|
||||
|
||||
// single color
|
||||
StateColor(wxColour const & color);
|
||||
|
||||
// single color
|
||||
StateColor(wxString const &color);
|
||||
|
||||
// single color
|
||||
StateColor(unsigned long color);
|
||||
|
||||
public:
|
||||
void append(wxColour const & color, int states);
|
||||
|
||||
void append(wxString const &color, int states);
|
||||
|
||||
void append(unsigned long color, int states);
|
||||
|
||||
void clear();
|
||||
|
||||
public:
|
||||
int count() const { return statesList_.size(); }
|
||||
|
||||
int states() const;
|
||||
|
||||
public:
|
||||
wxColour defaultColor();
|
||||
|
||||
wxColour colorForStates(int states);
|
||||
|
||||
int colorIndexForStates(int states);
|
||||
|
||||
bool setColorForStates(wxColour const & color, int states);
|
||||
|
||||
private:
|
||||
template<typename Color, typename ...Colors>
|
||||
void fill(std::pair<Color, int> color, std::pair<Colors, int>... colors) {
|
||||
fillOne(color);
|
||||
fill(colors...);
|
||||
}
|
||||
|
||||
template<typename Color>
|
||||
void fillOne(std::pair<Color, int> color) {
|
||||
append(color.first, color.second);
|
||||
}
|
||||
|
||||
void fill() {
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<int> statesList_;
|
||||
std::vector<wxColour> colors_;
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_StateColor_hpp_
|
79
src/slic3r/GUI/Widgets/StateHandler.cpp
Normal file
79
src/slic3r/GUI/Widgets/StateHandler.cpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
#include "StateHandler.hpp"
|
||||
|
||||
wxDEFINE_EVENT(EVT_ENABLE_CHANGED, wxCommandEvent);
|
||||
|
||||
StateHandler::StateHandler(wxWindow * owner)
|
||||
: owner_(owner)
|
||||
{
|
||||
if (owner->IsEnabled())
|
||||
states_ |= Enabled;
|
||||
if (owner->HasFocus())
|
||||
states_ |= Focused;
|
||||
}
|
||||
|
||||
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::update_binds()
|
||||
{
|
||||
int bind_states = 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) {
|
||||
owner_->Bind(events[i], &StateHandler::changed, this);
|
||||
if (events2[i])
|
||||
owner_->Bind(events2[i], &StateHandler::changed, this);
|
||||
} else {
|
||||
owner_->Unbind(events[i], &StateHandler::changed, this);
|
||||
if (events2[i])
|
||||
owner_->Unbind(events2[i], &StateHandler::changed, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
bind_states_ = bind_states;
|
||||
owner_->Refresh();
|
||||
}
|
||||
|
||||
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 = states2_ | states_;
|
||||
// some events are from another window (ex: text_ctrl of TextInput), save state in states2_ to avoid conflicts
|
||||
int & states = event.GetEventObject() == owner_ ? states_ : states2_;
|
||||
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 != (states2_ | states_))
|
||||
owner_->Refresh();
|
||||
}
|
49
src/slic3r/GUI/Widgets/StateHandler.hpp
Normal file
49
src/slic3r/GUI/Widgets/StateHandler.hpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
#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);
|
||||
|
||||
public:
|
||||
void attach(StateColor const & color);
|
||||
|
||||
void attach(std::vector<StateColor const *> const & colors);
|
||||
|
||||
void update_binds();
|
||||
|
||||
int states() const { return states_ | states2_; }
|
||||
|
||||
private:
|
||||
void changed(wxEvent & event);
|
||||
|
||||
private:
|
||||
wxWindow * owner_;
|
||||
std::vector<StateColor const *> colors_;
|
||||
int bind_states_ = 0;
|
||||
int states_ = 0;
|
||||
int states2_ = 0;
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_StateHandler_hpp_
|
185
src/slic3r/GUI/Widgets/StaticBox.cpp
Normal file
185
src/slic3r/GUI/Widgets/StaticBox.cpp
Normal file
|
@ -0,0 +1,185 @@
|
|||
#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)
|
||||
, border_color(0x303A3C)
|
||||
, radius(8)
|
||||
{
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
wxWindow::Create(parent, id, pos, size, style);
|
||||
#ifdef __WXMSW__
|
||||
SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
#endif
|
||||
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::SetBackgroundColor(StateColor const &color)
|
||||
{
|
||||
background_color = color;
|
||||
state_handler.update_binds();
|
||||
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__
|
||||
wxSize size = GetSize();
|
||||
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) {
|
||||
#ifdef __WXOSX__
|
||||
int d = ceil(border_width / 2.0);
|
||||
rc.Deflate(d, d);
|
||||
#endif
|
||||
dc.SetPen(wxPen(border_color.colorForStates(states), border_width));
|
||||
} else {
|
||||
dc.SetPen(wxPen(background_color.colorForStates(states)));
|
||||
}
|
||||
dc.SetBrush(wxBrush(background_color.colorForStates(states)));
|
||||
if (GetWindowStyle() & wxBORDER_NONE)
|
||||
dc.SetPen(wxPen(background_color.colorForStates(states)));
|
||||
if (radius == 0) {
|
||||
dc.DrawRectangle(rc);
|
||||
}
|
||||
else {
|
||||
dc.DrawRoundedRectangle(rc, radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
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; }
|
||||
}
|
||||
}
|
||||
}
|
58
src/slic3r/GUI/Widgets/StaticBox.hpp
Normal file
58
src/slic3r/GUI/Widgets/StaticBox.hpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
#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 SetBackgroundColor(StateColor 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_
|
77
src/slic3r/GUI/Widgets/StaticLine.cpp
Normal file
77
src/slic3r/GUI/Widgets/StaticLine.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
#include "StaticLine.hpp"
|
||||
#include "Label.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
BEGIN_EVENT_TABLE(StaticLine, wxWindow)
|
||||
|
||||
// catch paint events
|
||||
EVT_PAINT(StaticLine::paintEvent)
|
||||
|
||||
END_EVENT_TABLE()
|
||||
|
||||
StaticLine::StaticLine(wxWindow* parent, bool vertical, const wxString& label)
|
||||
: wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE)
|
||||
, vertical(vertical)
|
||||
{
|
||||
wxWindow::SetBackgroundColour(parent->GetBackgroundColour());
|
||||
this->pen = wxPen(wxColour("#C4C4C4"));
|
||||
SetFont(Label::Body_14);
|
||||
SetLabel(label);
|
||||
}
|
||||
|
||||
void StaticLine::SetLabel(const wxString& label)
|
||||
{
|
||||
wxWindow::SetLabel(label);
|
||||
int s = 1;
|
||||
if (!label.IsEmpty()) {
|
||||
wxClientDC dc(this);
|
||||
auto size = dc.GetTextExtent(label);
|
||||
s = vertical ? size.x : size.y;
|
||||
}
|
||||
if (vertical)
|
||||
SetMinSize({s, -1});
|
||||
else
|
||||
SetMinSize({-1, s});
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void StaticLine::SetLineColour(wxColour color)
|
||||
{
|
||||
this->pen = wxPen(color);
|
||||
}
|
||||
|
||||
void StaticLine::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 StaticLine::render(wxDC& dc)
|
||||
{
|
||||
wxSize size = GetSize();
|
||||
wxSize size2 {0, 0};
|
||||
auto label = GetLabel();
|
||||
if (!label.IsEmpty()) {
|
||||
size2 = dc.GetTextExtent(label);
|
||||
dc.DrawText(label, 0, 0);
|
||||
if (vertical)
|
||||
size2.y += 5;
|
||||
else
|
||||
size2.x += 5;
|
||||
}
|
||||
dc.SetPen(pen);
|
||||
if (vertical) {
|
||||
size.x /= 2;
|
||||
dc.DrawLine(size.x, size2.y, size.x, size.y);
|
||||
} else {
|
||||
size.y /= 2;
|
||||
dc.DrawLine(size2.x, size.y, size.x, size.y);
|
||||
}
|
||||
}
|
28
src/slic3r/GUI/Widgets/StaticLine.hpp
Normal file
28
src/slic3r/GUI/Widgets/StaticLine.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef slic3r_GUI_StaticLine_hpp_
|
||||
#define slic3r_GUI_StaticLine_hpp_
|
||||
|
||||
#include "wx/window.h"
|
||||
|
||||
class StaticLine : public wxWindow
|
||||
{
|
||||
public:
|
||||
StaticLine(wxWindow* parent, bool vertical = false, const wxString& label = {});
|
||||
|
||||
public:
|
||||
void SetLabel(const wxString& label) override;
|
||||
|
||||
void SetLineColour(wxColour color);
|
||||
|
||||
private:
|
||||
wxPen pen;
|
||||
bool vertical;
|
||||
|
||||
private:
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
|
||||
void render(wxDC& dc);
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_StaticLine_hpp_
|
288
src/slic3r/GUI/Widgets/StepCtrl.cpp
Normal file
288
src/slic3r/GUI/Widgets/StepCtrl.cpp
Normal file
|
@ -0,0 +1,288 @@
|
|||
#include "StepCtrl.hpp"
|
||||
#include "Label.hpp"
|
||||
|
||||
wxDEFINE_EVENT( EVT_STEP_CHANGING, wxCommandEvent );
|
||||
wxDEFINE_EVENT( EVT_STEP_CHANGED, wxCommandEvent );
|
||||
|
||||
BEGIN_EVENT_TABLE(StepCtrl, StepCtrlBase)
|
||||
EVT_LEFT_DOWN(StepCtrl::mouseDown)
|
||||
EVT_MOTION(StepCtrl::mouseMove)
|
||||
EVT_LEFT_UP(StepCtrl::mouseUp)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
StepCtrlBase::StepCtrlBase(wxWindow * parent,
|
||||
wxWindowID id,
|
||||
const wxPoint & pos,
|
||||
const wxSize & size,
|
||||
long style)
|
||||
: StaticBox(parent, id, pos, size, style)
|
||||
, font_tip(Label::Body_14)
|
||||
, clr_bar(0xACACAC)
|
||||
, clr_step(0xACACAC)
|
||||
, clr_text(std::make_pair(0x00AE42, (int) StateColor::Checked),
|
||||
std::make_pair(0x6B6B6B, (int) StateColor::Normal))
|
||||
, clr_tip(0x828280)
|
||||
{
|
||||
SetFont(Label::Body_14);
|
||||
border_color = StateColor(*wxLIGHT_GREY);
|
||||
StaticBox::radius = 0;
|
||||
//wxString reason;
|
||||
//IsTransparentBackgroundSupported(&reason);
|
||||
}
|
||||
|
||||
StepCtrlBase::~StepCtrlBase()
|
||||
{
|
||||
}
|
||||
|
||||
int StepCtrlBase::GetSelection() const { return step; }
|
||||
|
||||
void StepCtrlBase::SelectItem(int item)
|
||||
{
|
||||
if (item == step || item < -1 || item >= steps.size() || !sendStepCtrlEvent(true))
|
||||
return;
|
||||
step = item;
|
||||
sendStepCtrlEvent();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void StepCtrlBase::Idle()
|
||||
{
|
||||
step = -1;
|
||||
sendStepCtrlEvent();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
bool StepCtrlBase::SetTipFont(wxFont const& font)
|
||||
{
|
||||
font_tip = font;
|
||||
return true;
|
||||
}
|
||||
|
||||
int StepCtrlBase::AppendItem(const wxString &item, wxString const & tip)
|
||||
{
|
||||
steps.push_back(item);
|
||||
tips.push_back(tip);
|
||||
return steps.size() - 1;
|
||||
}
|
||||
|
||||
void StepCtrlBase::DeleteAllItems()
|
||||
{
|
||||
steps.clear();
|
||||
tips.clear();
|
||||
if (step >= 0) {
|
||||
step = -1;
|
||||
sendStepCtrlEvent();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int StepCtrlBase::GetCount() const { return steps.size(); }
|
||||
|
||||
wxString StepCtrlBase::GetItemText(unsigned int item) const
|
||||
{
|
||||
return item < steps.size() ? steps[item] : wxString{};
|
||||
}
|
||||
|
||||
void StepCtrlBase::SetItemText(unsigned int item, wxString const &value)
|
||||
{
|
||||
if (item >= steps.size()) return;
|
||||
steps[item] = value;
|
||||
}
|
||||
|
||||
bool StepCtrlBase::sendStepCtrlEvent(bool changing)
|
||||
{
|
||||
wxCommandEvent event(changing ? EVT_STEP_CHANGING : EVT_STEP_CHANGED, GetId());
|
||||
event.SetEventObject(this);
|
||||
event.SetInt(step);
|
||||
GetEventHandler()->ProcessEvent(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* StepCtrl */
|
||||
|
||||
StepCtrl::StepCtrl(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style)
|
||||
: StepCtrlBase(parent, id, pos, size, style)
|
||||
, bmp_thumb(this, "step_thumb", 36)
|
||||
{
|
||||
StaticBox::border_width = 3;
|
||||
radius = radius * bmp_thumb.GetBmpHeight() / 36;
|
||||
bar_width = bar_width * bmp_thumb.GetBmpHeight() / 36;
|
||||
}
|
||||
|
||||
void StepCtrl::Rescale()
|
||||
{
|
||||
bmp_thumb.msw_rescale();
|
||||
radius = radius * bmp_thumb.GetBmpHeight() / 36;
|
||||
bar_width = bar_width * bmp_thumb.GetBmpHeight() / 36;
|
||||
}
|
||||
|
||||
void StepCtrl::mouseDown(wxMouseEvent &event)
|
||||
{
|
||||
wxPoint pt;
|
||||
event.GetPosition(&pt.x, &pt.y);
|
||||
wxSize size = GetSize();
|
||||
int itemWidth = size.x / steps.size();
|
||||
wxRect rcBar = {0, (size.y - 60) / 2, size.x, 60};
|
||||
int circleX = itemWidth / 2 + itemWidth * step;
|
||||
wxRect rcThumb = {{circleX, size.y / 2}, bmp_thumb.GetBmpSize()};
|
||||
rcThumb.x -= rcThumb.width / 2;
|
||||
rcThumb.y -= rcThumb.height / 2;
|
||||
if (rcThumb.Contains(pt)) {
|
||||
pos_thumb = wxPoint{circleX, size.y / 2};
|
||||
drag_offset = pos_thumb - pt;
|
||||
} else if (rcBar.Contains(pt)) {
|
||||
if (pt.x < circleX) {
|
||||
if (step > 0) SelectItem(step - 1);
|
||||
} else {
|
||||
if (step < steps.size() - 1) SelectItem(step + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StepCtrl::mouseMove(wxMouseEvent &event)
|
||||
{
|
||||
if (pos_thumb == wxPoint{0, 0}) return;
|
||||
wxPoint pt;
|
||||
event.GetPosition(&pt.x, &pt.y);
|
||||
pos_thumb.x = pt.x + drag_offset.x;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void StepCtrl::mouseUp(wxMouseEvent &event)
|
||||
{
|
||||
if (pos_thumb == wxPoint{0, 0}) return;
|
||||
wxSize size = GetSize();
|
||||
int itemWidth = size.x / steps.size();
|
||||
int index = pos_thumb.x / itemWidth;
|
||||
pos_thumb = {0, 0};
|
||||
SelectItem(index < steps.size() ? index : steps.size() - 1);
|
||||
}
|
||||
|
||||
void StepCtrl::doRender(wxDC &dc)
|
||||
{
|
||||
if (steps.empty()) return;
|
||||
|
||||
StaticBox::doRender(dc);
|
||||
|
||||
wxSize size = GetSize();
|
||||
int states = state_handler.states();
|
||||
|
||||
int itemWidth = size.x / steps.size();
|
||||
wxRect rcBar = {itemWidth / 2, (size.y - bar_width) / 2, size.x - itemWidth, bar_width};
|
||||
|
||||
dc.SetPen(wxPen(clr_bar.colorForStates(states)));
|
||||
dc.SetBrush(wxBrush(clr_bar.colorForStates(states)));
|
||||
dc.DrawRectangle(rcBar);
|
||||
int circleX = itemWidth / 2;
|
||||
int circleY = size.y / 2;
|
||||
dc.SetPen(wxPen(clr_step.colorForStates(states)));
|
||||
dc.SetBrush(wxBrush(clr_step.colorForStates(states)));
|
||||
for (int i = 0; i < steps.size(); ++i) {
|
||||
bool check = pos_thumb == wxPoint{0, 0} ? step == i : (pos_thumb.x >= circleX - itemWidth / 2 && pos_thumb.x < circleX + itemWidth / 2);
|
||||
dc.DrawEllipse(circleX - radius, circleY - radius, radius * 2, radius * 2);
|
||||
dc.SetFont(GetFont());
|
||||
dc.SetTextForeground(clr_text.colorForStates(states | (check ? StateColor::Checked : 0)));
|
||||
wxSize sz = dc.GetTextExtent(steps[i]);
|
||||
dc.DrawText(steps[i], circleX - sz.x / 2, circleY + 20);
|
||||
if (check) {
|
||||
dc.SetFont(font_tip);
|
||||
dc.SetTextForeground(clr_tip.colorForStates(states));
|
||||
wxSize sz = dc.GetTextExtent(tips[i]);
|
||||
dc.DrawText(tips[i], circleX - sz.x / 2, circleY - 20 - sz.y);
|
||||
sz = bmp_thumb.GetBmpSize();
|
||||
dc.DrawBitmap(bmp_thumb.bmp(), circleX - sz.x / 2, circleY - sz.y / 2);
|
||||
}
|
||||
circleX += itemWidth;
|
||||
}
|
||||
}
|
||||
|
||||
/* StepIndicator */
|
||||
|
||||
StepIndicator::StepIndicator(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style)
|
||||
: StepCtrlBase(parent, id, pos, size, style)
|
||||
, bmp_ok(this, "step_ok", 12)
|
||||
{
|
||||
SetFont(Label::Body_12);
|
||||
font_tip = Label::Body_10;
|
||||
clr_bar = 0xE1E1E1;
|
||||
clr_step = StateColor(
|
||||
std::make_pair(0xACACAC, (int) StateColor::Disabled),
|
||||
std::make_pair(0x00AE42, 0));
|
||||
clr_text = StateColor(
|
||||
std::make_pair(0xACACAC, (int) StateColor::Disabled),
|
||||
std::make_pair(0x323A3D, (int) StateColor::Checked),
|
||||
std::make_pair(0x6B6B6B, 0));
|
||||
clr_tip = *wxWHITE;
|
||||
StaticBox::border_width = 0;
|
||||
radius = bmp_ok.GetBmpHeight() / 2;
|
||||
bar_width = bmp_ok.GetBmpHeight() / 20;
|
||||
if (bar_width < 2) bar_width = 2;
|
||||
}
|
||||
|
||||
void StepIndicator::Rescale()
|
||||
{
|
||||
bmp_ok.msw_rescale();
|
||||
radius = bmp_ok.GetBmpHeight() / 2;
|
||||
bar_width = bmp_ok.GetBmpHeight() / 20;
|
||||
if (bar_width < 2) bar_width = 2;
|
||||
}
|
||||
|
||||
void StepIndicator::SelectNext() { SelectItem(step + 1); }
|
||||
|
||||
|
||||
void StepIndicator::doRender(wxDC &dc)
|
||||
{
|
||||
if (steps.empty()) return;
|
||||
|
||||
StaticBox::doRender(dc);
|
||||
|
||||
wxSize size = GetSize();
|
||||
|
||||
int states = state_handler.states();
|
||||
if (!IsEnabled()) {
|
||||
states = clr_step.Disabled;
|
||||
}
|
||||
|
||||
int font_height = radius * 2;
|
||||
if (steps.size() > 0)
|
||||
font_height = dc.GetTextExtent(steps[0]).y;
|
||||
|
||||
int itemWidth = steps.size() == 1 ? size.y : (size.y - font_height) / (steps.size() - 1);
|
||||
wxRect rcBar = {radius - bar_width / 2, radius, bar_width, size.y - radius * 4};
|
||||
|
||||
dc.SetPen(wxPen(clr_bar.colorForStates(states)));
|
||||
dc.SetBrush(wxBrush(clr_bar.colorForStates(states)));
|
||||
dc.DrawRectangle(rcBar);
|
||||
int circleX = radius;
|
||||
int circleY = radius;
|
||||
dc.SetPen(wxPen(clr_step.colorForStates(states)));
|
||||
dc.SetBrush(wxBrush(clr_step.colorForStates(states)));
|
||||
for (int i = 0; i < steps.size(); ++i) {
|
||||
bool disabled = step > i;
|
||||
bool checked = step == i;
|
||||
dc.DrawEllipse(circleX - radius, circleY - radius, radius * 2, radius * 2);
|
||||
dc.SetTextForeground(clr_text.colorForStates(states
|
||||
| (disabled ? StateColor::Disabled : checked ? StateColor::Checked : 0)));
|
||||
dc.SetFont(checked ? GetFont().Bold() : GetFont());
|
||||
wxSize textSize = dc.GetTextExtent(steps[i]);
|
||||
|
||||
|
||||
if (steps[i].Find("\n") >= 0) {
|
||||
dc.DrawText(steps[i], circleX + radius * 3, circleY - textSize.y / 4);
|
||||
} else {
|
||||
dc.DrawText(steps[i], circleX + radius * 3, circleY - (textSize.y/2));
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
wxSize sz = bmp_ok.GetBmpSize();
|
||||
dc.DrawBitmap(bmp_ok.bmp(), circleX - radius, circleY - radius);
|
||||
} else {
|
||||
dc.SetFont(font_tip);
|
||||
dc.SetTextForeground(clr_tip.colorForStates(states));
|
||||
auto tip = tips[i];
|
||||
if (tip.IsEmpty()) tip.append(1, wchar_t(L'0' + i + 1));
|
||||
wxSize sz = dc.GetTextExtent(tip);
|
||||
dc.DrawText(tip, circleX - sz.x / 2, circleY - sz.y / 2 + 1);
|
||||
}
|
||||
circleY += itemWidth;
|
||||
}
|
||||
}
|
101
src/slic3r/GUI/Widgets/StepCtrl.hpp
Normal file
101
src/slic3r/GUI/Widgets/StepCtrl.hpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
#ifndef slic3r_GUI_StepCtrlBase_hpp_
|
||||
#define slic3r_GUI_StepCtrlBase_hpp_
|
||||
|
||||
#include "StaticBox.hpp"
|
||||
|
||||
wxDECLARE_EVENT( EVT_STEP_CHANGING, wxCommandEvent );
|
||||
wxDECLARE_EVENT( EVT_STEP_CHANGED, wxCommandEvent );
|
||||
|
||||
class StepCtrlBase : public StaticBox
|
||||
{
|
||||
protected:
|
||||
wxFont font_tip;
|
||||
StateColor clr_bar;
|
||||
StateColor clr_step;
|
||||
StateColor clr_text;
|
||||
StateColor clr_tip;
|
||||
int radius = 7;
|
||||
int bar_width = 4;
|
||||
|
||||
std::vector<wxString> steps;
|
||||
std::vector<wxString> tips;
|
||||
|
||||
int step = -1;
|
||||
|
||||
wxPoint drag_offset;
|
||||
wxPoint pos_thumb;
|
||||
|
||||
public:
|
||||
StepCtrlBase(wxWindow * parent,
|
||||
wxWindowID id,
|
||||
const wxPoint & pos = wxDefaultPosition,
|
||||
const wxSize & size = wxDefaultSize,
|
||||
long style = 0);
|
||||
|
||||
~StepCtrlBase();
|
||||
|
||||
public:
|
||||
bool SetTipFont(wxFont const & font);
|
||||
|
||||
public:
|
||||
int AppendItem(const wxString &item, wxString const & tip = {});
|
||||
|
||||
void DeleteAllItems();
|
||||
|
||||
unsigned int GetCount() const;
|
||||
|
||||
int GetSelection() const;
|
||||
|
||||
void SelectItem(int item);
|
||||
void Idle();
|
||||
|
||||
wxString GetItemText(unsigned int item) const;
|
||||
void SetItemText(unsigned int item, wxString const &value);
|
||||
|
||||
private:
|
||||
// some useful events
|
||||
bool sendStepCtrlEvent(bool changing = false);
|
||||
};
|
||||
|
||||
class StepCtrl : public StepCtrlBase
|
||||
{
|
||||
ScalableBitmap bmp_thumb;
|
||||
|
||||
public:
|
||||
StepCtrl(wxWindow * parent,
|
||||
wxWindowID id,
|
||||
const wxPoint & pos = wxDefaultPosition,
|
||||
const wxSize & size = wxDefaultSize,
|
||||
long style = 0);
|
||||
|
||||
virtual void Rescale();
|
||||
|
||||
private:
|
||||
void mouseDown(wxMouseEvent &event);
|
||||
void mouseMove(wxMouseEvent &event);
|
||||
void mouseUp(wxMouseEvent &event);
|
||||
|
||||
void doRender(wxDC &dc) override;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
class StepIndicator : public StepCtrlBase
|
||||
{
|
||||
ScalableBitmap bmp_ok;
|
||||
|
||||
public:
|
||||
StepIndicator(wxWindow *parent,
|
||||
wxWindowID id,
|
||||
const wxPoint & pos = wxDefaultPosition,
|
||||
const wxSize & size = wxDefaultSize,
|
||||
long style = 0);
|
||||
|
||||
virtual void Rescale();
|
||||
|
||||
void SelectNext();
|
||||
private:
|
||||
void doRender(wxDC &dc) override;
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_StepCtrlBase_hpp_
|
119
src/slic3r/GUI/Widgets/SwitchButton.cpp
Normal file
119
src/slic3r/GUI/Widgets/SwitchButton.cpp
Normal file
|
@ -0,0 +1,119 @@
|
|||
#include "SwitchButton.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "StaticBox.hpp"
|
||||
|
||||
#include "../wxExtensions.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
SwitchButton::SwitchButton(wxWindow* parent, wxWindowID id)
|
||||
: wxBitmapToggleButton(parent, id, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE | wxBU_EXACTFIT)
|
||||
, m_on(this, "toggle_on", 16)
|
||||
, m_off(this, "toggle_off", 16)
|
||||
, text_color(std::pair{*wxWHITE, (int) StateColor::Checked}, std::pair{0x6B6B6B, (int) StateColor::Normal})
|
||||
, track_color(0xD9D9D9)
|
||||
, thumb_color(std::pair{0x00AE42, (int) StateColor::Checked}, std::pair{0xD9D9D9, (int) StateColor::Normal})
|
||||
{
|
||||
SetBackgroundColour(StaticBox::GetParentBackgroundColor(parent));
|
||||
Bind(wxEVT_TOGGLEBUTTON, [this](auto& e) { update(); e.Skip(); });
|
||||
SetFont(Label::Body_12);
|
||||
Rescale();
|
||||
}
|
||||
|
||||
void SwitchButton::SetLabels(wxString const& lbl_on, wxString const& lbl_off)
|
||||
{
|
||||
labels[0] = lbl_on;
|
||||
labels[1] = lbl_off;
|
||||
Rescale();
|
||||
}
|
||||
|
||||
void SwitchButton::SetTextColor(StateColor const& color)
|
||||
{
|
||||
text_color = color;
|
||||
}
|
||||
|
||||
void SwitchButton::SetTrackColor(StateColor const& color)
|
||||
{
|
||||
track_color = color;
|
||||
}
|
||||
|
||||
void SwitchButton::SetThumbColor(StateColor const& color)
|
||||
{
|
||||
thumb_color = color;
|
||||
}
|
||||
|
||||
void SwitchButton::SetValue(bool value)
|
||||
{
|
||||
if (value != GetValue())
|
||||
wxBitmapToggleButton::SetValue(value);
|
||||
update();
|
||||
}
|
||||
|
||||
void SwitchButton::Rescale()
|
||||
{
|
||||
if (labels[0].IsEmpty()) {
|
||||
m_on.msw_rescale();
|
||||
m_off.msw_rescale();
|
||||
}
|
||||
else {
|
||||
constexpr int BS = 1;
|
||||
wxSize thumbSize;
|
||||
wxSize trackSize;
|
||||
wxClientDC dc(this);
|
||||
wxSize textSize[2];
|
||||
{
|
||||
textSize[0] = dc.GetTextExtent(labels[0]);
|
||||
textSize[1] = dc.GetTextExtent(labels[1]);
|
||||
}
|
||||
{
|
||||
thumbSize = textSize[0];
|
||||
auto size = textSize[1];
|
||||
if (size.x > thumbSize.x) thumbSize.x = size.x;
|
||||
else size.x = thumbSize.x;
|
||||
thumbSize.x += 12;
|
||||
thumbSize.y += 2;
|
||||
trackSize.x = thumbSize.x + size.x + 10;
|
||||
trackSize.y = thumbSize.y + BS * 2;
|
||||
auto maxWidth = GetMaxWidth();
|
||||
if (trackSize.x > maxWidth) {
|
||||
thumbSize.x -= (trackSize.x - maxWidth) / 2;
|
||||
trackSize.x = maxWidth;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
wxMemoryDC memdc(&dc);
|
||||
wxBitmap bmp(trackSize.x, trackSize.y);
|
||||
memdc.SelectObject(bmp);
|
||||
memdc.SetBackground(wxBrush(GetBackgroundColour()));
|
||||
memdc.Clear();
|
||||
memdc.SetFont(GetFont());
|
||||
auto state = i == 0 ? StateColor::Enabled : (StateColor::Checked | StateColor::Enabled);
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
wxGCDC dc2(memdc);
|
||||
#else
|
||||
wxDC &dc2(memdc);
|
||||
#endif
|
||||
dc2.SetBrush(wxBrush(track_color.colorForStates(state)));
|
||||
dc2.SetPen(wxPen(track_color.colorForStates(state)));
|
||||
dc2.DrawRoundedRectangle(wxRect({0, 0}, trackSize), trackSize.y / 2);
|
||||
dc2.SetBrush(wxBrush(thumb_color.colorForStates(StateColor::Checked | StateColor::Enabled)));
|
||||
dc2.SetPen(wxPen(thumb_color.colorForStates(StateColor::Checked | StateColor::Enabled)));
|
||||
dc2.DrawRoundedRectangle(wxRect({ i == 0 ? BS : (trackSize.x - thumbSize.x - BS), BS}, thumbSize), thumbSize.y / 2);
|
||||
}
|
||||
memdc.SetTextForeground(text_color.colorForStates(state ^ StateColor::Checked));
|
||||
memdc.DrawText(labels[0], {BS + (thumbSize.x - textSize[0].x) / 2, BS + (thumbSize.y - textSize[0].y) / 2});
|
||||
memdc.SetTextForeground(text_color.colorForStates(state));
|
||||
memdc.DrawText(labels[1], {trackSize.x - thumbSize.x - BS + (thumbSize.x - textSize[1].x) / 2, BS + (thumbSize.y - textSize[1].y) / 2});
|
||||
memdc.SelectObject(wxNullBitmap);
|
||||
(i == 0 ? m_off : m_on).bmp() = bmp;
|
||||
}
|
||||
}
|
||||
SetSize(m_on.GetBmpSize());
|
||||
update();
|
||||
}
|
||||
|
||||
void SwitchButton::update()
|
||||
{
|
||||
SetBitmap((GetValue() ? m_on : m_off).bmp());
|
||||
}
|
40
src/slic3r/GUI/Widgets/SwitchButton.hpp
Normal file
40
src/slic3r/GUI/Widgets/SwitchButton.hpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef slic3r_GUI_SwitchButton_hpp_
|
||||
#define slic3r_GUI_SwitchButton_hpp_
|
||||
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "StateColor.hpp"
|
||||
|
||||
#include <wx/tglbtn.h>
|
||||
|
||||
class SwitchButton : public wxBitmapToggleButton
|
||||
{
|
||||
public:
|
||||
SwitchButton(wxWindow * parent = NULL, wxWindowID id = wxID_ANY);
|
||||
|
||||
public:
|
||||
void SetLabels(wxString const & lbl_on, wxString const & lbl_off);
|
||||
|
||||
void SetTextColor(StateColor const &color);
|
||||
|
||||
void SetTrackColor(StateColor const &color);
|
||||
|
||||
void SetThumbColor(StateColor const &color);
|
||||
|
||||
void SetValue(bool value) override;
|
||||
|
||||
void Rescale();
|
||||
|
||||
private:
|
||||
void update();
|
||||
|
||||
private:
|
||||
ScalableBitmap m_on;
|
||||
ScalableBitmap m_off;
|
||||
|
||||
wxString labels[2];
|
||||
StateColor text_color;
|
||||
StateColor track_color;
|
||||
StateColor thumb_color;
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_SwitchButton_hpp_
|
278
src/slic3r/GUI/Widgets/TabCtrl.cpp
Normal file
278
src/slic3r/GUI/Widgets/TabCtrl.cpp
Normal file
|
@ -0,0 +1,278 @@
|
|||
#include "TabCtrl.hpp"
|
||||
|
||||
wxDEFINE_EVENT( wxEVT_TAB_SEL_CHANGING, wxCommandEvent );
|
||||
wxDEFINE_EVENT( wxEVT_TAB_SEL_CHANGED, wxCommandEvent );
|
||||
|
||||
BEGIN_EVENT_TABLE(TabCtrl, StaticBox)
|
||||
|
||||
// catch paint events
|
||||
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().
|
||||
*/
|
||||
|
||||
#define TAB_BUTTON_SPACE 2
|
||||
#define TAB_BUTTON_PADDING_X 2
|
||||
#define TAB_BUTTON_PADDING_Y 2
|
||||
#define TAB_BUTTON_PADDING TAB_BUTTON_PADDING_X, TAB_BUTTON_PADDING_Y
|
||||
|
||||
TabCtrl::TabCtrl(wxWindow * parent,
|
||||
wxWindowID id,
|
||||
const wxPoint & pos,
|
||||
const wxSize & size,
|
||||
long style)
|
||||
: StaticBox(parent, id, pos, size, style)
|
||||
{
|
||||
radius = 5;
|
||||
SetBorderColor(0xcecece);
|
||||
sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->AddSpacer(10);
|
||||
SetSizer(sizer);
|
||||
Bind(wxEVT_COMMAND_BUTTON_CLICKED, &TabCtrl::buttonClicked, this);
|
||||
//wxString reason;
|
||||
//IsTransparentBackgroundSupported(&reason);
|
||||
}
|
||||
|
||||
TabCtrl::~TabCtrl()
|
||||
{
|
||||
delete images;
|
||||
}
|
||||
|
||||
int TabCtrl::GetSelection() const { return sel; }
|
||||
|
||||
void TabCtrl::SelectItem(int item)
|
||||
{
|
||||
if (item == sel || !sendTabCtrlEvent(true))
|
||||
return;
|
||||
if (sel >= 0) {
|
||||
wxCommandEvent e(wxEVT_CHECKBOX);
|
||||
auto b = btns[sel];
|
||||
e.SetEventObject(b);
|
||||
b->GetEventHandler()->ProcessEvent(e);
|
||||
}
|
||||
sel = item;
|
||||
if (sel >= 0) {
|
||||
wxCommandEvent e(wxEVT_CHECKBOX);
|
||||
auto b = btns[sel];
|
||||
e.SetEventObject(b);
|
||||
b->GetEventHandler()->ProcessEvent(e);
|
||||
}
|
||||
sendTabCtrlEvent();
|
||||
relayout();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void TabCtrl::Unselect()
|
||||
{
|
||||
SelectItem(-1);
|
||||
}
|
||||
|
||||
void TabCtrl::Rescale()
|
||||
{
|
||||
for (auto & b : btns)
|
||||
b->Rescale();
|
||||
}
|
||||
|
||||
bool TabCtrl::SetFont(wxFont const& font)
|
||||
{
|
||||
StaticBox::SetFont(font);
|
||||
bold = font.Bold();
|
||||
for (size_t i = 0; i < btns.size(); ++i)
|
||||
btns[i]->SetFont(i == sel ? bold : font);
|
||||
return true;
|
||||
}
|
||||
|
||||
int TabCtrl::AppendItem(const wxString &item,
|
||||
int image, int selImage,
|
||||
void * clientData)
|
||||
{
|
||||
Button * btn = new Button();
|
||||
btn->Create(this, item, "", wxBORDER_NONE);
|
||||
btn->SetFont(GetFont());
|
||||
btn->SetTextColor(StateColor(
|
||||
std::make_pair(0x6B6B6B, (int) StateColor::NotChecked),
|
||||
std::make_pair(*wxLIGHT_GREY, (int) StateColor::Normal)));
|
||||
btn->SetBackgroundColor(GetBackgroundColour());
|
||||
btn->SetCornerRadius(0);
|
||||
btn->SetPaddingSize({TAB_BUTTON_PADDING});
|
||||
btns.push_back(btn);
|
||||
if (btns.size() > 1)
|
||||
sizer->GetItem(sizer->GetItemCount() - 1)->SetMinSize({0, 0});
|
||||
sizer->Add(btn, 0, wxALIGN_CENTER_VERTICAL | wxALL, TAB_BUTTON_SPACE * 2);
|
||||
sizer->AddStretchSpacer(1);
|
||||
relayout();
|
||||
return btns.size() - 1;
|
||||
}
|
||||
|
||||
bool TabCtrl::DeleteItem(int item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void TabCtrl::DeleteAllItems()
|
||||
{
|
||||
sizer->Clear(true);
|
||||
sizer->AddSpacer(10);
|
||||
btns.clear();
|
||||
if (sel >= 0) {
|
||||
sel = -1;
|
||||
sendTabCtrlEvent();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int TabCtrl::GetCount() const { return btns.size(); }
|
||||
|
||||
wxString TabCtrl::GetItemText(unsigned int item) const
|
||||
{
|
||||
return item < btns.size() ? btns[item]->GetLabel() : wxString{};
|
||||
}
|
||||
|
||||
void TabCtrl::SetItemText(unsigned int item, wxString const &value)
|
||||
{
|
||||
if (item >= btns.size()) return;
|
||||
btns[item]->SetLabel(value);
|
||||
}
|
||||
|
||||
bool TabCtrl::GetItemBold(unsigned int item) const
|
||||
{
|
||||
if (item >= btns.size()) return false;
|
||||
return btns[item]->GetFont() == bold;
|
||||
}
|
||||
|
||||
void TabCtrl::SetItemBold(unsigned int item, bool bold)
|
||||
{
|
||||
if (item >= btns.size()) return;
|
||||
btns[item]->SetFont(bold ? this->bold : GetFont());
|
||||
btns[item]->Rescale();
|
||||
}
|
||||
|
||||
void* TabCtrl::GetItemData(unsigned int item) const
|
||||
{
|
||||
if (item >= btns.size()) return nullptr;
|
||||
return btns[item]->GetClientData();
|
||||
}
|
||||
|
||||
void TabCtrl::SetItemData(unsigned int item, void* clientData)
|
||||
{
|
||||
if (item >= btns.size()) return;
|
||||
btns[item]->SetClientData(clientData);
|
||||
}
|
||||
|
||||
void TabCtrl::AssignImageList(wxImageList* imageList)
|
||||
{
|
||||
if (images == imageList) return;
|
||||
delete images;
|
||||
images = imageList;
|
||||
}
|
||||
|
||||
void TabCtrl::SetItemTextColour(unsigned int item, const StateColor &col)
|
||||
{
|
||||
if (item >= btns.size()) return;
|
||||
btns[item]->SetTextColor(col);
|
||||
}
|
||||
|
||||
int TabCtrl::GetFirstVisibleItem() const
|
||||
{
|
||||
return btns.size() == 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
int TabCtrl::GetNextVisible(int item) const
|
||||
{
|
||||
return ++item < btns.size() ? item : -1;
|
||||
}
|
||||
|
||||
bool TabCtrl::IsVisible(unsigned int item) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void TabCtrl::DoSetSize(int x, int y, int width, int height, int sizeFlags)
|
||||
{
|
||||
wxWindow::DoSetSize(x, y, width, height, sizeFlags);
|
||||
if (sizeFlags & wxSIZE_USE_EXISTING) return;
|
||||
relayout();
|
||||
}
|
||||
|
||||
void TabCtrl::relayout()
|
||||
{
|
||||
int offset = 10;
|
||||
int item = sel + 1;
|
||||
int first = 0;
|
||||
for (int i = 0; i < item; ++i)
|
||||
offset += btns[i]->GetMinSize().x + TAB_BUTTON_SPACE * 2;
|
||||
if (item < btns.size())
|
||||
offset += btns[item]->GetMinSize().x + TAB_BUTTON_SPACE * 2;
|
||||
int width = GetSize().x;
|
||||
auto sizer = GetSizer();
|
||||
for (int i = 0; i < btns.size(); ++i) {
|
||||
auto size = btns[i]->GetMinSize().x + TAB_BUTTON_SPACE * 2;
|
||||
if (i < sel && offset > width) {
|
||||
sizer->Show(i * 2 + 1, false);
|
||||
sizer->Show(i * 2 + 2, false);
|
||||
offset -= size;
|
||||
first = i + 1;
|
||||
} else if (i <= item) {
|
||||
sizer->Show(i * 2 + 1, true);
|
||||
sizer->Show(i * 2 + 2, true);
|
||||
} else if (offset <= width) {
|
||||
sizer->Show(i * 2 + 1, true);
|
||||
sizer->Show(i * 2 + 2, true);
|
||||
offset += size;
|
||||
item = i;
|
||||
} else {
|
||||
sizer->Show(i * 2 + 1, false);
|
||||
sizer->Show(i * 2 + 2, false);
|
||||
}
|
||||
sizer->GetItem(i * 2 + 2)->SetMinSize({0, 0});
|
||||
}
|
||||
if (item >= btns.size())
|
||||
-- item;
|
||||
// Keep spacing 2 ~ 10 TAB_BUTTON_SPACE
|
||||
int b = GetSize().x - offset - 10 - (item + 1 - first) * TAB_BUTTON_SPACE * 8;
|
||||
sizer->GetItem(item * 2 + 2)->SetMinSize({b > 0 ? b : 0, 0});
|
||||
sizer->Layout();
|
||||
}
|
||||
|
||||
void TabCtrl::buttonClicked(wxCommandEvent &event)
|
||||
{
|
||||
auto btn = event.GetEventObject();
|
||||
auto iter = std::find(btns.begin(), btns.end(), btn);
|
||||
SelectItem(iter == btns.end() ? -1 : iter - btns.begin());
|
||||
}
|
||||
|
||||
void TabCtrl::doRender(wxDC& dc)
|
||||
{
|
||||
wxSize size = GetSize();
|
||||
int states = state_handler.states();
|
||||
dc.SetPen(wxPen(border_color.colorForStates(states), border_width));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
|
||||
if (sel < 0) { return; }
|
||||
|
||||
auto x1 = btns[sel]->GetPosition().x;
|
||||
auto x2 = x1 + btns[sel]->GetSize().x;
|
||||
x1 -= TAB_BUTTON_SPACE; x2 += TAB_BUTTON_SPACE;
|
||||
const int BS = border_width / 2;
|
||||
const int BS2 = (1 + border_width) / 2;
|
||||
dc.DrawLine(0, size.y - BS2, x1 - radius + BS2, size.y - BS2);
|
||||
dc.DrawArc(x1 - radius, size.y, x1, size.y - radius, x1 - radius, size.y - radius);
|
||||
dc.DrawLine(x1, size.y - radius, x1, radius);
|
||||
dc.DrawArc(x1 + radius, 0, x1, radius, x1 + radius, radius);
|
||||
dc.DrawLine(x1 + radius, BS, x2 - radius, BS);
|
||||
dc.DrawArc(x2, radius, x2 - radius, 0, x2 - radius, radius);
|
||||
dc.DrawLine(x2, radius, x2, size.y - radius);
|
||||
dc.DrawArc(x2, size.y - radius, x2 + radius, size.y, x2 + radius, size.y - radius);
|
||||
dc.DrawLine(x2 + radius - BS2, size.y - BS2, size.x, size.y - BS2);
|
||||
}
|
||||
|
||||
bool TabCtrl::sendTabCtrlEvent(bool changing)
|
||||
{
|
||||
wxCommandEvent event(changing ? wxEVT_TAB_SEL_CHANGING : wxEVT_TAB_SEL_CHANGED, GetId());
|
||||
event.SetEventObject(this);
|
||||
event.SetInt(sel);
|
||||
GetEventHandler()->ProcessEvent(event);
|
||||
return true;
|
||||
}
|
80
src/slic3r/GUI/Widgets/TabCtrl.hpp
Normal file
80
src/slic3r/GUI/Widgets/TabCtrl.hpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
#ifndef slic3r_GUI_TabCtrl_hpp_
|
||||
#define slic3r_GUI_TabCtrl_hpp_
|
||||
|
||||
#include "Button.hpp"
|
||||
|
||||
wxDECLARE_EVENT( wxEVT_TAB_SEL_CHANGING, wxCommandEvent );
|
||||
wxDECLARE_EVENT( wxEVT_TAB_SEL_CHANGED, wxCommandEvent );
|
||||
|
||||
class TabCtrl : public StaticBox
|
||||
{
|
||||
std::vector<Button*> btns;
|
||||
wxImageList* images = nullptr;
|
||||
wxBoxSizer * sizer = nullptr;
|
||||
|
||||
int sel = -1;
|
||||
wxFont bold;
|
||||
|
||||
public:
|
||||
TabCtrl(wxWindow * parent,
|
||||
wxWindowID id,
|
||||
const wxPoint & pos = wxDefaultPosition,
|
||||
const wxSize & size = wxDefaultSize,
|
||||
long style = 0);
|
||||
|
||||
~TabCtrl();
|
||||
|
||||
public:
|
||||
virtual bool SetFont(wxFont const & font) override;
|
||||
|
||||
public:
|
||||
int AppendItem(const wxString &item, int image = -1, int selImage = -1, void *clientData = nullptr);
|
||||
|
||||
bool DeleteItem(int item);
|
||||
|
||||
void DeleteAllItems();
|
||||
|
||||
unsigned int GetCount() const;
|
||||
|
||||
int GetSelection() const;
|
||||
|
||||
void SelectItem(int item);
|
||||
|
||||
void Unselect();
|
||||
|
||||
virtual void Rescale();
|
||||
|
||||
wxString GetItemText(unsigned int item) const;
|
||||
void SetItemText(unsigned int item, wxString const &value);
|
||||
|
||||
bool GetItemBold(unsigned int item) const;
|
||||
void SetItemBold(unsigned int item, bool bold);
|
||||
|
||||
void* GetItemData(unsigned int item) const;
|
||||
void SetItemData(unsigned int item, void *clientData);
|
||||
|
||||
void AssignImageList(wxImageList *imageList);
|
||||
|
||||
void SetItemTextColour(unsigned int item, const StateColor& col);
|
||||
|
||||
/* fakes */
|
||||
int GetFirstVisibleItem() const;
|
||||
int GetNextVisible(int item) const;
|
||||
bool IsVisible(unsigned int item) const;
|
||||
|
||||
private:
|
||||
virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
|
||||
|
||||
void relayout();
|
||||
|
||||
void buttonClicked(wxCommandEvent & event);
|
||||
|
||||
void doRender(wxDC & dc) override;
|
||||
|
||||
// some useful events
|
||||
bool sendTabCtrlEvent(bool changing = false);
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_TabCtrl_hpp_
|
598
src/slic3r/GUI/Widgets/TempInput.cpp
Normal file
598
src/slic3r/GUI/Widgets/TempInput.cpp
Normal file
|
@ -0,0 +1,598 @@
|
|||
#include "TempInput.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "../I18N.hpp"
|
||||
#include <wx/dcgraph.h>
|
||||
#include "../GUI.hpp"
|
||||
#include "../GUI_App.hpp"
|
||||
|
||||
wxDEFINE_EVENT(wxCUSTOMEVT_SET_TEMP_FINISH, wxCommandEvent);
|
||||
|
||||
BEGIN_EVENT_TABLE(TempInput, wxPanel)
|
||||
EVT_MOTION(TempInput::mouseMoved)
|
||||
EVT_ENTER_WINDOW(TempInput::mouseEnterWindow)
|
||||
EVT_LEAVE_WINDOW(TempInput::mouseLeaveWindow)
|
||||
EVT_KEY_DOWN(TempInput::keyPressed)
|
||||
EVT_KEY_UP(TempInput::keyReleased)
|
||||
EVT_MOUSEWHEEL(TempInput::mouseWheelMoved)
|
||||
EVT_PAINT(TempInput::paintEvent)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
TempInput::TempInput()
|
||||
: state_handler(this)
|
||||
, border_color(std::make_pair(*wxWHITE, (int) StateColor::Disabled),
|
||||
std::make_pair(0x00AE42, (int) StateColor::Focused),
|
||||
std::make_pair(0x00AE42, (int) StateColor::Hovered),
|
||||
std::make_pair(*wxWHITE, (int) StateColor::Normal))
|
||||
, label_color(std::make_pair(wxColour(0xAC,0xAC,0xAC), (int) StateColor::Disabled),std::make_pair(0x323A3D, (int) StateColor::Normal))
|
||||
, text_color(std::make_pair(wxColour(0xAC,0xAC,0xAC), (int) StateColor::Disabled), std::make_pair(0x6B6B6B, (int) StateColor::Normal))
|
||||
, background_color(std::make_pair(*wxWHITE, (int) StateColor::Disabled),
|
||||
std::make_pair(*wxWHITE, (int) StateColor::Normal))
|
||||
{
|
||||
hover = false;
|
||||
radius = 0;
|
||||
SetFont(Label::Body_12);
|
||||
}
|
||||
|
||||
TempInput::TempInput(wxWindow *parent, int type, wxString text, wxString label, wxString normal_icon, wxString actice_icon, const wxPoint &pos, const wxSize &size, long style)
|
||||
: TempInput()
|
||||
{
|
||||
actice = false;
|
||||
temp_type = type;
|
||||
Create(parent, text, label, normal_icon, actice_icon, pos, size, style);
|
||||
}
|
||||
|
||||
void TempInput::Create(wxWindow *parent, wxString text, wxString label, wxString normal_icon, wxString actice_icon, const wxPoint &pos, const wxSize &size, long style)
|
||||
{
|
||||
wxWindow::Create(parent, wxID_ANY, pos, size, style);
|
||||
wxWindow::SetLabel(label);
|
||||
style &= ~wxALIGN_CENTER_HORIZONTAL;
|
||||
state_handler.attach({&border_color, &text_color, &background_color});
|
||||
state_handler.update_binds();
|
||||
|
||||
text_ctrl = new wxTextCtrl(this, wxID_ANY, text, {5, 5}, wxDefaultSize, wxTE_PROCESS_ENTER | wxBORDER_NONE, wxTextValidator(wxFILTER_NUMERIC), wxTextCtrlNameStr);
|
||||
text_ctrl->SetMaxLength(3);
|
||||
|
||||
text_ctrl->Bind(wxEVT_SET_FOCUS, [this](auto &e) {
|
||||
e.SetId(GetId());
|
||||
ProcessEventLocally(e);
|
||||
|
||||
//enter input mode
|
||||
auto temp = text_ctrl->GetValue();
|
||||
if (temp.length() > 0 && temp[0] == (0x5f)) {
|
||||
text_ctrl->SetValue(wxEmptyString);
|
||||
}
|
||||
|
||||
if (wdialog != nullptr) { wdialog->Dismiss(); }
|
||||
});
|
||||
text_ctrl->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) {
|
||||
if (m_read_only) {SetCursor(wxCURSOR_ARROW);}
|
||||
e.SetId(GetId());
|
||||
ProcessEventLocally(e);
|
||||
});
|
||||
text_ctrl->Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) {
|
||||
e.SetId(GetId());
|
||||
ProcessEventLocally(e);
|
||||
});
|
||||
text_ctrl->Bind(wxEVT_KILL_FOCUS, [this](auto &e) {
|
||||
OnEdit();
|
||||
e.SetId(GetId());
|
||||
ProcessEventLocally(e);
|
||||
|
||||
auto temp = text_ctrl->GetValue();
|
||||
if (temp.ToStdString().empty()) {
|
||||
text_ctrl->SetValue(wxString("_"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AllisNum(temp.ToStdString())) return;
|
||||
if (max_temp <= 0) return;
|
||||
|
||||
auto tempint = std::stoi(temp.ToStdString());
|
||||
if ((tempint > max_temp || tempint < min_temp) && !warning_mode) {
|
||||
if (tempint > max_temp)
|
||||
Warning(true, WARNING_TOO_HIGH);
|
||||
else if (tempint < min_temp)
|
||||
Warning(true, WARNING_TOO_LOW);
|
||||
return;
|
||||
} else {
|
||||
Warning(false);
|
||||
}
|
||||
SetFinish();
|
||||
});
|
||||
text_ctrl->Bind(wxEVT_TEXT_ENTER, [this](wxCommandEvent &e) {
|
||||
OnEdit();
|
||||
e.SetId(GetId());
|
||||
ProcessEventLocally(e);
|
||||
|
||||
auto temp = text_ctrl->GetValue();
|
||||
if (temp.ToStdString().empty()) return;
|
||||
if (!AllisNum(temp.ToStdString())) return;
|
||||
if (max_temp <= 0) return;
|
||||
|
||||
auto tempint = std::stoi(temp.ToStdString());
|
||||
if (tempint > max_temp) {
|
||||
Warning(true, WARNING_TOO_HIGH);
|
||||
return;
|
||||
} else {
|
||||
Warning(false, WARNING_TOO_LOW);
|
||||
}
|
||||
SetFinish();
|
||||
Slic3r::GUI::wxGetApp().GetMainTopWindow()->SetFocus();
|
||||
});
|
||||
text_ctrl->Bind(wxEVT_RIGHT_DOWN, [this](auto &e) {}); // disable context menu
|
||||
text_ctrl->Bind(wxEVT_LEFT_DOWN, [this](auto &e) {
|
||||
if (m_read_only) {
|
||||
return;
|
||||
} else {
|
||||
e.Skip();
|
||||
}
|
||||
});
|
||||
text_ctrl->SetFont(Label::Body_13);
|
||||
text_ctrl->SetForegroundColour(text_color.colorForStates(StateColor::Normal));
|
||||
if (!normal_icon.IsEmpty()) { this->normal_icon = ScalableBitmap(this, normal_icon.ToStdString(), 16); }
|
||||
if (!actice_icon.IsEmpty()) { this->actice_icon = ScalableBitmap(this, actice_icon.ToStdString(), 16); }
|
||||
this->degree_icon = ScalableBitmap(this, "degree", 16);
|
||||
messureSize();
|
||||
}
|
||||
|
||||
|
||||
bool TempInput::AllisNum(std::string str)
|
||||
{
|
||||
for (int i = 0; i < str.size(); i++) {
|
||||
int tmp = (int) str[i];
|
||||
if (tmp >= 48 && tmp <= 57) {
|
||||
continue;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void TempInput::SetFinish()
|
||||
{
|
||||
wxCommandEvent event(wxCUSTOMEVT_SET_TEMP_FINISH);
|
||||
event.SetInt(temp_type);
|
||||
wxPostEvent(this->GetParent(), event);
|
||||
}
|
||||
|
||||
wxString TempInput::erasePending(wxString &str)
|
||||
{
|
||||
wxString tmp = str;
|
||||
int index = tmp.size() - 1;
|
||||
while (index != -1) {
|
||||
if (tmp[index] < '0' || tmp[index] > '9') {
|
||||
tmp.erase(index, 1);
|
||||
index--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void TempInput::SetTagTemp(int temp)
|
||||
{
|
||||
text_ctrl->SetValue(wxString::Format("%d", temp));
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void TempInput::SetTagTemp(wxString temp)
|
||||
{
|
||||
text_ctrl->SetValue(temp);
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void TempInput::SetCurrTemp(int temp)
|
||||
{
|
||||
SetLabel(wxString::Format("%d", temp));
|
||||
}
|
||||
|
||||
void TempInput::SetCurrTemp(wxString temp)
|
||||
{
|
||||
SetLabel(temp);
|
||||
}
|
||||
|
||||
void TempInput::Warning(bool warn, WarningType type)
|
||||
{
|
||||
warning_mode = warn;
|
||||
//Refresh();
|
||||
|
||||
if (warning_mode) {
|
||||
if (wdialog == nullptr) {
|
||||
wdialog = new wxPopupTransientWindow(this);
|
||||
wdialog->SetBackgroundColour(wxColour(0xFFFFFF));
|
||||
|
||||
wdialog->SetSizeHints(wxDefaultSize, wxDefaultSize);
|
||||
|
||||
wxBoxSizer *sizer_body = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
auto body = new wxPanel(wdialog, wxID_ANY, wxDefaultPosition, {this->GetSize().x - 4, -1}, wxTAB_TRAVERSAL);
|
||||
body->SetBackgroundColour(wxColour(0xFFFFFF));
|
||||
|
||||
|
||||
wxBoxSizer *sizer_text;
|
||||
sizer_text = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
|
||||
|
||||
warning_text = new wxStaticText(body, wxID_ANY,
|
||||
wxEmptyString,
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxALIGN_CENTER_HORIZONTAL);
|
||||
warning_text->SetFont(::Label::Body_12);
|
||||
warning_text->SetForegroundColour(wxColour(255, 111, 0));
|
||||
warning_text->Wrap(-1);
|
||||
sizer_text->Add(warning_text, 1, wxEXPAND | wxTOP | wxBOTTOM, 2);
|
||||
|
||||
body->SetSizer(sizer_text);
|
||||
body->Layout();
|
||||
sizer_body->Add(body, 0, wxEXPAND, 0);
|
||||
|
||||
wdialog->SetSizer(sizer_body);
|
||||
wdialog->Layout();
|
||||
sizer_body->Fit(wdialog);
|
||||
}
|
||||
|
||||
wxPoint pos = this->ClientToScreen(wxPoint(2, 0));
|
||||
pos.y += this->GetRect().height - (this->GetSize().y - this->text_ctrl->GetSize().y) / 2 - 2;
|
||||
wdialog->SetPosition(pos);
|
||||
|
||||
wxString warning_string;
|
||||
if (type == WarningType::WARNING_TOO_HIGH)
|
||||
warning_string = _L("The maximum temperature cannot exceed" + wxString::Format("%d", max_temp));
|
||||
else if (type == WarningType::WARNING_TOO_LOW)
|
||||
warning_string = _L("The minmum temperature should not be less than " + wxString::Format("%d", max_temp));
|
||||
|
||||
warning_text->SetLabel(warning_string);
|
||||
wdialog->Popup();
|
||||
} else {
|
||||
if (wdialog)
|
||||
wdialog->Dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
void TempInput::SetIconActive()
|
||||
{
|
||||
actice = true;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void TempInput::SetIconNormal()
|
||||
{
|
||||
actice = false;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void TempInput::SetMaxTemp(int temp) { max_temp = temp; }
|
||||
|
||||
void TempInput::SetMinTemp(int temp) { min_temp = temp; }
|
||||
|
||||
void TempInput::SetCornerRadius(double radius)
|
||||
{
|
||||
this->radius = radius;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void TempInput::SetLabel(const wxString &label)
|
||||
{
|
||||
wxWindow::SetLabel(label);
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void TempInput::SetBorderColor(StateColor const &color)
|
||||
{
|
||||
border_color = color;
|
||||
state_handler.update_binds();
|
||||
}
|
||||
|
||||
void TempInput::SetTextColor(StateColor const &color)
|
||||
{
|
||||
text_color = color;
|
||||
state_handler.update_binds();
|
||||
}
|
||||
|
||||
void TempInput::SetLabelColor(StateColor const &color)
|
||||
{
|
||||
label_color = color;
|
||||
state_handler.update_binds();
|
||||
}
|
||||
|
||||
void TempInput::SetBackgroundColor(StateColor const &color)
|
||||
{
|
||||
background_color = color;
|
||||
state_handler.update_binds();
|
||||
}
|
||||
|
||||
void TempInput::Rescale()
|
||||
{
|
||||
if (this->normal_icon.bmp().IsOk()) this->normal_icon.msw_rescale();
|
||||
if (this->degree_icon.bmp().IsOk()) this->degree_icon.msw_rescale();
|
||||
messureSize();
|
||||
}
|
||||
|
||||
bool TempInput::Enable(bool enable)
|
||||
{
|
||||
bool result = wxWindow::Enable(enable);
|
||||
if (result) {
|
||||
wxCommandEvent e(EVT_ENABLE_CHANGED);
|
||||
e.SetEventObject(this);
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void TempInput::SetMinSize(const wxSize &size)
|
||||
{
|
||||
wxSize size2 = size;
|
||||
if (size2.y < 0) {
|
||||
#ifdef __WXMAC__
|
||||
if (GetPeer()) // peer is not ready in Create on mac
|
||||
#endif
|
||||
size2.y = GetSize().y;
|
||||
}
|
||||
wxWindow::SetMinSize(size2);
|
||||
messureMiniSize();
|
||||
}
|
||||
|
||||
void TempInput::DoSetSize(int x, int y, int width, int height, int sizeFlags)
|
||||
{
|
||||
wxWindow::DoSetSize(x, y, width, height, sizeFlags);
|
||||
if (sizeFlags & wxSIZE_USE_EXISTING) return;
|
||||
|
||||
auto left = padding_left;
|
||||
wxClientDC dc(this);
|
||||
if (normal_icon.bmp().IsOk()) {
|
||||
wxSize szIcon = normal_icon.GetBmpSize();
|
||||
left += szIcon.x;
|
||||
}
|
||||
|
||||
// interval
|
||||
left += 9;
|
||||
|
||||
// label
|
||||
dc.SetFont(::Label::Head_14);
|
||||
labelSize = dc.GetMultiLineTextExtent(wxWindow::GetLabel());
|
||||
left += labelSize.x;
|
||||
|
||||
// interval
|
||||
left += 10;
|
||||
|
||||
// separator
|
||||
dc.SetFont(::Label::Body_12);
|
||||
auto sepSize = dc.GetMultiLineTextExtent(wxString("/"));
|
||||
left += sepSize.x;
|
||||
|
||||
// text text
|
||||
auto textSize = text_ctrl->GetTextExtent(wxString("0000"));
|
||||
text_ctrl->SetSize(textSize);
|
||||
text_ctrl->SetPosition({left, (GetSize().y - text_ctrl->GetSize().y) / 2});
|
||||
}
|
||||
|
||||
void TempInput::DoSetToolTipText(wxString const &tip)
|
||||
{
|
||||
wxWindow::DoSetToolTipText(tip);
|
||||
text_ctrl->SetToolTip(tip);
|
||||
}
|
||||
|
||||
void TempInput::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 TempInput::render(wxDC &dc)
|
||||
{
|
||||
int states = state_handler.states();
|
||||
wxSize size = GetSize();
|
||||
bool align_right = GetWindowStyle() & wxRIGHT;
|
||||
|
||||
if (warning_mode) {
|
||||
dc.SetPen(wxPen(wxColour(255, 111, 0)));
|
||||
} else {
|
||||
dc.SetPen(wxPen(border_color.colorForStates(states)));
|
||||
}
|
||||
|
||||
dc.SetBrush(wxBrush(background_color.colorForStates(states)));
|
||||
dc.DrawRoundedRectangle(0, 0, size.x, size.y, radius);
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
// start draw
|
||||
wxPoint pt = {padding_left, 0};
|
||||
if (actice_icon.bmp().IsOk() && actice) {
|
||||
wxSize szIcon = actice_icon.GetBmpSize();
|
||||
pt.y = (size.y - szIcon.y) / 2;
|
||||
dc.DrawBitmap(actice_icon.bmp(), pt);
|
||||
pt.x += szIcon.x + 9;
|
||||
} else {
|
||||
actice = false;
|
||||
}
|
||||
|
||||
if (normal_icon.bmp().IsOk() && !actice) {
|
||||
wxSize szIcon = normal_icon.GetBmpSize();
|
||||
pt.y = (size.y - szIcon.y) / 2;
|
||||
dc.DrawBitmap(normal_icon.bmp(), pt);
|
||||
pt.x += szIcon.x + 9;
|
||||
}
|
||||
|
||||
// label
|
||||
auto text = wxWindow::GetLabel();
|
||||
dc.SetFont(::Label::Head_14);
|
||||
labelSize = dc.GetMultiLineTextExtent(wxWindow::GetLabel());
|
||||
dc.SetTextForeground(label_color.colorForStates((int) StateColor::Normal));
|
||||
if (!IsEnabled())
|
||||
dc.SetTextBackground(background_color.colorForStates((int) StateColor::Disabled));
|
||||
else
|
||||
dc.SetTextBackground(background_color.colorForStates((int) states));
|
||||
|
||||
if (!text.IsEmpty()) {
|
||||
wxSize textSize = text_ctrl->GetSize();
|
||||
if (align_right) {
|
||||
if (pt.x + labelSize.x > size.x) text = wxControl::Ellipsize(text, dc, wxELLIPSIZE_END, size.x - pt.x);
|
||||
pt.y = (size.y - labelSize.y) / 2;
|
||||
} else {
|
||||
pt.y = (size.y - labelSize.y) / 2;
|
||||
}
|
||||
dc.DrawText(text, pt);
|
||||
}
|
||||
|
||||
// separator
|
||||
dc.SetFont(::Label::Body_12);
|
||||
auto sepSize = dc.GetMultiLineTextExtent(wxString("/"));
|
||||
dc.SetTextForeground(text_color.colorForStates(states));
|
||||
dc.SetTextBackground(background_color.colorForStates(states));
|
||||
pt.x += labelSize.x + 10;
|
||||
pt.y = (size.y - sepSize.y) / 2;
|
||||
dc.DrawText(wxString("/"), pt);
|
||||
|
||||
// flag
|
||||
if (degree_icon.bmp().IsOk()) {
|
||||
auto pos = text_ctrl->GetPosition();
|
||||
wxSize szIcon = degree_icon.GetBmpSize();
|
||||
pt.y = (size.y - szIcon.y) / 2;
|
||||
pt.x = pos.x + text_ctrl->GetSize().x;
|
||||
dc.DrawBitmap(degree_icon.bmp(), pt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TempInput::messureMiniSize()
|
||||
{
|
||||
wxSize size = GetMinSize();
|
||||
|
||||
auto width = 0;
|
||||
auto height = 0;
|
||||
|
||||
wxClientDC dc(this);
|
||||
if (normal_icon.bmp().IsOk()) {
|
||||
wxSize szIcon = normal_icon.GetBmpSize();
|
||||
width += szIcon.x;
|
||||
height = szIcon.y;
|
||||
}
|
||||
|
||||
// interval
|
||||
width += 9;
|
||||
|
||||
// label
|
||||
dc.SetFont(::Label::Head_14);
|
||||
labelSize = dc.GetMultiLineTextExtent(wxWindow::GetLabel());
|
||||
width += labelSize.x;
|
||||
height = labelSize.y > height ? labelSize.y : height;
|
||||
|
||||
// interval
|
||||
width += 10;
|
||||
|
||||
// separator
|
||||
dc.SetFont(::Label::Body_12);
|
||||
auto sepSize = dc.GetMultiLineTextExtent(wxString("/"));
|
||||
width += sepSize.x;
|
||||
height = sepSize.y > height ? sepSize.y : height;
|
||||
|
||||
// text text
|
||||
auto textSize = text_ctrl->GetTextExtent(wxString("0000"));
|
||||
width += textSize.x;
|
||||
height = textSize.y > height ? textSize.y : height;
|
||||
|
||||
// flag flag
|
||||
auto flagSize = degree_icon.GetBmpSize();
|
||||
width += flagSize.x;
|
||||
height = flagSize.y > height ? flagSize.y : height;
|
||||
|
||||
if (size.x < width) {
|
||||
size.x = width;
|
||||
} else {
|
||||
padding_left = (size.x - width) / 2;
|
||||
}
|
||||
|
||||
if (size.y < height) size.y = height;
|
||||
|
||||
SetSize(size);
|
||||
}
|
||||
|
||||
|
||||
void TempInput::messureSize()
|
||||
{
|
||||
wxSize size = GetSize();
|
||||
|
||||
auto width = 0;
|
||||
auto height = 0;
|
||||
|
||||
wxClientDC dc(this);
|
||||
if (normal_icon.bmp().IsOk()) {
|
||||
wxSize szIcon = normal_icon.GetBmpSize();
|
||||
width += szIcon.x;
|
||||
height = szIcon.y;
|
||||
}
|
||||
|
||||
// interval
|
||||
width += 9;
|
||||
|
||||
// label
|
||||
dc.SetFont(::Label::Head_14);
|
||||
labelSize = dc.GetMultiLineTextExtent(wxWindow::GetLabel());
|
||||
width += labelSize.x;
|
||||
height = labelSize.y > height ? labelSize.y : height;
|
||||
|
||||
// interval
|
||||
width += 10;
|
||||
|
||||
// separator
|
||||
dc.SetFont(::Label::Body_12);
|
||||
auto sepSize = dc.GetMultiLineTextExtent(wxString("/"));
|
||||
width += sepSize.x;
|
||||
height = sepSize.y > height ? sepSize.y : height;
|
||||
|
||||
// text text
|
||||
auto textSize = text_ctrl->GetTextExtent(wxString("0000"));
|
||||
width += textSize.x;
|
||||
height = textSize.y > height ? textSize.y : height;
|
||||
|
||||
// flag flag
|
||||
auto flagSize = degree_icon.GetBmpSize();
|
||||
width += flagSize.x;
|
||||
height = flagSize.y > height ? flagSize.y : height;
|
||||
|
||||
if (size.x < width) {
|
||||
size.x = width;
|
||||
} else {
|
||||
padding_left = (size.x - width) / 2;
|
||||
}
|
||||
|
||||
if (size.y < height) size.y = height;
|
||||
|
||||
wxSize minSize = size;
|
||||
minSize.x = GetMinWidth();
|
||||
SetMinSize(minSize);
|
||||
SetSize(size);
|
||||
}
|
||||
|
||||
void TempInput::mouseEnterWindow(wxMouseEvent &event)
|
||||
{
|
||||
if (!hover) {
|
||||
hover = true;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void TempInput::mouseLeaveWindow(wxMouseEvent &event)
|
||||
{
|
||||
if (hover) {
|
||||
hover = false;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
// currently unused events
|
||||
void TempInput::mouseMoved(wxMouseEvent &event) {}
|
||||
void TempInput::mouseWheelMoved(wxMouseEvent &event) {}
|
||||
void TempInput::keyPressed(wxKeyEvent &event) {}
|
||||
void TempInput::keyReleased(wxKeyEvent &event) {}
|
144
src/slic3r/GUI/Widgets/TempInput.hpp
Normal file
144
src/slic3r/GUI/Widgets/TempInput.hpp
Normal file
|
@ -0,0 +1,144 @@
|
|||
#ifndef slic3r_GUI_TempInput_hpp_
|
||||
#define slic3r_GUI_TempInput_hpp_
|
||||
|
||||
#include <wx/textctrl.h>
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "StateHandler.hpp"
|
||||
|
||||
wxDECLARE_EVENT(wxCUSTOMEVT_SET_TEMP_FINISH, wxCommandEvent);
|
||||
|
||||
class TempInput : public wxWindow
|
||||
{
|
||||
bool hover;
|
||||
double radius;
|
||||
|
||||
bool m_read_only{false};
|
||||
wxSize labelSize;
|
||||
ScalableBitmap normal_icon;
|
||||
ScalableBitmap actice_icon;
|
||||
ScalableBitmap degree_icon;
|
||||
|
||||
StateHandler state_handler;
|
||||
StateColor label_color;
|
||||
StateColor text_color;
|
||||
StateColor border_color;
|
||||
StateColor background_color;
|
||||
|
||||
wxTextCtrl * text_ctrl;
|
||||
wxStaticText *warning_text;
|
||||
|
||||
int max_temp = 0;
|
||||
int min_temp = 0;
|
||||
bool warning_mode = false;
|
||||
|
||||
int padding_left = 0;
|
||||
static const int TempInputWidth = 200;
|
||||
static const int TempInputHeight = 50;
|
||||
public:
|
||||
enum WarningType {
|
||||
WARNING_TOO_HIGH,
|
||||
WARNING_TOO_LOW,
|
||||
WARNING_UNKNOWN,
|
||||
};
|
||||
|
||||
TempInput();
|
||||
|
||||
TempInput(wxWindow * parent,
|
||||
int type,
|
||||
wxString text,
|
||||
wxString label = "",
|
||||
wxString normal_icon = "",
|
||||
wxString actice_icon = "",
|
||||
const wxPoint &pos = wxDefaultPosition,
|
||||
const wxSize & size = wxDefaultSize,
|
||||
long style = 0);
|
||||
|
||||
public:
|
||||
void Create(wxWindow * parent,
|
||||
wxString text,
|
||||
wxString label = "",
|
||||
wxString normal_icon = "",
|
||||
wxString actice_icon = "",
|
||||
const wxPoint &pos = wxDefaultPosition,
|
||||
const wxSize & size = wxDefaultSize,
|
||||
long style = 0);
|
||||
|
||||
|
||||
wxPopupTransientWindow *wdialog{nullptr};
|
||||
int temp_type;
|
||||
bool actice = false;
|
||||
|
||||
|
||||
wxString erasePending(wxString &str);
|
||||
|
||||
void SetTagTemp(int temp);
|
||||
void SetTagTemp(wxString temp);
|
||||
|
||||
void SetCurrTemp(int temp);
|
||||
void SetCurrTemp(wxString temp);
|
||||
|
||||
bool AllisNum(std::string str);
|
||||
void SetFinish();
|
||||
void Warning(bool warn, WarningType type = WARNING_UNKNOWN);
|
||||
void SetIconActive();
|
||||
void SetIconNormal();
|
||||
|
||||
void SetReadOnly(bool ro) { m_read_only = ro; }
|
||||
|
||||
void SetMaxTemp(int temp);
|
||||
void SetMinTemp(int temp);
|
||||
|
||||
int GetType() { return temp_type; }
|
||||
|
||||
wxString GetTagTemp() { return text_ctrl->GetValue(); }
|
||||
wxString GetCurrTemp() { return GetLabel(); }
|
||||
|
||||
void SetCornerRadius(double radius);
|
||||
|
||||
void SetLabel(const wxString &label);
|
||||
|
||||
void SetBorderColor(StateColor const &color);
|
||||
|
||||
void SetTextColor(StateColor const &color);
|
||||
|
||||
void SetLabelColor(StateColor const &color);
|
||||
|
||||
void SetBackgroundColor(StateColor const &color);
|
||||
|
||||
virtual void Rescale();
|
||||
|
||||
virtual bool Enable(bool enable = true) override;
|
||||
|
||||
virtual void SetMinSize(const wxSize &size) override;
|
||||
|
||||
wxTextCtrl *GetTextCtrl() { return text_ctrl; }
|
||||
|
||||
wxTextCtrl const *GetTextCtrl() const { return text_ctrl; }
|
||||
|
||||
protected:
|
||||
virtual void OnEdit() {}
|
||||
|
||||
virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
|
||||
|
||||
void DoSetToolTipText(wxString const &tip) override;
|
||||
|
||||
private:
|
||||
void paintEvent(wxPaintEvent &evt);
|
||||
|
||||
void render(wxDC &dc);
|
||||
|
||||
void messureMiniSize();
|
||||
void messureSize();
|
||||
|
||||
// some useful events
|
||||
void mouseMoved(wxMouseEvent &event);
|
||||
void mouseWheelMoved(wxMouseEvent &event);
|
||||
void mouseEnterWindow(wxMouseEvent &event);
|
||||
void mouseLeaveWindow(wxMouseEvent &event);
|
||||
void keyPressed(wxKeyEvent &event);
|
||||
void keyReleased(wxKeyEvent &event);
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_TempInput_hpp_
|
283
src/slic3r/GUI/Widgets/TextInput.cpp
Normal file
283
src/slic3r/GUI/Widgets/TextInput.cpp
Normal file
|
@ -0,0 +1,283 @@
|
|||
#include "TextInput.hpp"
|
||||
#include "Label.hpp"
|
||||
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
BEGIN_EVENT_TABLE(TextInput, wxPanel)
|
||||
|
||||
EVT_MOTION(TextInput::mouseMoved)
|
||||
EVT_ENTER_WINDOW(TextInput::mouseEnterWindow)
|
||||
EVT_LEAVE_WINDOW(TextInput::mouseLeaveWindow)
|
||||
EVT_KEY_DOWN(TextInput::keyPressed)
|
||||
EVT_KEY_UP(TextInput::keyReleased)
|
||||
EVT_MOUSEWHEEL(TextInput::mouseWheelMoved)
|
||||
|
||||
// catch paint events
|
||||
EVT_PAINT(TextInput::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().
|
||||
*/
|
||||
|
||||
TextInput::TextInput()
|
||||
: state_handler(this)
|
||||
, border_color(std::make_pair(0xDBDBDB, (int) StateColor::Disabled),
|
||||
std::make_pair(0x00AE42, (int) StateColor::Focused),
|
||||
std::make_pair(0x00AE42, (int) StateColor::Hovered),
|
||||
std::make_pair(0xDBDBDB, (int) StateColor::Normal))
|
||||
, text_color(std::make_pair(0xACACAC, (int) StateColor::Disabled),
|
||||
std::make_pair(0x363636, (int) StateColor::Normal))
|
||||
, background_color(std::make_pair(0xF0F0F0, (int) StateColor::Disabled),
|
||||
std::make_pair(*wxWHITE, (int) StateColor::Normal))
|
||||
{
|
||||
hover = false;
|
||||
radius = 0;
|
||||
SetFont(Label::Body_12);
|
||||
}
|
||||
|
||||
TextInput::TextInput(wxWindow * parent,
|
||||
wxString text,
|
||||
wxString label,
|
||||
wxString icon,
|
||||
const wxPoint &pos,
|
||||
const wxSize & size,
|
||||
long style)
|
||||
: TextInput()
|
||||
{
|
||||
Create(parent, text, label, icon, pos, size, style);
|
||||
}
|
||||
|
||||
void TextInput::Create(wxWindow * parent,
|
||||
wxString text,
|
||||
wxString label,
|
||||
wxString icon,
|
||||
const wxPoint &pos,
|
||||
const wxSize & size,
|
||||
long style)
|
||||
{
|
||||
text_ctrl = nullptr;
|
||||
wxWindow::Create(parent, wxID_ANY, pos, size, style);
|
||||
|
||||
wxWindow::SetLabel(label);
|
||||
style &= ~wxRIGHT;
|
||||
state_handler.attach({&border_color, &text_color, &background_color});
|
||||
state_handler.update_binds();
|
||||
text_ctrl = new wxTextCtrl(this, wxID_ANY, text, {5, 5}, wxDefaultSize,
|
||||
style | wxBORDER_NONE);
|
||||
text_ctrl->Bind(wxEVT_SET_FOCUS, [this](auto &e) {
|
||||
e.SetId(GetId());
|
||||
ProcessEventLocally(e);
|
||||
});
|
||||
text_ctrl->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) {
|
||||
e.SetId(GetId());
|
||||
ProcessEventLocally(e);
|
||||
});
|
||||
text_ctrl->Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) {
|
||||
e.SetId(GetId());
|
||||
ProcessEventLocally(e);
|
||||
});
|
||||
text_ctrl->Bind(wxEVT_KILL_FOCUS, [this](auto &e) {
|
||||
OnEdit();
|
||||
e.SetId(GetId());
|
||||
ProcessEventLocally(e);
|
||||
});
|
||||
text_ctrl->Bind(wxEVT_TEXT_ENTER, [this](auto &e) {
|
||||
OnEdit();
|
||||
e.SetId(GetId());
|
||||
ProcessEventLocally(e);
|
||||
});
|
||||
text_ctrl->Bind(wxEVT_RIGHT_DOWN, [this](auto &e) {}); // disable context menu
|
||||
text_ctrl->SetFont(Label::Body_14);
|
||||
if (!icon.IsEmpty()) {
|
||||
this->icon = ScalableBitmap(this, icon.ToStdString(), 16);
|
||||
}
|
||||
messureSize();
|
||||
}
|
||||
|
||||
void TextInput::SetCornerRadius(double radius)
|
||||
{
|
||||
this->radius = radius;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void TextInput::SetLabel(const wxString& label)
|
||||
{
|
||||
wxWindow::SetLabel(label);
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void TextInput::SetIcon(const wxBitmap &icon)
|
||||
{
|
||||
this->icon.bmp() = icon;
|
||||
Rescale();
|
||||
}
|
||||
|
||||
void TextInput::SetBorderColor(StateColor const& color)
|
||||
{
|
||||
border_color = color;
|
||||
state_handler.update_binds();
|
||||
}
|
||||
|
||||
void TextInput::SetTextColor(StateColor const& color)
|
||||
{
|
||||
text_color= color;
|
||||
state_handler.update_binds();
|
||||
}
|
||||
|
||||
void TextInput::SetBackgroundColor(StateColor const& color)
|
||||
{
|
||||
background_color = color;
|
||||
state_handler.update_binds();
|
||||
}
|
||||
|
||||
void TextInput::Rescale()
|
||||
{
|
||||
if (!this->icon.name().empty())
|
||||
this->icon.msw_rescale();
|
||||
messureSize();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
bool TextInput::Enable(bool enable)
|
||||
{
|
||||
bool result = text_ctrl->Enable(enable) && wxWindow::Enable(enable);
|
||||
if (result) {
|
||||
wxCommandEvent e(EVT_ENABLE_CHANGED);
|
||||
e.SetEventObject(this);
|
||||
GetEventHandler()->ProcessEvent(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void TextInput::SetMinSize(const wxSize& size)
|
||||
{
|
||||
wxSize size2 = size;
|
||||
if (size2.y < 0) {
|
||||
#ifdef __WXMAC__
|
||||
if (GetPeer()) // peer is not ready in Create on mac
|
||||
#endif
|
||||
size2.y = GetSize().y;
|
||||
}
|
||||
wxWindow::SetMinSize(size2);
|
||||
}
|
||||
|
||||
void TextInput::DoSetSize(int x, int y, int width, int height, int sizeFlags)
|
||||
{
|
||||
wxWindow::DoSetSize(x, y, width, height, sizeFlags);
|
||||
if (sizeFlags & wxSIZE_USE_EXISTING) return;
|
||||
wxSize size = GetSize();
|
||||
wxPoint textPos = {5, 0};
|
||||
if (this->icon.bmp().IsOk()) {
|
||||
wxSize szIcon = this->icon.bmp().GetSize();
|
||||
textPos.x += szIcon.x;
|
||||
}
|
||||
bool align_right = GetWindowStyle() & wxRIGHT;
|
||||
if (align_right)
|
||||
textPos.x += labelSize.x;
|
||||
if (text_ctrl) {
|
||||
wxSize textSize = text_ctrl->GetSize();
|
||||
textSize.x = size.x - textPos.x - labelSize.x - 10;
|
||||
text_ctrl->SetSize(textSize);
|
||||
text_ctrl->SetPosition({textPos.x, (size.y - textSize.y) / 2});
|
||||
}
|
||||
}
|
||||
|
||||
void TextInput::DoSetToolTipText(wxString const &tip)
|
||||
{
|
||||
wxWindow::DoSetToolTipText(tip);
|
||||
text_ctrl->SetToolTip(tip);
|
||||
}
|
||||
|
||||
void TextInput::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 TextInput::render(wxDC& dc)
|
||||
{
|
||||
int states = state_handler.states();
|
||||
wxSize size = GetSize();
|
||||
bool align_right = GetWindowStyle() & wxRIGHT;
|
||||
dc.SetPen(wxPen(border_color.colorForStates(states)));
|
||||
dc.SetBrush(wxBrush(background_color.colorForStates(states)));
|
||||
dc.DrawRoundedRectangle(0, 0, size.x, size.y, radius);
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
// start draw
|
||||
wxPoint pt = {5, 0};
|
||||
if (icon.bmp().IsOk()) {
|
||||
wxSize szIcon = icon.GetBmpSize();
|
||||
pt.y = (size.y - szIcon.y) / 2;
|
||||
dc.DrawBitmap(icon.bmp(), pt);
|
||||
pt.x += szIcon.x + 5;
|
||||
}
|
||||
auto text = wxWindow::GetLabel();
|
||||
if (!text.IsEmpty()) {
|
||||
wxSize textSize = text_ctrl->GetSize();
|
||||
if (align_right) {
|
||||
if (pt.x + labelSize.x > size.x)
|
||||
text = wxControl::Ellipsize(text, dc, wxELLIPSIZE_END, size.x - pt.x);
|
||||
pt.y = (size.y - labelSize.y) / 2;
|
||||
} else {
|
||||
pt.x += textSize.x;
|
||||
pt.y = (size.y + textSize.y) / 2 - labelSize.y;
|
||||
}
|
||||
dc.SetTextForeground(text_color.colorForStates(states));
|
||||
dc.SetFont(GetFont());
|
||||
dc.DrawText(text, pt);
|
||||
}
|
||||
}
|
||||
|
||||
void TextInput::messureSize()
|
||||
{
|
||||
wxSize size = GetSize();
|
||||
wxClientDC dc(this);
|
||||
labelSize = dc.GetTextExtent(wxWindow::GetLabel());
|
||||
wxSize textSize = text_ctrl->GetSize();
|
||||
#ifdef __WXOSX__
|
||||
textSize.y -= 3; // TODO:
|
||||
#endif
|
||||
int h = textSize.y * 24 / 14;
|
||||
if (size.y < h) {
|
||||
size.y = h;
|
||||
}
|
||||
wxSize minSize = size;
|
||||
minSize.x = GetMinWidth();
|
||||
SetMinSize(minSize);
|
||||
SetSize(size);
|
||||
}
|
||||
|
||||
void TextInput::mouseEnterWindow(wxMouseEvent& event)
|
||||
{
|
||||
if (!hover)
|
||||
{
|
||||
hover = true;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void TextInput::mouseLeaveWindow(wxMouseEvent& event)
|
||||
{
|
||||
if (hover)
|
||||
{
|
||||
hover = false;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
// currently unused events
|
||||
void TextInput::mouseMoved(wxMouseEvent& event) {}
|
||||
void TextInput::mouseWheelMoved(wxMouseEvent& event) {}
|
||||
void TextInput::keyPressed(wxKeyEvent& event) {}
|
||||
void TextInput::keyReleased(wxKeyEvent& event) {}
|
92
src/slic3r/GUI/Widgets/TextInput.hpp
Normal file
92
src/slic3r/GUI/Widgets/TextInput.hpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
#ifndef slic3r_GUI_TextInput_hpp_
|
||||
#define slic3r_GUI_TextInput_hpp_
|
||||
|
||||
#include <wx/textctrl.h>
|
||||
#include "../wxExtensions.hpp"
|
||||
#include "StateHandler.hpp"
|
||||
|
||||
class TextInput : public wxWindow
|
||||
{
|
||||
|
||||
bool hover;
|
||||
wxSize labelSize;
|
||||
ScalableBitmap icon;
|
||||
double radius;
|
||||
StateHandler state_handler;
|
||||
StateColor text_color;
|
||||
StateColor border_color;
|
||||
StateColor background_color;
|
||||
wxTextCtrl * text_ctrl;
|
||||
|
||||
static const int TextInputWidth = 200;
|
||||
static const int TextInputHeight = 50;
|
||||
|
||||
public:
|
||||
TextInput();
|
||||
|
||||
TextInput(wxWindow * parent,
|
||||
wxString text,
|
||||
wxString label = "",
|
||||
wxString icon = "",
|
||||
const wxPoint &pos = wxDefaultPosition,
|
||||
const wxSize & size = wxDefaultSize,
|
||||
long style = 0);
|
||||
|
||||
public:
|
||||
void Create(wxWindow * parent,
|
||||
wxString text,
|
||||
wxString label = "",
|
||||
wxString icon = "",
|
||||
const wxPoint &pos = wxDefaultPosition,
|
||||
const wxSize & size = wxDefaultSize,
|
||||
long style = 0);
|
||||
|
||||
void SetCornerRadius(double radius);
|
||||
|
||||
void SetLabel(const wxString& label);
|
||||
|
||||
void SetIcon(const wxBitmap & icon);
|
||||
|
||||
void SetBorderColor(StateColor const & color);
|
||||
|
||||
void SetTextColor(StateColor const &color);
|
||||
|
||||
void SetBackgroundColor(StateColor const &color);
|
||||
|
||||
virtual void Rescale();
|
||||
|
||||
virtual bool Enable(bool enable = true) override;
|
||||
|
||||
virtual void SetMinSize(const wxSize& size) override;
|
||||
|
||||
wxTextCtrl *GetTextCtrl() { return text_ctrl; }
|
||||
|
||||
wxTextCtrl const *GetTextCtrl() const { return text_ctrl; }
|
||||
|
||||
protected:
|
||||
virtual void OnEdit() {}
|
||||
|
||||
virtual void DoSetSize(
|
||||
int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO);
|
||||
|
||||
void DoSetToolTipText(wxString const &tip) override;
|
||||
|
||||
private:
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
|
||||
void render(wxDC& dc);
|
||||
|
||||
void messureSize();
|
||||
|
||||
// some useful events
|
||||
void mouseMoved(wxMouseEvent& event);
|
||||
void mouseWheelMoved(wxMouseEvent& event);
|
||||
void mouseEnterWindow(wxMouseEvent& event);
|
||||
void mouseLeaveWindow(wxMouseEvent& event);
|
||||
void keyPressed(wxKeyEvent& event);
|
||||
void keyReleased(wxKeyEvent& event);
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_TextInput_hpp_
|
121
src/slic3r/GUI/Widgets/WebView.cpp
Normal file
121
src/slic3r/GUI/Widgets/WebView.cpp
Normal file
|
@ -0,0 +1,121 @@
|
|||
#include "WebView.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
|
||||
#include <wx/webviewarchivehandler.h>
|
||||
#include <wx/webviewfshandler.h>
|
||||
#include <wx/msw/webview_edge.h>
|
||||
#include <wx/uri.h>
|
||||
|
||||
#ifdef __WIN32__
|
||||
#include "../WebView2.h"
|
||||
#include "wx/private/jsscriptwrapper.h"
|
||||
#endif
|
||||
|
||||
class FakeWebView : public wxWebView
|
||||
{
|
||||
virtual bool Create(wxWindow* parent, wxWindowID id, const wxString& url, const wxPoint& pos, const wxSize& size, long style, const wxString& name) override { return false; }
|
||||
virtual wxString GetCurrentTitle() const override { return wxString(); }
|
||||
virtual wxString GetCurrentURL() const override { return wxString(); }
|
||||
virtual bool IsBusy() const override { return false; }
|
||||
virtual bool IsEditable() const override { return false; }
|
||||
virtual void LoadURL(const wxString& url) override { }
|
||||
virtual void Print() override { }
|
||||
virtual void RegisterHandler(wxSharedPtr<wxWebViewHandler> handler) override { }
|
||||
virtual void Reload(wxWebViewReloadFlags flags = wxWEBVIEW_RELOAD_DEFAULT) override { }
|
||||
virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const override { return false; }
|
||||
virtual void SetEditable(bool enable = true) override { }
|
||||
virtual void Stop() override { }
|
||||
virtual bool CanGoBack() const override { return false; }
|
||||
virtual bool CanGoForward() const override { return false; }
|
||||
virtual void GoBack() override { }
|
||||
virtual void GoForward() override { }
|
||||
virtual void ClearHistory() override { }
|
||||
virtual void EnableHistory(bool enable = true) override { }
|
||||
virtual wxVector<wxSharedPtr<wxWebViewHistoryItem>> GetBackwardHistory() override { return {}; }
|
||||
virtual wxVector<wxSharedPtr<wxWebViewHistoryItem>> GetForwardHistory() override { return {}; }
|
||||
virtual void LoadHistoryItem(wxSharedPtr<wxWebViewHistoryItem> item) override { }
|
||||
virtual bool CanSetZoomType(wxWebViewZoomType type) const override { return false; }
|
||||
virtual float GetZoomFactor() const override { return 0.0f; }
|
||||
virtual wxWebViewZoomType GetZoomType() const override { return wxWebViewZoomType(); }
|
||||
virtual void SetZoomFactor(float zoom) override { }
|
||||
virtual void SetZoomType(wxWebViewZoomType zoomType) override { }
|
||||
virtual bool CanUndo() const override { return false; }
|
||||
virtual bool CanRedo() const override { return false; }
|
||||
virtual void Undo() override { }
|
||||
virtual void Redo() override { }
|
||||
virtual void* GetNativeBackend() const override { return nullptr; }
|
||||
virtual void DoSetPage(const wxString& html, const wxString& baseUrl) override { }
|
||||
};
|
||||
|
||||
wxWebView* WebView::CreateWebView(wxWindow * parent, wxString const & url)
|
||||
{
|
||||
#if wxUSE_WEBVIEW_EDGE
|
||||
// Check if a fixed version of edge is present in
|
||||
// $executable_path/edge_fixed and use it
|
||||
wxFileName edgeFixedDir(wxStandardPaths::Get().GetExecutablePath());
|
||||
edgeFixedDir.SetFullName("");
|
||||
edgeFixedDir.AppendDir("edge_fixed");
|
||||
if (edgeFixedDir.DirExists()) {
|
||||
wxWebViewEdge::MSWSetBrowserExecutableDir(edgeFixedDir.GetFullPath());
|
||||
wxLogMessage("Using fixed edge version");
|
||||
}
|
||||
#endif
|
||||
auto url2 = url;
|
||||
#ifdef __WIN32__
|
||||
url2.Replace("\\", "/");
|
||||
#endif
|
||||
if (!url2.empty()) { url2 = wxURI(url2).BuildURI(); }
|
||||
|
||||
auto webView = wxWebView::New();
|
||||
if (webView) {
|
||||
#ifdef __WIN32__
|
||||
webView->SetUserAgent(wxString::Format("BBL-Slicer/v%s", SLIC3R_VERSION));
|
||||
webView->Create(parent, wxID_ANY, url2, wxDefaultPosition, wxDefaultSize);
|
||||
//We register the wxfs:// protocol for testing purposes
|
||||
webView->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewArchiveHandler("bbl")));
|
||||
//And the memory: file system
|
||||
webView->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewFSHandler("memory")));
|
||||
#else
|
||||
// With WKWebView handlers need to be registered before creation
|
||||
webView->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewArchiveHandler("wxfs")));
|
||||
// And the memory: file system
|
||||
webView->RegisterHandler(wxSharedPtr<wxWebViewHandler>(new wxWebViewFSHandler("memory")));
|
||||
webView->Create(parent, wxID_ANY, url2, wxDefaultPosition, wxDefaultSize);
|
||||
webView->SetUserAgent(wxString::Format("BBL-Slicer/v%s", SLIC3R_VERSION));
|
||||
#endif
|
||||
#ifdef __WXMAC__
|
||||
Slic3r::GUI::wxGetApp().CallAfter([webView] {
|
||||
#endif
|
||||
if (!webView->AddScriptMessageHandler("wx"))
|
||||
wxLogError("Could not add script message handler");
|
||||
#ifdef __WXMAC__
|
||||
});
|
||||
#endif
|
||||
webView->EnableContextMenu(false);
|
||||
} else {
|
||||
webView = new FakeWebView;
|
||||
}
|
||||
return webView;
|
||||
}
|
||||
|
||||
bool WebView::RunScript(wxWebView *webView, wxString const &javascript)
|
||||
{
|
||||
if (Slic3r::GUI::wxGetApp().get_mode() == Slic3r::comDevelop)
|
||||
wxLogMessage("Running JavaScript:\n%s\n", javascript);
|
||||
|
||||
try {
|
||||
#ifdef __WIN32__
|
||||
ICoreWebView2 * webView2 = (ICoreWebView2 *) webView->GetNativeBackend();
|
||||
if (webView2 == nullptr)
|
||||
return false;
|
||||
int count = 0;
|
||||
wxJSScriptWrapper wrapJS(javascript, &count);
|
||||
return webView2->ExecuteScript(wrapJS.GetWrappedCode(), NULL) == 0;
|
||||
#else
|
||||
wxString result;
|
||||
return webView->RunScript(javascript, &result);
|
||||
#endif
|
||||
} catch (std::exception &e) {
|
||||
return false;
|
||||
}
|
||||
}
|
14
src/slic3r/GUI/Widgets/WebView.hpp
Normal file
14
src/slic3r/GUI/Widgets/WebView.hpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef slic3r_GUI_WebView_hpp_
|
||||
#define slic3r_GUI_WebView_hpp_
|
||||
|
||||
#include <wx/webview.h>
|
||||
|
||||
class WebView
|
||||
{
|
||||
public:
|
||||
static wxWebView *CreateWebView(wxWindow *parent, wxString const &url);
|
||||
|
||||
static bool RunScript(wxWebView * webView, wxString const & msg);
|
||||
};
|
||||
|
||||
#endif // !slic3r_GUI_WebView_hpp_
|
Loading…
Add table
Add a link
Reference in a new issue