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

Revision 15781, 15.5 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.
Line 
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 "gtkvscrollbar.h"
28#include "gtksignal.h"
29#include "gdk/gdkkeysyms.h"
30
31
32#define EPSILON 0.01
33
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_vscrollbar_class_init       (GtkVScrollbarClass *klass);
42static void gtk_vscrollbar_init             (GtkVScrollbar      *vscrollbar);
43static void gtk_vscrollbar_set_arg          (GtkObject          *object,
44                                             GtkArg             *arg,
45                                             guint               arg_id);
46static void gtk_vscrollbar_get_arg          (GtkObject          *object,
47                                             GtkArg             *arg,
48                                             guint               arg_id);
49static void gtk_vscrollbar_realize          (GtkWidget          *widget);
50static void gtk_vscrollbar_size_request     (GtkWidget          *widget,
51                                             GtkRequisition     *requisition);
52static void gtk_vscrollbar_size_allocate    (GtkWidget          *widget,
53                                             GtkAllocation      *allocation);
54static void gtk_vscrollbar_draw_step_forw   (GtkRange           *range);
55static void gtk_vscrollbar_draw_step_back   (GtkRange           *range);
56static void gtk_vscrollbar_slider_update    (GtkRange           *range);
57static void gtk_vscrollbar_calc_slider_size (GtkVScrollbar      *vscrollbar);
58static gint gtk_vscrollbar_trough_keys      (GtkRange *range,
59                                             GdkEventKey *key,
60                                             GtkScrollType *scroll,
61                                             GtkTroughType *pos);
62
63
64GtkType
65gtk_vscrollbar_get_type (void)
66{
67  static GtkType vscrollbar_type = 0;
68 
69  if (!vscrollbar_type)
70    {
71      static const GtkTypeInfo vscrollbar_info =
72      {
73        "GtkVScrollbar",
74        sizeof (GtkVScrollbar),
75        sizeof (GtkVScrollbarClass),
76        (GtkClassInitFunc) gtk_vscrollbar_class_init,
77        (GtkObjectInitFunc) gtk_vscrollbar_init,
78        /* reserved_1 */ NULL,
79        /* reserved_2 */ NULL,
80        (GtkClassInitFunc) NULL,
81      };
82     
83      vscrollbar_type = gtk_type_unique (GTK_TYPE_SCROLLBAR, &vscrollbar_info);
84    }
85 
86  return vscrollbar_type;
87}
88
89static void
90gtk_vscrollbar_class_init (GtkVScrollbarClass *class)
91{
92  GtkObjectClass *object_class;
93  GtkWidgetClass *widget_class;
94  GtkRangeClass *range_class;
95 
96  object_class = (GtkObjectClass*) class;
97  widget_class = (GtkWidgetClass*) class;
98  range_class = (GtkRangeClass*) class;
99 
100  gtk_object_add_arg_type ("GtkVScrollbar::adjustment",
101                           GTK_TYPE_ADJUSTMENT,
102                           GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
103                           ARG_ADJUSTMENT);
104 
105  object_class->set_arg = gtk_vscrollbar_set_arg;
106  object_class->get_arg = gtk_vscrollbar_get_arg;
107 
108  widget_class->realize = gtk_vscrollbar_realize;
109  widget_class->size_request = gtk_vscrollbar_size_request;
110  widget_class->size_allocate = gtk_vscrollbar_size_allocate;
111 
112  range_class->draw_step_forw = gtk_vscrollbar_draw_step_forw;
113  range_class->draw_step_back = gtk_vscrollbar_draw_step_back;
114  range_class->slider_update = gtk_vscrollbar_slider_update;
115  range_class->trough_click = gtk_range_default_vtrough_click;
116  range_class->trough_keys = gtk_vscrollbar_trough_keys;
117  range_class->motion = gtk_range_default_vmotion;
118}
119
120static void
121gtk_vscrollbar_set_arg (GtkObject          *object,
122                        GtkArg             *arg,
123                        guint               arg_id)
124{
125  GtkVScrollbar *vscrollbar;
126 
127  vscrollbar = GTK_VSCROLLBAR (object);
128 
129  switch (arg_id)
130    {
131    case ARG_ADJUSTMENT:
132      gtk_range_set_adjustment (GTK_RANGE (vscrollbar), GTK_VALUE_POINTER (*arg));
133      break;
134    default:
135      break;
136    }
137}
138
139static void
140gtk_vscrollbar_get_arg (GtkObject          *object,
141                        GtkArg             *arg,
142                        guint               arg_id)
143{
144  GtkVScrollbar *vscrollbar;
145 
146  vscrollbar = GTK_VSCROLLBAR (object);
147 
148  switch (arg_id)
149    {
150    case ARG_ADJUSTMENT:
151      GTK_VALUE_POINTER (*arg) = GTK_RANGE (vscrollbar);
152      break;
153    default:
154      arg->type = GTK_TYPE_INVALID;
155      break;
156    }
157}
158
159static void
160gtk_vscrollbar_init (GtkVScrollbar *vscrollbar)
161{
162}
163
164GtkWidget*
165gtk_vscrollbar_new (GtkAdjustment *adjustment)
166{
167  GtkWidget *vscrollbar;
168 
169  vscrollbar = gtk_widget_new (GTK_TYPE_VSCROLLBAR,
170                               "adjustment", adjustment,
171                               NULL);
172 
173  return vscrollbar;
174}
175
176
177static void
178gtk_vscrollbar_realize (GtkWidget *widget)
179{
180  GtkRange *range;
181  GdkWindowAttr attributes;
182  gint attributes_mask;
183  gint slider_width;
184  gint stepper_size;
185  gint trough_border;
186 
187  g_return_if_fail (widget != NULL);
188  g_return_if_fail (GTK_IS_VSCROLLBAR (widget));
189 
190  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
191  range = GTK_RANGE (widget);
192 
193  _gtk_range_get_props (range, &slider_width, &trough_border,
194                        &stepper_size, NULL);
195
196  attributes.x = widget->allocation.x + (widget->allocation.width - widget->requisition.width) / 2;
197  attributes.y = widget->allocation.y;
198  attributes.width = widget->requisition.width;
199  attributes.height = widget->allocation.height;
200  attributes.wclass = GDK_INPUT_OUTPUT;
201  attributes.window_type = GDK_WINDOW_CHILD;
202  attributes.visual = gtk_widget_get_visual (widget);
203  attributes.colormap = gtk_widget_get_colormap (widget);
204  attributes.event_mask = gtk_widget_get_events (widget);
205  attributes.event_mask |= (GDK_EXPOSURE_MASK |
206                            GDK_BUTTON_PRESS_MASK |
207                            GDK_BUTTON_RELEASE_MASK |
208                            GDK_ENTER_NOTIFY_MASK |
209                            GDK_LEAVE_NOTIFY_MASK);
210 
211  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
212  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
213 
214  range->trough = widget->window;
215  gdk_window_ref (range->trough);
216 
217  attributes.x = trough_border;
218  attributes.y = trough_border;
219  attributes.width = stepper_size;
220  attributes.height = stepper_size;
221 
222  range->step_back = gdk_window_new (range->trough, &attributes, attributes_mask);
223 
224  attributes.y = (widget->allocation.height -
225                  trough_border -
226                  stepper_size);
227 
228  range->step_forw = gdk_window_new (range->trough, &attributes, attributes_mask);
229 
230  attributes.x = trough_border;
231  attributes.y = 0;
232  attributes.width = slider_width;
233  attributes.height = RANGE_CLASS (widget)->min_slider_size;
234  attributes.event_mask |= (GDK_BUTTON_MOTION_MASK |
235                            GDK_POINTER_MOTION_HINT_MASK);
236 
237  range->slider = gdk_window_new (range->trough, &attributes, attributes_mask);
238 
239  gtk_vscrollbar_calc_slider_size (GTK_VSCROLLBAR (widget));
240  gtk_range_slider_update (GTK_RANGE (widget));
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  gdk_window_set_user_data (range->step_forw, widget);
247  gdk_window_set_user_data (range->step_back, widget);
248 
249  gtk_style_set_background (widget->style, range->trough, GTK_STATE_ACTIVE);
250  gtk_style_set_background (widget->style, range->slider, GTK_STATE_NORMAL);
251  gtk_style_set_background (widget->style, range->step_forw, GTK_STATE_ACTIVE);
252  gtk_style_set_background (widget->style, range->step_back, GTK_STATE_ACTIVE);
253 
254  gdk_window_show (range->slider);
255  gdk_window_show (range->step_forw);
256  gdk_window_show (range->step_back);
257}
258
259static void
260gtk_vscrollbar_size_request (GtkWidget      *widget,
261                             GtkRequisition *requisition)
262{
263  gint slider_width;
264  gint trough_border;
265  gint stepper_size;
266  gint stepper_spacing;
267 
268  GtkRange *range = GTK_RANGE (widget);
269
270  _gtk_range_get_props (range, &slider_width, &trough_border,
271                        &stepper_size, &stepper_spacing);
272 
273  requisition->width = (slider_width +
274                        trough_border * 2);
275  requisition->height = (RANGE_CLASS (widget)->min_slider_size +
276                         stepper_size +
277                         stepper_spacing +
278                         trough_border) * 2;
279}
280
281static void
282gtk_vscrollbar_size_allocate (GtkWidget     *widget,
283                              GtkAllocation *allocation)
284{
285  GtkRange *range;
286  gint trough_border;
287  gint stepper_size;
288 
289  g_return_if_fail (widget != NULL);
290  g_return_if_fail (GTK_IS_VSCROLLBAR (widget));
291  g_return_if_fail (allocation != NULL);
292 
293  widget->allocation = *allocation;
294  if (GTK_WIDGET_REALIZED (widget))
295    {
296      range = GTK_RANGE (widget);
297
298      _gtk_range_get_props (range, NULL, &trough_border, &stepper_size, NULL);
299     
300      gdk_window_move_resize (range->trough,
301                              allocation->x + (allocation->width - widget->requisition.width) / 2,
302                              allocation->y,
303                              widget->requisition.width, allocation->height);
304      gdk_window_move_resize (range->step_back,
305                              trough_border,
306                              trough_border,
307                              widget->requisition.width - trough_border * 2,
308                              stepper_size);
309      gdk_window_move_resize (range->step_forw,
310                              trough_border,
311                              allocation->height - trough_border -
312                              stepper_size,
313                              widget->requisition.width - trough_border * 2,
314                              stepper_size);
315      gdk_window_resize (range->slider,
316                         widget->requisition.width - trough_border * 2,
317                         RANGE_CLASS (range)->min_slider_size);
318     
319      gtk_range_slider_update (GTK_RANGE (widget));
320    }
321}
322
323static void
324gtk_vscrollbar_draw_step_forw (GtkRange *range)
325{
326  GtkStateType state_type;
327  GtkShadowType shadow_type;
328 
329  g_return_if_fail (range != NULL);
330  g_return_if_fail (GTK_IS_VSCROLLBAR (range));
331 
332  if (GTK_WIDGET_DRAWABLE (range))
333    {
334      if (range->in_child == RANGE_CLASS (range)->step_forw)
335        {
336          if (range->click_child == RANGE_CLASS (range)->step_forw)
337            state_type = GTK_STATE_ACTIVE;
338          else
339            state_type = GTK_STATE_PRELIGHT;
340        }
341      else
342        state_type = GTK_STATE_NORMAL;
343     
344      if (range->click_child == RANGE_CLASS (range)->step_forw)
345        shadow_type = GTK_SHADOW_IN;
346      else
347        shadow_type = GTK_SHADOW_OUT;
348     
349      gtk_paint_arrow (GTK_WIDGET (range)->style, range->step_forw,
350                       state_type, shadow_type,
351                       NULL, GTK_WIDGET (range), "vscrollbar",
352                       GTK_ARROW_DOWN,
353                       TRUE, 0, 0, -1, -1);
354    }
355}
356
357static void
358gtk_vscrollbar_draw_step_back (GtkRange *range)
359{
360  GtkStateType state_type;
361  GtkShadowType shadow_type;
362 
363  g_return_if_fail (range != NULL);
364  g_return_if_fail (GTK_IS_VSCROLLBAR (range));
365 
366  if (GTK_WIDGET_DRAWABLE (range))
367    {
368      if (range->in_child == RANGE_CLASS (range)->step_back)
369        {
370          if (range->click_child == RANGE_CLASS (range)->step_back)
371            state_type = GTK_STATE_ACTIVE;
372          else
373            state_type = GTK_STATE_PRELIGHT;
374        }
375      else
376        state_type = GTK_STATE_NORMAL;
377     
378      if (range->click_child == RANGE_CLASS (range)->step_back)
379        shadow_type = GTK_SHADOW_IN;
380      else
381        shadow_type = GTK_SHADOW_OUT;
382     
383      gtk_paint_arrow (GTK_WIDGET (range)->style, range->step_back,
384                       state_type, shadow_type,
385                       NULL, GTK_WIDGET (range), "vscrollbar",
386                       GTK_ARROW_UP,
387                       TRUE, 0, 0, -1, -1);
388    }
389}
390
391static void
392gtk_vscrollbar_slider_update (GtkRange *range)
393{
394  g_return_if_fail (range != NULL);
395  g_return_if_fail (GTK_IS_VSCROLLBAR (range));
396 
397  gtk_vscrollbar_calc_slider_size (GTK_VSCROLLBAR (range));
398  gtk_range_default_vslider_update (range);
399}
400
401static void
402gtk_vscrollbar_calc_slider_size (GtkVScrollbar *vscrollbar)
403{
404  GtkRange *range;
405  gint step_back_y;
406  gint step_back_height;
407  gint step_forw_y;
408  gint stepper_spacing;
409  gint slider_width;
410  gint slider_height;
411  gint top, bottom;
412  gint height;
413 
414  g_return_if_fail (vscrollbar != NULL);
415  g_return_if_fail (GTK_IS_VSCROLLBAR (vscrollbar));
416 
417  if (GTK_WIDGET_REALIZED (vscrollbar))
418    {
419      range = GTK_RANGE (vscrollbar);
420     
421      _gtk_range_get_props (range, NULL, NULL, NULL, &stepper_spacing);
422     
423      gdk_window_get_size (range->step_back, NULL, &step_back_height);
424      gdk_window_get_position (range->step_back, NULL, &step_back_y);
425      gdk_window_get_position (range->step_forw, NULL, &step_forw_y);
426     
427      top = (step_back_y +
428             step_back_height +
429             stepper_spacing);
430      bottom = step_forw_y - stepper_spacing;
431      height = bottom - top;
432     
433      if ((range->adjustment->page_size > 0) &&
434          (range->adjustment->lower != range->adjustment->upper))
435        {
436          if (range->adjustment->page_size >
437              (range->adjustment->upper - range->adjustment->lower))
438            range->adjustment->page_size = range->adjustment->upper - range->adjustment->lower;
439         
440          height = (height * range->adjustment->page_size /
441                    (range->adjustment->upper - range->adjustment->lower));
442         
443          if (height < RANGE_CLASS (vscrollbar)->min_slider_size)
444            height = RANGE_CLASS (vscrollbar)->min_slider_size;
445        }
446     
447      gdk_window_get_size (range->slider, &slider_width, &slider_height);
448     
449      if (slider_height != height)
450        gdk_window_resize (range->slider, slider_width, height);
451    }
452}
453
454static gint
455gtk_vscrollbar_trough_keys(GtkRange *range,
456                           GdkEventKey *key,
457                           GtkScrollType *scroll,
458                           GtkTroughType *pos)
459{
460  gint return_val = FALSE;
461  switch (key->keyval)
462    {
463    case GDK_Up:
464      return_val = TRUE;
465      *scroll = GTK_SCROLL_STEP_BACKWARD;
466      break;
467    case GDK_Down:
468      return_val = TRUE;
469      *scroll = GTK_SCROLL_STEP_FORWARD;
470      break;
471    case GDK_Page_Up:
472      return_val = TRUE;
473      if (key->state & GDK_CONTROL_MASK)
474        *pos = GTK_TROUGH_START;
475      else
476        *scroll = GTK_SCROLL_PAGE_BACKWARD;
477      break;
478    case GDK_Page_Down:
479      return_val = TRUE;
480      if (key->state & GDK_CONTROL_MASK)
481        *pos = GTK_TROUGH_END;
482      else
483        *scroll = GTK_SCROLL_PAGE_FORWARD;
484      break;
485    }
486  return return_val;
487}
Note: See TracBrowser for help on using the repository browser.