/* Tabs Widget for XEmacs.
Copyright (C) 1999 Edward A. Falk
-
+
This file is part of XEmacs.
-
+
XEmacs is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
-
+
XEmacs is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
-
+
You should have received a copy of the GNU General Public License
along with XEmacs; see the file COPYING. If not, write to
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.27.
+
+ #### This file contains essential XEmacs related fixes to the original
+ verison of the Tabs widget. Be VERY careful about syncing if you ever
+ update to a more recent version. In general this is probably now a
+ bad idea. */
+
/*
* Tabs.c - Index Tabs composite widget
*
<Key>KP_Down: highlight(down) \n\
<Key> : page(select) \n\
" ;
-static XtAccelerators defaultAccelerators ;
+static XtAccelerators defaultAccelerators ; /* #### Never used */
#define offset(field) XtOffsetOf(TabsRec, tabs.field)
static XtResource resources[] = {
#define assert(e)
#endif
-
+#define TabsNumChildren(tw) (((TabsWidget)tw)->composite.num_children)
+#define TabVisible(tab) \
+ (XtIsManaged(tab) && \
+ ((TabsConstraints)((tab)->core.constraints))->tabs.visible)
\f
/****************************************************************
TabsWidget newTw = (TabsWidget)new;
newTw->tabs.numRows = 0 ;
- newTw->tabs.displayChildren = 0;
+ newTw->tabs.realRows = 0;
GetPreferredSizes(newTw) ;
{
TabsConstraints tab = (TabsConstraints) new->core.constraints ;
tab->tabs.greyAlloc = False ; /* defer allocation of pixel */
+ tab->tabs.visible = False ;
getBitmapInfo((TabsWidget)XtParent(new), tab) ;
TabWidth(new) ;
int i ;
int num_children = tw->composite.num_children ;
Widget *childP ;
- TabsConstraints tab ;
+ TabsConstraints tab ; /* #### unused */
Dimension cw,ch,bw ;
/* Our size has now been dictated by the parent. Lay out the
{
/* Loop through the tabs and assign rows & x positions */
(void) TabLayout(tw, tw->core.width, tw->core.height, NULL, False) ;
- num_children = tw->tabs.displayChildren;
+ num_children = TabsNumChildren (tw);
/* assign a top widget, bring it to bottom row. */
TabsShuffleRows(tw) ;
for(i=0, childP=tw->composite.children;
i < num_children;
++i, ++childP)
- if( XtIsManaged(*childP) )
+ if( TabVisible(*childP) )
{
tab = (TabsConstraints) (*childP)->core.constraints ;
bw = (*childP)->core.border_width ;
* 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) )
{
/*
* Return preferred size. Happily accept anything >= our preferred size.
* (TODO: is that the right thing to do? Should we always return "almost"
- * if offerred more than we need?)
+ * if offered more than we need?)
*/
static XtGeometryResult
Widget *childP = tw->composite.children ;
int i,bw ;
w->core.border_width = req->border_width ;
- for(i=tw->tabs.displayChildren; --i >= 0; ++childP)
- if( XtIsManaged(*childP) )
+ for(i=TabsNumChildren (tw); --i >= 0; ++childP)
+ if( TabVisible(*childP) )
{
bw = (*childP)->core.border_width ;
XtConfigureWidget(*childP, s,tw->tabs.tab_total+s,
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 && XtIsRealized(tw->tabs.topWidget) )
{
- for(i=tw->tabs.displayChildren; --i >= 0; ++childP)
+ for(i=TabsNumChildren (tw); --i >= 0; ++childP)
if( !XtIsRealized(*childP) )
XtRealizeWidget(*childP) ;
* widget to be top of stacking order with XawTabsSetTop().
*/
for(i=0, childP=tw->composite.children;
- i < tw->tabs.displayChildren;
+ i < TabsNumChildren (tw);
++i, ++childP)
- if( XtIsManaged(*childP) )
+ if( TabVisible(*childP) )
{
TabsConstraints tab = (TabsConstraints)(*childP)->core.constraints;
if( x > tab->tabs.x && x < tab->tabs.x + tab->tabs.width &&
Widget newtop = NULL;
Widget *childP ;
int idx ;
- int nc = tw->composite.num_children ;
+ int nc = TabsNumChildren (tw) ;
if( nc <= 0 )
return ;
Widget newhl = NULL;
Widget *childP ;
int idx ;
- int nc = tw->composite.num_children ;
+ int nc = TabsNumChildren (tw) ;
if( nc <= 0 )
return ;
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
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( !XtIsRealized((Widget)tw))
return ;
-
+
/* draw tabs and frames by row except for the top tab, which
* is drawn last. (This is inefficiently written, but should not
* be too slow as long as there are not a lot of rows.)
y = tw->tabs.numRows == 1 ? TABDELTA : 0 ;
for(i=0; i<tw->tabs.numRows; ++i, y += th)
{
- for( j=tw->tabs.displayChildren, childP=tw->composite.children;
+ for( j=TabsNumChildren (tw), childP=tw->composite.children;
--j >= 0; ++childP )
- if( XtIsManaged(*childP) )
+ if( TabVisible(*childP) )
{
tab = (TabsConstraints)(*childP)->core.constraints;
if( tab->tabs.row == i && *childP != tw->tabs.topWidget )
static int
TabLayout(TabsWidget tw, int wid, int hgt, Dimension *reply_height, Bool query_only)
{
- int i, row ;
+ int i, row, done = 0, display_rows = 0 ;
int num_children = tw->composite.num_children ;
Widget *childP ;
Dimension w ;
Position x,y ;
TabsConstraints tab ;
- if (!query_only)
- tw->tabs.displayChildren = 0;
-
/* Algorithm: loop through children, assign X positions. If a tab
* would extend beyond the right edge, start a new row. After all
* rows are assigned, make a second pass and assign Y positions.
{
tab = (TabsConstraints) (*childP)->core.constraints ;
w = tab->tabs.width ;
+
if( x + w > wid ) { /* new row */
- if (y + tw->tabs.tab_height > hgt)
- break;
- ++row ;
+ if (y + tw->tabs.tab_height > hgt && !done)
+ {
+ display_rows = row;
+ done = 1;
+ }
+ ++row;
x = INDENT ;
y += tw->tabs.tab_height ;
}
tab->tabs.row = row ;
}
x += w + SPACING ;
- if (!query_only)
- tw->tabs.displayChildren++;
+ if (!query_only && !done)
+ tab->tabs.visible = 1;
+
}
- /* If there was only one row, increse the height by TABDELTA */
- if( ++row == 1 )
+ /* If there was only one row, increase the height by TABDELTA */
+ if( ++display_rows == 1 )
{
+ row++;
y = TABDELTA ;
if( !query_only )
for(i=num_children, childP=tw->composite.children;
y += tw->tabs.tab_height ;
}
else
- row = y = 0 ;
+ display_rows = row = y = 0 ;
if( !query_only ) {
tw->tabs.tab_total = y ;
- tw->tabs.numRows = row ;
+ tw->tabs.numRows = display_rows ;
+ tw->tabs.realRows = row;
}
if( reply_height != NULL )
*reply_height = y ;
- return row ;
+ return display_rows ;
}
{
TabsConstraints tab ;
int move ;
- int nrows ;
+ int real_rows, display_rows ;
Widget *childP ;
Dimension th = tw->tabs.tab_height ;
Position bottom ;
/* There must be a top widget. If not, assign one. */
if( tw->tabs.topWidget == NULL && tw->composite.children != NULL )
- for(i=tw->composite.num_children, childP=tw->composite.children;
+ for(i=TabsNumChildren (tw), childP=tw->composite.children;
--i >= 0;
++childP)
if( XtIsManaged(*childP) ) {
if( tw->tabs.topWidget != NULL )
{
- nrows = tw->tabs.numRows ;
- assert( nrows > 0 ) ;
+ display_rows = tw->tabs.numRows ;
+ real_rows = tw->tabs.realRows ;
+ assert( display_rows >= real_rows ) ;
- if( nrows > 1 )
+ if( real_rows > 1 )
{
tab = (TabsConstraints) tw->tabs.topWidget->core.constraints ;
assert( tab != NULL ) ;
- /* how far to move top row */
- move = nrows - tab->tabs.row ;
+ /* How far to move top row. The selected tab must be on
+ the bottom row of the *visible* rows. */
+ move = (real_rows + 1 - display_rows) - tab->tabs.row ;
+ if (move < 0)
+ move = real_rows - move;
bottom = tw->tabs.tab_total - th ;
- for(i=tw->tabs.displayChildren, childP=tw->composite.children;
+ for(i=tw->composite.num_children, childP=tw->composite.children;
--i >= 0;
++childP)
if( XtIsManaged(*childP) )
{
tab = (TabsConstraints) (*childP)->core.constraints ;
- tab->tabs.row = (tab->tabs.row + move) % nrows ;
+ tab->tabs.row = (tab->tabs.row + move) % real_rows ;
tab->tabs.y = bottom - tab->tabs.row * th ;
+ tab->tabs.visible = (tab->tabs.row < display_rows);
}
}
}
*
* This function requires that max_cw, max_ch already be set.
*/
-
static int
PreferredSize(
TabsWidget tw,