2 static char Xrcsid
[] = "$XConsortium: Paned.c,v 1.13 90/03/01 10:48:51 jim Exp $";
6 /***********************************************************
7 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
8 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
12 Permission to use, copy, modify, and distribute this software and its
13 documentation for any purpose and without fee is hereby granted,
14 provided that the above copyright notice appear in all copies and that
15 both that copyright notice and this permission notice appear in
16 supporting documentation, and that the names of Digital or MIT not be
17 used in advertising or publicity pertaining to distribution of the
18 software without specific, written prior permission.
20 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
21 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
22 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
23 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
24 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
25 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
28 ******************************************************************/
31 * Paned.c - Paned Composite Widget.
33 * Updated and significantly modifided from the Athena VPaned Widget.
37 * By: Chris D. Peterson
39 * kit@expo.lcs.mit.edu
44 #include <X11/IntrinsicP.h>
45 #include <X11/cursorfont.h>
46 #include <X11/StringDefs.h>
48 #include <X11/Xmu/Misc.h>
49 #include <X11/Xmu/Converters.h>
51 #include <./Xaw3_1XawInit.h>
52 #include <./Xaw3_1Grip.h>
53 #include <./Xaw3_1PanedP.h>
55 typedef enum {UpLeftPane
= 'U', LowRightPane
= 'L',
56 ThisBorderOnly
= 'T', AnyPane
= 'A' } Direction
;
61 #define PaneInfo(w) ((Pane)(w)->core.constraints)
62 #define HasGrip(w) (PaneInfo(w)->grip != NULL)
63 #define IsPane(w) ((w)->core.widget_class != gripWidgetClass)
64 #define PaneIndex(w) (PaneInfo(w)->position)
65 #define IsVert(w) ( (w)->paned.orientation == XtorientVertical )
67 #define ForAllPanes(pw, childP) \
68 for ( (childP) = (pw)->composite.children ; \
69 (childP) < (pw)->composite.children + (pw)->paned.num_panes ; \
72 #define ForAllChildren(pw, childP) \
73 for ( (childP) = (pw)->composite.children ; \
74 (childP) < (pw)->composite.children + (pw)->composite.num_children ; \
77 /*****************************************************************************
79 * Full instance record declaration
81 ****************************************************************************/
83 static char defGripTranslations
[] =
84 "<Btn1Down>: GripAction(Start, UpLeftPane) \n\
85 <Btn2Down>: GripAction(Start, ThisBorderOnly) \n\
86 <Btn3Down>: GripAction(Start, LowRightPane) \n\
87 <Btn1Motion>: GripAction(Move, UpLeft) \n\
88 <Btn2Motion>: GripAction(Move, ThisBorder) \n\
89 <Btn3Motion>: GripAction(Move, LowRight) \n\
90 Any<BtnUp>: GripAction(Commit)";
92 #define offset(field) XtOffset(PanedWidget, paned.field)
94 static XtResource resources
[] = {
95 {XtNinternalBorderColor
, XtCBorderColor
, XtRPixel
, sizeof(Pixel
),
96 offset(internal_bp
), XtRString
,
97 (caddr_t
) "XtDefaultForeground"},
98 {XtNinternalBorderWidth
, XtCBorderWidth
, XtRDimension
, sizeof(Dimension
),
99 offset(internal_bw
), XtRImmediate
, (caddr_t
) 1},
100 {XtNgripIndent
, XtCGripIndent
, XtRPosition
, sizeof(Position
),
101 offset(grip_indent
), XtRImmediate
, (caddr_t
) 10},
102 {XtNrefigureMode
, XtCBoolean
, XtRBoolean
, sizeof(Boolean
),
103 offset(refiguremode
), XtRImmediate
, (caddr_t
) TRUE
},
104 {XtNgripTranslations
, XtCTranslations
, XtRTranslationTable
,
105 sizeof(XtTranslations
),
106 offset(grip_translations
), XtRString
, (caddr_t
)defGripTranslations
},
107 {XtNorientation
, XtCOrientation
, XtROrientation
, sizeof(XtOrientation
),
108 offset(orientation
), XtRImmediate
, (caddr_t
) XtorientVertical
},
110 /* Cursors - both horiz and vertical have to work. */
112 {XtNcursor
, XtCCursor
, XtRCursor
, sizeof(Cursor
),
113 offset(cursor
), XtRImmediate
, None
},
114 {XtNgripCursor
, XtCCursor
, XtRCursor
, sizeof(Cursor
),
115 offset(grip_cursor
), XtRImmediate
, None
},
116 {XtNverticalGripCursor
, XtCCursor
, XtRCursor
, sizeof(Cursor
),
117 offset(v_grip_cursor
), XtRString
, "sb_v_double_arrow"},
118 {XtNhorizontalGripCursor
, XtCCursor
, XtRCursor
, sizeof(Cursor
),
119 offset(h_grip_cursor
), XtRString
, "sb_h_double_arrow"},
121 {XtNbetweenCursor
, XtCCursor
, XtRCursor
, sizeof(Cursor
),
122 offset(adjust_this_cursor
), XtRString
, None
},
123 {XtNverticalBetweenCursor
, XtCCursor
, XtRCursor
, sizeof(Cursor
),
124 offset(v_adjust_this_cursor
), XtRString
, "sb_left_arrow"},
125 {XtNhorizontalBetweenCursor
, XtCCursor
, XtRCursor
, sizeof(Cursor
),
126 offset(h_adjust_this_cursor
), XtRString
, "sb_up_arrow"},
128 {XtNupperCursor
, XtCCursor
, XtRCursor
, sizeof(Cursor
),
129 offset(adjust_upper_cursor
), XtRString
, "sb_up_arrow"},
130 {XtNlowerCursor
, XtCCursor
, XtRCursor
, sizeof(Cursor
),
131 offset(adjust_lower_cursor
), XtRString
, "sb_down_arrow"},
132 {XtNleftCursor
, XtCCursor
, XtRCursor
, sizeof(Cursor
),
133 offset(adjust_left_cursor
), XtRString
, "sb_left_arrow"},
134 {XtNrightCursor
, XtCCursor
, XtRCursor
, sizeof(Cursor
),
135 offset(adjust_right_cursor
), XtRString
, "sb_right_arrow"},
140 #define offset(field) XtOffset(Pane, field)
142 static XtResource subresources
[] = {
143 {XtNallowResize
, XtCBoolean
, XtRBoolean
, sizeof(Boolean
),
144 offset(allow_resize
), XtRImmediate
, (caddr_t
) FALSE
},
145 {XtNposition
, XtCPosition
, XtRInt
, sizeof(int),
146 offset(position
), XtRImmediate
, (caddr_t
) 0},
147 {XtNmin
, XtCMin
, XtRDimension
, sizeof(Dimension
),
148 offset(min
), XtRImmediate
, (caddr_t
) PANED_GRIP_SIZE
},
149 {XtNmax
, XtCMax
, XtRDimension
, sizeof(Dimension
),
150 offset(max
), XtRImmediate
, (caddr_t
) ~0},
151 {XtNpreferredPaneSize
, XtCPreferredPaneSize
, XtRDimension
,
152 sizeof(Dimension
), offset(preferred_size
),
153 XtRImmediate
, (caddr_t
) PANED_ASK_CHILD
},
154 {XtNresizeToPreferred
, XtCBoolean
, XtRBoolean
, sizeof(Boolean
),
155 offset(resize_to_pref
), XtRImmediate
, (caddr_t
) FALSE
},
156 {XtNskipAdjust
, XtCBoolean
, XtRBoolean
, sizeof(Boolean
),
157 offset(skip_adjust
), XtRImmediate
, (caddr_t
) FALSE
},
158 {XtNshowGrip
, XtCShowGrip
, XtRBoolean
, sizeof(Boolean
),
159 offset(show_grip
), XtRImmediate
, (caddr_t
) TRUE
},
164 static void ClassInitialize(), Initialize();
165 static void Realize(), Resize();
166 static void Redisplay();
167 static void GetGCs(), ReleaseGCs();
168 static void RefigureLocationsAndCommit();
169 static Boolean
SetValues();
170 static XtGeometryResult
GeometryManager();
171 static void ChangeManaged();
172 static void InsertChild();
173 static void DeleteChild();
174 static Boolean
PaneSetValues();
175 static Dimension
PaneSize(), GetRequestInfo();
176 static Boolean
SatisfiesRule1(), SatisfiesRule2(), SatisfiesRule3();
178 static void PushPaneStack();
179 static void GetPaneStack();
180 static Boolean
PopPaneStack();
181 static void ClearPaneStack();
183 #define SuperClass ((ConstraintWidgetClass)&constraintClassRec)
185 PanedClassRec panedClassRec
= {
187 /* core class fields */
188 /* superclass */ (WidgetClass
) SuperClass
,
189 /* class name */ "Paned",
190 /* size */ sizeof(PanedRec
),
191 /* class_initialize */ ClassInitialize
,
192 /* class_part init */ NULL
,
193 /* class_inited */ FALSE
,
194 /* initialize */ Initialize
,
195 /* initialize_hook */ NULL
,
196 /* realize */ Realize
,
199 /* resourses */ resources
,
200 /* resource_count */ XtNumber(resources
),
201 /* xrm_class */ NULLQUARK
,
202 /* compress_motion */ TRUE
,
203 /* compress_exposure */ TRUE
,
204 /* compress_enterleave*/ TRUE
,
205 /* visible_interest */ FALSE
,
206 /* destroy */ ReleaseGCs
,
208 /* expose */ Redisplay
,
209 /* set_values */ SetValues
,
210 /* set_values_hook */ NULL
,
211 /* set_values_almost */ XtInheritSetValuesAlmost
,
212 /* get_values_hook */ NULL
,
213 /* accept_focus */ NULL
,
214 /* version */ XtVersion
,
215 /* callback_private */ NULL
,
217 /* query_geometry */ XtInheritQueryGeometry
,
218 /* display_accelerator*/ XtInheritDisplayAccelerator
,
221 /* composite class fields */
222 /* geometry_manager */ GeometryManager
,
223 /* change_managed */ ChangeManaged
,
224 /* insert_child */ InsertChild
,
225 /* delete_child */ DeleteChild
,
228 /* constraint class fields */
229 /* subresourses */ subresources
,
230 /* subresource_count */ XtNumber(subresources
),
231 /* constraint_size */ sizeof(PanedConstraintsRec
),
232 /* initialize */ NULL
,
234 /* set_values */ PaneSetValues
,
239 WidgetClass panedWidgetClass
= (WidgetClass
) &panedClassRec
;
241 /* For compatability. */
242 WidgetClass vPanedWidgetClass
= (WidgetClass
) &panedClassRec
;
244 /***********************************************************
248 ************************************************************/
250 /* Function Name: AdjustPanedSize
251 * Description: Adjusts the size of the pane.
252 * Arguments: pw - the paned widget to adjust.
253 * off_size - the new off_size to use.
254 * result_ret - result of query ** RETURNED **
255 * on_size_ret - the new on_size ** RETURNED **
256 * off_size_ret - the new off_size ** RETURNED **
257 * Returns: the amount of change in size.
261 AdjustPanedSize(pw
, off_size
, result_ret
, on_size_ret
, off_size_ret
)
264 XtGeometryResult
* result_ret
;
265 Dimension
* on_size_ret
, * off_size_ret
;
267 Dimension old_size
= PaneSize( (Widget
) pw
, IsVert(pw
));
268 Dimension newsize
= 0;
270 XtWidgetGeometry request
, reply
;
271 request
.request_mode
= CWWidth
| CWHeight
;
273 ForAllPanes(pw
, childP
) {
274 int size
= (int) Max(PaneInfo(*childP
)->size
, PaneInfo(*childP
)->min
);
275 AssignMin(size
, (int) PaneInfo(*childP
)->max
);
276 newsize
+= size
+ pw
->paned
.internal_bw
;
278 newsize
-= pw
->paned
.internal_bw
;
280 if (newsize
< 1) newsize
= 1;
283 request
.width
= off_size
;
284 request
.height
= newsize
;
287 request
.width
= newsize
;
288 request
.height
= off_size
;
291 if (result_ret
!= NULL
) {
292 request
.request_mode
|= XtCWQueryOnly
;
294 *result_ret
= XtMakeGeometryRequest( (Widget
) pw
, &request
, &reply
);
296 if ( (newsize
== old_size
) || (*result_ret
== XtGeometryNo
) ) {
297 *on_size_ret
= old_size
;
298 *off_size_ret
= off_size
;
301 if (*result_ret
!= XtGeometryAlmost
) {
302 *on_size_ret
= GetRequestInfo( &request
, IsVert(pw
) );
303 *off_size_ret
= GetRequestInfo( &request
, !IsVert(pw
) );
306 *on_size_ret
= GetRequestInfo( &reply
, IsVert(pw
) );
307 *off_size_ret
= GetRequestInfo( &reply
, !IsVert(pw
) );
311 if (newsize
== old_size
) return;
313 if (XtMakeGeometryRequest( (Widget
) pw
,
314 &request
, &reply
) == XtGeometryAlmost
)
315 XtMakeGeometryRequest( (Widget
) pw
, &reply
, &request
);
318 /* Function Name: PaneSize
319 * Description: returns the width or height of the pane depending
320 * upon the orientation we are using.
321 * Arguments: w - and widget.
322 * vertical - TRUE if this is vertically oriented pane.
323 * Returns: the size requested
325 * vertical - return height
326 * !vertical - return width
330 PaneSize(w
, vertical
)
334 if (vertical
) return (w
->core
.height
);
335 return (w
->core
.width
);
338 /* Function Name: GetRequestInfo
339 * Description: returns request information.
340 * Arguments: geo_struct - a geometry struct to get information out of.
341 * vert - TRUE if this is a vertical paned widget.
342 * Returns: the request information.
346 GetRequestInfo(geo_struct
, vert
)
347 XtWidgetGeometry
* geo_struct
;
350 if ( vert
) return ( (Dimension
) geo_struct
->height
);
351 return ( (Dimension
) geo_struct
->width
);
354 /* Function Name: ChoosePaneToResize.
355 * Description: This function chooses a pane to resize.
356 * They are choosen using the following rules:
358 * 1) size < max && size > min
359 * 2) skip adjust == FALSE
360 * 3) widget not its prefered height &&
361 * this change will bring it closer &&
362 * The user has not resized this pane.
364 * If no widgets are found that fits all the rules then
366 * If there are still no widgets found than
368 * Rule #1 is never broken.
369 * If no widgets are found then NULL is returned.
371 * Arguments: pw - the paned widget.
372 * index - the index of the current pane.
373 * dir - direction to search first.
374 * shrink - TRUE if we need to shrink a pane, FALSE otherwise.
375 * Returns: pane to resize or NULL.
379 ChoosePaneToResize(pw
, index
, dir
, shrink
)
387 Direction _dir
= dir
;
390 if ( (index
== NO_INDEX
) || (dir
== AnyPane
) ) { /* Use defaults. */
391 _dir
= LowRightPane
; /* Go up. - really. */
392 _index
= pw
->paned
.num_panes
- 1; /* Start the last pane, and work
395 childP
= pw
->composite
.children
+ _index
;
397 register Pane pane
= PaneInfo(*childP
);
399 if ( (rules
< 3 || SatisfiesRule3(pane
, shrink
)) &&
400 (rules
< 2 || SatisfiesRule2(pane
)) &&
401 (SatisfiesRule1(pane
, shrink
)) &&
402 ((index
!= PaneIndex(*childP
)) || (dir
== AnyPane
)) )
406 * This is counter-intiutive, but if we are resizing the pane
407 * above the grip we want to choose a pane below the grip to lose,
411 if (_dir
== LowRightPane
) --childP
; else ++childP
;
414 * If we have come to and edge then reduce the rule set, and try again.
415 * If we are reduced the rules to none, then return NULL.
418 if ( (childP
- pw
->composite
.children
< 0) ||
419 (childP
- pw
->composite
.children
>= pw
->paned
.num_panes
) ) {
420 if (--rules
< 1) /* less strict rules. */
422 childP
= pw
->composite
.children
+ _index
;
427 /* Function Name: StatisfiesRule1
428 * Description: check for to see if this pane satisfies rule 1.
429 * Arguments: pane - the pane to check.
430 * shrink -TRUE if we want to shrink this pane, FALSE otherwise
431 * Returns: TRUE if the rule is satisfied.
435 SatisfiesRule1(pane
, shrink
)
439 return( (shrink
&& (pane
->size
!= pane
->min
)) ||
440 (!shrink
&& (pane
->size
!= pane
->max
)) );
443 /* Function Name: StatisfiesRule2
444 * Description: check for to see if this pane satisfies rule 2.
445 * Arguments: pane - the pane to check.
446 * Returns: TRUE if the rule is satisfied.
453 return(!pane
->skip_adjust
|| pane
->paned_adjusted_me
);
456 /* Function Name: StatisfiesRule3
457 * Description: check for to see if this pane satisfies rule 3.
458 * Arguments: pane - the pane to check.
459 * shrink -TRUE if we want to shrink this pane, FALSE otherwise
460 * Returns: TRUE if the rule is satisfied.
464 SatisfiesRule3(pane
, shrink
)
468 return ( pane
->paned_adjusted_me
&&
469 ( (shrink
&& (pane
->wp_size
<= pane
->size
)) ||
470 (!shrink
&& (pane
->wp_size
>= pane
->size
))) );
473 /* Function Name: LoopAndRefigureChildren.
474 * Description: if we are resizeing either the UpleftPane or LowRight Pane
475 * loop through all the children to see if any will allow us
477 * Arguments: pw - the paned widget.
478 * index - the number of the pane border we are moving.
479 * dir - the pane to move (either UpLeftPane or LowRightPane).
480 * sizeused - current amount of space used.
481 * THIS VALUE IS USED AND RETURNED.
486 LoopAndRefigureChildren(pw
, index
, dir
, sizeused
)
488 int index
, *sizeused
;
491 int pane_size
= (int) PaneSize( (Widget
) pw
, IsVert(pw
));
492 Boolean shrink
= (*sizeused
> pane_size
);
494 if (dir
== LowRightPane
) index
++;
496 while (*sizeused
!= pane_size
) { /* While all panes do not fit properly. */
498 * Choose a pane to resize.
499 * First look on the Pane Stack, and then go hunting for another one.
500 * If we fail to find a pane to resize then give up.
505 Boolean rule3_ok
= FALSE
, from_stack
= TRUE
;
507 GetPaneStack(pw
, shrink
, &pane
, &start_size
);
509 pane
= ChoosePaneToResize(pw
, index
, dir
, shrink
);
511 return; /* no one to resize, give up. */
513 rule3_ok
= SatisfiesRule3(pane
, shrink
);
515 PushPaneStack(pw
, pane
);
520 * Try to resize this pane so that all panes will fit, take min and max
524 pane
->size
+= pane_size
- *sizeused
;
528 AssignMax(pane
->size
, start_size
);
529 } /* don't remove these braces. */
531 AssignMin(pane
->size
, start_size
);
533 if (pane
->size
== start_size
) (void) PopPaneStack(pw
);
537 AssignMax(pane
->size
, (int) pane
->wp_size
);
538 } /* don't remove these braces. */
540 AssignMin(pane
->size
, (int) pane
->wp_size
);
543 pane
->paned_adjusted_me
= (pane
->size
!= pane
->wp_size
);
544 AssignMax(pane
->size
, (int) pane
->min
);
545 AssignMin(pane
->size
, (int) pane
->max
);
546 *sizeused
+= (pane
->size
- old
);
550 /* Function Name: RefigureLocations
551 * Description: refigures all locations of children.
552 * Arguments: pw - the paned widget.
553 * index - child to start refiguring at.
554 * dir - direction to move from child.
557 * There are special arguements to index and dir, they are:
561 * If either of these is true then all panes may be resized and
562 * the choosing of panes proceedes in reverse order starting with the
567 RefigureLocations(pw
, index
, dir
)
572 register Widget
*childP
;
573 int pane_size
= (int) PaneSize( (Widget
) pw
, IsVert(pw
) );
577 if (pw
->paned
.num_panes
== 0 || !pw
->paned
.refiguremode
) return;
580 * Get an initial estimate of the size we will use.
583 ForAllPanes(pw
, childP
) {
584 register Pane pane
= PaneInfo(*childP
);
585 AssignMax(pane
->size
, (int) pane
->min
);
586 AssignMin(pane
->size
, (int) pane
->max
);
587 sizeused
+= (int) pane
->size
+ (int) pw
->paned
.internal_bw
;
589 sizeused
-= (int) pw
->paned
.internal_bw
;
591 if ( (dir
!= ThisBorderOnly
) && (sizeused
!= pane_size
) )
592 LoopAndRefigureChildren(pw
, index
, dir
, &sizeused
);
595 * If we still are not the right size, then tell the pane that
596 * wanted to resize that it can't.
600 if ( (index
!= NO_INDEX
) && (dir
!= AnyPane
) ) {
601 Pane pane
= PaneInfo(*(pw
->composite
.children
+ index
));
602 Dimension old
= pane
->size
;
604 pane
->size
+= pane_size
- sizeused
;
605 AssignMax(pane
->size
, (int) pane
->min
);
606 AssignMin(pane
->size
, (int) pane
->max
);
607 sizeused
+= pane
->size
- old
;
611 * It is possible that the panes will not fit inside the vpaned widget, but
612 * we have tried out best.
614 * Assign each pane a location.
617 ForAllPanes(pw
, childP
) {
618 PaneInfo(*childP
)->delta
= loc
;
619 loc
+= PaneInfo(*childP
)->size
+ pw
->paned
.internal_bw
;
623 /* Function Name: CommitNewLocations
624 * Description: Commits all of the previously figured locations.
625 * Arguments: pw - the paned widget.
630 CommitNewLocations(pw
)
633 register Widget
*childP
;
634 XWindowChanges changes
;
636 changes
.stack_mode
= Above
;
638 ForAllPanes(pw
, childP
) {
639 register Pane pane
= PaneInfo(*childP
);
640 register Widget grip
= pane
->grip
; /* may be NULL. */
643 XtMoveWidget(*childP
, (Position
) 0, pane
->delta
);
644 XtResizeWidget(*childP
, pw
->core
.width
, (Dimension
) pane
->size
,
647 if (HasGrip(*childP
)) { /* Move and Display the Grip */
648 changes
.x
= pw
->core
.width
- pw
->paned
.grip_indent
-
649 grip
->core
.width
- grip
->core
.border_width
*2;
650 changes
.y
= (*childP
)->core
.y
+ (*childP
)->core
.height
-
651 grip
->core
.height
/2 - grip
->core
.border_width
+
652 pw
->paned
.internal_bw
/2;
656 XtMoveWidget(*childP
, pane
->delta
, (Position
) 0);
657 XtResizeWidget(*childP
, (Dimension
) pane
->size
, pw
->core
.height
,
661 if (HasGrip(*childP
)) { /* Move and Display the Grip */
662 changes
.x
= (*childP
)->core
.x
+ (*childP
)->core
.width
-
663 grip
->core
.width
/2 - grip
->core
.border_width
+
664 pw
->paned
.internal_bw
/2;
665 changes
.y
= pw
->core
.height
- pw
->paned
.grip_indent
-
666 grip
->core
.height
- grip
->core
.border_width
*2;
671 * This should match XtMoveWidget, except that we're also insuring the
672 * grip is Raised in the same request.
675 if (HasGrip(*childP
)) {
676 grip
->core
.x
= changes
.x
;
677 grip
->core
.y
= changes
.y
;
679 if (XtIsRealized(pane
->grip
))
680 XConfigureWindow( XtDisplay(pane
->grip
), XtWindow(pane
->grip
),
681 CWX
| CWY
| CWStackMode
, &changes
);
687 /* Function Name: RefigureLocationsAndCommit
688 * Description: Refigures all locations in a paned widget and
689 * commits them immediatly.
690 * Arguments: pw - the paned widget.
693 * This function does nothing if any of the following are true.
694 * o refiguremode is false.
695 * o The widget is unrealized.
696 * o There are no panes is the paned widget.
698 * NOTE: This is the resize Proceedure for the Paned widget.
702 RefigureLocationsAndCommit(w
)
705 PanedWidget pw
= (PanedWidget
) w
;
706 if (pw
->paned
.refiguremode
&& XtIsRealized( (Widget
) pw
) &&
707 pw
->paned
.num_panes
> 0 ) {
708 RefigureLocations(pw
, NO_INDEX
, AnyPane
);
709 CommitNewLocations(pw
);
713 /* Function Name: _DrawRect
714 * Description: Draws a rectangle in the proper orientation.
715 * Arguments: pw - the paned widget.
716 * gc - gc to used for the draw.
717 * on_olc, off_loc - location of upper left corner of rect.
718 * on_size, off_size - size of rectangle.
723 _DrawRect(pw
, gc
, on_loc
, off_loc
, on_size
, off_size
)
727 unsigned int on_size
, off_size
;
730 XFillRectangle(XtDisplay(pw
), XtWindow(pw
), gc
,
731 off_loc
, on_loc
, off_size
, on_size
);
733 XFillRectangle(XtDisplay(pw
), XtWindow(pw
), gc
,
734 on_loc
, off_loc
, on_size
, off_size
);
737 /* Function Name: _DrawInternalBorders
738 * Description: Draws the internal borders into the paned widget.
739 * Arguments: pw - the paned widget.
740 * gc - the GC to use to draw the borders.
745 _DrawInternalBorders(pw
, gc
)
751 unsigned int on_size
, off_size
;
754 * This is an optomization. Do not paint the internal borders if
755 * they are the same color as the background.
758 if (pw
->core
.background_pixel
== pw
->paned
.internal_bp
)
762 off_size
= (unsigned int) PaneSize( (Widget
) pw
, !IsVert(pw
) );
763 on_size
= (unsigned int) pw
->paned
.internal_bw
;
765 ForAllPanes(pw
, childP
) {
766 on_loc
= IsVert(pw
) ? (*childP
)->core
.y
: (*childP
)->core
.x
;
767 on_loc
-= (int) on_size
;
769 _DrawRect( pw
, gc
, on_loc
, off_loc
, on_size
, off_size
);
774 * This allows good reuse of code, as well as descriptive function names.
777 #define DrawInternalBorders(pw) _DrawInternalBorders((pw), (pw)->paned.normgc);
778 #define EraseInternalBorders(pw) _DrawInternalBorders((pw), (pw)->paned.invgc);
780 /* Function Name: _DrawTrackLines
781 * Description: Draws the lines that animate the pane borders when the
783 * Arguments: pw - the Paned widget.
784 * erase - if True then just erase track lines, else
790 _DrawTrackLines(pw
, erase
)
797 unsigned int on_size
, off_size
;
800 off_size
= PaneSize( (Widget
) pw
, !IsVert(pw
));
802 ForAllPanes(pw
, childP
) {
803 pane
= PaneInfo(*childP
);
804 if ( erase
|| (pane
->olddelta
!= pane
->delta
) ) {
805 on_size
= pw
->paned
.internal_bw
;
807 on_loc
= PaneInfo(*childP
)->olddelta
- (int) on_size
;
809 _DrawRect( pw
, pw
->paned
.flipgc
,
810 on_loc
, off_loc
, on_size
, off_size
);
813 on_loc
= PaneInfo(*childP
)->delta
- (int) on_size
;
815 _DrawRect(pw
, pw
->paned
.flipgc
,
816 on_loc
, off_loc
, on_size
, off_size
);
818 pane
->olddelta
= pane
->delta
;
824 * This allows good reuse of code, as well as descriptive function names.
827 #define DrawTrackLines(pw) _DrawTrackLines((pw), FALSE);
828 #define EraseTrackLines(pw) _DrawTrackLines((pw), TRUE);
830 /* Function Name: GetEventLocation
831 * Description: Converts and event to an x and y locaion.
832 * Arguments: pw - the paned widget.
833 * event - a pointer to an event.
834 * Returns: if this is a vertical pane then (y) else (x).
838 GetEventLocation(pw
, event
)
844 switch (event
->xany
.type
) {
847 x
= event
->xbutton
.x_root
;
848 y
= event
->xbutton
.y_root
;
852 x
= event
->xkey
.x_root
;
853 y
= event
->xkey
.y_root
;
856 x
= event
->xmotion
.x_root
;
857 y
= event
->xmotion
.y_root
;
860 x
= pw
->paned
.start_loc
;
861 y
= pw
->paned
.start_loc
;
868 /* Function Name: StartGripAdjustment
869 * Description: Starts the grip adjustment proceedure.
870 * Arguments: pw - the paned widget.
871 * grip - the grip widget selected.
872 * dir - the direction that we are to be moving.
877 StartGripAdjustment(pw
, grip
, dir
)
885 pw
->paned
.whichadd
= pw
->paned
.whichsub
= (Widget
) NULL
;
887 if (dir
== ThisBorderOnly
|| dir
== UpLeftPane
)
888 pw
->paned
.whichadd
= pw
->composite
.children
[PaneIndex(grip
)];
889 if (dir
== ThisBorderOnly
|| dir
== LowRightPane
)
890 pw
->paned
.whichsub
= pw
->composite
.children
[PaneIndex(grip
) + 1];
896 if (XtIsRealized(grip
)) {
898 if (dir
== UpLeftPane
)
899 cursor
= pw
->paned
.adjust_upper_cursor
;
900 else if (dir
== LowRightPane
)
901 cursor
= pw
->paned
.adjust_lower_cursor
;
903 if ( pw
->paned
.adjust_this_cursor
== None
)
904 cursor
= pw
->paned
.v_adjust_this_cursor
;
906 cursor
= pw
->paned
.adjust_this_cursor
;
910 if (dir
== UpLeftPane
)
911 cursor
= pw
->paned
.adjust_left_cursor
;
912 else if (dir
== LowRightPane
)
913 cursor
= pw
->paned
.adjust_right_cursor
;
915 if (pw
->paned
.adjust_this_cursor
== None
)
916 cursor
= pw
->paned
.h_adjust_this_cursor
;
918 cursor
= pw
->paned
.adjust_this_cursor
;
922 XDefineCursor(XtDisplay(grip
), XtWindow(grip
), cursor
);
925 EraseInternalBorders(pw
);
926 ForAllPanes(pw
, childP
)
927 PaneInfo(*childP
)->olddelta
= -99;
930 /* Function Name: MoveGripAdjustment
931 * Description: This routine moves all panes around when a grip is moved.
932 * Arguments: pw - the paned widget.
933 * grip - the grip that we are moving.
934 * dir - the direction the pane we are interested is w.r.t the
936 * loc - location of pointer in proper direction.
941 MoveGripAdjustment(pw
, grip
, dir
, loc
)
947 int diff
, add_size
= 0, sub_size
= 0;
949 diff
= loc
- pw
->paned
.start_loc
;
951 if (pw
->paned
.whichadd
)
952 add_size
= PaneSize(pw
->paned
.whichadd
, IsVert(pw
) ) + diff
;
954 if (pw
->paned
.whichsub
)
955 sub_size
= PaneSize(pw
->paned
.whichsub
, IsVert(pw
) ) - diff
;
958 * If moving this border only then do not allow either of the borders
959 * to go beyond the min or max size allowed.
962 if ( (dir
== ThisBorderOnly
) ) {
963 int old_add_size
= add_size
, old_sub_size
;
965 AssignMax(add_size
, (int) PaneInfo(pw
->paned
.whichadd
)->min
);
966 AssignMin(add_size
, (int) PaneInfo(pw
->paned
.whichadd
)->max
);
967 if (add_size
!= old_add_size
)
968 sub_size
+= old_add_size
- add_size
;
970 old_sub_size
= sub_size
;
971 AssignMax(sub_size
, (int) PaneInfo(pw
->paned
.whichsub
)->min
);
972 AssignMin(sub_size
, (int) PaneInfo(pw
->paned
.whichsub
)->max
);
973 if (sub_size
!= old_sub_size
) return; /* Abort to current sizes. */
977 PaneInfo(pw
->paned
.whichadd
)->size
= add_size
;
979 PaneInfo(pw
->paned
.whichsub
)->size
= sub_size
;
980 RefigureLocations(pw
, PaneIndex(grip
), dir
);
984 /* Function Name: CommitGripAdjustment
985 * Description: Commits the grip adjustment.
986 * Arguments: pw - the paned widget.
990 CommitGripAdjustment(pw
)
994 CommitNewLocations(pw
);
995 DrawInternalBorders(pw
);
998 * Since the user selected this size then use it as the preferred size.
1001 if (pw
->paned
.whichadd
) {
1002 Pane pane
= PaneInfo(pw
->paned
.whichadd
);
1003 pane
->wp_size
= pane
->size
;
1005 if (pw
->paned
.whichsub
) {
1006 Pane pane
= PaneInfo(pw
->paned
.whichsub
);
1007 pane
->wp_size
= pane
->size
;
1011 /* Function Name: HandleGrip
1012 * Description: Handles the grip manipulations.
1013 * Arguments: grip - the grip widget that has been moved.
1014 * junk - ** NOT USED **
1015 * call_data - data passed to us from the grip widget.
1021 HandleGrip(grip
, junk
, callData
)
1023 caddr_t junk
, callData
;
1025 GripCallData call_data
= (GripCallData
)callData
;
1026 PanedWidget pw
= (PanedWidget
) XtParent(grip
);
1030 Direction direction
;
1033 action_type
= *call_data
->params
[0];
1035 if (call_data
->num_params
== 0 ||
1036 (action_type
== 'C' && call_data
->num_params
!= 1) ||
1037 (action_type
!= 'C' && call_data
->num_params
!= 2))
1038 XtError( "Paned GripAction has been passed incorrect parameters." );
1040 if (islower(action_type
)) action_type
= toupper(action_type
);
1042 loc
= GetEventLocation(pw
, (XEvent
*) (call_data
->event
));
1044 if (action_type
!= 'C') {
1045 if ( isupper(*call_data
->params
[1]) )
1046 direction
= (Direction
) *call_data
->params
[1];
1048 direction
= (Direction
) toupper(*call_data
->params
[1]);
1051 switch (action_type
) {
1052 case 'S': /* Start adjustment */
1053 pw
->paned
.resize_children_to_pref
= FALSE
;
1054 StartGripAdjustment(pw
, grip
, direction
);
1055 pw
->paned
.start_loc
= loc
;
1059 MoveGripAdjustment(pw
, grip
, direction
, loc
);
1063 XtSetArg(arglist
[0], XtNcursor
, &cursor
);
1064 XtGetValues(grip
, arglist
, (Cardinal
) 1);
1065 XDefineCursor(XtDisplay(grip
), XtWindow(grip
), cursor
);
1066 CommitGripAdjustment(pw
);
1070 XtError( "Paned GripAction(); 1st parameter invalid" );
1074 /* Function Name: ResortChildren
1075 * Description: Resorts the children so that all managed children
1077 * Arguments: pw - the paned widget.
1085 Widget
* unmanagedP
, * childP
;
1088 ForAllChildren(pw
, childP
) {
1089 if (!IsPane(*childP
) || !XtIsManaged(*childP
)) {
1091 * We only keep track of the first unmanaged pane.
1093 if (unmanagedP
== NULL
)
1094 unmanagedP
= childP
;
1096 else { /* must be a managed pane */
1098 * If an earlier widget was not a managed pane, then swap
1100 if (unmanagedP
!= NULL
) {
1101 Widget child
= *unmanagedP
;
1102 *unmanagedP
= *childP
;
1104 childP
= unmanagedP
; /* easiest to just back-track */
1105 unmanagedP
= NULL
; /* in case there is another managed */
1111 /* Function Name: ManageAndUnmanageGrips
1112 * Description: This function manages and unmanages the grips so that
1113 * the managed state of each grip matches that of its pane.
1114 * Arguments: pw - the paned widget.
1119 ManageAndUnmanageGrips(pw
)
1122 WidgetList managed_grips
, unmanaged_grips
;
1123 Widget
*managedP
, *unmanagedP
, *childP
;
1124 Cardinal alloc_size
;
1126 alloc_size
= (Cardinal
) sizeof(Widget
) * pw
->composite
.num_children
/ 2;
1127 managedP
= managed_grips
= (WidgetList
) XtMalloc(alloc_size
);
1128 unmanagedP
= unmanaged_grips
= (WidgetList
) XtMalloc(alloc_size
);
1130 ForAllChildren(pw
, childP
)
1131 if (IsPane(*childP
) && HasGrip(*childP
))
1132 if ( XtIsManaged(*childP
) )
1133 *managedP
++ = PaneInfo(*childP
)->grip
;
1135 *unmanagedP
++ = PaneInfo(*childP
)->grip
;
1137 if (managedP
!= managed_grips
) {
1138 *unmanagedP
++ = *--managedP
; /* Last grip is never managed */
1139 XtManageChildren( managed_grips
, (Cardinal
)(managedP
- managed_grips
) );
1142 if (unmanagedP
!= unmanaged_grips
)
1143 XtUnmanageChildren( unmanaged_grips
,
1144 (Cardinal
)(unmanagedP
- unmanaged_grips
) );
1146 XtFree((caddr_t
)managed_grips
);
1147 XtFree((caddr_t
)unmanaged_grips
);
1150 /* Function Name: CreateGrip
1151 * Description: Creates a grip widget.
1152 * Arguments: child - the child that wants a grip to be created for it.
1160 PanedWidget pw
= (PanedWidget
) XtParent(child
);
1162 Cardinal num_args
= 0;
1165 XtSetArg(arglist
[num_args
], XtNtranslations
, pw
->paned
.grip_translations
);
1167 if ( (cursor
= pw
->paned
.grip_cursor
) == None
)
1169 cursor
= pw
->paned
.v_grip_cursor
;
1171 cursor
= pw
->paned
.h_grip_cursor
;
1173 XtSetArg(arglist
[num_args
], XtNcursor
, cursor
);
1175 PaneInfo(child
)->grip
= XtCreateWidget("grip", gripWidgetClass
, (Widget
)pw
,
1178 XtAddCallback(PaneInfo(child
)->grip
, XtNcallback
,
1179 (XtCallbackProc
)HandleGrip
, (caddr_t
) child
);
1182 /* Function Name: GetGCs
1183 * Description: Gets new GC's.
1184 * Arguments: w - the paned widget.
1192 PanedWidget pw
= (PanedWidget
) w
;
1197 * Draw pane borders in internal border color.
1200 values
.foreground
= pw
->paned
.internal_bp
;
1201 valuemask
= GCForeground
;
1202 pw
->paned
.normgc
= XtGetGC(w
, valuemask
, &values
);
1205 * Erase pane borders with background color.
1208 values
.foreground
= pw
->core
.background_pixel
;
1209 valuemask
= GCForeground
;
1210 pw
->paned
.invgc
= XtGetGC(w
, valuemask
, &values
);
1213 * Draw Track lines (animate pane borders) in internal border color ^ bg color.
1216 values
.function
= GXinvert
;
1217 values
.plane_mask
= pw
->paned
.internal_bp
^ pw
->core
.background_pixel
;
1218 values
.subwindow_mode
= IncludeInferiors
;
1219 valuemask
= GCPlaneMask
| GCFunction
| GCSubwindowMode
;
1220 pw
->paned
.flipgc
= XtGetGC(w
, valuemask
, &values
);
1223 /* Function Name: SetChildrenPrefSizes.
1224 * Description: Sets the preferred sizes of the children.
1225 * Arguments: pw - the paned widget.
1230 SetChildrenPrefSizes(pw
, off_size
)
1235 Boolean vert
= IsVert(pw
);
1236 XtWidgetGeometry request
, reply
;
1238 ForAllPanes(pw
, childP
)
1239 if ( pw
->paned
.resize_children_to_pref
||
1240 (PaneInfo(*childP
)->size
== 0) ||
1241 (PaneInfo(*childP
)->resize_to_pref
) ) {
1243 if (PaneInfo(*childP
)->preferred_size
!= PANED_ASK_CHILD
)
1244 PaneInfo(*childP
)->wp_size
=PaneInfo(*childP
)->preferred_size
;
1247 request
.request_mode
= CWWidth
;
1248 request
.width
= off_size
;
1251 request
.request_mode
= CWHeight
;
1252 request
.height
= off_size
;
1255 if ((XtQueryGeometry( *childP
, &request
, &reply
)
1256 == XtGeometryAlmost
) &&
1257 (reply
.request_mode
= (vert
? CWHeight
: CWWidth
)))
1258 PaneInfo(*childP
)->wp_size
= GetRequestInfo(&reply
, vert
);
1260 PaneInfo(*childP
)->wp_size
= PaneSize(*childP
, vert
);
1263 PaneInfo(*childP
)->size
= PaneInfo(*childP
)->wp_size
;
1267 /* Function Name: ChangeAllGripCursors
1268 * Description: Changes all the grip cursors.
1269 * Arguments: pw - the paned widget.
1274 ChangeAllGripCursors(pw
)
1279 ForAllPanes(pw
, childP
) {
1283 if ( (cursor
= pw
->paned
.grip_cursor
) == None
)
1285 cursor
= pw
->paned
.v_grip_cursor
;
1287 cursor
= pw
->paned
.h_grip_cursor
;
1289 if (HasGrip (*childP
)) {
1290 XtSetArg(arglist
[0], XtNcursor
, cursor
);
1291 XtSetValues(PaneInfo(*childP
)->grip
, arglist
, (Cardinal
) 1);
1296 /************************************************************
1298 * Stack Manipulation routines (Private).
1300 ************************************************************/
1302 /* Function Name: PushPaneStack
1303 * Description: Pushes a value onto the pane stack.
1304 * Arguments: pw - the paned widget.
1305 * pane - the pane that we are pushing.
1310 PushPaneStack(pw
, pane
)
1314 PaneStack
* stack
= (PaneStack
*) XtMalloc(sizeof(PaneStack
));
1316 stack
->next
= pw
->paned
.stack
;
1318 stack
->start_size
= pane
->size
;
1320 pw
->paned
.stack
= stack
;
1323 /* Function Name: GetPaneStack
1324 * Description: Gets the top value from the pane stack.
1325 * Arguments: pw - the paned widget.
1326 * shrink - TRUE if we want to shrink this pane,
1328 * ** RETURNED ** pane - the pane that we are popping.
1329 * ** RETURNED ** start_size - the size that this pane started at.
1334 GetPaneStack(pw
, shrink
, pane
, start_size
)
1340 if (pw
->paned
.stack
== NULL
) {
1345 *pane
= pw
->paned
.stack
->pane
;
1346 *start_size
= pw
->paned
.stack
->start_size
;
1348 if (shrink
!= ((*pane
)->size
> *start_size
)) *pane
= NULL
;
1351 /* Function Name: PopPaneStack
1352 * Description: Pops the top item off the pane stack.
1353 * Arguments: pw - the paned widget.
1354 * Returns: TRUE if this is not the last element on the stack.
1361 PaneStack
* stack
= pw
->paned
.stack
;
1363 if (stack
== NULL
) return(FALSE
);
1365 pw
->paned
.stack
= stack
->next
;
1366 XtFree((char *)stack
);
1368 if (pw
->paned
.stack
== NULL
) return(FALSE
);
1372 /* Function Name: ClearPaneStack
1373 * Description: removes all entries from the pane stack.
1374 * Arguments: pw - the paned widget.
1382 while(PopPaneStack(pw
));
1385 /************************************************************
1387 * Semi-public routines.
1389 ************************************************************/
1391 /* Function Name: ClassInitialize
1392 * Description: The Paned widgets class initialization proc.
1400 XawInitializeWidgetSet();
1401 XtAddConverter( XtRString
, XtROrientation
, XmuCvtStringToOrientation
,
1402 NULL
, (Cardinal
)0 );
1405 /* The Geometry Manager only allows changes after Realize if
1406 * allow_resize is True in the constraints record.
1408 * For vertically paned widgets:
1410 * It only allows height changes, but offers the requested height
1411 * as a compromise if both width and height changes were requested.
1413 * For horizontal widgets the coverse is true.
1414 * As all good Geometry Managers should, we will return No if the
1415 * request will have no effect; i.e. when the requestor is already
1416 * of the desired geometry.
1419 static XtGeometryResult
GeometryManager(w
, request
, reply
)
1421 XtWidgetGeometry
*request
, *reply
;
1423 PanedWidget pw
= (PanedWidget
) XtParent(w
);
1424 XtGeometryMask mask
= request
->request_mode
;
1425 Dimension old_size
, old_wpsize
, old_paned_size
;
1426 Pane pane
= PaneInfo(w
);
1427 register Boolean vert
= IsVert(pw
);
1428 Dimension on_size
, off_size
;
1429 XtGeometryResult result
;
1430 Boolean almost
= FALSE
;
1433 * If any of the following is true, disallow the geometry change.
1435 * o The paned widget is realized and allow_resize is false for the pane.
1436 * o The child did not ask to change the on_size.
1437 * o The request is not a width or height request.
1438 * o The requested size is the same as the current size.
1441 if ( (XtIsRealized((Widget
)pw
) && !pane
->allow_resize
) ||
1442 !(mask
& ((vert
) ? CWHeight
: CWWidth
)) ||
1443 (mask
& ~(CWWidth
| CWHeight
)) ||
1444 (GetRequestInfo(request
, vert
) == PaneSize(w
, vert
)) ) {
1445 return XtGeometryNo
;
1448 old_paned_size
= PaneSize( (Widget
) pw
, vert
);
1449 old_wpsize
= pane
->wp_size
;
1450 old_size
= pane
->size
;
1452 pane
->wp_size
= pane
->size
= GetRequestInfo(request
, vert
);
1454 AdjustPanedSize(pw
, PaneSize((Widget
) pw
, !vert
), &result
, &on_size
,
1458 * Fool the Refigure Locations proc to thinking that we are
1459 * a different on_size;
1462 if (result
!= XtGeometryNo
)
1464 pw
->core
.height
= on_size
;
1466 pw
->core
.width
= on_size
;
1468 RefigureLocations(pw
, PaneIndex(w
), AnyPane
);
1471 * Set up reply struct and reset core on_size.
1475 pw
->core
.height
= old_paned_size
;
1476 reply
->height
= pane
->size
;
1477 reply
->width
= off_size
;
1480 pw
->core
.width
= old_paned_size
;
1481 reply
->height
= off_size
;
1482 reply
->width
= pane
->size
;
1486 * IF either of the following is true.
1488 * o There was a "off_size" request and the new "off_size" is different
1489 * from that requested.
1490 * o There was no "off_size" request and the new "off_size" is different
1492 * o The "on_size" we will allow is different from that requested.
1497 if ( !((vert
? CWWidth
: CWHeight
) & mask
))
1499 request
->width
= w
->core
.width
;
1501 request
->height
= w
->core
.height
;
1503 almost
= GetRequestInfo(request
, !vert
) != GetRequestInfo(reply
, !vert
);
1504 almost
|= GetRequestInfo(request
, vert
) != GetRequestInfo(reply
, vert
);
1506 if ( (mask
& XtCWQueryOnly
) || almost
) {
1507 pane
->wp_size
= old_wpsize
;
1508 pane
->size
= old_size
;
1509 RefigureLocations(pw
, PaneIndex(w
), AnyPane
);
1510 reply
->request_mode
= CWWidth
| CWHeight
;
1511 if (almost
) return XtGeometryAlmost
;
1514 AdjustPanedSize(pw
, PaneSize((Widget
) pw
, !vert
), NULL
, NULL
, NULL
);
1515 CommitNewLocations( pw
); /* layout already refigured. */
1517 return XtGeometryDone
;
1521 static void Initialize(request
, new)
1522 Widget request
, new;
1524 PanedWidget pw
= (PanedWidget
)new;
1526 GetGCs( (Widget
) pw
);
1528 pw
->paned
.recursively_called
= False
;
1529 pw
->paned
.stack
= NULL
;
1530 pw
->paned
.resize_children_to_pref
= TRUE
;
1531 pw
->paned
.num_panes
= 0;
1535 Realize(w
, valueMask
, attributes
)
1538 XSetWindowAttributes
*attributes
;
1540 PanedWidget pw
= (PanedWidget
) w
;
1543 if ((attributes
->cursor
= (pw
)->paned
.cursor
) != None
)
1544 *valueMask
|= CWCursor
;
1546 (*SuperClass
->core_class
.realize
) (w
, valueMask
, attributes
);
1549 * Before we commit the new locations we need to realize all the panes and
1553 ForAllPanes(pw
, childP
) {
1554 XtRealizeWidget( *childP
);
1555 if (HasGrip (*childP
))
1556 XtRealizeWidget( PaneInfo(*childP
)->grip
);
1559 RefigureLocationsAndCommit(w
);
1566 register PanedWidget pw
= (PanedWidget
)w
;
1568 XtReleaseGC( w
, pw
->paned
.normgc
);
1569 XtReleaseGC( w
, pw
->paned
.invgc
);
1570 XtReleaseGC( w
, pw
->paned
.flipgc
);
1573 static void InsertChild(w
)
1576 Pane pane
= PaneInfo(w
);
1578 /* insert the child widget in the composite children list with the */
1579 /* superclass insert_child routine. */
1580 (*SuperClass
->composite_class
.insert_child
)(w
);
1582 if (!IsPane(w
)) return;
1584 /* ||| Panes will be added in the order they are created, temporarilly */
1586 if ( pane
->show_grip
== TRUE
) {
1588 if (pane
->min
== PANED_GRIP_SIZE
)
1589 pane
->min
= PaneSize(pane
->grip
, IsVert((PanedWidget
) XtParent(w
)));
1592 if (pane
->min
== PANED_GRIP_SIZE
)
1598 pane
->paned_adjusted_me
= FALSE
;
1602 static void DeleteChild(w
)
1605 /* remove the subwidget info and destroy the grip */
1607 if ( IsPane(w
) && HasGrip(w
) ) XtDestroyWidget(PaneInfo(w
)->grip
);
1609 /* delete the child widget in the composite children list with the */
1610 /* superclass delete_child routine. */
1611 (*SuperClass
->composite_class
.delete_child
) (w
);
1615 static void ChangeManaged(w
)
1618 PanedWidget pw
= (PanedWidget
)w
;
1619 Boolean vert
= IsVert(pw
);
1621 register Widget
*childP
;
1623 if (pw
->paned
.recursively_called
++) return;
1626 * If the size is zero then set it to the size of the widest or tallest pane.
1629 if ( (size
= PaneSize( (Widget
) pw
, !vert
)) == 0) {
1631 ForAllChildren(pw
, childP
)
1632 if ( XtIsManaged(*childP
) && (PaneSize( *childP
, !vert
) > size
) )
1633 size
= PaneSize( *childP
, !vert
);
1636 ManageAndUnmanageGrips(pw
);
1637 pw
->paned
.recursively_called
= False
;
1640 pw
->paned
.num_panes
= 0;
1641 ForAllChildren(pw
, childP
)
1642 if ( IsPane(*childP
) )
1643 if ( XtIsManaged(*childP
) ) {
1644 Pane pane
= PaneInfo(*childP
);
1645 if (HasGrip(*childP
))
1646 PaneInfo(pane
->grip
)->position
= pw
->paned
.num_panes
;
1647 pane
->position
= pw
->paned
.num_panes
; /*TEMPORY -CDP 3/89 */
1648 pw
->paned
.num_panes
++;
1651 break; /* This list is already sorted. */
1653 SetChildrenPrefSizes( (PanedWidget
) w
, size
);
1656 * ForAllPanes can now be used.
1659 if ( PaneSize((Widget
) pw
, vert
) == 0 )
1660 AdjustPanedSize(pw
, size
, NULL
, NULL
, NULL
);
1662 if (XtIsRealized( (Widget
) pw
))
1663 RefigureLocationsAndCommit( (Widget
) pw
);
1665 } /* ChangeManaged */
1667 /* Function Name: Resize
1668 * Description: The paned widget's resize proc.
1669 * Arguments: w - the paned widget.
1677 SetChildrenPrefSizes( (PanedWidget
) w
,
1678 PaneSize(w
, !IsVert((PanedWidget
) w
)) );
1679 RefigureLocationsAndCommit(w
);
1684 Redisplay(w
, event
, region
)
1686 XEvent
* event
; /* unused. */
1687 Region region
; /* unused. */
1689 ((PanedWidget
) w
)->paned
.resize_children_to_pref
= FALSE
;
1690 DrawInternalBorders( (PanedWidget
) w
);
1695 SetValues(old
, request
, new)
1696 Widget old
, request
, new;
1698 PanedWidget old_pw
= (PanedWidget
) old
;
1699 PanedWidget new_pw
= (PanedWidget
) new;
1700 Boolean redisplay
= FALSE
;
1702 if ( (old_pw
->paned
.cursor
!= new_pw
->paned
.cursor
) && XtIsRealized(new))
1703 XDefineCursor(XtDisplay(new), XtWindow(new), new_pw
->paned
.cursor
);
1705 if ( (old_pw
->paned
.internal_bp
!= new_pw
->paned
.internal_bp
) ||
1706 (old_pw
->core
.background_pixel
!= new_pw
->core
.background_pixel
) ) {
1712 if ( (old_pw
->paned
.grip_cursor
!= new_pw
->paned
.grip_cursor
) ||
1713 (old_pw
->paned
.v_grip_cursor
!= new_pw
->paned
.v_grip_cursor
) ||
1714 (old_pw
->paned
.h_grip_cursor
!= new_pw
->paned
.h_grip_cursor
) ) {
1715 ChangeAllGripCursors(new_pw
);
1718 if ( IsVert(old_pw
) != IsVert(new_pw
)) {
1720 * We are fooling the paned widget into thinking that is needs to
1721 * fully refigure everything, which is what we want.
1724 new_pw
->core
.width
= 0;
1726 new_pw
->core
.height
= 0;
1728 new_pw
->paned
.resize_children_to_pref
= TRUE
;
1729 ChangeManaged(new); /* Seems weird, but does the right thing. */
1730 new_pw
->paned
.resize_children_to_pref
= FALSE
;
1731 if (new_pw
->paned
.grip_cursor
== None
)
1732 ChangeAllGripCursors(new_pw
);
1736 if (old_pw
->paned
.internal_bw
!= new_pw
->paned
.internal_bw
) {
1737 AdjustPanedSize( new_pw
, PaneSize(new, !IsVert(old_pw
)),
1739 RefigureLocationsAndCommit(new);
1740 return(TRUE
); /* We have done a full configuration, return.*/
1743 if ( (old_pw
->paned
.grip_indent
!= new_pw
->paned
.grip_indent
) &&
1744 (XtIsRealized(new)) ) {
1745 CommitNewLocations(new_pw
);
1755 PaneSetValues(old
, request
, new)
1756 Widget old
, request
, new;
1758 Pane old_pane
= PaneInfo(old
);
1759 Pane new_pane
= PaneInfo(new);
1760 Boolean redisplay
= FALSE
;
1762 /* Check for new min and max. */
1764 if (old_pane
->min
!= new_pane
->min
|| old_pane
->max
!= new_pane
->max
)
1765 XawPanedSetMinMax(new, (int)new_pane
->min
, (int)new_pane
->max
);
1767 /* Check for change in XtNshowGrip. */
1769 if (old_pane
->show_grip
!= new_pane
->show_grip
)
1770 if (new_pane
->show_grip
== TRUE
) {
1772 if (XtIsRealized(XtParent(new))) {
1773 if (XtIsManaged(new)) /* if paned is unrealized this will
1774 happen automatically at realize time.*/
1775 XtManageChild(PaneInfo(new)->grip
); /* manage the grip. */
1776 XtRealizeWidget(PaneInfo(new)->grip
); /* realize the grip. */
1777 CommitNewLocations( (PanedWidget
) XtParent(new) );
1780 else if ( HasGrip(old
) ) {
1781 XtDestroyWidget( old_pane
->grip
);
1782 new_pane
->grip
= NULL
;
1786 /* ||| need to look at position changes */
1791 /************************************************************
1795 ************************************************************/
1797 /* Function Name: XawPanedSetMinMax
1798 * Description: Sets the min and max size for a pane.
1799 * Arguments: widget - the widget that is a child of the Paned widget.
1800 * min, max - the new min and max size for the pane.
1805 XawPanedSetMinMax(widget
, min
, max
)
1809 Pane pane
= PaneInfo(widget
);
1813 RefigureLocationsAndCommit( widget
->core
.parent
);
1816 /* Function Name: XawPanedGetMinMax
1817 * Description: Gets the min and max size for a pane.
1818 * Arguments: widget - the widget that is a child of the Paned widget.
1819 ** RETURNED ** min, max - the current min and max size for the pane.
1824 XawPanedGetMinMax(widget
, min
, max
)
1828 Pane pane
= PaneInfo(widget
);
1834 /* Function Name: XawPanedSetRefigureMode
1835 * Description: Allows a flag to be set the will inhibit
1836 * the paned widgets relayout routine.
1837 * Arguments: w - the paned widget.
1838 * mode - if FALSE then inhibit refigure.
1843 XawPanedSetRefigureMode(w
, mode
)
1847 ((PanedWidget
) w
)->paned
.refiguremode
= mode
;
1848 RefigureLocationsAndCommit( w
);
1851 /* Function Name: XawPanedGetNumSub
1852 * Description: Returns the number of panes in the paned widget.
1853 * Arguments: w - the paned widget.
1854 * Returns: the number of panes in the paned widget.
1858 XawPanedGetNumSub(w
)
1861 return ((PanedWidget
)w
)->paned
.num_panes
;
1864 /* Function Name: XawPanedAllowResize
1865 * Description: Allows a flag to be set that determines if the paned
1866 * widget will allow geometry requests from this child
1867 * Arguments: widget - a child of the paned widget.
1872 XawPanedAllowResize(widget
, allow_resize
)
1874 Boolean allow_resize
;
1876 PaneInfo(widget
)->allow_resize
= allow_resize
;