2 * Copyright 1989 O'Reilly and Associates, Inc.
4 The X Consortium, and any party obtaining a copy of these files from
5 the X Consortium, directly or indirectly, is granted, free of charge, a
6 full and unrestricted irrevocable, world-wide, paid up, royalty-free,
7 nonexclusive right and license to deal in this software and
8 documentation files (the "Software"), including without limitation the
9 rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons who receive
11 copies from any such party to do so. This license includes without
12 limitation a license to do the foregoing actions under any patents of
13 the party supplying this software to the X Consortium.
15 $Id: ScrollBox.c,v 1.15 2008/07/14 04:24:52 wmcbrine Exp $
18 /* ScrollBox.c - scrollBox composite widget */
20 #include <X11/IntrinsicP.h>
21 #include <X11/StringDefs.h>
22 #include <X11/Shell.h>
24 #include "x11/ScrollBoxP.h"
28 #define INITIAL_WIDTH 300
29 #define INITIAL_HEIGHT 300
31 /************************************************************************
33 * scrollBox Resources *
35 ************************************************************************/
37 static XtResource resources
[] =
39 { XtNhSpace
, XtCHSpace
, XtRDimension
, sizeof(Dimension
),
40 XtOffset(ScrollBoxWidget
, scrollBox
.h_space
),
41 XtRImmediate
, (XtPointer
)4 },
42 { XtNvSpace
, XtCVSpace
, XtRDimension
, sizeof(Dimension
),
43 XtOffset(ScrollBoxWidget
, scrollBox
.v_space
),
44 XtRImmediate
, (XtPointer
)4 },
45 { XtNheightInc
, XtCHeightInc
, XtRDimension
, sizeof(Dimension
),
46 XtOffset(ScrollBoxWidget
, scrollBox
.increment_height
),
47 XtRImmediate
, (XtPointer
)13 },
48 { XtNwidthInc
, XtCWidthInc
, XtRDimension
, sizeof(Dimension
),
49 XtOffset(ScrollBoxWidget
, scrollBox
.increment_width
),
50 XtRImmediate
, (XtPointer
)7 },
53 /************************************************************************
55 * Full class record constant *
57 ************************************************************************/
59 static void Initialize(Widget
, Widget
, ArgList
, Cardinal
*);
60 static void Resize(Widget
);
61 static Boolean
SetValues(Widget
, Widget
, Widget
, ArgList
, Cardinal
*);
62 static void ChangeManaged(Widget
);
63 static XtGeometryResult
QueryGeometry(Widget
, XtWidgetGeometry
*,
65 static XtGeometryResult
GeometryManager(Widget
, XtWidgetGeometry
*,
67 static void RefigureLocations(Widget
);
69 ScrollBoxClassRec scrollBoxClassRec
= {
71 /* core_class fields */
72 /* superclass */ (WidgetClass
) &compositeClassRec
,
73 /* class_name */ "scrollBox",
74 /* widget_size */ sizeof(ScrollBoxRec
),
75 /* class_initialize */ NULL
,
76 /* class_part_init */ NULL
,
77 /* class_inited */ FALSE
,
78 /* initialize */ Initialize
,
79 /* initialize_hook */ NULL
,
80 /* realize */ XtInheritRealize
,
83 /* resources */ resources
,
84 /* num_resources */ XtNumber(resources
),
85 /* xrm_class */ NULLQUARK
,
86 /* compress_motion */ TRUE
,
87 /* compress_exposure */ TRUE
,
88 /* compress_enterleave */ TRUE
,
89 /* visible_interest */ FALSE
,
93 /* set_values */ SetValues
,
94 /* set_values_hook */ NULL
,
95 /* set_values_almost */ XtInheritSetValuesAlmost
,
96 /* get_values_hook */ NULL
,
97 /* accept_focus */ NULL
,
98 /* version */ XtVersion
,
99 /* callback_private */ NULL
,
101 /* query_geometry */ QueryGeometry
,
102 /* display_accelerator */ XtInheritDisplayAccelerator
,
105 /* composite_class fields */
106 /* geometry_manager */ GeometryManager
,
107 /* change_managed */ ChangeManaged
,
108 /* insert_child */ XtInheritInsertChild
,
109 /* delete_child */ XtInheritDeleteChild
,
112 /* scrollBox class fields */
117 WidgetClass scrollBoxWidgetClass
= (WidgetClass
)&scrollBoxClassRec
;
119 /************************************************************************
123 ************************************************************************/
125 /* Do a layout, either actually assigning positions, or just
128 static void DoLayout(Widget w
, Boolean doit
)
130 ScrollBoxWidget sbw
= (ScrollBoxWidget
)w
;
131 Widget wmain
, vscroll
, hscroll
, child
;
132 Dimension mw
, mh
; /* main window */
133 Dimension vh
; /* vertical scrollbar length (height) */
134 Dimension hw
; /* horizontal scrollbar length (width) */
139 if (sbw
->composite
.num_children
!= 3)
140 XtAppError(XtWidgetToApplicationContext(w
),
141 "ScrollBox: must manage exactly three widgets.");
143 for (i
= 0; i
< sbw
->composite
.num_children
; i
++)
145 child
= sbw
->composite
.children
[i
];
147 if (!XtIsManaged(child
))
148 XtAppError(XtWidgetToApplicationContext(w
),
149 "ScrollBox: all three widgets must be managed.");
152 /* Child one is the main window, two is the vertical scrollbar,
153 and three is the horizontal scrollbar. */
155 wmain
= sbw
->composite
.children
[0];
156 vscroll
= sbw
->composite
.children
[1];
157 hscroll
= sbw
->composite
.children
[2];
159 /* Size all three widgets so that space is fully utilized. */
161 mw
= sbw
->core
.width
- (2 * sbw
->scrollBox
.h_space
) -
162 vscroll
->core
.width
- (2 * vscroll
->core
.border_width
) -
163 (2 * wmain
->core
.border_width
);
165 mh
= sbw
->core
.height
- (2 * sbw
->scrollBox
.v_space
) -
166 hscroll
->core
.height
- (2 * hscroll
->core
.border_width
) -
167 (2 * wmain
->core
.border_width
);
169 /* Force the main window to be sized to the appropriate increment. */
171 mw
= (mw
/ sbw
->scrollBox
.increment_width
) *
172 sbw
->scrollBox
.increment_width
;
174 mh
= ((mh
/ sbw
->scrollBox
.increment_height
) *
175 sbw
->scrollBox
.increment_height
) +
176 sbw
->scrollBox
.increment_height
;
178 vx
= wmain
->core
.x
+ mw
+ sbw
->scrollBox
.h_space
+
179 wmain
->core
.border_width
+ vscroll
->core
.border_width
;
181 hy
= wmain
->core
.y
+ mh
+ sbw
->scrollBox
.v_space
+
182 wmain
->core
.border_width
+ hscroll
->core
.border_width
;
184 vh
= mh
; /* scrollbars are always same length as main window */
189 XtResizeWidget(wmain
, mw
, mh
, 1);
191 XtResizeWidget(vscroll
, vscroll
->core
.width
, vh
, 1);
192 XtMoveWidget(vscroll
, vx
, vscroll
->core
.y
);
194 XtResizeWidget(hscroll
, hw
, hscroll
->core
.height
, 1);
195 XtMoveWidget(hscroll
, hscroll
->core
.x
, hy
);
199 static XtGeometryResult
GeometryManager(Widget w
, XtWidgetGeometry
*request
,
200 XtWidgetGeometry
*reply
)
202 XtWidgetGeometry allowed
;
204 if (request
->request_mode
& ~(XtCWQueryOnly
| CWWidth
| CWHeight
))
207 if (request
->request_mode
& CWWidth
)
208 allowed
.width
= request
->width
;
210 allowed
.width
= w
->core
.width
;
212 if (request
->request_mode
& CWHeight
)
213 allowed
.height
= request
->height
;
215 allowed
.height
= w
->core
.height
;
217 if (allowed
.width
== w
->core
.width
&& allowed
.height
== w
->core
.height
)
220 if (!(request
->request_mode
& XtCWQueryOnly
))
221 RefigureLocations(w
);
223 return XtGeometryYes
;
226 static void RefigureLocations(Widget w
)
231 /* Calculate preferred size. We can't just use the current sizes
232 of the children, because that calculation would always end up with
233 our current size. Could query each child, and use that size to
234 recalculate a size for us, then if it ends up being larger than width
235 and height passed in, accept bounding box. However, we know our
236 children and they don't have any particular preferred geometry,
237 except the bigger the better. Therefore, if the parent suggested a
238 size, we'll take it. */
240 static XtGeometryResult
QueryGeometry(Widget w
, XtWidgetGeometry
*request
,
241 XtWidgetGeometry
*reply_return
)
243 XtGeometryResult result
=XtGeometryNo
;
245 request
->request_mode
&= CWWidth
| CWHeight
;
247 /* parent isn't going to change w or h, so nothing to re-compute */
249 if (request
->request_mode
== 0)
250 return XtGeometryYes
;
252 /* if proposed size is large enough, accept it. Otherwise, suggest
253 our arbitrary initial size. */
255 if (request
->request_mode
& CWHeight
)
257 if (request
->height
< INITIAL_HEIGHT
)
259 result
= XtGeometryAlmost
;
260 reply_return
->height
= INITIAL_HEIGHT
;
261 reply_return
->request_mode
&= CWHeight
;
264 result
= XtGeometryYes
;
267 if (request
->request_mode
& CWWidth
)
269 if (request
->width
< INITIAL_WIDTH
)
271 result
= XtGeometryAlmost
;
272 reply_return
->width
= INITIAL_WIDTH
;
273 reply_return
->request_mode
&= CWWidth
;
276 result
= XtGeometryYes
;
282 /* Actually layout the scrollBox */
284 static void Resize(Widget w
)
289 static void ChangeManaged(Widget w
)
294 static void Initialize(Widget request
, Widget
new,
295 ArgList args
, Cardinal
*num_args
)
297 ScrollBoxWidget newsbw
= (ScrollBoxWidget
)new;
299 if (newsbw
->core
.width
== 0)
300 newsbw
->core
.width
= INITIAL_WIDTH
;
302 if (newsbw
->core
.height
== 0)
303 newsbw
->core
.height
= INITIAL_HEIGHT
;
307 static Boolean
SetValues(Widget current
, Widget request
, Widget
new,
308 ArgList args
, Cardinal
*num_args
)
310 ScrollBoxWidget sbwcurrent
= (ScrollBoxWidget
)current
;
311 ScrollBoxWidget sbwnew
= (ScrollBoxWidget
)new;
313 /* need to relayout if h_space or v_space change */
315 if ((sbwnew
->scrollBox
.h_space
!= sbwcurrent
->scrollBox
.h_space
) ||
316 (sbwnew
->scrollBox
.v_space
!= sbwcurrent
->scrollBox
.v_space
))