Mercurial > hg > xemacs-beta
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 |