comparison lwlib/xlwtabs.c @ 434:9d177e8d4150 r21-2-25

Import from CVS: tag r21-2-25
author cvs
date Mon, 13 Aug 2007 11:30:53 +0200
parents 3a7e78e1142d
children 080151679be2
comparison
equal deleted inserted replaced
433:892ca416f0fb 434:9d177e8d4150
16 You should have received a copy of the GNU General Public License 16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to 17 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */ 19 Boston, MA 02111-1307, USA. */
20 20
21 /* Synched up with: Tabs.c 1.25 */ 21 /* Synched up with: Tabs.c 1.27 */
22 22
23 /* 23 /*
24 * Tabs.c - Index Tabs composite widget 24 * Tabs.c - Index Tabs composite widget
25 * 25 *
26 * Author: Edward A. Falk 26 * Author: Edward A. Falk
49 * The tabs overlap the frame and each other vertically by the shadow 49 * The tabs overlap the frame and each other vertically by the shadow
50 * width, so that when the topmost tab is drawn, it obliterates part of 50 * width, so that when the topmost tab is drawn, it obliterates part of
51 * the frame. 51 * the frame.
52 */ 52 */
53 53
54 /* TODO: min child height = tab height 54 /*
55 * 55 * TODO: min child height = tab height
56 */ 56 */
57 57
58 #include <config.h> 58 #include <config.h>
59 #include <stdio.h> 59 #include <stdio.h>
60 60
187 static void TabsResize(); 187 static void TabsResize();
188 static void TabsExpose(); 188 static void TabsExpose();
189 static void TabsDestroy(); 189 static void TabsDestroy();
190 static void TabsRealize(); 190 static void TabsRealize();
191 static Boolean TabsSetValues(); 191 static Boolean TabsSetValues();
192 static Boolean TabsAcceptFocus();
192 static XtGeometryResult TabsQueryGeometry(); 193 static XtGeometryResult TabsQueryGeometry();
193 static XtGeometryResult TabsGeometryManager(); 194 static XtGeometryResult TabsGeometryManager();
194 static void TabsChangeManaged(); 195 static void TabsChangeManaged();
195 static void TabsConstraintInitialize() ; 196 static void TabsConstraintInitialize() ;
196 static Boolean TabsConstraintSetValues() ; 197 static Boolean TabsConstraintSetValues() ;
235 static void TabsRealize(Widget, Mask *, XSetWindowAttributes *) ; 236 static void TabsRealize(Widget, Mask *, XSetWindowAttributes *) ;
236 static void TabsDestroy( Widget w) ; 237 static void TabsDestroy( Widget w) ;
237 static void TabsResize( Widget w) ; 238 static void TabsResize( Widget w) ;
238 static void TabsExpose( Widget w, XEvent *event, Region region) ; 239 static void TabsExpose( Widget w, XEvent *event, Region region) ;
239 static Boolean TabsSetValues(Widget, Widget, Widget, ArgList, Cardinal *) ; 240 static Boolean TabsSetValues(Widget, Widget, Widget, ArgList, Cardinal *) ;
241 static Boolean TabsAcceptFocus(Widget, Time *);
240 static Boolean TabsConstraintSetValues(Widget, Widget, Widget, 242 static Boolean TabsConstraintSetValues(Widget, Widget, Widget,
241 ArgList, Cardinal *) ; 243 ArgList, Cardinal *) ;
242 static XtGeometryResult TabsQueryGeometry(Widget, 244 static XtGeometryResult TabsQueryGeometry(Widget,
243 XtWidgetGeometry *, XtWidgetGeometry *) ; 245 XtWidgetGeometry *, XtWidgetGeometry *) ;
244 static XtGeometryResult TabsGeometryManager(Widget, 246 static XtGeometryResult TabsGeometryManager(Widget,
261 263
262 static void TabWidth( Widget w) ; 264 static void TabWidth( Widget w) ;
263 static int TabLayout( TabsWidget, int wid, int hgt, Dimension *r_hgt, 265 static int TabLayout( TabsWidget, int wid, int hgt, Dimension *r_hgt,
264 Bool query_only) ; 266 Bool query_only) ;
265 static void GetPreferredSizes(TabsWidget) ; 267 static void GetPreferredSizes(TabsWidget) ;
266 static void MaxChild(TabsWidget) ; 268 static void MaxChild(TabsWidget, Widget except, Dimension, Dimension) ;
267 static void TabsShuffleRows( TabsWidget tw) ; 269 static void TabsShuffleRows( TabsWidget tw) ;
268 static int PreferredSize( TabsWidget, 270 static int PreferredSize( TabsWidget,
269 Dimension *reply_width, Dimension *reply_height, 271 Dimension *reply_width, Dimension *reply_height,
270 Dimension *reply_cw, Dimension *reply_ch) ; 272 Dimension *reply_cw, Dimension *reply_ch) ;
271 static int PreferredSize2( TabsWidget, int cw, int ch, 273 static int PreferredSize2( TabsWidget, int cw, int ch,
323 /* num_actions */ XtNumber(actionsList), 325 /* num_actions */ XtNumber(actionsList),
324 /* resources */ resources, 326 /* resources */ resources,
325 /* num_resources */ XtNumber(resources), 327 /* num_resources */ XtNumber(resources),
326 /* xrm_class */ NULLQUARK, 328 /* xrm_class */ NULLQUARK,
327 /* compress_motion */ TRUE, 329 /* compress_motion */ TRUE,
328 /* compress_exposure */ TRUE, 330 #if XtSpecificationRelease < 6
331 /* compress_exposure */ XtExposeCompressMaximal,
332 #else
333 /* compress_exposure */ XtExposeCompressMaximal|XtExposeNoRegion,
334 #endif
329 /* compress_enterleave*/ TRUE, 335 /* compress_enterleave*/ TRUE,
330 /* visible_interest */ FALSE, 336 /* visible_interest */ TRUE,
331 /* destroy */ TabsDestroy, 337 /* destroy */ TabsDestroy,
332 /* resize */ TabsResize, 338 /* resize */ TabsResize,
333 /* expose */ TabsExpose, 339 /* expose */ TabsExpose,
334 /* set_values */ TabsSetValues, 340 /* set_values */ TabsSetValues,
335 /* set_values_hook */ NULL, 341 /* set_values_hook */ NULL,
336 /* set_values_almost */ XtInheritSetValuesAlmost, 342 /* set_values_almost */ XtInheritSetValuesAlmost,
337 /* get_values_hook */ NULL, 343 /* get_values_hook */ NULL,
338 /* accept_focus */ NULL, 344 /* accept_focus */ TabsAcceptFocus,
339 /* version */ XtVersion, 345 /* version */ XtVersion,
340 /* callback_private */ NULL, 346 /* callback_private */ NULL,
341 /* tm_table */ defaultTranslations, 347 /* tm_table */ defaultTranslations,
342 /* query_geometry */ TabsQueryGeometry, 348 /* query_geometry */ TabsQueryGeometry,
343 /* display_accelerator*/ XtInheritDisplayAccelerator, 349 /* display_accelerator*/ XtInheritDisplayAccelerator,
458 newTw->tabs.botGC = None ; 464 newTw->tabs.botGC = None ;
459 465
460 newTw->tabs.grey50 = None ; 466 newTw->tabs.grey50 = None ;
461 467
462 newTw->tabs.needs_layout = False ; 468 newTw->tabs.needs_layout = False ;
463 469
464 newTw->tabs.hilight = NULL ; 470 newTw->tabs.hilight = NULL ;
465 471
466 #ifdef NEED_MOTIF 472 #ifdef NEED_MOTIF
467 newTw->manager.navigation_type = XmTAB_GROUP ; 473 newTw->manager.navigation_type = XmTAB_GROUP ;
468 newTw->manager.traversal_on = True ; 474 newTw->manager.traversal_on = True ;
478 TabsConstraintInitialize(Widget request, Widget new, 484 TabsConstraintInitialize(Widget request, Widget new,
479 ArgList args, Cardinal *num_args) 485 ArgList args, Cardinal *num_args)
480 { 486 {
481 TabsConstraints tab = (TabsConstraints) new->core.constraints ; 487 TabsConstraints tab = (TabsConstraints) new->core.constraints ;
482 tab->tabs.greyAlloc = False ; /* defer allocation of pixel */ 488 tab->tabs.greyAlloc = False ; /* defer allocation of pixel */
483 tab->tabs.queried = False ; /* defer size query */
484 489
485 getBitmapInfo((TabsWidget)XtParent(new), tab) ; 490 getBitmapInfo((TabsWidget)XtParent(new), tab) ;
486 TabWidth(new) ; 491 TabWidth(new) ;
487 } 492 }
488 493
537 * Once the tabs are laid out, if there is more than one 542 * Once the tabs are laid out, if there is more than one
538 * row, we may need to shuffle the rows to bring the top tab 543 * row, we may need to shuffle the rows to bring the top tab
539 * to the bottom row. 544 * to the bottom row.
540 */ 545 */
541 546
547 tw->tabs.needs_layout = False ;
548
542 if( num_children > 0 && tw->composite.children != NULL ) 549 if( num_children > 0 && tw->composite.children != NULL )
543 { 550 {
544 /* Loop through the tabs and assign rows & x positions */ 551 /* Loop through the tabs and assign rows & x positions */
545 (void) TabLayout(tw, tw->core.width, tw->core.height, NULL, False) ; 552 (void) TabLayout(tw, tw->core.width, tw->core.height, NULL, False) ;
546 num_children = tw->tabs.displayChildren; 553 num_children = tw->tabs.displayChildren;
552 * same: just inside the frame. Sizes are also all the same. 559 * same: just inside the frame. Sizes are also all the same.
553 */ 560 */
554 561
555 tw->tabs.child_width = cw = tw->core.width - 2 * SHADWID ; 562 tw->tabs.child_width = cw = tw->core.width - 2 * SHADWID ;
556 tw->tabs.child_height = ch = 563 tw->tabs.child_height = ch =
557 tw->core.height - tw->tabs.tab_total - 2 * SHADWID ; 564 tw->core.height - tw->tabs.tab_total - 2 * SHADWID ;
558 565
559 566
560 for(i=0, childP=tw->composite.children; 567 for(i=0, childP=tw->composite.children;
561 i < num_children; 568 i < num_children;
562 ++i, ++childP) 569 ++i, ++childP)
563 if( XtIsManaged(*childP) ) 570 if( XtIsManaged(*childP) )
564 { 571 {
565 tab = (TabsConstraints) (*childP)->core.constraints ; 572 tab = (TabsConstraints) (*childP)->core.constraints ;
566 bw = tab->tabs.bwid ; 573 bw = (*childP)->core.border_width ;
567 XtConfigureWidget(*childP, SHADWID,tw->tabs.tab_total+SHADWID, 574 XtConfigureWidget(*childP, SHADWID,tw->tabs.tab_total+SHADWID,
568 cw-bw*2,ch-bw*2, bw) ; 575 cw-bw*2,ch-bw*2, bw) ;
569 } 576 }
570 if( XtIsRealized(w) ) 577 if( XtIsRealized(w) ) {
571 { 578 XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ;
572 XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ; 579 /* should not be necessary to explicitly repaint after a
573 tw->tabs.needs_layout = False ; 580 * resize, but XEmacs folks tell me it is.
574 XtClass(tw)->core_class.expose((Widget)tw,NULL,None) ; 581 */
575 } 582 XtClass(tw)->core_class.expose((Widget)tw,NULL,None) ;
576 } 583 }
577 584 }
578 tw->tabs.needs_layout = False ;
579 } /* Resize */ 585 } /* Resize */
580 586
581 587
582 588
583 /* Redraw entire Tabs widget */ 589 /* Redraw entire Tabs widget */
729 735
730 return False ; 736 return False ;
731 } 737 }
732 738
733 739
740 static Boolean
741 TabsAcceptFocus(Widget w, Time *t)
742 {
743 if( !w->core.being_destroyed && XtIsRealized(w) &&
744 XtIsSensitive(w) && XtIsManaged(w) && w->core.visible )
745 {
746 Widget p ;
747 for(p = XtParent(w); !XtIsShell(p); p = XtParent(p)) ;
748 XtSetKeyboardFocus(p,w) ;
749 return True ;
750 }
751 else
752 return False ;
753 }
754
755
734 756
735 /* 757 /*
736 * Return preferred size. Happily accept anything >= our preferred size. 758 * Return preferred size. Happily accept anything >= our preferred size.
737 * (TODO: is that the right thing to do? Should we always return "almost" 759 * (TODO: is that the right thing to do? Should we always return "almost"
738 * if offerred more than we need?) 760 * if offerred more than we need?)
750 772
751 if( (!(mode & CWWidth) || intended->width == w->core.width) && 773 if( (!(mode & CWWidth) || intended->width == w->core.width) &&
752 (!(mode & CWHeight) || intended->height == w->core.height) ) 774 (!(mode & CWHeight) || intended->height == w->core.height) )
753 return XtGeometryNo ; 775 return XtGeometryNo ;
754 776
755 #ifdef COMMENT
756 if( (!(mode & CWWidth) || intended->width >= preferred->width) && 777 if( (!(mode & CWWidth) || intended->width >= preferred->width) &&
757 (!(mode & CWHeight) || intended->height >= preferred->height) ) 778 (!(mode & CWHeight) || intended->height >= preferred->height) )
758 return XtGeometryYes; 779 return XtGeometryYes;
759 #endif /* COMMENT */
760 780
761 return XtGeometryAlmost; 781 return XtGeometryAlmost;
762 } 782 }
763 783
764 784
772 { 792 {
773 TabsWidget tw = (TabsWidget) XtParent(w); 793 TabsWidget tw = (TabsWidget) XtParent(w);
774 Dimension s = SHADWID ; 794 Dimension s = SHADWID ;
775 TabsConstraints tab = (TabsConstraints)w->core.constraints; 795 TabsConstraints tab = (TabsConstraints)w->core.constraints;
776 XtGeometryResult result ; 796 XtGeometryResult result ;
797 Dimension rw, rh ;
777 798
778 /* Position request always denied */ 799 /* Position request always denied */
779 800
780 if( ((req->request_mode & CWX) && req->x != w->core.x) || 801 if( ((req->request_mode & CWX) && req->x != w->core.x) ||
781 ((req->request_mode & CWY) && req->y != w->core.y) || 802 ((req->request_mode & CWY) && req->y != w->core.y) ||
793 if( req->width == w->core.width && 814 if( req->width == w->core.width &&
794 req->height == w->core.height && 815 req->height == w->core.height &&
795 req->border_width == w->core.border_width ) 816 req->border_width == w->core.border_width )
796 return XtGeometryNo ; 817 return XtGeometryNo ;
797 818
798 /* updated cached preferred size of the child */ 819 rw = req->width + 2 * req->border_width ;
799 tab->tabs.bwid = req->border_width ; 820 rh = req->height + 2 * req->border_width ;
800 tab->tabs.wid = req->width + req->border_width * 2 ; 821
801 tab->tabs.hgt = req->height + req->border_width * 2 ; 822 /* find out how big the children want to be now */
802 MaxChild(tw) ; 823 MaxChild(tw, w, rw, rh) ;
803 824
804 825
805 /* Size changes must see if the new size can be accommodated. 826 /* Size changes must see if the new size can be accommodated.
806 * The Tabs widget keeps all of its children the same 827 * The Tabs widget keeps all of its children the same
807 * size. A request to shrink will be accepted only if the 828 * size. A request to shrink will be accepted only if the
808 * new size is still big enough for all other children. A 829 * new size is still big enough for all other children. A
809 * request to shrink that is not big enough for all children 830 * request to shrink that is not big enough for all children
810 * returns an "almost" response with the new proposed size. 831 * returns an "almost" response with the new proposed size
832 * or a "no" response if unable to shrink at all.
833 *
811 * A request to grow will be accepted only if the Tabs parent can 834 * A request to grow will be accepted only if the Tabs parent can
812 * grow to accommodate. 835 * grow to accommodate.
813 * 836 *
814 * TODO: 837 * TODO:
815 * We could get fancy here and re-arrange the tabs if it is 838 * We could get fancy here and re-arrange the tabs if it is
817 * for another day. 840 * for another day.
818 */ 841 */
819 842
820 if (req->request_mode & (CWWidth | CWHeight | CWBorderWidth)) 843 if (req->request_mode & (CWWidth | CWHeight | CWBorderWidth))
821 { 844 {
822 Dimension rw,rh ; /* child's requested width, height */
823 Dimension cw,ch ; /* children's preferred size */ 845 Dimension cw,ch ; /* children's preferred size */
824 Dimension aw,ah ; /* available size we can give child */ 846 Dimension aw,ah ; /* available size we can give child */
825 Dimension th ; /* space used by tabs */ 847 Dimension th ; /* space used by tabs */
826 Dimension wid,hgt ; /* Tabs widget size */ 848 Dimension wid,hgt ; /* Tabs widget size */
827 849
828 rw = cw = tab->tabs.wid ; 850 cw = tw->tabs.max_cw ;
829 rh = ch = tab->tabs.hgt ; 851 ch = tw->tabs.max_ch ;
830 852
831 /* find out what the resulting preferred size would be */ 853 /* find out what *my* resulting preferred size would be */
832 854
833 #ifdef COMMENT 855 PreferredSize2(tw, cw, ch, &wid, &hgt) ;
834 MaxChild(tw, &cw, &ch) ; 856
835 #endif /* COMMENT */ 857 /* Would my size change? If so, ask to be resized. */
836 PreferredSize2(tw,
837 cw=tw->tabs.max_cw, ch=tw->tabs.max_ch, &wid, &hgt) ;
838
839 /* Ask to be resized to accommodate. */
840 858
841 if( wid != tw->core.width || hgt != tw->core.height ) 859 if( wid != tw->core.width || hgt != tw->core.height )
842 { 860 {
843 Dimension oldWid = tw->core.width, oldHgt = tw->core.height ; 861 Dimension oldWid = tw->core.width, oldHgt = tw->core.height ;
844 XtWidgetGeometry myrequest, myreply ; 862 XtWidgetGeometry myrequest, myreply ;
854 if( (req->request_mode & XtCWQueryOnly) || rw < cw || rh < ch ) 872 if( (req->request_mode & XtCWQueryOnly) || rw < cw || rh < ch )
855 myrequest.request_mode |= XtCWQueryOnly ; 873 myrequest.request_mode |= XtCWQueryOnly ;
856 874
857 result = XtMakeGeometryRequest((Widget)tw, &myrequest, &myreply) ; 875 result = XtMakeGeometryRequest((Widget)tw, &myrequest, &myreply) ;
858 876
859 /* !$@# Box widget changes the core size even if QueryOnly 877 /* !$@# Athena Box widget changes the core size even if QueryOnly
860 * is set. I'm convinced this is a bug. At any rate, to work 878 * is set. I'm convinced this is a bug. At any rate, to work
861 * around the bug, we need to restore the core size after every 879 * around the bug, we need to restore the core size after every
862 * query geometry request. This is only partly effective, 880 * query geometry request. This is only partly effective,
863 * as there may be other boxes further up the tree. 881 * as there may be other boxes further up the tree.
864 */ 882 */
872 */ 890 */
873 891
874 switch( result ) { 892 switch( result ) {
875 case XtGeometryYes: 893 case XtGeometryYes:
876 case XtGeometryDone: 894 case XtGeometryDone:
895 tw->tabs.needs_layout = True ;
877 break ; 896 break ;
878 897
879 case XtGeometryNo: 898 case XtGeometryNo:
880 wid = tw->core.width ; 899 wid = tw->core.width ;
881 hgt = tw->core.height ; 900 hgt = tw->core.height ;
882 break ; 901 break ;
883 902
884 case XtGeometryAlmost: 903 case XtGeometryAlmost:
885 wid = myreply.width ; 904 wid = myreply.width ;
886 hgt = myreply.height ; 905 hgt = myreply.height ;
906 tw->tabs.needs_layout = True ;
907 break ;
887 } 908 }
888 } 909 }
889 910
890 /* Within the constraints imposed by the parent, what is 911 /* Within the constraints imposed by the parent, what is
891 * the max size we can give the child? 912 * the max size we can give the child?
993 } 1014 }
994 1015
995 if( tw->tabs.topWidget != NULL ) 1016 if( tw->tabs.topWidget != NULL )
996 XtVaSetValues(tw->tabs.topWidget, XmNtraversalOn, True, 0) ; 1017 XtVaSetValues(tw->tabs.topWidget, XmNtraversalOn, True, 0) ;
997 #endif 1018 #endif
998
999
1000
1001 } 1019 }
1002 1020
1003 1021
1004 1022
1005 1023
1222 TabsConstraints tab ; 1240 TabsConstraints tab ;
1223 Widget oldtop = tw->tabs.topWidget ; 1241 Widget oldtop = tw->tabs.topWidget ;
1224 1242
1225 if( !XtIsSubclass(w->core.parent, tabsWidgetClass) ) 1243 if( !XtIsSubclass(w->core.parent, tabsWidgetClass) )
1226 { 1244 {
1227 char line[1024] ; 1245 char line[256] ;
1228 sprintf(line, "XawTabsSetTop: widget \"%s\" is not the child of a tabs widget.", XtName(w)) ; 1246 sprintf(line, "XawTabsSetTop: widget \"%.64s\" is not the child of a tabs widget.", XtName(w)) ;
1229 XtAppWarning(XtWidgetToApplicationContext(w), line) ; 1247 XtAppWarning(XtWidgetToApplicationContext(w), line) ;
1230 return ; 1248 return ;
1231 } 1249 }
1232 1250
1233 if( callCallbacks ) 1251 if( callCallbacks )
1234 XtCallCallbackList(w, tw->tabs.popdownCallbacks, 1252 XtCallCallbackList(w, tw->tabs.popdownCallbacks,
1235 (XtPointer)tw->tabs.topWidget) ; 1253 (XtPointer)tw->tabs.topWidget) ;
1236 1254
1237 if( !XtIsRealized(w) ) { 1255 if( !XtIsRealized(w) ) {
1238 tw->tabs.topWidget = w ; 1256 tw->tabs.topWidget = w ;
1239 tw->tabs.needs_layout = True ; 1257 tw->tabs.needs_layout = True ;
1240 return ; 1258 return ;
1435 1453
1436 if( tab->tabs.left_bitmap != None && tab->tabs.lbm_width > 0 ) 1454 if( tab->tabs.left_bitmap != None && tab->tabs.lbm_width > 0 )
1437 { 1455 {
1438 if( tab->tabs.lbm_depth == 1 ) 1456 if( tab->tabs.lbm_depth == 1 )
1439 XCopyPlane(dpy, tab->tabs.left_bitmap, win,gc, 1457 XCopyPlane(dpy, tab->tabs.left_bitmap, win,gc,
1440 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height, 1458 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
1441 x+tab->tabs.lbm_x, y+tab->tabs.lbm_y, 1L) ; 1459 x+tab->tabs.lbm_x, y+tab->tabs.lbm_y, 1L) ;
1442 else 1460 else
1443 XCopyArea(dpy, tab->tabs.left_bitmap, win,gc, 1461 XCopyArea(dpy, tab->tabs.left_bitmap, win,gc,
1444 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height, 1462 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
1445 x+tab->tabs.lbm_x, y+tab->tabs.lbm_y) ; 1463 x+tab->tabs.lbm_x, y+tab->tabs.lbm_y) ;
1446 } 1464 }
1447 1465
1448 if( lbl != NULL && tw->tabs.font != NULL ) 1466 if( lbl != NULL && tw->tabs.font != NULL )
1449 XDrawString(dpy,win,gc, 1467 XDrawString(dpy,win,gc,
1598 1616
1599 1617
1600 1618
1601 /* GEOMETRY UTILITIES */ 1619 /* GEOMETRY UTILITIES */
1602 1620
1603 1621 /* Overview:
1604 /* Compute the size of one child's tab. Positions will be computed 1622 *
1623 * MaxChild(): ask all children (except possibly one) their
1624 * preferred sizes, set max_cw, max_ch accordingly.
1625 *
1626 * GetPreferredSizes(): ask all children their preferred sizes,
1627 * set max_cw, max_ch accordingly.
1628 *
1629 * PreferredSize(): given max_cw, max_ch, return tabs widget
1630 * preferred size. Iterate with other widths in order to get
1631 * a reasonable aspect ratio.
1632 *
1633 * PreferredSize2(): Given child dimensions, return Tabs
1634 * widget dimensions.
1635 *
1636 * PreferredSize3(): Same, except given child dimensions plus
1637 * shadow.
1638 */
1639
1640
1641 /* Compute the width of one child's tab. Positions will be computed
1605 * elsewhere. 1642 * elsewhere.
1606 * 1643 *
1607 * height: font height + vertical_space*2 + shadowWid*2 1644 * height: font height + vertical_space*2 + shadowWid*2
1608 * width: string width + horizontal_space*2 + shadowWid*2 1645 * width: string width + horizontal_space*2 + shadowWid*2
1609 * 1646 *
1632 1669
1633 if( lbl != NULL && font != NULL ) 1670 if( lbl != NULL && font != NULL )
1634 { 1671 {
1635 tab->tabs.width += XTextWidth( font, lbl, (int)strlen(lbl) ) + iw ; 1672 tab->tabs.width += XTextWidth( font, lbl, (int)strlen(lbl) ) + iw ;
1636 tab->tabs.l_y = (tw->tabs.tab_height + 1673 tab->tabs.l_y = (tw->tabs.tab_height +
1637 tw->tabs.font->max_bounds.ascent - 1674 tw->tabs.font->max_bounds.ascent -
1638 tw->tabs.font->max_bounds.descent)/2 ; 1675 tw->tabs.font->max_bounds.descent)/2 ;
1639 } 1676 }
1640 } 1677 }
1641 1678
1642 1679
1729 } 1766 }
1730 1767
1731 1768
1732 1769
1733 /* Find max preferred child size. Returned sizes include child 1770 /* Find max preferred child size. Returned sizes include child
1734 * border widths. We only ever ask a child its preferred 1771 * border widths.
1735 * size once. After that, the preferred size is updated only
1736 * if the child makes a geometry request.
1737 */ 1772 */
1738 1773
1739 static void 1774 static void
1740 GetPreferredSizes(TabsWidget tw) 1775 GetPreferredSizes(TabsWidget tw)
1776 {
1777 MaxChild(tw, NULL, 0,0) ;
1778 }
1779
1780
1781
1782 /* Find max preferred child size. Returned sizes include child
1783 * border widths. If except is non-null, don't ask that one.
1784 */
1785
1786 static void
1787 MaxChild(TabsWidget tw, Widget except, Dimension cw, Dimension ch)
1741 { 1788 {
1742 int i ; 1789 int i ;
1743 Widget *childP = tw->composite.children ; 1790 Widget *childP = tw->composite.children ;
1744 XtWidgetGeometry preferred ; 1791 XtWidgetGeometry preferred ;
1745 TabsConstraints tab ; 1792
1746 Dimension cw = 0, ch = 0 ; 1793 for(i=tw->composite.num_children; --i >=0; ++childP)
1747 1794 if( XtIsManaged(*childP) && *childP != except )
1748 for(i=tw->tabs.displayChildren; --i >= 0; ++childP)
1749 if( XtIsManaged(*childP) )
1750 { 1795 {
1751 tab = (TabsConstraints) (*childP)->core.constraints ; 1796 (void) XtQueryGeometry(*childP, NULL, &preferred) ;
1752 if( !tab->tabs.queried ) { 1797 cw = Max(cw, preferred.width + preferred.border_width * 2 ) ;
1753 (void) XtQueryGeometry(*childP, NULL, &preferred) ; 1798 ch = Max(ch, preferred.height + preferred.border_width * 2 ) ;
1754 tab->tabs.bwid = preferred.border_width ;
1755 tab->tabs.wid = preferred.width + preferred.border_width * 2 ;
1756 tab->tabs.hgt = preferred.height + preferred.border_width * 2 ;
1757 tab->tabs.queried = True ;
1758 }
1759 cw = Max(cw, tab->tabs.wid ) ;
1760 ch = Max(ch, tab->tabs.hgt ) ;
1761 }
1762 tw->tabs.max_cw = cw ;
1763 tw->tabs.max_ch = ch ;
1764 }
1765
1766
1767
1768 /* Find max preferred child size. Returned sizes include child
1769 * border widths. */
1770
1771 static void
1772 MaxChild(TabsWidget tw)
1773 {
1774 Dimension cw,ch ; /* child width, height */
1775 int i ;
1776 Widget *childP = tw->composite.children ;
1777 TabsConstraints tab ;
1778
1779 cw = ch = 0 ;
1780
1781 for(i=tw->composite.num_children; --i >=0; ++childP)
1782 if( XtIsManaged(*childP) )
1783 {
1784 tab = (TabsConstraints) (*childP)->core.constraints ;
1785 cw = Max(cw, tab->tabs.wid ) ;
1786 ch = Max(ch, tab->tabs.hgt ) ;
1787 } 1799 }
1788 1800
1789 tw->tabs.max_cw = cw ; 1801 tw->tabs.max_cw = cw ;
1790 tw->tabs.max_ch = ch ; 1802 tw->tabs.max_ch = ch ;
1791 } 1803 }
1843 } 1855 }
1844 } 1856 }
1845 } 1857 }
1846 1858
1847 1859
1848 /* find preferred size. Ask children, find size of largest, 1860 /* Find preferred size. Ask children, find size of largest,
1849 * add room for tabs & return. This can get a little involved, 1861 * add room for tabs & return. This can get a little involved,
1850 * as we don't want to have too many rows of tabs; we may widen 1862 * as we don't want to have too many rows of tabs; we may widen
1851 * the widget to reduce # of rows. 1863 * the widget to reduce # of rows.
1864 *
1865 * This function requires that max_cw, max_ch already be set.
1852 */ 1866 */
1853 1867
1854 static int 1868 static int
1855 PreferredSize( 1869 PreferredSize(
1856 TabsWidget tw, 1870 TabsWidget tw,
1862 Dimension cw,ch ; /* child width, height */ 1876 Dimension cw,ch ; /* child width, height */
1863 Dimension wid,hgt ; 1877 Dimension wid,hgt ;
1864 Dimension rwid,rhgt ; 1878 Dimension rwid,rhgt ;
1865 int nrow ; 1879 int nrow ;
1866 1880
1867
1868 /* find max desired child height */
1869 #ifdef COMMENT
1870 MaxChild(tw, &cw, &ch) ;
1871 #endif /* COMMENT */
1872
1873 wid = cw = tw->tabs.max_cw ; 1881 wid = cw = tw->tabs.max_cw ;
1874 hgt = ch = tw->tabs.max_ch ; 1882 hgt = ch = tw->tabs.max_ch ;
1875 1883
1876 nrow = PreferredSize2(tw, wid,hgt, &rwid, &rhgt) ; 1884 nrow = PreferredSize2(tw, wid,hgt, &rwid, &rhgt) ;
1877 1885
1881 */ 1889 */
1882 1890
1883 if( nrow > 2 && rhgt > rwid ) 1891 if( nrow > 2 && rhgt > rwid )
1884 { 1892 {
1885 Dimension w0, w1 ; 1893 Dimension w0, w1 ;
1894 int maxloop = 20 ;
1886 1895
1887 /* step 1: start doubling size until it's too big */ 1896 /* step 1: start doubling size until it's too big */
1888 do { 1897 do {
1889 w0 = wid ; 1898 w0 = wid ;
1890 wid = Max(wid*2, wid+20) ; 1899 wid = Max(wid*2, wid+20) ;
1893 w1 = wid ; 1902 w1 = wid ;
1894 1903
1895 /* step 2: use Newton's method to find ideal size. Stop within 1904 /* step 2: use Newton's method to find ideal size. Stop within
1896 * 8 pixels. 1905 * 8 pixels.
1897 */ 1906 */
1898 while( w1 > w0 + 8 ) 1907 while( --maxloop > 0 && w1 > w0 + 8 )
1899 { 1908 {
1900 wid = (w0+w1)/2 ; 1909 wid = (w0+w1)/2 ;
1901 nrow = PreferredSize2(tw, wid,hgt, &rwid,&rhgt) ; 1910 nrow = PreferredSize2(tw, wid,hgt, &rwid,&rhgt) ;
1902 if( nrow > 2 && rhgt > rwid ) 1911 if( nrow > 2 && rhgt > rwid )
1903 w0 = wid ; 1912 w0 = wid ;
2011 int x,y ; 2020 int x,y ;
2012 unsigned int bw ; 2021 unsigned int bw ;
2013 2022
2014 if( tab->tabs.left_bitmap == None || 2023 if( tab->tabs.left_bitmap == None ||
2015 !XGetGeometry(XtDisplay(tw), tab->tabs.left_bitmap, &root, &x, &y, 2024 !XGetGeometry(XtDisplay(tw), tab->tabs.left_bitmap, &root, &x, &y,
2016 &tab->tabs.lbm_width, &tab->tabs.lbm_height, 2025 &tab->tabs.lbm_width, &tab->tabs.lbm_height,
2017 &bw, &tab->tabs.lbm_depth) ) 2026 &bw, &tab->tabs.lbm_depth) )
2018 tab->tabs.lbm_width = tab->tabs.lbm_height = 0 ; 2027 tab->tabs.lbm_width = tab->tabs.lbm_height = 0 ;
2019 } 2028 }
2020 2029
2021 2030