#ifndef slic3r_GUI_DoubleSlider_hpp_ #define slic3r_GUI_DoubleSlider_hpp_ #include "libslic3r/CustomGCode.hpp" #include "wxExtensions.hpp" #include #include #include #include #include #include #include class wxMenu; namespace Slic3r { namespace DoubleSlider { /* For exporting GCode in GCodeWriter is used XYZF_NUM(val) = PRECISION(val, 3) for XYZ values. * So, let use same value as a permissible error for layer height. */ static double epsilon() { return 0.0011;} // custom message the slider sends to its parent to notify a tick-change: wxDECLARE_EVENT(wxCUSTOMEVT_TICKSCHANGED, wxEvent); enum SelectedSlider { ssUndef, ssLower, ssHigher }; enum FocusedItem { fiNone, fiRevertIcon, fiOneLayerIcon, fiCogIcon, fiColorBand, fiActionIcon, fiTick }; enum ConflictType { ctNone, ctModeConflict, ctMeaninglessColorChange, ctMeaninglessToolChange, ctRedundant }; enum MouseAction { maNone, maAddMenu, // show "Add" context menu for NOTexist active tick maEditMenu, // show "Edit" context menu for exist active tick maCogIconMenu, // show context for "cog" icon maForceColorEdit, // force color editing from colored band maAddTick, // force tick adding maDeleteTick, // force tick deleting maCogIconClick, // LeftMouseClick on "cog" icon maOneLayerIconClick, // LeftMouseClick on "one_layer" icon maRevertIconClick, // LeftMouseClick on "revert" icon }; enum DrawMode { dmRegular, dmSlaPrint, dmSequentialFffPrint, }; using t_mode = CustomGCode::Mode; struct TickCode { bool operator<(const TickCode& other) const { return other.tick > this->tick; } bool operator>(const TickCode& other) const { return other.tick < this->tick; } int tick = 0; std::string gcode = ColorChangeCode; int extruder = 0; std::string color; }; class TickCodeInfo { std::string custom_gcode; std::string pause_print_msg; bool m_suppress_plus = false; bool m_suppress_minus = false; bool m_use_default_colors= false; int m_default_color_idx = 0; std::vector* m_colors {nullptr}; std::string get_color_for_tick(TickCode tick, const std::string& code, const int extruder); public: std::set ticks {}; t_mode mode = t_mode::Undef; bool empty() const { return ticks.empty(); } void set_pause_print_msg(const std::string& message) { pause_print_msg = message; } bool add_tick(const int tick, std::string& code, int extruder, double print_z); bool edit_tick(std::set::iterator it, double print_z); void switch_code(const std::string& code_from, const std::string& code_to); bool switch_code_for_tick(std::set::iterator it, const std::string& code_to, const int extruder); void erase_all_ticks_with_code(const std::string& gcode); bool has_tick_with_code(const std::string& gcode); ConflictType is_conflict_tick(const TickCode& tick, t_mode out_mode, int only_extruder, double print_z); // Get used extruders for tick. // Means all extruders(tools) which will be used during printing from current tick to the end std::set get_used_extruders_for_tick(int tick, int only_extruder, double print_z, t_mode force_mode = t_mode::Undef) const; void suppress_plus (bool suppress) { m_suppress_plus = suppress; } void suppress_minus(bool suppress) { m_suppress_minus = suppress; } bool suppressed_plus () { return m_suppress_plus; } bool suppressed_minus() { return m_suppress_minus; } void set_default_colors(bool default_colors_on) { m_use_default_colors = default_colors_on; } void set_extruder_colors(std::vector* extruder_colors) { m_colors = extruder_colors; } }; struct ExtrudersSequence { bool is_mm_intervals = true; double interval_by_mm = 3.0; int interval_by_layers = 10; std::vector extruders = { 0 }; bool operator==(const ExtrudersSequence& other) const { return (other.is_mm_intervals == this->is_mm_intervals ) && (other.interval_by_mm == this->interval_by_mm ) && (other.interval_by_layers == this->interval_by_layers ) && (other.extruders == this->extruders ) ; } bool operator!=(const ExtrudersSequence& other) const { return (other.is_mm_intervals != this->is_mm_intervals ) && (other.interval_by_mm != this->interval_by_mm ) && (other.interval_by_layers != this->interval_by_layers ) && (other.extruders != this->extruders ) ; } void add_extruder(size_t pos) { extruders.insert(extruders.begin() + pos+1, size_t(0)); } void delete_extruder(size_t pos) { if (extruders.size() == 1) return;// last item can't be deleted extruders.erase(extruders.begin() + pos); } }; class Control : public wxControl { public: Control( wxWindow *parent, wxWindowID id, int lowerValue, int higherValue, int minValue, int maxValue, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxSL_VERTICAL, const wxValidator& val = wxDefaultValidator, const wxString& name = wxEmptyString); ~Control() {} void msw_rescale(); int GetMinValue() const { return m_min_value; } int GetMaxValue() const { return m_max_value; } double GetMinValueD() { return m_values.empty() ? 0. : m_values[m_min_value]; } double GetMaxValueD() { return m_values.empty() ? 0. : m_values[m_max_value]; } int GetLowerValue() const { return m_lower_value; } int GetHigherValue() const { return m_higher_value; } int GetActiveValue() const; double GetLowerValueD() { return get_double_value(ssLower); } double GetHigherValueD() { return get_double_value(ssHigher); } wxSize DoGetBestSize() const override; wxSize get_min_size() const ; // Set low and high slider position. If the span is non-empty, disable the "one layer" mode. void SetLowerValue (const int lower_val); void SetHigherValue(const int higher_val); void SetSelectionSpan(const int lower_val, const int higher_val); void SetMaxValue(const int max_value); void SetKoefForLabels(const double koef) { m_label_koef = koef; } void SetSliderValues(const std::vector& values) { m_values = values; } void ChangeOneLayerLock(); CustomGCode::Info GetTicksValues() const; void SetTicksValues(const Slic3r::CustomGCode::Info &custom_gcode_per_print_z); void SetDrawMode(bool is_sla_print, bool is_sequential_print); void SetManipulationMode(t_mode mode) { m_mode = mode; } t_mode GetManipulationMode() const { return m_mode; } void SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder); void SetExtruderColors(const std::vector& extruder_colors); bool is_horizontal() const { return m_style == wxSL_HORIZONTAL; } bool is_one_layer() const { return m_is_one_layer; } bool is_lower_at_min() const { return m_lower_value == m_min_value; } bool is_higher_at_max() const { return m_higher_value == m_max_value; } bool is_full_span() const { return this->is_lower_at_min() && this->is_higher_at_max(); } void OnPaint(wxPaintEvent& ) { render();} void OnLeftDown(wxMouseEvent& event); void OnMotion(wxMouseEvent& event); void OnLeftUp(wxMouseEvent& event); void OnEnterWin(wxMouseEvent& event) { enter_window(event, true); } void OnLeaveWin(wxMouseEvent& event) { enter_window(event, false); } void UseDefaultColors(bool def_colors_on) { m_ticks.set_default_colors(def_colors_on); } void OnWheel(wxMouseEvent& event); void OnKeyDown(wxKeyEvent &event); void OnKeyUp(wxKeyEvent &event); void OnChar(wxKeyEvent &event); void OnRightDown(wxMouseEvent& event); void OnRightUp(wxMouseEvent& event); void add_code_as_tick(std::string code, int selected_extruder = -1); // add default action for tick, when press "+" void add_current_tick(bool call_from_keyboard = false); // delete current tick, when press "-" void delete_current_tick(); void edit_tick(int tick = -1); void switch_one_layer_mode(); void discard_all_thicks(); void move_current_thumb_to_pos(wxPoint pos); void edit_extruder_sequence(); void jump_to_print_z(); void show_add_context_menu(); void show_edit_context_menu(); void show_cog_icon_context_menu(); ExtrudersSequence m_extruders_sequence; protected: void render(); void draw_focus_rect(); void draw_action_icon(wxDC& dc, const wxPoint pt_beg, const wxPoint pt_end); void draw_scroll_line(wxDC& dc, const int lower_pos, const int higher_pos); void draw_thumb(wxDC& dc, const wxCoord& pos_coord, const SelectedSlider& selection); void draw_thumbs(wxDC& dc, const wxCoord& lower_pos, const wxCoord& higher_pos); void draw_ticks(wxDC& dc); void draw_colored_band(wxDC& dc); void draw_one_layer_icon(wxDC& dc); void draw_revert_icon(wxDC& dc); void draw_cog_icon(wxDC &dc); void draw_thumb_item(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection); void draw_info_line_with_icon(wxDC& dc, const wxPoint& pos, SelectedSlider selection); void draw_tick_on_mouse_position(wxDC &dc); void draw_tick_text(wxDC& dc, const wxPoint& pos, int tick, bool right_side = true) const; void draw_thumb_text(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) const; void update_thumb_rect(const wxCoord& begin_x, const wxCoord& begin_y, const SelectedSlider& selection); bool detect_selected_slider(const wxPoint& pt); void correct_lower_value(); void correct_higher_value(); void move_current_thumb(const bool condition); void enter_window(wxMouseEvent& event, const bool enter); private: bool is_point_in_rect(const wxPoint& pt, const wxRect& rect); int get_tick_near_point(const wxPoint& pt); double get_scroll_step(); wxString get_label(int tick) const; void get_lower_and_higher_position(int& lower_pos, int& higher_pos); int get_value_from_position(const wxCoord x, const wxCoord y); int get_value_from_position(const wxPoint pos) { return get_value_from_position(pos.x, pos.y); } wxCoord get_position_from_value(const int value); wxSize get_size(); void get_size(int *w, int *h); double get_double_value(const SelectedSlider& selection); wxString get_tooltip(int tick = -1); int get_edited_tick_for_position(wxPoint pos, const std::string& gcode = ColorChangeCode); std::string get_color_for_tool_change_tick(std::set::const_iterator it) const; std::string get_color_for_color_change_tick(std::set::const_iterator it) const; wxRect get_colored_band_rect(); // Get active extruders for tick. // Means one current extruder for not existing tick OR // 2 extruders - for existing tick (extruder before ToolChangeCode and extruder of current existing tick) // Use those values to disable selection of active extruders std::array get_active_extruders_for_tick(int tick) const; void post_ticks_changed_event(const std::string& gcode = ""); bool check_ticks_changed_event(const std::string& gcode); void append_change_extruder_menu_item (wxMenu*, bool switch_current_code = false); void append_add_color_change_menu_item(wxMenu*, bool switch_current_code = false); bool is_osx { false }; wxFont m_font; int m_min_value; int m_max_value; int m_lower_value; int m_higher_value; ScalableBitmap m_bmp_thumb_higher; ScalableBitmap m_bmp_thumb_lower; ScalableBitmap m_bmp_add_tick_on; ScalableBitmap m_bmp_add_tick_off; ScalableBitmap m_bmp_del_tick_on; ScalableBitmap m_bmp_del_tick_off; ScalableBitmap m_bmp_one_layer_lock_on; ScalableBitmap m_bmp_one_layer_lock_off; ScalableBitmap m_bmp_one_layer_unlock_on; ScalableBitmap m_bmp_one_layer_unlock_off; ScalableBitmap m_bmp_revert; ScalableBitmap m_bmp_cog; SelectedSlider m_selection; bool m_is_left_down = false; bool m_is_right_down = false; bool m_is_one_layer = false; bool m_is_focused = false; bool m_force_mode_apply = true; DrawMode m_draw_mode = dmRegular; t_mode m_mode = t_mode::SingleExtruder; int m_only_extruder = -1; MouseAction m_mouse = maNone; FocusedItem m_focus = fiNone; wxPoint m_moving_pos = wxDefaultPosition; wxRect m_rect_lower_thumb; wxRect m_rect_higher_thumb; wxRect m_rect_tick_action; wxRect m_rect_one_layer_icon; wxRect m_rect_revert_icon; wxRect m_rect_cog_icon; wxSize m_thumb_size; int m_tick_icon_dim; int m_lock_icon_dim; int m_revert_icon_dim; int m_cog_icon_dim; long m_style; float m_label_koef = 1.0; std::vector m_values; TickCodeInfo m_ticks; std::vector m_extruder_colors; // control's view variables wxCoord SLIDER_MARGIN; // margin around slider wxPen DARK_ORANGE_PEN; wxPen ORANGE_PEN; wxPen LIGHT_ORANGE_PEN; wxPen DARK_GREY_PEN; wxPen GREY_PEN; wxPen LIGHT_GREY_PEN; std::vector m_line_pens; std::vector m_segm_pens; }; } // DoubleSlider; } // Slic3r #endif // slic3r_GUI_DoubleSlider_hpp_