summaryrefslogtreecommitdiffstats
path: root/src/ui/widget/paint-selector.h
blob: 34ebc17bffb72713aaee624db370c4f7b7bfe70c (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
// SPDX-License-Identifier: GPL-2.0-or-later
/** @file
 * Generic paint selector widget
 *//*
 * Authors:
 *   Lauris
 *   Jon A. Cruz <jon@joncruz.org>
 *
 * Copyright (C) 2018 Authors
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */
#ifndef SEEN_SP_PAINT_SELECTOR_H
#define SEEN_SP_PAINT_SELECTOR_H

#include "color.h"
#include "fill-or-stroke.h"
#include <glib.h>
#include <gtkmm/box.h>
#include <optional>

#include "object/sp-gradient-spread.h"
#include "object/sp-gradient-units.h"
#include "gradient-selector-interface.h"
#include "ui/selected-color.h"
#include "ui/widget/gradient-selector.h"
#include "ui/widget/swatch-selector.h"

class SPGradient;
class SPLinearGradient;
class SPRadialGradient;
#ifdef WITH_MESH
class SPMeshGradient;
#endif
class SPDesktop;
class SPPattern;
class SPStyle;

namespace Gtk {
class Label;
class RadioButton;
class ToggleButton;
} // namespace Gtk

namespace Inkscape {
namespace UI {
namespace Widget {

class FillRuleRadioButton;
class StyleToggleButton;
class GradientEditor;
class PatternEditor;

/**
 * Generic paint selector widget.
 */
class PaintSelector : public Gtk::Box {
  public:
    enum Mode {
        MODE_EMPTY,
        MODE_MULTIPLE,
        MODE_NONE,
        MODE_SOLID_COLOR,
        MODE_GRADIENT_LINEAR,
        MODE_GRADIENT_RADIAL,
#ifdef WITH_MESH
        MODE_GRADIENT_MESH,
#endif
        MODE_PATTERN,
        MODE_HATCH,
        MODE_SWATCH,
        MODE_UNSET
    };

    enum FillRule { FILLRULE_NONZERO, FILLRULE_EVENODD };

  private:
    bool _update = false;

    Mode _mode;

    Gtk::Box *_style;
    StyleToggleButton *_none;
    StyleToggleButton *_solid;
    StyleToggleButton *_gradient;
    StyleToggleButton *_radial;
#ifdef WITH_MESH
    StyleToggleButton *_mesh;
#endif
    StyleToggleButton *_pattern;
    StyleToggleButton *_swatch;
    StyleToggleButton *_unset;

    Gtk::Box *_fillrulebox;
    FillRuleRadioButton *_evenodd;
    FillRuleRadioButton *_nonzero;

    Gtk::Box *_frame;

    Gtk::Box         *_selector_solid_color = nullptr;
    GradientEditor   *_selector_gradient = nullptr;
    Gtk::Box         *_selector_mesh = nullptr;
    SwatchSelector   *_selector_swatch = nullptr;
    PatternEditor* _selector_pattern = nullptr;

    Gtk::Label *_label;
    GtkWidget *_patternmenu = nullptr;
    bool _patternmenu_update = false;
#ifdef WITH_MESH
    GtkWidget *_meshmenu = nullptr;
    bool _meshmenu_update = false;
#endif

    Inkscape::UI::SelectedColor *_selected_color;
    bool _updating_color;

    void getColorAlpha(SPColor &color, gfloat &alpha) const;

    static gboolean isSeparator(GtkTreeModel *model, GtkTreeIter *iter, gpointer data);

  private:
    sigc::signal<void (FillRule)> _signal_fillrule_changed;
    sigc::signal<void ()> _signal_dragged;
    sigc::signal<void (Mode, bool)> _signal_mode_changed;
    sigc::signal<void ()> _signal_grabbed;
    sigc::signal<void ()> _signal_released;
    sigc::signal<void ()> _signal_changed;
    sigc::signal<void (SPStop*)> _signal_stop_selected;
    sigc::signal<void> _signal_edit_pattern;

    StyleToggleButton *style_button_add(gchar const *px, PaintSelector::Mode mode, gchar const *tip);
    void style_button_toggled(StyleToggleButton *tb);
    void fillrule_toggled(FillRuleRadioButton *tb);
    void onSelectedColorGrabbed();
    void onSelectedColorDragged();
    void onSelectedColorReleased();
    void onSelectedColorChanged();
    void set_mode_empty();
    void set_style_buttons(Gtk::ToggleButton *active);
    void set_mode_multiple();
    void set_mode_none();
    GradientSelectorInterface *getGradientFromData() const;
    void clear_frame();
    void set_mode_unset();
    void set_mode_color(PaintSelector::Mode mode);
    void set_mode_gradient(PaintSelector::Mode mode);
#ifdef WITH_MESH
    void set_mode_mesh(PaintSelector::Mode mode);
#endif
    void set_mode_pattern(PaintSelector::Mode mode);
    void set_mode_hatch(PaintSelector::Mode mode);
    void set_mode_swatch(PaintSelector::Mode mode);
    void set_mode_ex(Mode mode, bool switch_style);

    void gradient_grabbed();
    void gradient_dragged();
    void gradient_released();
    void gradient_changed(SPGradient *gr);

    static void mesh_change(GtkWidget *widget, PaintSelector *psel);
    static void mesh_destroy(GtkWidget *widget, PaintSelector *psel);

    static void pattern_change(GtkWidget *widget, PaintSelector *psel);
    static void pattern_destroy(GtkWidget *widget, PaintSelector *psel);

  public:
    PaintSelector(FillOrStroke kind);
    ~PaintSelector() override;

    inline decltype(_signal_fillrule_changed) signal_fillrule_changed() const { return _signal_fillrule_changed; }
    inline decltype(_signal_dragged) signal_dragged() const { return _signal_dragged; }
    inline decltype(_signal_mode_changed) signal_mode_changed() const { return _signal_mode_changed; }
    inline decltype(_signal_grabbed) signal_grabbed() const { return _signal_grabbed; }
    inline decltype(_signal_released) signal_released() const { return _signal_released; }
    inline decltype(_signal_changed) signal_changed() const { return _signal_changed; }
    inline decltype(_signal_stop_selected) signal_stop_selected() const { return _signal_stop_selected; }
    inline decltype(_signal_edit_pattern) signal_edit_pattern() const { return _signal_edit_pattern; }

    void setMode(Mode mode);
    static Mode getModeForStyle(SPStyle const &style, FillOrStroke kind);
    void setFillrule(FillRule fillrule);
    void setColorAlpha(SPColor const &color, float alpha);
    void setSwatch(SPGradient *vector);
    void setGradientLinear(SPGradient *vector, SPLinearGradient* gradient, SPStop* selected);
    void setGradientRadial(SPGradient *vector, SPRadialGradient* gradient, SPStop* selected);
#ifdef WITH_MESH
    void setGradientMesh(SPMeshGradient *array);
#endif
    void setGradientProperties(SPGradientUnits units, SPGradientSpread spread);
    void getGradientProperties(SPGradientUnits &units, SPGradientSpread &spread) const;

#ifdef WITH_MESH
    SPMeshGradient *getMeshGradient();
    void updateMeshList(SPMeshGradient *pat);
#endif

    void updatePatternList(SPPattern *pat);
    inline decltype(_mode) get_mode() const { return _mode; }

    // TODO move this elsewhere:
    void setFlatColor(SPDesktop *desktop, const gchar *color_property, const gchar *opacity_property);

    SPGradient *getGradientVector();
    void pushAttrsToGradient(SPGradient *gr) const;
    SPPattern *getPattern();
    std::optional<unsigned int> get_pattern_color();
    Geom::Affine get_pattern_transform();
    Geom::Point get_pattern_offset();
    Geom::Scale get_pattern_gap();
    Glib::ustring get_pattern_label();
    bool is_pattern_scale_uniform();
};

enum {
    COMBO_COL_LABEL = 0,
    COMBO_COL_STOCK = 1,
    COMBO_COL_PATTERN = 2,
    COMBO_COL_MESH = COMBO_COL_PATTERN,
    COMBO_COL_SEP = 3,
    COMBO_N_COLS = 4
};

} // namespace Widget
} // namespace UI
} // namespace Inkscape
#endif // SEEN_SP_PAINT_SELECTOR_H

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :