1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimpbrushfactoryview.c
5  * Copyright (C) 2001 Michael Natterer <mitch@gimp.org>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include <gegl.h>
24 #include <gtk/gtk.h>
25 
26 #include "libgimpwidgets/gimpwidgets.h"
27 
28 #include "widgets-types.h"
29 
30 #include "core/gimpcontainer.h"
31 #include "core/gimpcontext.h"
32 #include "core/gimpbrush.h"
33 #include "core/gimpbrushgenerated.h"
34 #include "core/gimpdatafactory.h"
35 
36 #include "gimpbrushfactoryview.h"
37 #include "gimpcontainerview.h"
38 #include "gimpeditor.h"
39 #include "gimpmenufactory.h"
40 #include "gimpspinscale.h"
41 #include "gimpviewrenderer.h"
42 
43 #include "gimp-intl.h"
44 
45 
46 static void   gimp_brush_factory_view_dispose         (GObject              *object);
47 
48 static void   gimp_brush_factory_view_select_item     (GimpContainerEditor  *editor,
49                                                        GimpViewable         *viewable);
50 
51 static void   gimp_brush_factory_view_spacing_changed (GimpBrush            *brush,
52                                                        GimpBrushFactoryView *view);
53 static void   gimp_brush_factory_view_spacing_update  (GtkAdjustment        *adjustment,
54                                                        GimpBrushFactoryView *view);
55 
56 
G_DEFINE_TYPE(GimpBrushFactoryView,gimp_brush_factory_view,GIMP_TYPE_DATA_FACTORY_VIEW)57 G_DEFINE_TYPE (GimpBrushFactoryView, gimp_brush_factory_view,
58                GIMP_TYPE_DATA_FACTORY_VIEW)
59 
60 #define parent_class gimp_brush_factory_view_parent_class
61 
62 
63 static void
64 gimp_brush_factory_view_class_init (GimpBrushFactoryViewClass *klass)
65 {
66   GObjectClass             *object_class = G_OBJECT_CLASS (klass);
67   GimpContainerEditorClass *editor_class = GIMP_CONTAINER_EDITOR_CLASS (klass);
68 
69   object_class->dispose     = gimp_brush_factory_view_dispose;
70 
71   editor_class->select_item = gimp_brush_factory_view_select_item;
72 }
73 
74 static void
gimp_brush_factory_view_init(GimpBrushFactoryView * view)75 gimp_brush_factory_view_init (GimpBrushFactoryView *view)
76 {
77   view->spacing_adjustment =
78     GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 1.0, 5000.0,
79                                         1.0, 10.0, 0.0));
80 
81   view->spacing_scale = gimp_spin_scale_new (view->spacing_adjustment,
82                                              _("Spacing"), 1);
83   gimp_spin_scale_set_scale_limits (GIMP_SPIN_SCALE (view->spacing_scale),
84                                    1.0, 200.0);
85   gimp_help_set_help_data (view->spacing_scale,
86                            _("Percentage of width of brush"),
87                            NULL);
88 
89   g_signal_connect (view->spacing_adjustment, "value-changed",
90                     G_CALLBACK (gimp_brush_factory_view_spacing_update),
91                     view);
92 }
93 
94 static void
gimp_brush_factory_view_dispose(GObject * object)95 gimp_brush_factory_view_dispose (GObject *object)
96 {
97   GimpBrushFactoryView *view   = GIMP_BRUSH_FACTORY_VIEW (object);
98   GimpContainerEditor  *editor = GIMP_CONTAINER_EDITOR (object);
99 
100   if (view->spacing_changed_handler_id)
101     {
102       GimpDataFactory *factory;
103       GimpContainer   *container;
104 
105       factory   = gimp_data_factory_view_get_data_factory (GIMP_DATA_FACTORY_VIEW (editor));
106       container = gimp_data_factory_get_container (factory);
107 
108       gimp_container_remove_handler (container,
109                                      view->spacing_changed_handler_id);
110 
111       view->spacing_changed_handler_id = 0;
112     }
113 
114   G_OBJECT_CLASS (parent_class)->dispose (object);
115 }
116 
117 GtkWidget *
gimp_brush_factory_view_new(GimpViewType view_type,GimpDataFactory * factory,GimpContext * context,gboolean change_brush_spacing,gint view_size,gint view_border_width,GimpMenuFactory * menu_factory)118 gimp_brush_factory_view_new (GimpViewType     view_type,
119                              GimpDataFactory *factory,
120                              GimpContext     *context,
121                              gboolean         change_brush_spacing,
122                              gint             view_size,
123                              gint             view_border_width,
124                              GimpMenuFactory *menu_factory)
125 {
126   GimpBrushFactoryView *factory_view;
127   GimpContainerEditor  *editor;
128 
129   g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
130   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
131   g_return_val_if_fail (view_size > 0 &&
132                         view_size <= GIMP_VIEWABLE_MAX_PREVIEW_SIZE, NULL);
133   g_return_val_if_fail (view_border_width >= 0 &&
134                         view_border_width <= GIMP_VIEW_MAX_BORDER_WIDTH,
135                         NULL);
136   g_return_val_if_fail (menu_factory == NULL ||
137                         GIMP_IS_MENU_FACTORY (menu_factory), NULL);
138 
139   factory_view = g_object_new (GIMP_TYPE_BRUSH_FACTORY_VIEW,
140                                "view-type",         view_type,
141                                "data-factory",      factory,
142                                "context",           context,
143                                "view-size",         view_size,
144                                "view-border-width", view_border_width,
145                                "menu-factory",      menu_factory,
146                                "menu-identifier",   "<Brushes>",
147                                "ui-path",           "/brushes-popup",
148                                "action-group",      "brushes",
149                                NULL);
150 
151   factory_view->change_brush_spacing = change_brush_spacing;
152 
153   editor = GIMP_CONTAINER_EDITOR (factory_view);
154 
155   gimp_editor_add_action_button (GIMP_EDITOR (editor->view),
156                                  "brushes", "brushes-open-as-image",
157                                  NULL);
158 
159   gtk_box_pack_end (GTK_BOX (editor->view), factory_view->spacing_scale,
160                     FALSE, FALSE, 0);
161   gtk_widget_show (factory_view->spacing_scale);
162 
163   factory_view->spacing_changed_handler_id =
164     gimp_container_add_handler (gimp_data_factory_get_container (factory), "spacing-changed",
165                                 G_CALLBACK (gimp_brush_factory_view_spacing_changed),
166                                 factory_view);
167 
168   return GTK_WIDGET (factory_view);
169 }
170 
171 static void
gimp_brush_factory_view_select_item(GimpContainerEditor * editor,GimpViewable * viewable)172 gimp_brush_factory_view_select_item (GimpContainerEditor *editor,
173                                      GimpViewable        *viewable)
174 {
175   GimpBrushFactoryView *view = GIMP_BRUSH_FACTORY_VIEW (editor);
176   GimpContainer        *container;
177   gboolean              spacing_sensitive = FALSE;
178 
179   if (GIMP_CONTAINER_EDITOR_CLASS (parent_class)->select_item)
180     GIMP_CONTAINER_EDITOR_CLASS (parent_class)->select_item (editor, viewable);
181 
182   container = gimp_container_view_get_container (editor->view);
183 
184   if (viewable && gimp_container_have (container, GIMP_OBJECT (viewable)))
185     {
186       GimpBrush *brush = GIMP_BRUSH (viewable);
187 
188       spacing_sensitive = TRUE;
189 
190       g_signal_handlers_block_by_func (view->spacing_adjustment,
191                                        gimp_brush_factory_view_spacing_update,
192                                        view);
193 
194       gtk_adjustment_set_value (view->spacing_adjustment,
195                                 gimp_brush_get_spacing (brush));
196 
197       g_signal_handlers_unblock_by_func (view->spacing_adjustment,
198                                          gimp_brush_factory_view_spacing_update,
199                                          view);
200     }
201 
202   gtk_widget_set_sensitive (view->spacing_scale, spacing_sensitive);
203 }
204 
205 static void
gimp_brush_factory_view_spacing_changed(GimpBrush * brush,GimpBrushFactoryView * view)206 gimp_brush_factory_view_spacing_changed (GimpBrush            *brush,
207                                          GimpBrushFactoryView *view)
208 {
209   GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (view);
210   GimpContext         *context;
211 
212   context = gimp_container_view_get_context (editor->view);
213 
214   if (brush == gimp_context_get_brush (context))
215     {
216       g_signal_handlers_block_by_func (view->spacing_adjustment,
217                                        gimp_brush_factory_view_spacing_update,
218                                        view);
219 
220       gtk_adjustment_set_value (view->spacing_adjustment,
221                                 gimp_brush_get_spacing (brush));
222 
223       g_signal_handlers_unblock_by_func (view->spacing_adjustment,
224                                          gimp_brush_factory_view_spacing_update,
225                                          view);
226     }
227 }
228 
229 static void
gimp_brush_factory_view_spacing_update(GtkAdjustment * adjustment,GimpBrushFactoryView * view)230 gimp_brush_factory_view_spacing_update (GtkAdjustment        *adjustment,
231                                         GimpBrushFactoryView *view)
232 {
233   GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (view);
234   GimpContext         *context;
235   GimpBrush           *brush;
236 
237   context = gimp_container_view_get_context (editor->view);
238 
239   brush = gimp_context_get_brush (context);
240 
241   if (brush && view->change_brush_spacing)
242     {
243       g_signal_handlers_block_by_func (brush,
244                                        gimp_brush_factory_view_spacing_changed,
245                                        view);
246 
247       gimp_brush_set_spacing (brush, gtk_adjustment_get_value (adjustment));
248 
249       g_signal_handlers_unblock_by_func (brush,
250                                          gimp_brush_factory_view_spacing_changed,
251                                          view);
252     }
253 }
254