the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
- /* Synched up with: Tabs.c 1.27 */
+ /* Synched up with: Tabs.c 1.23 */
/*
* Tabs.c - Index Tabs composite widget
* the frame.
*/
-/*
- * TODO: min child height = tab height
+/* TODO: min child height = tab height
+ *
*/
#include <config.h>
static void TabsDestroy();
static void TabsRealize();
static Boolean TabsSetValues();
-static Boolean TabsAcceptFocus();
static XtGeometryResult TabsQueryGeometry();
static XtGeometryResult TabsGeometryManager();
static void TabsChangeManaged();
static void TabsResize( Widget w) ;
static void TabsExpose( Widget w, XEvent *event, Region region) ;
static Boolean TabsSetValues(Widget, Widget, Widget, ArgList, Cardinal *) ;
-static Boolean TabsAcceptFocus(Widget, Time *);
static Boolean TabsConstraintSetValues(Widget, Widget, Widget,
ArgList, Cardinal *) ;
static XtGeometryResult TabsQueryGeometry(Widget,
static int TabLayout( TabsWidget, int wid, int hgt, Dimension *r_hgt,
Bool query_only) ;
static void GetPreferredSizes(TabsWidget) ;
-static void MaxChild(TabsWidget, Widget except, Dimension, Dimension) ;
+static void MaxChild(TabsWidget) ;
static void TabsShuffleRows( TabsWidget tw) ;
static int PreferredSize( TabsWidget,
Dimension *reply_width, Dimension *reply_height,
/* num_resources */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
-#if XtSpecificationRelease < 6
- /* compress_exposure */ XtExposeCompressMaximal,
-#else
- /* compress_exposure */ XtExposeCompressMaximal|XtExposeNoRegion,
-#endif
+ /* compress_exposure */ TRUE,
/* compress_enterleave*/ TRUE,
- /* visible_interest */ TRUE,
+ /* visible_interest */ FALSE,
/* destroy */ TabsDestroy,
/* resize */ TabsResize,
/* expose */ TabsExpose,
/* set_values_hook */ NULL,
/* set_values_almost */ XtInheritSetValuesAlmost,
/* get_values_hook */ NULL,
- /* accept_focus */ TabsAcceptFocus,
+ /* accept_focus */ NULL,
/* version */ XtVersion,
/* callback_private */ NULL,
/* tm_table */ defaultTranslations,
newTw->tabs.grey50 = None ;
newTw->tabs.needs_layout = False ;
-
+
newTw->tabs.hilight = NULL ;
#ifdef NEED_MOTIF
{
TabsConstraints tab = (TabsConstraints) new->core.constraints ;
tab->tabs.greyAlloc = False ; /* defer allocation of pixel */
+ tab->tabs.queried = False ; /* defer size query */
getBitmapInfo((TabsWidget)XtParent(new), tab) ;
TabWidth(new) ;
* to the bottom row.
*/
- tw->tabs.needs_layout = False ;
-
if( num_children > 0 && tw->composite.children != NULL )
{
/* Loop through the tabs and assign rows & x positions */
tw->tabs.child_width = cw = tw->core.width - 2 * SHADWID ;
tw->tabs.child_height = ch =
- tw->core.height - tw->tabs.tab_total - 2 * SHADWID ;
+ tw->core.height - tw->tabs.tab_total - 2 * SHADWID ;
for(i=0, childP=tw->composite.children;
- i < num_children;
+ i < num_children;
++i, ++childP)
if( XtIsManaged(*childP) )
{
tab = (TabsConstraints) (*childP)->core.constraints ;
- bw = (*childP)->core.border_width ;
+ bw = tab->tabs.bwid ;
XtConfigureWidget(*childP, SHADWID,tw->tabs.tab_total+SHADWID,
cw-bw*2,ch-bw*2, bw) ;
}
- if( XtIsRealized(w) ) {
+ if( XtIsRealized(w) )
XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ;
- /* should not be necessary to explicitly repaint after a
- * resize, but XEmacs folks tell me it is.
- */
- XtClass(tw)->core_class.expose((Widget)tw,NULL,None) ;
- }
}
+
+ tw->tabs.needs_layout = False ;
} /* Resize */
/* TODO: if any color changes, need to recompute GCs and redraw */
if( tw->core.background_pixel != curtw->core.background_pixel ||
- tw->core.background_pixmap != curtw->core.background_pixmap ||
- tw->tabs.font != curtw->tabs.font )
+ tw->core.background_pixmap != curtw->core.background_pixmap )
if( XtIsRealized(new) )
{
TabsFreeGCs(tw) ;
* Window system will handle the redraws.
*/
- if( tw->tabs.topWidget != curtw->tabs.topWidget )
- {
+ if( tw->tabs.topWidget != curtw->tabs.topWidget )
if( XtIsRealized(tw->tabs.topWidget) )
{
Widget w = tw->tabs.topWidget ;
}
else
tw->tabs.needs_layout = True ;
- }
return needRedraw ;
}
}
-static Boolean
-TabsAcceptFocus(Widget w, Time *t)
-{
- if( !w->core.being_destroyed && XtIsRealized(w) &&
- XtIsSensitive(w) && XtIsManaged(w) && w->core.visible )
- {
- Widget p ;
- for(p = XtParent(w); !XtIsShell(p); p = XtParent(p)) ;
- XtSetKeyboardFocus(p,w) ;
- return True ;
- }
- else
- return False ;
-}
-
-
/*
* Return preferred size. Happily accept anything >= our preferred size.
(!(mode & CWHeight) || intended->height == w->core.height) )
return XtGeometryNo ;
+#ifdef COMMENT
if( (!(mode & CWWidth) || intended->width >= preferred->width) &&
(!(mode & CWHeight) || intended->height >= preferred->height) )
return XtGeometryYes;
+#endif /* COMMENT */
return XtGeometryAlmost;
}
Dimension s = SHADWID ;
TabsConstraints tab = (TabsConstraints)w->core.constraints;
XtGeometryResult result ;
- Dimension rw, rh ;
/* Position request always denied */
req->border_width == w->core.border_width )
return XtGeometryNo ;
- rw = req->width + 2 * req->border_width ;
- rh = req->height + 2 * req->border_width ;
-
- /* find out how big the children want to be now */
- MaxChild(tw, w, rw, rh) ;
+ /* updated cached preferred size of the child */
+ tab->tabs.bwid = req->border_width ;
+ tab->tabs.wid = req->width + req->border_width * 2 ;
+ tab->tabs.hgt = req->height + req->border_width * 2 ;
+ MaxChild(tw) ;
/* Size changes must see if the new size can be accommodated.
* size. A request to shrink will be accepted only if the
* new size is still big enough for all other children. A
* request to shrink that is not big enough for all children
- * returns an "almost" response with the new proposed size
- * or a "no" response if unable to shrink at all.
- *
+ * returns an "almost" response with the new proposed size.
* A request to grow will be accepted only if the Tabs parent can
* grow to accommodate.
*
if (req->request_mode & (CWWidth | CWHeight | CWBorderWidth))
{
+ Dimension rw,rh ; /* child's requested width, height */
Dimension cw,ch ; /* children's preferred size */
Dimension aw,ah ; /* available size we can give child */
Dimension th ; /* space used by tabs */
Dimension wid,hgt ; /* Tabs widget size */
- cw = tw->tabs.max_cw ;
- ch = tw->tabs.max_ch ;
+ rw = tab->tabs.wid ;
+ rh = tab->tabs.hgt ;
- /* find out what *my* resulting preferred size would be */
+ /* find out what the resulting preferred size would be */
- PreferredSize2(tw, cw, ch, &wid, &hgt) ;
+#ifdef COMMENT
+ MaxChild(tw, &cw, &ch) ;
+#endif /* COMMENT */
+ PreferredSize2(tw, tw->tabs.max_cw,tw->tabs.max_ch, &wid, &hgt) ;
- /* Would my size change? If so, ask to be resized. */
+ /* Ask to be resized to accommodate. */
if( wid != tw->core.width || hgt != tw->core.height )
{
result = XtMakeGeometryRequest((Widget)tw, &myrequest, &myreply) ;
- /* !$@# Athena Box widget changes the core size even if QueryOnly
+ /* !$@# Box widget changes the core size even if QueryOnly
* is set. I'm convinced this is a bug. At any rate, to work
* around the bug, we need to restore the core size after every
* query geometry request. This is only partly effective,
switch( result ) {
case XtGeometryYes:
case XtGeometryDone:
- tw->tabs.needs_layout = True ;
break ;
case XtGeometryNo:
case XtGeometryAlmost:
wid = myreply.width ;
hgt = myreply.height ;
- tw->tabs.needs_layout = True ;
- break ;
}
}
tw->tabs.topWidget->core.being_destroyed ) )
tw->tabs.topWidget = NULL ;
- /* Check whether the highlight tab is still valid. */
- if( tw->tabs.hilight != NULL &&
- ( !XtIsManaged(tw->tabs.hilight) ||
- tw->tabs.hilight->core.being_destroyed ) )
- tw->tabs.hilight = NULL ;
-
GetPreferredSizes(tw) ;
MakeSizeRequest(tw) ;
if( tw->tabs.topWidget != NULL )
XtVaSetValues(tw->tabs.topWidget, XmNtraversalOn, True, 0) ;
#endif
+
+
+
}
TabsPage(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
TabsWidget tw = (TabsWidget) w ;
- Widget newtop = NULL;
+ Widget newtop ;
Widget *childP ;
int idx ;
- int nc = tw->tabs.displayChildren ;
+ int i ;
+ int nc = tw->composite.num_children ;
if( nc <= 0 )
return ;
switch( params[0][0] ) {
case 'u': /* up */
case 'U':
- if( --idx < 0 )
- idx = nc-1 ;
- newtop = tw->composite.children[idx] ;
+ if( idx == 0 )
+ idx = nc ;
+ newtop = tw->composite.children[idx-1] ;
break ;
case 'd': /* down */
case 'h':
case 'H':
- default:
newtop = tw->composite.children[0] ;
break ;
TabsHighlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
{
TabsWidget tw = (TabsWidget) w ;
- Widget newhl = NULL;
+ Widget newhl ;
Widget *childP ;
int idx ;
- int nc = tw->tabs.displayChildren ;
+ int i ;
+ int nc = tw->composite.num_children ;
if( nc <= 0 )
return ;
else
{
- /* find index of currently highlit child */
for(idx=0, childP=tw->composite.children; idx < nc; ++idx, ++childP )
if( tw->tabs.hilight == *childP )
break ;
switch( params[0][0] ) {
case 'u': /* up */
case 'U':
- if( --idx < 0 )
- idx = nc-1 ;
- newhl = tw->composite.children[idx] ;
+ if( idx == 0 )
+ idx = nc ;
+ newhl = tw->composite.children[idx-1] ;
break ;
case 'd': /* down */
case 'E':
newhl = tw->composite.children[nc-1] ;
break ;
-
- default:
- newhl = tw->tabs.hilight ;
- break ;
}
}
if( !XtIsSubclass(w->core.parent, tabsWidgetClass) )
{
- char line[256] ;
- sprintf(line, "XawTabsSetTop: widget \"%.64s\" is not the child of a tabs widget.", XtName(w)) ;
+ char line[1024] ;
+ sprintf(line, "XawTabsSetTop: widget \"%s\" is not the child of a tabs widget.", XtName(w)) ;
XtAppWarning(XtWidgetToApplicationContext(w), line) ;
return ;
}
if( callCallbacks )
XtCallCallbackList(w, tw->tabs.popdownCallbacks,
- (XtPointer)tw->tabs.topWidget) ;
+ (XtPointer)tw->tabs.topWidget) ;
if( !XtIsRealized(w) ) {
tw->tabs.topWidget = w ;
tw->tabs.needs_layout = True ;
- tw->tabs.hilight = NULL; /* The highlight tab might disappear. */
return ;
}
#endif
tab = (TabsConstraints) w->core.constraints ;
-
- /* Unhighlight before we start messing with the stacking order. */
- if( tw->tabs.hilight != NULL )
- {
- DrawHighlight(tw, tw->tabs.hilight, True) ;
- tw->tabs.hilight = NULL;
- }
-
if( tab->tabs.row == 0 )
{
/* Easy case; undraw current top, undraw new top, assign new
XawTabsSetHighlight(Widget t, Widget w)
{
TabsWidget tw = (TabsWidget)t ;
+ TabsConstraints tab ;
+ Widget oldtop = tw->tabs.topWidget ;
if( !XtIsSubclass(t, tabsWidgetClass) )
return ;
if( XtIsRealized(t) && w != tw->tabs.hilight )
{
+ if( tw->tabs.hilight != NULL )
+ DrawHighlight(tw, tw->tabs.hilight, True) ;
if( w != NULL )
DrawHighlight(tw, w, False) ;
}
{
if( tab->tabs.lbm_depth == 1 )
XCopyPlane(dpy, tab->tabs.left_bitmap, win,gc,
- 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
+ 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
x+tab->tabs.lbm_x, y+tab->tabs.lbm_y, 1L) ;
else
XCopyArea(dpy, tab->tabs.left_bitmap, win,gc,
- 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
+ 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
x+tab->tabs.lbm_x, y+tab->tabs.lbm_y) ;
}
\f
/* GEOMETRY UTILITIES */
- /* Overview:
- *
- * MaxChild(): ask all children (except possibly one) their
- * preferred sizes, set max_cw, max_ch accordingly.
- *
- * GetPreferredSizes(): ask all children their preferred sizes,
- * set max_cw, max_ch accordingly.
- *
- * PreferredSize(): given max_cw, max_ch, return tabs widget
- * preferred size. Iterate with other widths in order to get
- * a reasonable aspect ratio.
- *
- * PreferredSize2(): Given child dimensions, return Tabs
- * widget dimensions.
- *
- * PreferredSize3(): Same, except given child dimensions plus
- * shadow.
- */
-
- /* Compute the width of one child's tab. Positions will be computed
+ /* Compute the size of one child's tab. Positions will be computed
* elsewhere.
*
* height: font height + vertical_space*2 + shadowWid*2
{
tab->tabs.width += XTextWidth( font, lbl, (int)strlen(lbl) ) + iw ;
tab->tabs.l_y = (tw->tabs.tab_height +
- tw->tabs.font->max_bounds.ascent -
+ tw->tabs.font->max_bounds.ascent -
tw->tabs.font->max_bounds.descent)/2 ;
}
}
/* Find max preferred child size. Returned sizes include child
- * border widths.
+ * border widths. We only ever ask a child its preferred
+ * size once. After that, the preferred size is updated only
+ * if the child makes a geometry request.
*/
static void
GetPreferredSizes(TabsWidget tw)
{
- MaxChild(tw, NULL, 0,0) ;
+ int i ;
+ Widget *childP = tw->composite.children ;
+ XtWidgetGeometry preferred ;
+ TabsConstraints tab ;
+ Dimension cw = 0, ch = 0 ;
+
+ for(i=tw->tabs.displayChildren; --i >= 0; ++childP)
+ if( XtIsManaged(*childP) )
+ {
+ tab = (TabsConstraints) (*childP)->core.constraints ;
+ if( !tab->tabs.queried ) {
+ (void) XtQueryGeometry(*childP, NULL, &preferred) ;
+ tab->tabs.bwid = preferred.border_width ;
+ tab->tabs.wid = preferred.width + preferred.border_width * 2 ;
+ tab->tabs.hgt = preferred.height + preferred.border_width * 2 ;
+ tab->tabs.queried = True ;
+ }
+ cw = Max(cw, tab->tabs.wid ) ;
+ ch = Max(ch, tab->tabs.hgt ) ;
+ }
+ tw->tabs.max_cw = cw ;
+ tw->tabs.max_ch = ch ;
}
/* Find max preferred child size. Returned sizes include child
- * border widths. If except is non-null, don't ask that one.
- */
+ * border widths. */
static void
-MaxChild(TabsWidget tw, Widget except, Dimension cw, Dimension ch)
+MaxChild(TabsWidget tw)
{
- int i ;
- Widget *childP = tw->composite.children ;
- XtWidgetGeometry preferred ;
+ Dimension cw,ch ; /* child width, height */
+ int i ;
+ Widget *childP = tw->composite.children ;
+ TabsConstraints tab ;
+
+ cw = ch = 0 ;
for(i=tw->composite.num_children; --i >=0; ++childP)
- if( XtIsManaged(*childP) && *childP != except )
+ if( XtIsManaged(*childP) )
{
- (void) XtQueryGeometry(*childP, NULL, &preferred) ;
- cw = Max(cw, preferred.width + preferred.border_width * 2 ) ;
- ch = Max(ch, preferred.height + preferred.border_width * 2 ) ;
+ tab = (TabsConstraints) (*childP)->core.constraints ;
+ cw = Max(cw, tab->tabs.wid ) ;
+ ch = Max(ch, tab->tabs.hgt ) ;
}
tw->tabs.max_cw = cw ;
}
- /* Find preferred size. Ask children, find size of largest,
+ /* find preferred size. Ask children, find size of largest,
* add room for tabs & return. This can get a little involved,
* as we don't want to have too many rows of tabs; we may widen
* the widget to reduce # of rows.
- *
- * This function requires that max_cw, max_ch already be set.
*/
static int
Dimension rwid,rhgt ;
int nrow ;
+
+ /* find max desired child height */
+#ifdef COMMENT
+ MaxChild(tw, &cw, &ch) ;
+#endif /* COMMENT */
+
wid = cw = tw->tabs.max_cw ;
hgt = ch = tw->tabs.max_ch ;
if( nrow > 2 && rhgt > rwid )
{
Dimension w0, w1 ;
- int maxloop = 20 ;
/* step 1: start doubling size until it's too big */
do {
/* step 2: use Newton's method to find ideal size. Stop within
* 8 pixels.
*/
- while( --maxloop > 0 && w1 > w0 + 8 )
+ while( w1 > w0 + 8 )
{
wid = (w0+w1)/2 ;
nrow = PreferredSize2(tw, wid,hgt, &rwid,&rhgt) ;
if( tab->tabs.left_bitmap == None ||
!XGetGeometry(XtDisplay(tw), tab->tabs.left_bitmap, &root, &x, &y,
- &tab->tabs.lbm_width, &tab->tabs.lbm_height,
+ &tab->tabs.lbm_width, &tab->tabs.lbm_height,
&bw, &tab->tabs.lbm_depth) )
tab->tabs.lbm_width = tab->tabs.lbm_height = 0 ;
}