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 Library 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 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library 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.
20 #include "gtkhscale.h"
21 #include "gtksignal.h"
22 #include "gdk/gdkkeysyms.h"
25 #define SCALE_CLASS(w) GTK_SCALE_CLASS (GTK_OBJECT (w)->klass)
26 #define RANGE_CLASS(w) GTK_RANGE_CLASS (GTK_OBJECT (w)->klass)
29 static void gtk_hscale_class_init (GtkHScaleClass *klass);
30 static void gtk_hscale_init (GtkHScale *hscale);
31 static void gtk_hscale_realize (GtkWidget *widget);
32 static void gtk_hscale_size_request (GtkWidget *widget,
33 GtkRequisition *requisition);
34 static void gtk_hscale_size_allocate (GtkWidget *widget,
35 GtkAllocation *allocation);
36 static void gtk_hscale_pos_trough (GtkHScale *hscale,
41 static void gtk_hscale_draw_slider (GtkRange *range);
42 static void gtk_hscale_draw_value (GtkScale *scale);
43 static gint gtk_hscale_trough_keys (GtkRange *range,
45 GtkScrollType *scroll,
49 gtk_hscale_get_type (void)
51 static guint hscale_type = 0;
55 GtkTypeInfo hscale_info =
59 sizeof (GtkHScaleClass),
60 (GtkClassInitFunc) gtk_hscale_class_init,
61 (GtkObjectInitFunc) gtk_hscale_init,
62 /* reversed_1 */ NULL,
63 /* reversed_2 */ NULL,
64 (GtkClassInitFunc) NULL,
67 hscale_type = gtk_type_unique (gtk_scale_get_type (), &hscale_info);
74 gtk_hscale_class_init (GtkHScaleClass *class)
76 GtkWidgetClass *widget_class;
77 GtkRangeClass *range_class;
78 GtkScaleClass *scale_class;
80 widget_class = (GtkWidgetClass*) class;
81 range_class = (GtkRangeClass*) class;
82 scale_class = (GtkScaleClass*) class;
84 widget_class->realize = gtk_hscale_realize;
85 widget_class->size_request = gtk_hscale_size_request;
86 widget_class->size_allocate = gtk_hscale_size_allocate;
88 range_class->slider_update = gtk_range_default_hslider_update;
89 range_class->trough_click = gtk_range_default_htrough_click;
90 range_class->motion = gtk_range_default_hmotion;
91 range_class->draw_slider = gtk_hscale_draw_slider;
92 range_class->trough_keys = gtk_hscale_trough_keys;
94 scale_class->draw_value = gtk_hscale_draw_value;
98 gtk_hscale_init (GtkHScale *hscale)
103 gtk_hscale_new (GtkAdjustment *adjustment)
107 hscale = gtk_type_new (gtk_hscale_get_type ());
110 adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
112 gtk_range_set_adjustment (GTK_RANGE (hscale), adjustment);
114 return GTK_WIDGET (hscale);
119 gtk_hscale_realize (GtkWidget *widget)
122 GdkWindowAttr attributes;
123 gint attributes_mask;
126 g_return_if_fail (widget != NULL);
127 g_return_if_fail (GTK_IS_HSCALE (widget));
129 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
130 range = GTK_RANGE (widget);
132 attributes.x = widget->allocation.x;
133 attributes.y = widget->allocation.y;
134 attributes.width = widget->allocation.width;
135 attributes.height = widget->allocation.height;
136 attributes.wclass = GDK_INPUT_OUTPUT;
137 attributes.window_type = GDK_WINDOW_CHILD;
138 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
139 attributes.visual = gtk_widget_get_visual (widget);
140 attributes.colormap = gtk_widget_get_colormap (widget);
142 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
143 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
145 gtk_hscale_pos_trough (GTK_HSCALE (widget), &x, &y, &w, &h);
148 attributes.width = w;
149 attributes.height = h;
150 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
151 GDK_BUTTON_RELEASE_MASK |
152 GDK_ENTER_NOTIFY_MASK |
153 GDK_LEAVE_NOTIFY_MASK);
155 range->trough = gdk_window_new (widget->window, &attributes, attributes_mask);
157 attributes.width = SCALE_CLASS (range)->slider_length;
158 attributes.height = RANGE_CLASS (range)->slider_width;
159 attributes.event_mask |= (GDK_BUTTON_MOTION_MASK |
160 GDK_POINTER_MOTION_HINT_MASK);
162 range->slider = gdk_window_new (range->trough, &attributes, attributes_mask);
164 widget->style = gtk_style_attach (widget->style, widget->window);
166 gdk_window_set_user_data (widget->window, widget);
167 gdk_window_set_user_data (range->trough, widget);
168 gdk_window_set_user_data (range->slider, widget);
170 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
171 gtk_style_set_background (widget->style, range->trough, GTK_STATE_ACTIVE);
172 gtk_style_set_background (widget->style, range->slider, GTK_STATE_NORMAL);
174 gtk_range_slider_update (GTK_RANGE (widget));
176 gdk_window_show (range->slider);
177 gdk_window_show (range->trough);
181 gtk_hscale_size_request (GtkWidget *widget,
182 GtkRequisition *requisition)
187 g_return_if_fail (widget != NULL);
188 g_return_if_fail (GTK_IS_HSCALE (widget));
189 g_return_if_fail (requisition != NULL);
191 scale = GTK_SCALE (widget);
193 requisition->width = (SCALE_CLASS (scale)->slider_length +
194 widget->style->klass->xthickness) * 2;
195 requisition->height = (RANGE_CLASS (scale)->slider_width +
196 widget->style->klass->ythickness * 2);
198 if (scale->draw_value)
200 value_width = gtk_scale_value_width (scale);
202 if ((scale->value_pos == GTK_POS_LEFT) ||
203 (scale->value_pos == GTK_POS_RIGHT))
205 requisition->width += value_width + SCALE_CLASS (scale)->value_spacing;
206 if (requisition->height < (widget->style->font->ascent + widget->style->font->descent))
207 requisition->height = widget->style->font->ascent + widget->style->font->descent;
209 else if ((scale->value_pos == GTK_POS_TOP) ||
210 (scale->value_pos == GTK_POS_BOTTOM))
212 if (requisition->width < value_width)
213 requisition->width = value_width;
214 requisition->height += widget->style->font->ascent + widget->style->font->descent;
220 gtk_hscale_size_allocate (GtkWidget *widget,
221 GtkAllocation *allocation)
228 g_return_if_fail (widget != NULL);
229 g_return_if_fail (GTK_IS_HSCALE (widget));
230 g_return_if_fail (allocation != NULL);
232 widget->allocation = *allocation;
233 if (GTK_WIDGET_REALIZED (widget))
235 range = GTK_RANGE (widget);
236 scale = GTK_SCALE (widget);
238 gdk_window_move_resize (widget->window,
239 allocation->x, allocation->y,
240 allocation->width, allocation->height);
242 gtk_hscale_pos_trough (GTK_HSCALE (widget), &x, &y, &width, &height);
244 gdk_window_move_resize (range->trough, x, y, width, height);
245 gtk_range_slider_update (GTK_RANGE (widget));
250 gtk_hscale_pos_trough (GtkHScale *hscale,
259 g_return_if_fail (hscale != NULL);
260 g_return_if_fail (GTK_IS_HSCALE (hscale));
261 g_return_if_fail ((x != NULL) && (y != NULL) && (w != NULL) && (h != NULL));
263 widget = GTK_WIDGET (hscale);
264 scale = GTK_SCALE (hscale);
266 *w = widget->allocation.width;
267 *h = (RANGE_CLASS (scale)->slider_width +
268 widget->style->klass->ythickness * 2);
270 if (scale->draw_value)
275 switch (scale->value_pos)
278 *x += gtk_scale_value_width (scale) + SCALE_CLASS (scale)->value_spacing;
279 *y = (widget->allocation.height - *h) / 2;
283 *w -= gtk_scale_value_width (scale) + SCALE_CLASS (scale)->value_spacing;
284 *y = (widget->allocation.height - *h) / 2;
287 *y = (widget->style->font->ascent + widget->style->font->descent +
288 (widget->allocation.height - widget->requisition.height) / 2);
291 *y = (widget->allocation.height - widget->requisition.height) / 2;
298 *y = (widget->allocation.height - *h) / 2;
305 gtk_hscale_draw_slider (GtkRange *range)
307 GtkStateType state_type;
310 g_return_if_fail (range != NULL);
311 g_return_if_fail (GTK_IS_HSCALE (range));
315 if ((range->in_child == RANGE_CLASS (range)->slider) ||
316 (range->click_child == RANGE_CLASS (range)->slider))
317 state_type = GTK_STATE_PRELIGHT;
319 state_type = GTK_STATE_NORMAL;
321 gtk_style_set_background (GTK_WIDGET (range)->style, range->slider, state_type);
322 gdk_window_clear (range->slider);
324 gdk_window_get_size (range->slider, &width, &height);
325 gtk_draw_vline (GTK_WIDGET (range)->style, range->slider,
326 state_type, 1, height - 2, width / 2);
328 gtk_draw_shadow (GTK_WIDGET (range)->style, range->slider,
329 state_type, GTK_SHADOW_OUT,
335 gtk_hscale_draw_value (GtkScale *scale)
337 GtkStateType state_type;
343 g_return_if_fail (scale != NULL);
344 g_return_if_fail (GTK_IS_HSCALE (scale));
346 if (scale->draw_value)
348 gdk_window_get_size (GTK_WIDGET (scale)->window, &width, &height);
349 gdk_window_clear_area (GTK_WIDGET (scale)->window, 1, 1, width - 2, height - 2);
351 sprintf (buffer, "%0.*f", GTK_RANGE (scale)->digits, GTK_RANGE (scale)->adjustment->value);
352 text_width = gdk_string_measure (GTK_WIDGET (scale)->style->font, buffer);
354 switch (scale->value_pos)
357 gdk_window_get_position (GTK_RANGE (scale)->trough, &x, &y);
358 gdk_window_get_size (GTK_RANGE (scale)->trough, &width, &height);
360 x -= SCALE_CLASS (scale)->value_spacing + text_width;
362 (GTK_WIDGET (scale)->style->font->ascent +
363 GTK_WIDGET (scale)->style->font->descent)) / 2 +
364 GTK_WIDGET (scale)->style->font->ascent);
367 gdk_window_get_position (GTK_RANGE (scale)->trough, &x, &y);
368 gdk_window_get_size (GTK_RANGE (scale)->trough, &width, &height);
370 x += width + SCALE_CLASS (scale)->value_spacing;
372 (GTK_WIDGET (scale)->style->font->ascent +
373 GTK_WIDGET (scale)->style->font->descent)) / 2 +
374 GTK_WIDGET (scale)->style->font->ascent);
377 gdk_window_get_position (GTK_RANGE (scale)->slider, &x, NULL);
378 gdk_window_get_position (GTK_RANGE (scale)->trough, NULL, &y);
379 gdk_window_get_size (GTK_RANGE (scale)->slider, &width, NULL);
380 gdk_window_get_size (GTK_RANGE (scale)->trough, NULL, &height);
382 x += (width - text_width) / 2;
383 y -= GTK_WIDGET (scale)->style->font->descent;
386 gdk_window_get_position (GTK_RANGE (scale)->slider, &x, NULL);
387 gdk_window_get_position (GTK_RANGE (scale)->trough, NULL, &y);
388 gdk_window_get_size (GTK_RANGE (scale)->slider, &width, NULL);
389 gdk_window_get_size (GTK_RANGE (scale)->trough, NULL, &height);
391 x += (width - text_width) / 2;
392 y += height + GTK_WIDGET (scale)->style->font->ascent;
396 state_type = GTK_STATE_NORMAL;
397 if (!GTK_WIDGET_IS_SENSITIVE (scale))
398 state_type = GTK_STATE_INSENSITIVE;
400 gtk_draw_string (GTK_WIDGET (scale)->style,
401 GTK_WIDGET (scale)->window,
402 state_type, x, y, buffer);
407 gtk_hscale_trough_keys(GtkRange *range,
409 GtkScrollType *scroll,
412 gint return_val = FALSE;
417 if (key->state & GDK_CONTROL_MASK)
418 *scroll = GTK_SCROLL_PAGE_BACKWARD;
420 *scroll = GTK_SCROLL_STEP_BACKWARD;
424 if (key->state & GDK_CONTROL_MASK)
425 *scroll = GTK_SCROLL_PAGE_FORWARD;
427 *scroll = GTK_SCROLL_STEP_FORWARD;
431 *pos = GTK_TROUGH_START;
435 *pos = GTK_TROUGH_END;