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

Revision 15781, 18.7 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 "gtkvscale.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_vscale_class_init    (GtkVScaleClass *klass);
42static void gtk_vscale_init          (GtkVScale      *vscale);
43static void gtk_vscale_set_arg       (GtkObject      *object,
44                                      GtkArg         *arg,
45                                      guint           arg_id);
46static void gtk_vscale_get_arg       (GtkObject      *object,
47                                      GtkArg         *arg,
48                                      guint           arg_id);
49static void gtk_vscale_realize       (GtkWidget      *widget);
50static void gtk_vscale_size_request  (GtkWidget      *widget,
51                                      GtkRequisition *requisition);
52static void gtk_vscale_size_allocate (GtkWidget      *widget,
53                                      GtkAllocation  *allocation);
54static void gtk_vscale_pos_trough    (GtkVScale      *vscale,
55                                      gint           *x,
56                                      gint           *y,
57                                      gint           *w,
58                                      gint           *h);
59static void gtk_vscale_pos_background (GtkVScale     *vscale,
60                                       gint          *x,
61                                       gint          *y,
62                                       gint          *w,
63                                       gint          *h);
64static void gtk_vscale_draw_slider   (GtkRange       *range);
65static void gtk_vscale_draw_value    (GtkScale       *scale);
66static void gtk_vscale_draw          (GtkWidget      *widget,
67                                      GdkRectangle   *area);
68static gint gtk_vscale_trough_keys   (GtkRange *range,
69                                      GdkEventKey *key,
70                                      GtkScrollType *scroll,
71                                      GtkTroughType *pos);
72static void gtk_vscale_clear_background (GtkRange    *range);
73
74GtkType
75gtk_vscale_get_type (void)
76{
77  static GtkType vscale_type = 0;
78 
79  if (!vscale_type)
80    {
81      static const GtkTypeInfo vscale_info =
82      {
83        "GtkVScale",
84        sizeof (GtkVScale),
85        sizeof (GtkVScaleClass),
86        (GtkClassInitFunc) gtk_vscale_class_init,
87        (GtkObjectInitFunc) gtk_vscale_init,
88        /* reserved_1 */ NULL,
89        /* reserved_2 */ NULL,
90        (GtkClassInitFunc) NULL,
91      };
92     
93      vscale_type = gtk_type_unique (GTK_TYPE_SCALE, &vscale_info);
94    }
95 
96  return vscale_type;
97}
98
99static void
100gtk_vscale_class_init (GtkVScaleClass *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 ("GtkVScale::adjustment",
113                           GTK_TYPE_ADJUSTMENT,
114                           GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
115                           ARG_ADJUSTMENT);
116 
117  object_class->set_arg = gtk_vscale_set_arg;
118  object_class->get_arg = gtk_vscale_get_arg;
119 
120  widget_class->realize = gtk_vscale_realize;
121  widget_class->size_request = gtk_vscale_size_request;
122  widget_class->size_allocate = gtk_vscale_size_allocate;
123  widget_class->draw = gtk_vscale_draw;
124 
125  range_class->slider_update = gtk_range_default_vslider_update;
126  range_class->trough_click = gtk_range_default_vtrough_click;
127  range_class->motion = gtk_range_default_vmotion;
128  range_class->draw_slider = gtk_vscale_draw_slider;
129  range_class->trough_keys = gtk_vscale_trough_keys;
130  range_class->clear_background = gtk_vscale_clear_background;
131 
132  scale_class->draw_value = gtk_vscale_draw_value;
133}
134
135static void
136gtk_vscale_set_arg (GtkObject          *object,
137                    GtkArg             *arg,
138                    guint               arg_id)
139{
140  GtkVScale *vscale;
141 
142  vscale = GTK_VSCALE (object);
143 
144  switch (arg_id)
145    {
146    case ARG_ADJUSTMENT:
147      gtk_range_set_adjustment (GTK_RANGE (vscale), GTK_VALUE_POINTER (*arg));
148      break;
149    default:
150      break;
151    }
152}
153
154static void
155gtk_vscale_get_arg (GtkObject          *object,
156                    GtkArg             *arg,
157                    guint               arg_id)
158{
159  GtkVScale *vscale;
160 
161  vscale = GTK_VSCALE (object);
162 
163  switch (arg_id)
164    {
165    case ARG_ADJUSTMENT:
166      GTK_VALUE_POINTER (*arg) = GTK_RANGE (vscale);
167      break;
168    default:
169      arg->type = GTK_TYPE_INVALID;
170      break;
171    }
172}
173
174static void
175gtk_vscale_init (GtkVScale *vscale)
176{
177  GTK_WIDGET_SET_FLAGS (vscale, GTK_NO_WINDOW);
178}
179
180GtkWidget*
181gtk_vscale_new (GtkAdjustment *adjustment)
182{
183  GtkWidget *vscale;
184 
185  vscale = gtk_widget_new (GTK_TYPE_VSCALE,
186                           "adjustment", adjustment,
187                           NULL);
188 
189  return vscale;
190}
191
192
193static void
194gtk_vscale_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_VSCALE (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_vscale_pos_trough (GTK_VSCALE (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 
[15780]235  attributes.width = slider_width;
[14481]236  attributes.height = SCALE_CLASS (range)->slider_length;
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_vscale_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_vscale_pos_background (GTK_VSCALE (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_vscale_pos_trough (GTK_VSCALE (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_vscale_clear_background (GtkRange    *range)
301{
302  GtkWidget *widget;
303  GtkScale *scale;
304  gint x, y, width, height;
305 
306  g_return_if_fail (range != NULL);
307  g_return_if_fail (GTK_IS_SCALE (range));
308 
309  widget = GTK_WIDGET (range);
310  scale = GTK_SCALE (range);
311 
312  gtk_vscale_pos_background (GTK_VSCALE (widget), &x, &y, &width, &height);
313 
314  gtk_widget_queue_clear_area (GTK_WIDGET (range),
315                               x, y, width, height);
316}
317
318static void
319gtk_vscale_size_request (GtkWidget      *widget,
320                         GtkRequisition *requisition)
321{
322  GtkScale *scale;
323  gint value_width;
[15780]324  gint slider_width, trough_border;
[14481]325 
326  g_return_if_fail (widget != NULL);
327  g_return_if_fail (GTK_IS_VSCALE (widget));
328  g_return_if_fail (requisition != NULL);
329 
330  scale = GTK_SCALE (widget);
331 
[15780]332  _gtk_range_get_props (GTK_RANGE (scale),
333                        &slider_width, &trough_border, NULL, NULL);
334 
335  requisition->width = (slider_width + trough_border * 2);
[14481]336  requisition->height = (SCALE_CLASS (scale)->slider_length +
[15780]337                         trough_border) * 2;
[14481]338 
339  if (scale->draw_value)
340    {
341      value_width = gtk_scale_get_value_width (scale);
342     
343      if ((scale->value_pos == GTK_POS_LEFT) ||
344          (scale->value_pos == GTK_POS_RIGHT))
345        {
346          requisition->width += value_width + SCALE_CLASS (scale)->value_spacing;
347          if (requisition->height < (widget->style->font->ascent + widget->style->font->descent))
348            requisition->height = widget->style->font->ascent + widget->style->font->descent;
349        }
350      else if ((scale->value_pos == GTK_POS_TOP) ||
351               (scale->value_pos == GTK_POS_BOTTOM))
352        {
353          if (requisition->width < value_width)
354            requisition->width = value_width;
355          requisition->height += widget->style->font->ascent + widget->style->font->descent;
356        }
357    }
358}
359
360static void
361gtk_vscale_size_allocate (GtkWidget     *widget,
362                          GtkAllocation *allocation)
363{
364  GtkRange *range;
365  GtkScale *scale;
366  gint width, height;
367  gint x, y;
368 
369  g_return_if_fail (widget != NULL);
370  g_return_if_fail (GTK_IS_VSCALE (widget));
371  g_return_if_fail (allocation != NULL);
372 
373  widget->allocation = *allocation;
374  if (GTK_WIDGET_REALIZED (widget))
375    {
376      range = GTK_RANGE (widget);
377      scale = GTK_SCALE (widget);
378     
379      gtk_vscale_pos_trough (GTK_VSCALE (widget), &x, &y, &width, &height);
380     
381      gdk_window_move_resize (range->trough, x, y, width, height);
382      gtk_range_slider_update (GTK_RANGE (widget));
383    }
384}
385
386static void
387gtk_vscale_pos_trough (GtkVScale *vscale,
388                       gint      *x,
389                       gint      *y,
390                       gint      *w,
391                       gint      *h)
392{
393  GtkWidget *widget;
394  GtkScale *scale;
[15780]395  gint slider_width, trough_border;
[14481]396 
397  g_return_if_fail (vscale != NULL);
398  g_return_if_fail (GTK_IS_VSCALE (vscale));
399  g_return_if_fail ((x != NULL) && (y != NULL) && (w != NULL) && (h != NULL));
400 
401  widget = GTK_WIDGET (vscale);
402  scale = GTK_SCALE (vscale);
403 
[15780]404  _gtk_range_get_props (GTK_RANGE (scale),
405                        &slider_width, &trough_border, NULL, NULL);
406 
407  *w = (slider_width + trough_border * 2);
[14481]408  *h = widget->allocation.height;
409 
410  if (scale->draw_value)
411    {
412      *x = 0;
413      *y = 0;
414     
415      switch (scale->value_pos)
416        {
417        case GTK_POS_LEFT:
418          *x = (gtk_scale_get_value_width (scale) + SCALE_CLASS (scale)->value_spacing +
419                (widget->allocation.width - widget->requisition.width) / 2);
420          break;
421        case GTK_POS_RIGHT:
422          *x = (widget->allocation.width - widget->requisition.width) / 2;
423          break;
424        case GTK_POS_TOP:
425          *x = (widget->allocation.width - *w) / 2;
426          *y = widget->style->font->ascent + widget->style->font->descent;
427          *h -= *y;
428          break;
429        case GTK_POS_BOTTOM:
430          *x = (widget->allocation.width - *w) / 2;
431          *h -= widget->style->font->ascent + widget->style->font->descent;
432          break;
433        }
434    }
435  else
436    {
437      *x = (widget->allocation.width - *w) / 2;
438      *y = 0;
439    }
440  *y += 1;
441  *h -= 2;
442 
443  *x += widget->allocation.x;
444  *y += widget->allocation.y;
445}
446
447static void
448gtk_vscale_pos_background (GtkVScale *vscale,
449                           gint      *x,
450                           gint      *y,
451                           gint      *w,
452                           gint      *h)
453{
454  GtkWidget *widget;
455  GtkScale *scale;
456 
457  gint tx, ty, twidth, theight;
458 
459  g_return_if_fail (vscale != NULL);
460  g_return_if_fail (GTK_IS_VSCALE (vscale));
461  g_return_if_fail ((x != NULL) && (y != NULL) && (w != NULL) && (h != NULL));
462 
463  gtk_vscale_pos_trough (vscale, &tx, &ty, &twidth, &theight);
464 
465  widget = GTK_WIDGET (vscale);
466  scale = GTK_SCALE (vscale);
467 
468  *x = widget->allocation.x;
469  *y = widget->allocation.y;
470  *w = widget->allocation.width;
471  *h = widget->allocation.height;
472 
473  switch (scale->value_pos)
474    {
475    case GTK_POS_LEFT:
476      *w -= twidth;
477      break;
478    case GTK_POS_RIGHT:
479      *x += twidth;
480      *w -= twidth;
481      break;
482    case GTK_POS_TOP:
483      *h -= theight;
484      break;
485    case GTK_POS_BOTTOM:
486      *y += theight;
487      *h -= theight;
488      break;
489    }
490  *w = MAX (*w, 0);
491  *h = MAX (*h, 0);
492}
493
494static void
495gtk_vscale_draw_slider (GtkRange *range)
496{
497  GtkStateType state_type;
498 
499  g_return_if_fail (range != NULL);
500  g_return_if_fail (GTK_IS_VSCALE (range));
501 
502  if (range->slider)
503    {
504      if ((range->in_child == RANGE_CLASS (range)->slider) ||
505          (range->click_child == RANGE_CLASS (range)->slider))
506        state_type = GTK_STATE_PRELIGHT;
507      else
508        state_type = GTK_STATE_NORMAL;
509     
510      gtk_paint_slider (GTK_WIDGET (range)->style, range->slider, state_type,
511                        GTK_SHADOW_OUT,
512                        NULL, GTK_WIDGET (range), "vscale",
513                        0, 0, -1, -1,
514                        GTK_ORIENTATION_VERTICAL);
515    }
516}
517
518static void
519gtk_vscale_draw_value (GtkScale *scale)
520{
521  GtkStateType state_type;
522  GtkWidget *widget;
523  gchar buffer[32];
524  gint text_width;
525  gint width, height;
526  gint x, y;
527 
528  g_return_if_fail (scale != NULL);
529  g_return_if_fail (GTK_IS_VSCALE (scale));
530 
531  widget = GTK_WIDGET (scale);
532 
533  if (scale->draw_value)
534    {
535      sprintf (buffer, "%0.*f", GTK_RANGE (scale)->digits, GTK_RANGE (scale)->adjustment->value);
536      text_width = gdk_string_measure (GTK_WIDGET (scale)->style->font, buffer);
537     
538      switch (scale->value_pos)
539        {
540        case GTK_POS_LEFT:
541          gdk_window_get_position (GTK_RANGE (scale)->trough, &x, NULL);
542          gdk_window_get_position (GTK_RANGE (scale)->slider, NULL, &y);
543          gdk_window_get_size (GTK_RANGE (scale)->trough, &width, NULL);
544          gdk_window_get_size (GTK_RANGE (scale)->slider, NULL, &height);
545         
546          x -= SCALE_CLASS (scale)->value_spacing + text_width;
547          y += widget->allocation.y + ((height -
548                                        (GTK_WIDGET (scale)->style->font->ascent +
549                                         GTK_WIDGET (scale)->style->font->descent)) / 2 +
550                                       GTK_WIDGET (scale)->style->font->ascent);
551          break;
552        case GTK_POS_RIGHT:
553          gdk_window_get_position (GTK_RANGE (scale)->trough, &x, NULL);
554          gdk_window_get_position (GTK_RANGE (scale)->slider, NULL, &y);
555          gdk_window_get_size (GTK_RANGE (scale)->trough, &width, NULL);
556          gdk_window_get_size (GTK_RANGE (scale)->slider, NULL, &height);
557         
558          x += width + SCALE_CLASS (scale)->value_spacing;
559          y += widget->allocation.y + ((height -
560                                        (GTK_WIDGET (scale)->style->font->ascent +
561                                         GTK_WIDGET (scale)->style->font->descent)) / 2 +
562                                       GTK_WIDGET (scale)->style->font->ascent);
563          break;
564        case GTK_POS_TOP:
565          gdk_window_get_position (GTK_RANGE (scale)->trough, &x, &y);
566          gdk_window_get_size (GTK_RANGE (scale)->slider, &width, NULL);
567          gdk_window_get_size (GTK_RANGE (scale)->trough, NULL, &height);
568         
569          x += (width - text_width) / 2;
570          y -= GTK_WIDGET (scale)->style->font->descent;
571          break;
572        case GTK_POS_BOTTOM:
573          gdk_window_get_position (GTK_RANGE (scale)->trough, &x, &y);
574          gdk_window_get_size (GTK_RANGE (scale)->slider, &width, NULL);
575          gdk_window_get_size (GTK_RANGE (scale)->trough, NULL, &height);
576         
577          x += (width - text_width) / 2;
578          y += height + GTK_WIDGET (scale)->style->font->ascent;
579          break;
580        }
581     
582      state_type = GTK_STATE_NORMAL;
583      if (!GTK_WIDGET_IS_SENSITIVE (scale))
584        state_type = GTK_STATE_INSENSITIVE;
585     
586      gtk_paint_string (GTK_WIDGET (scale)->style,
587                        GTK_WIDGET (scale)->window,
588                        state_type,
589                        NULL, GTK_WIDGET (scale), "vscale",
590                        x, y, buffer);
591    }
592}
593
594static gint
595gtk_vscale_trough_keys (GtkRange *range,
596                        GdkEventKey *key,
597                        GtkScrollType *scroll,
598                        GtkTroughType *pos)
599{
600  gint return_val = FALSE;
601  switch (key->keyval)
602    {
603    case GDK_Up:
604      return_val = TRUE;
605      *scroll = GTK_SCROLL_STEP_BACKWARD;
606      break;
607    case GDK_Down:
608      return_val = TRUE;
609      *scroll = GTK_SCROLL_STEP_FORWARD;
610      break;
611    case GDK_Page_Up:
612      return_val = TRUE;
613      *scroll = GTK_SCROLL_PAGE_BACKWARD;
614      break;
615    case GDK_Page_Down:
616      return_val = TRUE;
617      *scroll = GTK_SCROLL_PAGE_FORWARD;
618      break;
619    case GDK_Home:
620      return_val = TRUE;
621      *pos = GTK_TROUGH_START;
622      break;
623    case GDK_End:
624      return_val = TRUE;
625      *pos = GTK_TROUGH_END;
626      break;
627    }
628  return return_val;
629}
Note: See TracBrowser for help on using the repository browser.