source: trunk/third/gtk/gtk/gtkhscale.c @ 15781

Revision 15781, 18.6 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15780, which included commits to RCS files with non-trunk default branches.
RevLine 
[14481]1/* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
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.
8 *
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.
13 *
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.
18 */
19
20/*
21 * Modified by the GTK+ Team and others 1997-1999.  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/.
25 */
26
27#include <stdio.h>
28#include "gtkhscale.h"
29#include "gtksignal.h"
30#include "gdk/gdkkeysyms.h"
31
32
33#define SCALE_CLASS(w)  GTK_SCALE_CLASS (GTK_OBJECT (w)->klass)
34#define RANGE_CLASS(w)  GTK_RANGE_CLASS (GTK_OBJECT (w)->klass)
35
36enum {
37  ARG_0,
38  ARG_ADJUSTMENT
39};
40
41static void gtk_hscale_class_init    (GtkHScaleClass *klass);
42static void gtk_hscale_init          (GtkHScale      *hscale);
43static void gtk_hscale_set_arg       (GtkObject      *object,
44                                      GtkArg         *arg,
45                                      guint           arg_id);
46static void gtk_hscale_get_arg       (GtkObject      *object,
47                                      GtkArg         *arg,
48                                      guint           arg_id);
49static void gtk_hscale_realize       (GtkWidget      *widget);
50static void gtk_hscale_size_request  (GtkWidget      *widget,
51                                      GtkRequisition *requisition);
52static void gtk_hscale_size_allocate (GtkWidget      *widget,
53                                      GtkAllocation  *allocation);
54static void gtk_hscale_pos_trough    (GtkHScale      *hscale,
55                                      gint           *x,
56                                      gint           *y,
57                                      gint           *w,
58                                      gint           *h);
59static void gtk_hscale_pos_background (GtkHScale     *hscale,
60                                       gint          *x,
61                                       gint          *y,
62                                       gint          *w,
63                                       gint          *h);
64static void gtk_hscale_draw_slider   (GtkRange       *range);
65static void gtk_hscale_draw_value    (GtkScale       *scale);
66static void gtk_hscale_draw          (GtkWidget      *widget,
67                                      GdkRectangle   *area);
68static gint gtk_hscale_trough_keys   (GtkRange *range,
69                                      GdkEventKey *key,
70                                      GtkScrollType *scroll,
71                                      GtkTroughType *pos);
72static void gtk_hscale_clear_background (GtkRange    *range);
73
74GtkType
75gtk_hscale_get_type (void)
76{
77  static GtkType hscale_type = 0;
78 
79  if (!hscale_type)
80    {
81      static const GtkTypeInfo hscale_info =
82      {
83        "GtkHScale",
84        sizeof (GtkHScale),
85        sizeof (GtkHScaleClass),
86        (GtkClassInitFunc) gtk_hscale_class_init,
87        (GtkObjectInitFunc) gtk_hscale_init,
88        /* reserved_1 */ NULL,
89        /* reserved_2 */ NULL,
90        (GtkClassInitFunc) NULL,
91      };
92     
93      hscale_type = gtk_type_unique (GTK_TYPE_SCALE, &hscale_info);
94    }
95 
96  return hscale_type;
97}
98
99static void
100gtk_hscale_class_init (GtkHScaleClass *class)
101{
102  GtkObjectClass *object_class;
103  GtkWidgetClass *widget_class;
104  GtkRangeClass *range_class;
105  GtkScaleClass *scale_class;
106 
107  object_class = (GtkObjectClass*) class;
108  widget_class = (GtkWidgetClass*) class;
109  range_class = (GtkRangeClass*) class;
110  scale_class = (GtkScaleClass*) class;
111 
112  gtk_object_add_arg_type ("GtkHScale::adjustment",
113                           GTK_TYPE_ADJUSTMENT,
114                           GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
115                           ARG_ADJUSTMENT);
116 
117  object_class->set_arg = gtk_hscale_set_arg;
118  object_class->get_arg = gtk_hscale_get_arg;
119 
120  widget_class->realize = gtk_hscale_realize;
121  widget_class->size_request = gtk_hscale_size_request;
122  widget_class->size_allocate = gtk_hscale_size_allocate;
123  widget_class->draw = gtk_hscale_draw;
124 
125  range_class->slider_update = gtk_range_default_hslider_update;
126  range_class->trough_click = gtk_range_default_htrough_click;
127  range_class->motion = gtk_range_default_hmotion;
128  range_class->draw_slider = gtk_hscale_draw_slider;
129  range_class->trough_keys = gtk_hscale_trough_keys;
130  range_class->clear_background = gtk_hscale_clear_background;
131 
132  scale_class->draw_value = gtk_hscale_draw_value;
133}
134
135static void
136gtk_hscale_set_arg (GtkObject          *object,
137                    GtkArg             *arg,
138                    guint               arg_id)
139{
140  GtkHScale *hscale;
141 
142  hscale = GTK_HSCALE (object);
143 
144  switch (arg_id)
145    {
146    case ARG_ADJUSTMENT:
147      gtk_range_set_adjustment (GTK_RANGE (hscale), GTK_VALUE_POINTER (*arg));
148      break;
149    default:
150      break;
151    }
152}
153
154static void
155gtk_hscale_get_arg (GtkObject          *object,
156                    GtkArg             *arg,
157                    guint               arg_id)
158{
159  GtkHScale *hscale;
160 
161  hscale = GTK_HSCALE (object);
162 
163  switch (arg_id)
164    {
165    case ARG_ADJUSTMENT:
166      GTK_VALUE_POINTER (*arg) = GTK_RANGE (hscale);
167      break;
168    default:
169      arg->type = GTK_TYPE_INVALID;
170      break;
171    }
172}
173
174static void
175gtk_hscale_init (GtkHScale *hscale)
176{
177  GTK_WIDGET_SET_FLAGS (hscale, GTK_NO_WINDOW);
178}
179
180GtkWidget*
181gtk_hscale_new (GtkAdjustment *adjustment)
182{
183  GtkWidget *hscale;
184 
185  hscale = gtk_widget_new (GTK_TYPE_HSCALE,
186                           "adjustment", adjustment,
187                           NULL);
188
189  return hscale;
190}
191
192
193static void
194gtk_hscale_realize (GtkWidget *widget)
195{
196  GtkRange *range;
197  GdkWindowAttr attributes;
198  gint attributes_mask;
199  gint x, y, w, h;
[15780]200  gint slider_width;
[14481]201 
202  g_return_if_fail (widget != NULL);
203  g_return_if_fail (GTK_IS_HSCALE (widget));
204 
205  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
206  range = GTK_RANGE (widget);
[15780]207
208  _gtk_range_get_props (range, &slider_width, NULL, NULL, NULL);
[14481]209 
210  widget->window = gtk_widget_get_parent_window (widget);
211  gdk_window_ref (widget->window);
212 
213  gtk_hscale_pos_trough (GTK_HSCALE (widget), &x, &y, &w, &h);
214
215  attributes.x = x;
216  attributes.y = y;
217  attributes.width = w;
218  attributes.height = h;
219  attributes.wclass = GDK_INPUT_OUTPUT;
220  attributes.window_type = GDK_WINDOW_CHILD;
221 
222  attributes.event_mask = gtk_widget_get_events (widget) |
223    (GDK_EXPOSURE_MASK |
224     GDK_BUTTON_PRESS_MASK |
225     GDK_BUTTON_RELEASE_MASK |
226     GDK_ENTER_NOTIFY_MASK |
227     GDK_LEAVE_NOTIFY_MASK);
228  attributes.visual = gtk_widget_get_visual (widget);
229  attributes.colormap = gtk_widget_get_colormap (widget);
230 
231  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
232 
233  range->trough = gdk_window_new (widget->window, &attributes, attributes_mask);
234 
235  attributes.width = SCALE_CLASS (range)->slider_length;
[15780]236  attributes.height = slider_width;
[14481]237  attributes.event_mask |= (GDK_BUTTON_MOTION_MASK |
238                            GDK_POINTER_MOTION_HINT_MASK);
239 
240  range->slider = gdk_window_new (range->trough, &attributes, attributes_mask);
241 
242  widget->style = gtk_style_attach (widget->style, widget->window);
243 
244  gdk_window_set_user_data (range->trough, widget);
245  gdk_window_set_user_data (range->slider, widget);
246 
247  gtk_style_set_background (widget->style, range->trough, GTK_STATE_ACTIVE);
248  gtk_style_set_background (widget->style, range->slider, GTK_STATE_NORMAL);
249 
250  gtk_range_slider_update (GTK_RANGE (widget));
251 
252  gdk_window_show (range->slider);
253}
254
255static void
256gtk_hscale_draw (GtkWidget    *widget,
257                 GdkRectangle *area)
258{
259  GtkRange *range;
260  GdkRectangle tmp_area;
261  GdkRectangle child_area;
262  gint x, y, width, height;
263 
264  g_return_if_fail (widget != NULL);
265  g_return_if_fail (GTK_IS_RANGE (widget));
266  g_return_if_fail (area != NULL);
267 
268  if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
269    {
270      range = GTK_RANGE (widget);
271     
272      gtk_hscale_pos_background (GTK_HSCALE (widget), &x, &y, &width, &height);
273     
274      tmp_area.x = x;
275      tmp_area.y = y;
276      tmp_area.width = width;
277      tmp_area.height = height;
278     
279      if (gdk_rectangle_intersect (area, &tmp_area, &child_area))
280        gtk_range_draw_background (range);
281     
282      gtk_hscale_pos_trough (GTK_HSCALE (widget), &x, &y, &width, &height);
283     
284      tmp_area.x = x;
285      tmp_area.y = y;
286      tmp_area.width = width;
287      tmp_area.height = height;
288     
289      if (gdk_rectangle_intersect (area, &tmp_area, &child_area))
290        {
291          gtk_range_draw_trough (range);
292          gtk_range_draw_slider (range);
293          gtk_range_draw_step_forw (range);
294          gtk_range_draw_step_back (range);
295        }
296    }
297}
298
299static void
300gtk_hscale_clear_background (GtkRange    *range)
301{
302  GtkWidget *widget;
303  gint x, y, width, height;
304 
305  g_return_if_fail (range != NULL);
306 
307  widget = GTK_WIDGET (range);
308 
309  gtk_hscale_pos_background (GTK_HSCALE (range), &x, &y, &width, &height);
310 
311  gtk_widget_queue_clear_area (GTK_WIDGET (range),
312                               x, y, width, height);
313}
314
315static void
316gtk_hscale_size_request (GtkWidget      *widget,
317                         GtkRequisition *requisition)
318{
319  GtkScale *scale;
320  gint value_width;
[15780]321  gint slider_width;
322  gint trough_border;
[14481]323 
324  g_return_if_fail (widget != NULL);
325  g_return_if_fail (GTK_IS_HSCALE (widget));
326  g_return_if_fail (requisition != NULL);
327 
328  scale = GTK_SCALE (widget);
[15780]329
330  _gtk_range_get_props (GTK_RANGE (scale),
331                        &slider_width, &trough_border, NULL, NULL);
[14481]332 
[15780]333  requisition->width = (SCALE_CLASS (scale)->slider_length + trough_border) * 2;
334  requisition->height = (slider_width + trough_border * 2);
[14481]335 
336  if (scale->draw_value)
337    {
338      value_width = gtk_scale_get_value_width (scale);
339     
340      if ((scale->value_pos == GTK_POS_LEFT) ||
341          (scale->value_pos == GTK_POS_RIGHT))
342        {
343          requisition->width += value_width + SCALE_CLASS (scale)->value_spacing;
344          if (requisition->height < (widget->style->font->ascent + widget->style->font->descent))
345            requisition->height = widget->style->font->ascent + widget->style->font->descent;
346        }
347      else if ((scale->value_pos == GTK_POS_TOP) ||
348               (scale->value_pos == GTK_POS_BOTTOM))
349        {
350          if (requisition->width < value_width)
351            requisition->width = value_width;
352          requisition->height += widget->style->font->ascent + widget->style->font->descent;
353        }
354    }
355}
356
357static void
358gtk_hscale_size_allocate (GtkWidget     *widget,
359                          GtkAllocation *allocation)
360{
361  GtkRange *range;
362  GtkScale *scale;
363  gint width, height;
364  gint x, y;
365 
366  g_return_if_fail (widget != NULL);
367  g_return_if_fail (GTK_IS_HSCALE (widget));
368  g_return_if_fail (allocation != NULL);
369 
370  widget->allocation = *allocation;
371  if (GTK_WIDGET_REALIZED (widget))
372    {
373      range = GTK_RANGE (widget);
374      scale = GTK_SCALE (widget);
375     
376      gtk_hscale_pos_trough (GTK_HSCALE (widget), &x, &y, &width, &height);
377     
378      gdk_window_move_resize (range->trough,
379                              x, y, width, height);
380      gtk_range_slider_update (GTK_RANGE (widget));
381    }
382}
383
384static void
385gtk_hscale_pos_trough (GtkHScale *hscale,
386                       gint      *x,
387                       gint      *y,
388                       gint      *w,
389                       gint      *h)
390{
391  GtkWidget *widget;
392  GtkScale *scale;
[15780]393  gint slider_width;
394  gint trough_border;
[14481]395 
396  g_return_if_fail (hscale != NULL);
397  g_return_if_fail (GTK_IS_HSCALE (hscale));
398  g_return_if_fail ((x != NULL) && (y != NULL) && (w != NULL) && (h != NULL));
399 
400  widget = GTK_WIDGET (hscale);
401  scale = GTK_SCALE (hscale);
[15780]402
403  _gtk_range_get_props (GTK_RANGE (scale),
404                        &slider_width, &trough_border, NULL, NULL);
405
[14481]406  *w = widget->allocation.width;
[15780]407  *h = (slider_width + trough_border * 2);
[14481]408 
409  if (scale->draw_value)
410    {
411      *x = 0;
412      *y = 0;
413     
414      switch (scale->value_pos)
415        {
416        case GTK_POS_LEFT:
417          *x += gtk_scale_get_value_width (scale) + SCALE_CLASS (scale)->value_spacing;
418          *y = (widget->allocation.height - *h) / 2;
419          *w -= *x;
420          break;
421        case GTK_POS_RIGHT:
422          *w -= gtk_scale_get_value_width (scale) + SCALE_CLASS (scale)->value_spacing;
423          *y = (widget->allocation.height - *h) / 2;
424          break;
425        case GTK_POS_TOP:
426          *y = (widget->style->font->ascent + widget->style->font->descent +
427                (widget->allocation.height - widget->requisition.height) / 2);
428          break;
429        case GTK_POS_BOTTOM:
430          *y = (widget->allocation.height - widget->requisition.height) / 2;
431          break;
432        }
433    }
434  else
435    {
436      *x = 0;
437      *y = (widget->allocation.height - *h) / 2;
438    }
439  *x += 1;
440  *w -= 2;
441 
442  *x += widget->allocation.x;
443  *y += widget->allocation.y;
444}
445
446static void
447gtk_hscale_pos_background (GtkHScale *hscale,
448                           gint      *x,
449                           gint      *y,
450                           gint      *w,
451                           gint      *h)
452{
453  GtkWidget *widget;
454  GtkScale *scale;
455 
456  gint tx, ty, twidth, theight;
457 
458  g_return_if_fail (hscale != NULL);
459  g_return_if_fail (GTK_IS_HSCALE (hscale));
460  g_return_if_fail ((x != NULL) && (y != NULL) && (w != NULL) && (h != NULL));
461 
462  gtk_hscale_pos_trough (hscale, &tx, &ty, &twidth, &theight);
463 
464  widget = GTK_WIDGET (hscale);
465  scale = GTK_SCALE (hscale);
466 
467  *x = widget->allocation.x;
468  *y = widget->allocation.y;
469  *w = widget->allocation.width;
470  *h = widget->allocation.height;
471 
472  switch (scale->value_pos)
473    {
474    case GTK_POS_LEFT:
475      *w -= twidth;
476      break;
477    case GTK_POS_RIGHT:
478      *x += twidth;
479      *w -= twidth;
480      break;
481    case GTK_POS_TOP:
482      *h -= theight;
483      break;
484    case GTK_POS_BOTTOM:
485      *y += theight;
486      *h -= theight;
487      break;
488    }
489  *w = MAX (*w, 0);
490  *h = MAX (*h, 0);
491}
492
493static void
494gtk_hscale_draw_slider (GtkRange *range)
495{
496  GtkStateType state_type;
497 
498  g_return_if_fail (range != NULL);
499  g_return_if_fail (GTK_IS_HSCALE (range));
500 
501  if (range->slider)
502    {
503      if ((range->in_child == RANGE_CLASS (range)->slider) ||
504          (range->click_child == RANGE_CLASS (range)->slider))
505        state_type = GTK_STATE_PRELIGHT;
506      else
507        state_type = GTK_STATE_NORMAL;
508     
509      gtk_paint_slider (GTK_WIDGET (range)->style, range->slider, state_type,
510                        GTK_SHADOW_OUT,
511                        NULL, GTK_WIDGET (range), "hscale",
512                        0, 0, -1, -1,
513                        GTK_ORIENTATION_HORIZONTAL);
514    }
515}
516
517static void
518gtk_hscale_draw_value (GtkScale *scale)
519{
520  GtkStateType state_type;
521  GtkWidget *widget;
522  gchar buffer[32];
523  gint text_width;
524  gint width, height;
525  gint x, y;
526 
527  g_return_if_fail (scale != NULL);
528  g_return_if_fail (GTK_IS_HSCALE (scale));
529 
530  widget = GTK_WIDGET (scale);
531 
532  if (scale->draw_value)
533    {
534      sprintf (buffer, "%0.*f", GTK_RANGE (scale)->digits, GTK_RANGE (scale)->adjustment->value);
535      text_width = gdk_string_measure (GTK_WIDGET (scale)->style->font, buffer);
536     
537      switch (scale->value_pos)
538        {
539        case GTK_POS_LEFT:
540          gdk_window_get_position (GTK_RANGE (scale)->trough, &x, &y);
541          gdk_window_get_size (GTK_RANGE (scale)->trough, &width, &height);
542         
543          x -= SCALE_CLASS (scale)->value_spacing + text_width;
544          y += ((height -
545                 (GTK_WIDGET (scale)->style->font->ascent +
546                  GTK_WIDGET (scale)->style->font->descent)) / 2 +
547                GTK_WIDGET (scale)->style->font->ascent);
548          break;
549        case GTK_POS_RIGHT:
550          gdk_window_get_position (GTK_RANGE (scale)->trough, &x, &y);
551          gdk_window_get_size (GTK_RANGE (scale)->trough, &width, &height);
552         
553          x += width + SCALE_CLASS (scale)->value_spacing;
554          y += ((height -
555                 (GTK_WIDGET (scale)->style->font->ascent +
556                  GTK_WIDGET (scale)->style->font->descent)) / 2 +
557                GTK_WIDGET (scale)->style->font->ascent);
558          break;
559        case GTK_POS_TOP:
560          gdk_window_get_position (GTK_RANGE (scale)->slider, &x, NULL);
561          gdk_window_get_position (GTK_RANGE (scale)->trough, NULL, &y);
562          gdk_window_get_size (GTK_RANGE (scale)->slider, &width, NULL);
563          gdk_window_get_size (GTK_RANGE (scale)->trough, NULL, &height);
564         
565          x += widget->allocation.x + (width - text_width) / 2;
566          x = CLAMP (x, widget->allocation.x,
567                     widget->allocation.x + widget->allocation.width - text_width);
568          y -= GTK_WIDGET (scale)->style->font->descent;
569          break;
570        case GTK_POS_BOTTOM:
571          gdk_window_get_position (GTK_RANGE (scale)->slider, &x, NULL);
572          gdk_window_get_position (GTK_RANGE (scale)->trough, NULL, &y);
573          gdk_window_get_size (GTK_RANGE (scale)->slider, &width, NULL);
574          gdk_window_get_size (GTK_RANGE (scale)->trough, NULL, &height);
575         
576          x += widget->allocation.x + (width - text_width) / 2;
577          x = CLAMP (x, widget->allocation.x,
578                     widget->allocation.x + widget->allocation.width - text_width);
579          y += height + GTK_WIDGET (scale)->style->font->ascent;
580          break;
581        }
582     
583      state_type = GTK_STATE_NORMAL;
584      if (!GTK_WIDGET_IS_SENSITIVE (scale))
585        state_type = GTK_STATE_INSENSITIVE;
586     
587      gtk_paint_string (GTK_WIDGET (scale)->style,
588                        GTK_WIDGET (scale)->window,
589                        state_type,
590                        NULL, GTK_WIDGET (scale), "hscale",
591                        x, y, buffer);
592    }
593}
594
595static gint
596gtk_hscale_trough_keys (GtkRange *range,
597                        GdkEventKey *key,
598                        GtkScrollType *scroll,
599                        GtkTroughType *pos)
600{
601  gint return_val = FALSE;
602  switch (key->keyval)
603    {
604    case GDK_Left:
605      return_val = TRUE;
606      if (key->state & GDK_CONTROL_MASK)
607        *scroll = GTK_SCROLL_PAGE_BACKWARD;
608      else
609        *scroll = GTK_SCROLL_STEP_BACKWARD;
610      break;
611    case GDK_Right:
612      return_val = TRUE;
613      if (key->state & GDK_CONTROL_MASK)
614        *scroll = GTK_SCROLL_PAGE_FORWARD;
615      else
616        *scroll = GTK_SCROLL_STEP_FORWARD;
617      break;
618    case GDK_Home:
619      return_val = TRUE;
620      *pos = GTK_TROUGH_START;
621      break;
622    case GDK_End:
623      return_val = TRUE;
624      *pos = GTK_TROUGH_END;
625      break;
626    }
627  return return_val;
628}
Note: See TracBrowser for help on using the repository browser.