Welcome to mirror list, hosted at ThFree Co, Russian Federation.

DoubleSlider.hpp « GUI « slic3r « src - github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: bf8f54d6c9cedc7836b33293917785b7f772c2d8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
#ifndef slic3r_GUI_DoubleSlider_hpp_
#define slic3r_GUI_DoubleSlider_hpp_

#include "libslic3r/CustomGCode.hpp"
#include "wxExtensions.hpp"

#include <wx/wx.h>
#include <wx/window.h>
#include <wx/control.h>
#include <wx/dc.h>
#include <wx/slider.h>

#include <vector>
#include <set>

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<std::string>* m_colors {nullptr};

    std::string get_color_for_tick(TickCode tick, const std::string& code, const int extruder);

public:
    std::set<TickCode>  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<TickCode>::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<TickCode>::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<int>   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<std::string>* 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<size_t>  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<double>& 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<std::string>& 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<TickCode>::const_iterator it) const;
    std::string get_color_for_color_change_tick(std::set<TickCode>::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<int, 2> 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<double> m_values;
    TickCodeInfo        m_ticks;

    std::vector<std::string>    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<wxPen*> m_line_pens;
    std::vector<wxPen*> m_segm_pens;
};

} // DoubleSlider;

} // Slic3r



#endif // slic3r_GUI_DoubleSlider_hpp_