the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
- /* Synched up with: Tabs.c 1.23 */
+ /* Synched up with: Tabs.c 1.27 */
/*
* 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) ;
+static void MaxChild(TabsWidget, Widget except, Dimension, Dimension) ;
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,
- /* compress_exposure */ TRUE,
+#if XtSpecificationRelease < 6
+ /* compress_exposure */ XtExposeCompressMaximal,
+#else
+ /* compress_exposure */ XtExposeCompressMaximal|XtExposeNoRegion,
+#endif
/* compress_enterleave*/ TRUE,
- /* visible_interest */ FALSE,
+ /* visible_interest */ TRUE,
/* destroy */ TabsDestroy,
/* resize */ TabsResize,
/* expose */ TabsExpose,
/* set_values_hook */ NULL,
/* set_values_almost */ XtInheritSetValuesAlmost,
/* get_values_hook */ NULL,
- /* accept_focus */ NULL,
+ /* accept_focus */ TabsAcceptFocus,
/* 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 = tab->tabs.bwid ;
+ bw = (*childP)->core.border_width ;
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 */
TabsSetValues(Widget current, Widget request, Widget new,
ArgList args, Cardinal *num_args)
{
- TabsWidget curtw = (TabsWidget) current ;
- TabsWidget tw = (TabsWidget) new ;
- Boolean needRedraw = False ;
- Widget *childP ;
- int i ;
+ TabsWidget curtw = (TabsWidget) current ;
+ TabsWidget tw = (TabsWidget) new ;
+ Boolean needRedraw = False ;
+ Widget *childP ;
+ int i ;
- if( tw->tabs.font != curtw->tabs.font ||
- tw->tabs.internalWidth != curtw->tabs.internalWidth ||
- tw->tabs.internalHeight != curtw->tabs.internalHeight )
- {
- tw->tabs.tab_height = 2 * tw->tabs.internalHeight + SHADWID ;
-
- if( tw->tabs.font != NULL )
- tw->tabs.tab_height += tw->tabs.font->max_bounds.ascent +
- tw->tabs.font->max_bounds.descent ;
-
- /* Tab size has changed. Resize all tabs and request a new size */
- for(i=0, childP=tw->composite.children;
- i < tw->composite.num_children;
- ++i, ++childP)
- if( XtIsManaged(*childP) )
- TabWidth(*childP) ;
- PreferredSize(tw, &tw->core.width, &tw->core.height, NULL,NULL) ;
- needRedraw = True ;
- tw->tabs.needs_layout = True ;
- }
+ if( tw->tabs.font != curtw->tabs.font ||
+ tw->tabs.internalWidth != curtw->tabs.internalWidth ||
+ tw->tabs.internalHeight != curtw->tabs.internalHeight )
+ {
+ tw->tabs.tab_height = 2 * tw->tabs.internalHeight + SHADWID ;
- /* TODO: if any color changes, need to recompute GCs and redraw */
+ if( tw->tabs.font != NULL )
+ tw->tabs.tab_height += tw->tabs.font->max_bounds.ascent +
+ tw->tabs.font->max_bounds.descent ;
- if( tw->core.background_pixel != curtw->core.background_pixel ||
- tw->core.background_pixmap != curtw->core.background_pixmap )
- if( XtIsRealized(new) )
- {
- TabsFreeGCs(tw) ;
- TabsAllocGCs(tw) ;
- needRedraw = True ;
- }
+ /* Tab size has changed. Resize all tabs and request a new size */
+ for(i=0, childP=tw->composite.children;
+ i < tw->composite.num_children;
+ ++i, ++childP)
+ if( XtIsManaged(*childP) )
+ TabWidth(*childP) ;
+ PreferredSize(tw, &tw->core.width, &tw->core.height, NULL,NULL) ;
+ needRedraw = True ;
+ tw->tabs.needs_layout = True ;
+ }
- if( tw->core.sensitive != curtw->core.sensitive )
- needRedraw = True ;
+ /* TODO: if any color changes, need to recompute GCs and redraw */
- /* If top widget changes, need to change stacking order, redraw tabs.
- * Window system will handle the redraws.
- */
+ if( tw->core.background_pixel != curtw->core.background_pixel ||
+ tw->core.background_pixmap != curtw->core.background_pixmap ||
+ tw->tabs.font != curtw->tabs.font )
+ if( XtIsRealized(new) )
+ {
+ TabsFreeGCs(tw) ;
+ TabsAllocGCs(tw) ;
+ needRedraw = True ;
+ }
- if( tw->tabs.topWidget != curtw->tabs.topWidget )
- {
- if( XtIsRealized(tw->tabs.topWidget) )
+ if( tw->core.sensitive != curtw->core.sensitive )
+ needRedraw = True ;
+
+ /* If top widget changes, need to change stacking order, redraw tabs.
+ * Window system will handle the redraws.
+ */
+
+ if( tw->tabs.topWidget != curtw->tabs.topWidget )
{
- Widget w = tw->tabs.topWidget ;
- TabsConstraints tab = (TabsConstraints) w->core.constraints ;
+ if( XtIsRealized(tw->tabs.topWidget) )
+ {
+ Widget w = tw->tabs.topWidget ;
+ TabsConstraints tab = (TabsConstraints) w->core.constraints ;
- XRaiseWindow(XtDisplay(w), XtWindow(w)) ;
+ XRaiseWindow(XtDisplay(w), XtWindow(w)) ;
#ifdef NEED_MOTIF
- XtVaSetValues(curtw->tabs.topWidget, XmNtraversalOn, False, 0) ;
- XtVaSetValues(w, XmNtraversalOn, True, 0) ;
+ XtVaSetValues(curtw->tabs.topWidget, XmNtraversalOn, False, 0) ;
+ XtVaSetValues(w, XmNtraversalOn, True, 0) ;
#endif
- if( tab->tabs.row != tw->tabs.numRows-1 )
- TabsShuffleRows(tw) ;
+ if( tab->tabs.row != tw->tabs.numRows-1 )
+ TabsShuffleRows(tw) ;
- needRedraw = True ;
+ needRedraw = True ;
+ }
+ else
+ tw->tabs.needs_layout = True ;
}
- else
- tw->tabs.needs_layout = True ;
- }
- return needRedraw ;
+ 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 ;
- /* 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) ;
+ 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) ;
/* 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.
+ * returns an "almost" response with the new proposed size
+ * or a "no" response if unable to shrink at all.
+ *
* 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 */
- rw = tab->tabs.wid ;
- rh = tab->tabs.hgt ;
+ cw = tw->tabs.max_cw ;
+ ch = tw->tabs.max_ch ;
- /* find out what the resulting preferred size would be */
+ /* find out what *my* resulting preferred size would be */
-#ifdef COMMENT
- MaxChild(tw, &cw, &ch) ;
-#endif /* COMMENT */
- PreferredSize2(tw, tw->tabs.max_cw,tw->tabs.max_ch, &wid, &hgt) ;
+ PreferredSize2(tw, cw, ch, &wid, &hgt) ;
- /* Ask to be resized to accommodate. */
+ /* Would my size change? If so, ask to be resized. */
if( wid != tw->core.width || hgt != tw->core.height )
{
result = XtMakeGeometryRequest((Widget)tw, &myrequest, &myreply) ;
- /* !$@# Box widget changes the core size even if QueryOnly
+ /* !$@# Athena 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 ;
}
}
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 ;
+ Widget newtop = NULL;
Widget *childP ;
int idx ;
- int nc = tw->composite.num_children ;
+ int nc = tw->tabs.displayChildren ;
if( nc <= 0 )
return ;
switch( params[0][0] ) {
case 'u': /* up */
case 'U':
- if( idx == 0 )
- idx = nc ;
- newtop = tw->composite.children[idx-1] ;
+ if( --idx < 0 )
+ idx = nc-1 ;
+ newtop = tw->composite.children[idx] ;
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 ;
+ Widget newhl = NULL;
Widget *childP ;
int idx ;
- int nc = tw->composite.num_children ;
+ int nc = tw->tabs.displayChildren ;
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 ;
- newhl = tw->composite.children[idx-1] ;
+ if( --idx < 0 )
+ idx = nc-1 ;
+ newhl = tw->composite.children[idx] ;
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[1024] ;
- sprintf(line, "XawTabsSetTop: widget \"%s\" is not the child of a tabs widget.", XtName(w)) ;
+ char line[256] ;
+ sprintf(line, "XawTabsSetTop: widget \"%.64s\" 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 ;
{
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 size of one child's tab. Positions will be computed
+ /* Compute the width 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. 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.
+ * border widths.
*/
static void
GetPreferredSizes(TabsWidget tw)
{
- 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 ;
+ MaxChild(tw, NULL, 0,0) ;
}
/* Find max preferred child size. Returned sizes include child
- * border widths. */
+ * border widths. If except is non-null, don't ask that one.
+ */
static void
-MaxChild(TabsWidget tw)
+MaxChild(TabsWidget tw, Widget except, Dimension cw, Dimension ch)
{
- Dimension cw,ch ; /* child width, height */
- int i ;
- Widget *childP = tw->composite.children ;
- TabsConstraints tab ;
-
- cw = ch = 0 ;
+ int i ;
+ Widget *childP = tw->composite.children ;
+ XtWidgetGeometry preferred ;
for(i=tw->composite.num_children; --i >=0; ++childP)
- if( XtIsManaged(*childP) )
+ if( XtIsManaged(*childP) && *childP != except )
{
- tab = (TabsConstraints) (*childP)->core.constraints ;
- cw = Max(cw, tab->tabs.wid ) ;
- ch = Max(ch, tab->tabs.hgt ) ;
+ (void) XtQueryGeometry(*childP, NULL, &preferred) ;
+ cw = Max(cw, preferred.width + preferred.border_width * 2 ) ;
+ ch = Max(ch, preferred.height + preferred.border_width * 2 ) ;
}
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( w1 > w0 + 8 )
+ while( --maxloop > 0 && 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 ;
}