1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
28 #include "gtkvscale.h"
29 #include "gtksignal.h"
30 #include "gdk/gdkkeysyms.h"
34 #define SCALE_CLASS(w) GTK_SCALE_GET_CLASS (w)
35 #define RANGE_CLASS(w) GTK_RANGE_GET_CLASS (w)
42 static void gtk_vscale_class_init (GtkVScaleClass *klass);
43 static void gtk_vscale_init (GtkVScale *vscale);
44 static void gtk_vscale_set_property (GObject *object,
48 static void gtk_vscale_get_property (GObject *object,
52 static void gtk_vscale_realize (GtkWidget *widget);
53 static void gtk_vscale_size_request (GtkWidget *widget,
54 GtkRequisition *requisition);
55 static void gtk_vscale_size_allocate (GtkWidget *widget,
56 GtkAllocation *allocation);
57 static void gtk_vscale_pos_trough (GtkVScale *vscale,
62 static void gtk_vscale_pos_background (GtkVScale *vscale,
67 static void gtk_vscale_draw_slider (GtkRange *range);
68 static void gtk_vscale_draw_value (GtkScale *scale);
69 static gboolean gtk_vscale_trough_keys (GtkRange *range,
71 GtkScrollType *scroll,
73 static void gtk_vscale_clear_background (GtkRange *range);
76 gtk_vscale_get_type (void)
78 static GtkType vscale_type = 0;
82 static const GtkTypeInfo vscale_info =
86 sizeof (GtkVScaleClass),
87 (GtkClassInitFunc) gtk_vscale_class_init,
88 (GtkObjectInitFunc) gtk_vscale_init,
89 /* reserved_1 */ NULL,
90 /* reserved_2 */ NULL,
91 (GtkClassInitFunc) NULL,
94 vscale_type = gtk_type_unique (GTK_TYPE_SCALE, &vscale_info);
101 gtk_vscale_class_init (GtkVScaleClass *class)
103 GtkObjectClass *object_class;
104 GObjectClass *gobject_class;
105 GtkWidgetClass *widget_class;
106 GtkRangeClass *range_class;
107 GtkScaleClass *scale_class;
109 object_class = (GtkObjectClass*) class;
110 gobject_class = G_OBJECT_CLASS (class);
111 widget_class = (GtkWidgetClass*) class;
112 range_class = (GtkRangeClass*) class;
113 scale_class = (GtkScaleClass*) class;
115 gobject_class->set_property = gtk_vscale_set_property;
116 gobject_class->get_property = gtk_vscale_get_property;
118 widget_class->realize = gtk_vscale_realize;
119 widget_class->size_request = gtk_vscale_size_request;
120 widget_class->size_allocate = gtk_vscale_size_allocate;
122 range_class->slider_update = _gtk_range_default_vslider_update;
123 range_class->trough_click = _gtk_range_default_vtrough_click;
124 range_class->motion = _gtk_range_default_vmotion;
125 range_class->draw_slider = gtk_vscale_draw_slider;
126 range_class->trough_keys = gtk_vscale_trough_keys;
127 range_class->clear_background = gtk_vscale_clear_background;
129 scale_class->draw_value = gtk_vscale_draw_value;
131 g_object_class_install_property (gobject_class,
133 g_param_spec_object ("adjustment",
135 _("The GtkAdjustment that determines the values to use for this VScale."),
141 gtk_vscale_set_property (GObject *object,
148 vscale = GTK_VSCALE (object);
152 case PROP_ADJUSTMENT:
153 gtk_range_set_adjustment (GTK_RANGE (vscale), g_value_get_object (value));
156 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
162 gtk_vscale_get_property (GObject *object,
169 vscale = GTK_VSCALE (object);
173 case PROP_ADJUSTMENT:
174 g_value_set_object (value,
175 G_OBJECT (gtk_range_get_adjustment (GTK_RANGE (vscale))));
178 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
184 gtk_vscale_init (GtkVScale *vscale)
186 GTK_WIDGET_SET_FLAGS (vscale, GTK_NO_WINDOW);
190 gtk_vscale_new (GtkAdjustment *adjustment)
194 vscale = gtk_widget_new (GTK_TYPE_VSCALE,
195 "adjustment", adjustment,
203 gtk_vscale_realize (GtkWidget *widget)
206 GdkWindowAttr attributes;
207 gint attributes_mask;
210 g_return_if_fail (widget != NULL);
211 g_return_if_fail (GTK_IS_VSCALE (widget));
213 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
214 range = GTK_RANGE (widget);
216 widget->window = gtk_widget_get_parent_window (widget);
217 gdk_window_ref (widget->window);
219 gtk_vscale_pos_trough (GTK_VSCALE (widget), &x, &y, &w, &h);
223 attributes.width = w;
224 attributes.height = h;
225 attributes.wclass = GDK_INPUT_OUTPUT;
226 attributes.window_type = GDK_WINDOW_CHILD;
228 attributes.event_mask = gtk_widget_get_events (widget) |
230 GDK_BUTTON_PRESS_MASK |
231 GDK_BUTTON_RELEASE_MASK |
232 GDK_ENTER_NOTIFY_MASK |
233 GDK_LEAVE_NOTIFY_MASK);
234 attributes.visual = gtk_widget_get_visual (widget);
235 attributes.colormap = gtk_widget_get_colormap (widget);
237 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
239 range->trough = gdk_window_new (widget->window, &attributes, attributes_mask);
241 attributes.width = RANGE_CLASS (range)->slider_width;
242 attributes.height = SCALE_CLASS (range)->slider_length;
243 attributes.event_mask |= (GDK_BUTTON_MOTION_MASK |
244 GDK_POINTER_MOTION_HINT_MASK);
246 range->slider = gdk_window_new (range->trough, &attributes, attributes_mask);
248 widget->style = gtk_style_attach (widget->style, widget->window);
250 gdk_window_set_user_data (range->trough, widget);
251 gdk_window_set_user_data (range->slider, widget);
253 gtk_style_set_background (widget->style, range->trough, GTK_STATE_ACTIVE);
254 gtk_style_set_background (widget->style, range->slider, GTK_STATE_NORMAL);
256 _gtk_range_slider_update (GTK_RANGE (widget));
258 gdk_window_show (range->slider);
262 gtk_vscale_clear_background (GtkRange *range)
266 gint x, y, width, height;
268 g_return_if_fail (range != NULL);
269 g_return_if_fail (GTK_IS_SCALE (range));
271 widget = GTK_WIDGET (range);
272 scale = GTK_SCALE (range);
274 gtk_vscale_pos_background (GTK_VSCALE (widget), &x, &y, &width, &height);
276 gtk_widget_queue_clear_area (GTK_WIDGET (range),
277 x, y, width, height);
281 gtk_vscale_size_request (GtkWidget *widget,
282 GtkRequisition *requisition)
285 gint value_width, value_height;
287 g_return_if_fail (widget != NULL);
288 g_return_if_fail (GTK_IS_VSCALE (widget));
289 g_return_if_fail (requisition != NULL);
291 scale = GTK_SCALE (widget);
293 requisition->width = (RANGE_CLASS (scale)->slider_width +
294 widget->style->ythickness * 2);
295 requisition->height = (SCALE_CLASS (scale)->slider_length +
296 widget->style->xthickness) * 2;
298 if (scale->draw_value)
300 gtk_scale_get_value_size (scale, &value_width, &value_height);
302 if ((scale->value_pos == GTK_POS_LEFT) ||
303 (scale->value_pos == GTK_POS_RIGHT))
305 requisition->width += value_width + SCALE_CLASS (scale)->value_spacing;
306 if (requisition->height < (value_height))
307 requisition->height = value_height;
309 else if ((scale->value_pos == GTK_POS_TOP) ||
310 (scale->value_pos == GTK_POS_BOTTOM))
312 if (requisition->width < value_width)
313 requisition->width = value_width;
314 requisition->height += value_height;
320 gtk_vscale_size_allocate (GtkWidget *widget,
321 GtkAllocation *allocation)
328 g_return_if_fail (widget != NULL);
329 g_return_if_fail (GTK_IS_VSCALE (widget));
330 g_return_if_fail (allocation != NULL);
332 widget->allocation = *allocation;
333 if (GTK_WIDGET_REALIZED (widget))
335 range = GTK_RANGE (widget);
336 scale = GTK_SCALE (widget);
338 gtk_vscale_pos_trough (GTK_VSCALE (widget), &x, &y, &width, &height);
340 gdk_window_move_resize (range->trough, x, y, width, height);
341 _gtk_range_slider_update (GTK_RANGE (widget));
346 gtk_vscale_pos_trough (GtkVScale *vscale,
354 gint value_width, value_height;
356 g_return_if_fail (vscale != NULL);
357 g_return_if_fail (GTK_IS_VSCALE (vscale));
358 g_return_if_fail ((x != NULL) && (y != NULL) && (w != NULL) && (h != NULL));
360 widget = GTK_WIDGET (vscale);
361 scale = GTK_SCALE (vscale);
363 *w = (RANGE_CLASS (scale)->slider_width +
364 widget->style->xthickness * 2);
365 *h = widget->allocation.height;
367 if (scale->draw_value)
372 gtk_scale_get_value_size (scale, &value_width, &value_height);
374 switch (scale->value_pos)
377 *x = (value_width + SCALE_CLASS (scale)->value_spacing +
378 (widget->allocation.width - widget->requisition.width) / 2);
381 *x = (widget->allocation.width - widget->requisition.width) / 2;
384 *x = (widget->allocation.width - *w) / 2;
389 *x = (widget->allocation.width - *w) / 2;
396 *x = (widget->allocation.width - *w) / 2;
402 *x += widget->allocation.x;
403 *y += widget->allocation.y;
407 gtk_vscale_pos_background (GtkVScale *vscale,
416 gint tx, ty, twidth, theight;
418 g_return_if_fail (vscale != NULL);
419 g_return_if_fail (GTK_IS_VSCALE (vscale));
420 g_return_if_fail ((x != NULL) && (y != NULL) && (w != NULL) && (h != NULL));
422 gtk_vscale_pos_trough (vscale, &tx, &ty, &twidth, &theight);
424 widget = GTK_WIDGET (vscale);
425 scale = GTK_SCALE (vscale);
427 *x = widget->allocation.x;
428 *y = widget->allocation.y;
429 *w = widget->allocation.width;
430 *h = widget->allocation.height;
432 switch (scale->value_pos)
454 gtk_vscale_draw_slider (GtkRange *range)
456 GtkStateType state_type;
458 g_return_if_fail (range != NULL);
459 g_return_if_fail (GTK_IS_VSCALE (range));
463 if ((range->in_child == RANGE_CLASS (range)->slider) ||
464 (range->click_child == RANGE_CLASS (range)->slider))
465 state_type = GTK_STATE_PRELIGHT;
467 state_type = GTK_STATE_NORMAL;
469 gtk_paint_slider (GTK_WIDGET (range)->style, range->slider, state_type,
471 NULL, GTK_WIDGET (range), "vscale",
473 GTK_ORIENTATION_VERTICAL);
478 gtk_vscale_draw_value (GtkScale *scale)
480 GtkStateType state_type;
486 g_return_if_fail (scale != NULL);
487 g_return_if_fail (GTK_IS_VSCALE (scale));
489 widget = GTK_WIDGET (scale);
491 if (scale->draw_value)
494 PangoRectangle logical_rect;
496 sprintf (buffer, "%0.*f", GTK_RANGE (scale)->digits, GTK_RANGE (scale)->adjustment->value);
498 layout = gtk_widget_create_pango_layout (widget, buffer);
499 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
501 switch (scale->value_pos)
504 gdk_window_get_position (GTK_RANGE (scale)->trough, &x, NULL);
505 gdk_window_get_position (GTK_RANGE (scale)->slider, NULL, &y);
506 gdk_window_get_size (GTK_RANGE (scale)->trough, &width, NULL);
507 gdk_window_get_size (GTK_RANGE (scale)->slider, NULL, &height);
509 x -= SCALE_CLASS (scale)->value_spacing + logical_rect.width;
510 y += widget->allocation.y + (height - logical_rect.height) / 2 +
511 PANGO_ASCENT (logical_rect);
514 gdk_window_get_position (GTK_RANGE (scale)->trough, &x, NULL);
515 gdk_window_get_position (GTK_RANGE (scale)->slider, NULL, &y);
516 gdk_window_get_size (GTK_RANGE (scale)->trough, &width, NULL);
517 gdk_window_get_size (GTK_RANGE (scale)->slider, NULL, &height);
519 x += width + SCALE_CLASS (scale)->value_spacing;
520 y += widget->allocation.y + (height - logical_rect.height) / 2 +
521 PANGO_ASCENT (logical_rect);
524 gdk_window_get_position (GTK_RANGE (scale)->trough, &x, &y);
525 gdk_window_get_size (GTK_RANGE (scale)->slider, &width, NULL);
526 gdk_window_get_size (GTK_RANGE (scale)->trough, NULL, &height);
528 x += (width - logical_rect.width) / 2;
529 y -= PANGO_DESCENT (logical_rect);
532 gdk_window_get_position (GTK_RANGE (scale)->trough, &x, &y);
533 gdk_window_get_size (GTK_RANGE (scale)->slider, &width, NULL);
534 gdk_window_get_size (GTK_RANGE (scale)->trough, NULL, &height);
536 x += (width - logical_rect.width) / 2;
537 y += height + PANGO_ASCENT (logical_rect);
541 state_type = GTK_STATE_NORMAL;
542 if (!GTK_WIDGET_IS_SENSITIVE (scale))
543 state_type = GTK_STATE_INSENSITIVE;
545 gtk_paint_layout (widget->style,
554 g_object_unref (G_OBJECT (layout));
559 gtk_vscale_trough_keys (GtkRange *range,
561 GtkScrollType *scroll,
564 gint return_val = FALSE;
569 if (key->state & GDK_CONTROL_MASK)
570 *scroll = GTK_SCROLL_PAGE_UP;
572 *scroll = GTK_SCROLL_STEP_UP;
576 if (key->state & GDK_CONTROL_MASK)
577 *scroll = GTK_SCROLL_PAGE_DOWN;
579 *scroll = GTK_SCROLL_STEP_DOWN;
583 *scroll = GTK_SCROLL_PAGE_BACKWARD;
587 *scroll = GTK_SCROLL_PAGE_FORWARD;
591 *pos = GTK_TROUGH_START;
595 *pos = GTK_TROUGH_END;