2 * Copyright 2008 Department of Mathematical Sciences, New Mexico State University
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * DEPARTMENT OF MATHEMATICAL SCIENCES OR NEW MEXICO STATE UNIVERSITY BE
18 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include <gtk/gtkdrawingarea.h>
26 #include <gtk/gtkspinbutton.h>
27 #include "grayswatch.h"
31 #define _(s) dgettext(GETTEXT_PACKAGE,s)
36 static GtkVBoxClass *parent_class = 0;
38 #define SWATCH_MIN_WIDTH 20
39 #define SWATCH_MIN_HEIGHT 100
56 static guint grayswatch_signals[VALUE_CHANGED + 1];
58 /**************************************************************************
62 **************************************************************************/
65 value_changed(GtkSpinButton *b, gpointer data)
68 Grayswatch *gs = GRAYSWATCH(data);
69 GtkWidget *sw = gs->swatch;
71 v = gtk_spin_button_get_value_as_int(b);
75 memset(gs->image, v, gs->image_size);
77 if (GTK_WIDGET_DRAWABLE(sw))
78 gdk_draw_gray_image(sw->window,
79 sw->style->fg_gc[GTK_WIDGET_STATE(sw)],
80 GTK_CONTAINER(gs)->border_width,
81 GTK_CONTAINER(gs)->border_width,
82 sw->allocation.width, sw->allocation.height,
83 GDK_RGB_DITHER_NONE, gs->image,
84 sw->allocation.width);
86 if (gs->signal_blocked == FALSE)
88 * Now we emit the value_changed signal for this widget.
90 g_signal_emit(G_OBJECT(data), grayswatch_signals[VALUE_CHANGED], 0, v);
93 /**************************************************************************
97 **************************************************************************/
100 grayswatch_configure(GtkWidget *widget, GdkEventConfigure *event,
103 Grayswatch *gs = GRAYSWATCH(data);
106 nbytes = gs->swatch->allocation.width *
107 gs->swatch->allocation.height;
108 if (nbytes > gs->image_size) {
109 if (gs->image_size == 0)
110 gs->image = (guchar *) g_malloc(nbytes);
112 gs->image = (guchar *) g_realloc(gs->image, nbytes);
113 gs->image_size = nbytes;
115 memset(gs->image, gs->gray, gs->image_size);
121 grayswatch_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data)
123 Grayswatch *gs = GRAYSWATCH(data);
125 if (gs->image_size > 0)
126 gdk_draw_gray_image(widget->window,
127 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
128 GTK_CONTAINER(gs)->border_width,
129 GTK_CONTAINER(gs)->border_width,
130 widget->allocation.width,
131 widget->allocation.height,
132 GDK_RGB_DITHER_NONE, gs->image,
133 widget->allocation.width);
139 grayswatch_get_property(GObject *obj, guint propid, GValue *val,
144 gs = GRAYSWATCH(obj);
146 if (propid == PROP_GRAYLEVEL)
147 g_value_set_uint(val, gs->gray);
151 grayswatch_set_property(GObject *obj, guint propid, const GValue *val,
157 gs = GRAYSWATCH(obj);
159 if (propid == PROP_GRAYLEVEL) {
160 gray = g_value_get_uint(val);
163 if (gray != gs->gray)
164 gtk_spin_button_set_value(GTK_SPIN_BUTTON(gs->value),
170 grayswatch_add(GtkContainer *container, GtkWidget *child)
173 * This is here as a placeholder as it seems the container doesn't
174 * work quite right without it for some reason.
179 grayswatch_remove(GtkContainer *container, GtkWidget *child)
182 * This is here as a placeholder as it seems the container doesn't
183 * work quite right without it for some reason.
188 grayswatch_foreach(GtkContainer *container, gboolean int_kids,
189 GtkCallback callback, gpointer callback_data)
191 Grayswatch *gs = GRAYSWATCH(container);
194 (*callback)(gs->swatch, callback_data);
195 (*callback)(gs->value, callback_data);
199 /**************************************************************************
201 * Class and object initialization routines.
203 **************************************************************************/
206 grayswatch_class_init(gpointer g_class, gpointer class_data)
208 GtkContainerClass *cc = GTK_CONTAINER_CLASS(g_class);
209 GObjectClass *oc = G_OBJECT_CLASS(g_class);
211 cc->forall = grayswatch_foreach;
212 cc->add = grayswatch_add;
213 cc->remove = grayswatch_remove;
215 oc->set_property = grayswatch_set_property;
216 oc->get_property = grayswatch_get_property;
218 g_object_class_install_property(oc, PROP_GRAYLEVEL,
219 g_param_spec_uint("grayLevel",
221 _("The gray level."),
225 grayswatch_signals[VALUE_CHANGED] =
226 g_signal_new("value-changed",
227 G_TYPE_FROM_CLASS(oc),
229 G_STRUCT_OFFSET(GrayswatchClass, value_changed),
231 g_cclosure_marshal_VOID__INT,
232 G_TYPE_NONE, 1, G_TYPE_INT);
234 parent_class = g_type_class_peek_parent(g_class);
238 grayswatch_init(GTypeInstance *obj, gpointer klass)
240 Grayswatch *gs = GRAYSWATCH(obj);
242 GTK_WIDGET_SET_FLAGS(obj, GTK_NO_WINDOW);
243 gtk_widget_set_redraw_on_allocate(GTK_WIDGET(obj), FALSE);
245 gs->swatch = gtk_drawing_area_new();
246 g_signal_connect(G_OBJECT(gs->swatch), "configure_event",
247 G_CALLBACK(grayswatch_configure), (gpointer) gs);
248 g_signal_connect(G_OBJECT(gs->swatch), "expose_event",
249 G_CALLBACK(grayswatch_expose), (gpointer) gs);
250 gtk_box_pack_start(GTK_BOX(obj), gs->swatch, TRUE, TRUE, 0);
251 gtk_widget_show(gs->swatch);
253 gs->value = gtk_spin_button_new_with_range(0.0, 255.0, 1.0);
254 g_signal_connect(G_OBJECT(gs->value), "value-changed",
255 G_CALLBACK(value_changed), (gpointer) gs);
257 gtk_box_pack_start(GTK_BOX(obj), gs->value, FALSE, FALSE, 0);
258 gtk_widget_show(gs->value);
265 /**************************************************************************
269 **************************************************************************/
271 static const GTypeInfo grayswatch_info = {
272 sizeof(GrayswatchClass),
275 grayswatch_class_init,
284 grayswatch_get_type(void)
286 static GType grayswatch_type = 0;
288 if (!grayswatch_type)
289 grayswatch_type = g_type_register_static(GTK_TYPE_VBOX,
291 &grayswatch_info, 0);
293 return grayswatch_type;
297 grayswatch_new(guint gray)
299 return gtk_widget_new(grayswatch_get_type(),
300 "grayLevel", gray, NULL);
304 grayswatch_set_gray(Grayswatch *gs, guint gray)
306 g_return_if_fail(gs != 0);
307 g_return_if_fail(IS_GRAYSWATCH(gs));
312 gtk_spin_button_set_value(GTK_SPIN_BUTTON(gs->value), gray);
316 grayswatch_get_gray(Grayswatch *gs)
318 g_return_val_if_fail(gs != 0, 256);
319 g_return_val_if_fail(IS_GRAYSWATCH(gs), 256);
325 grayswatch_block_signal(Grayswatch *gs, gboolean block)
327 g_return_if_fail(gs != 0);
328 g_return_if_fail(IS_GRAYSWATCH(gs));
330 gs->signal_blocked = block;