summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--doc/grid.n17
-rw-r--r--generic/tkGrid.c298
-rw-r--r--tests/grid.test51
4 files changed, 260 insertions, 114 deletions
diff --git a/ChangeLog b/ChangeLog
index 8ff3d56..a8324f4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2004-01-09 Peter Spjuth <peter.spjuth@space.se>
+ * doc/grid.n:
+ * tests/grid.test:
+ * generic/tkGrid.c: Implementation of TIP#146,
+ "Add Overall Anchoring to the Grid Geometry Manager",
+ adding [grid anchor] subcommand.
+ **** POTENTIAL VISUAL INCOMPATABILITY ****
+
2004-01-07 Vince Darley <vincentdarley@users.sourceforge.net>
* generic/tkTextDisp.c:
diff --git a/doc/grid.n b/doc/grid.n
index 07c1ddd..b2790e9 100644
--- a/doc/grid.n
+++ b/doc/grid.n
@@ -4,7 +4,7 @@
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
-'\" RCS: @(#) $Id: grid.n,v 1.6 2003/09/18 18:22:22 pspjuth Exp $
+'\" RCS: @(#) $Id: grid.n,v 1.7 2004/01/09 22:23:26 pspjuth Exp $
'\"
.so man.macros
.TH grid n 8.5 Tk "Tk Built-In Commands"
@@ -31,6 +31,13 @@ starting with \fB.\fP) or one of the characters \fBx\fP or \fB^\fP
(see the ``RELATIVE PLACEMENT'' section below), then the command is
processed in the same way as \fBgrid configure\fR.
.TP
+.VS 8.5
+\fBgrid anchor \fImaster\fR ?\fIanchor\fR?
+The anchor value controls how to place the grid within the master
+when no row/column has any weight. See ``THE GRID ALGORITHM'' below
+for further details. The default \fIanchor\fR is \fInw\fR.
+.VE
+.TP
\fBgrid bbox \fImaster\fR ?\fIcolumn row\fR? ?\fIcolumn2 row2\fR?
With no arguments,
the bounding box (in pixels) of the grid is returned.
@@ -333,15 +340,19 @@ minimum size. For example, if all rows or columns in a group have the
same weight, then each row or column will have the same size as the
largest row or column in the group.
.PP
+
+.VS 8.5
For masters whose size is larger than the requested layout, the additional
space is apportioned according to the row and column weights. If all of
-the weights are zero, the layout is centered within its master.
+the weights are zero, the layout is placed within its master according to
+the \fIanchor\fR value.
For masters whose size is smaller than the requested layout, space is taken
away from columns and rows according to their weights. However, once a
column or row shrinks to its minsize, its weight is taken to be zero.
If more space needs to be removed from a layout than would be permitted, as
when all the rows or columns are at there minimum sizes, the layout is
-clipped on the bottom and right.
+placed and clipped according to the \fIanchor\fR value.
+.VE
.SH "GEOMETRY PROPAGATION"
.PP
The grid geometry manager normally computes how large a master must be to
diff --git a/generic/tkGrid.c b/generic/tkGrid.c
index b449b10..fe8e47d 100644
--- a/generic/tkGrid.c
+++ b/generic/tkGrid.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkGrid.c,v 1.29 2003/09/18 20:34:07 pspjuth Exp $
+ * RCS: @(#) $Id: tkGrid.c,v 1.30 2004/01/09 22:23:26 pspjuth Exp $
*/
#include "tkInt.h"
@@ -48,7 +48,7 @@
#define UNIFORM_PREALLOC 10
-/*
+/*
* Data structures are allocated dynamically to support arbitrary sized tables.
* However, the space is proportional to the highest numbered slot with
* some non-default property. This limit is used to head off mistakes and
@@ -66,6 +66,12 @@
#define REL_VERT '^' /* Extend widget from row above. */
/*
+ * Default value for 'grid anchor'.
+ */
+
+#define GRID_DEFAULT_ANCHOR TK_ANCHOR_NW
+
+/*
* Structure to hold information for grid masters. A slot is either
* a row or column.
*/
@@ -144,6 +150,8 @@ typedef struct {
* master. */
int startY; /* Pixel offset of this layout within its
* master. */
+ Tk_Anchor anchor; /* Value of anchor option: specifies where
+ * a grid without weight should be placed. */
} GridMaster;
/*
@@ -173,7 +181,7 @@ typedef struct Gridder {
int numCols, numRows; /* Number of columns or rows this slave spans.
* Should be at least 1. */
int padX, padY; /* Total additional pixels to leave around the
- * window. Some is of this space is on each
+ * window. Some is of this space is on each
* side. This is space *outside* the window:
* we'll allocate extra space in frame but
* won't enlarge window). */
@@ -250,7 +258,7 @@ typedef struct UniformGroup {
* Prototypes for procedures used only in this file:
*/
-static void AdjustForSticky _ANSI_ARGS_((Gridder *slavePtr, int *xPtr,
+static void AdjustForSticky _ANSI_ARGS_((Gridder *slavePtr, int *xPtr,
int *yPtr, int *widthPtr, int *heightPtr));
static int AdjustOffsets _ANSI_ARGS_((int width,
int elements, SlotInfo *slotPtr));
@@ -261,6 +269,8 @@ static int ConfigureSlaves _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Window tkwin, int objc, Tcl_Obj *CONST objv[]));
static void DestroyGrid _ANSI_ARGS_((char *memPtr));
static Gridder *GetGrid _ANSI_ARGS_((Tk_Window tkwin));
+static int GridAnchorCommand _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
static int GridBboxCommand _ANSI_ARGS_((Tk_Window tkwin,
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
static int GridForgetRemoveCommand _ANSI_ARGS_((Tk_Window tkwin,
@@ -334,16 +344,16 @@ Tk_GridObjCmd(clientData, interp, objc, objv)
{
Tk_Window tkwin = (Tk_Window) clientData;
static CONST char *optionStrings[] = {
- "bbox", "columnconfigure", "configure", "forget",
- "info", "location", "propagate", "remove",
+ "anchor", "bbox", "columnconfigure", "configure",
+ "forget", "info", "location", "propagate", "remove",
"rowconfigure", "size", "slaves", (char *) NULL };
enum options {
- GRID_BBOX, GRID_COLUMNCONFIGURE, GRID_CONFIGURE, GRID_FORGET,
- GRID_INFO, GRID_LOCATION, GRID_PROPAGATE, GRID_REMOVE,
+ GRID_ANCHOR, GRID_BBOX, GRID_COLUMNCONFIGURE, GRID_CONFIGURE,
+ GRID_FORGET, GRID_INFO, GRID_LOCATION, GRID_PROPAGATE, GRID_REMOVE,
GRID_ROWCONFIGURE, GRID_SIZE, GRID_SLAVES };
int index;
-
-
+
+
if (objc >= 2) {
char *argv1 = Tcl_GetString(objv[1]);
if ((argv1[0] == '.') || (argv1[0] == REL_SKIP) ||
@@ -362,6 +372,8 @@ Tk_GridObjCmd(clientData, interp, objc, objv)
}
switch ((enum options) index) {
+ case GRID_ANCHOR:
+ return GridAnchorCommand(tkwin, interp, objc, objv);
case GRID_BBOX:
return GridBboxCommand(tkwin, interp, objc, objv);
case GRID_CONFIGURE:
@@ -402,6 +414,75 @@ Tk_GridObjCmd(clientData, interp, objc, objv)
/*
*----------------------------------------------------------------------
*
+ * GridAnchorCommand --
+ *
+ * Implementation of the [grid anchor] subcommand. See the user
+ * documentation for details on what it does.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * May recompute grid geometry.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+GridAnchorCommand(tkwin, interp, objc, objv)
+ Tk_Window tkwin; /* Main window of the application. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ Tk_Window master;
+ Gridder *masterPtr;
+ GridMaster *gridPtr;
+ Tk_Anchor old;
+
+ if (objc > 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?anchor?");
+ return TCL_ERROR;
+ }
+
+ if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ masterPtr = GetGrid(master);
+
+ if (objc == 3) {
+ gridPtr = masterPtr->masterDataPtr;
+ Tcl_SetResult(interp, (char *) Tk_NameOfAnchor(gridPtr == NULL ?
+ GRID_DEFAULT_ANCHOR : gridPtr->anchor), TCL_VOLATILE);
+ return TCL_OK;
+ }
+
+ InitMasterData(masterPtr);
+ gridPtr = masterPtr->masterDataPtr;
+ old = gridPtr->anchor;
+ if (Tk_GetAnchorFromObj(interp, objv[3], &gridPtr->anchor) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Only request a relayout if the anchor changes.
+ */
+
+ if (old != gridPtr->anchor) {
+ if (masterPtr->abortPtr != NULL) {
+ *masterPtr->abortPtr = 1;
+ }
+ if (!(masterPtr->flags & REQUESTED_RELAYOUT)) {
+ masterPtr->flags |= REQUESTED_RELAYOUT;
+ Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* GridBboxCommand --
*
* Implementation of the [grid bbox] subcommand.
@@ -430,17 +511,17 @@ GridBboxCommand(tkwin, interp, objc, objv)
int endX, endY; /* last column/row in the layout */
int x=0, y=0; /* starting pixels for this bounding box */
int width, height; /* size of the bounding box */
-
+
if (objc!=3 && objc != 5 && objc != 7) {
Tcl_WrongNumArgs(interp, 2, objv, "master ?column row ?column row??");
return TCL_ERROR;
}
-
+
if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
return TCL_ERROR;
}
masterPtr = GetGrid(master);
-
+
if (objc >= 5) {
if (Tcl_GetIntFromObj(interp, objv[3], &column) != TCL_OK) {
return TCL_ERROR;
@@ -451,7 +532,7 @@ GridBboxCommand(tkwin, interp, objc, objv)
column2 = column;
row2 = row;
}
-
+
if (objc == 7) {
if (Tcl_GetIntFromObj(interp, objv[5], &column2) != TCL_OK) {
return TCL_ERROR;
@@ -460,17 +541,17 @@ GridBboxCommand(tkwin, interp, objc, objv)
return TCL_ERROR;
}
}
-
+
gridPtr = masterPtr->masterDataPtr;
if (gridPtr == NULL) {
Tcl_SetObjResult(interp, NewQuadObj(interp, 0, 0, 0, 0));
return TCL_OK;
}
-
+
SetGridSize(masterPtr);
endX = MAX(gridPtr->columnEnd, gridPtr->columnMax);
endY = MAX(gridPtr->rowEnd, gridPtr->rowMax);
-
+
if ((endX == 0) || (endY == 0)) {
Tcl_SetObjResult(interp, NewQuadObj(interp, 0, 0, 0, 0));
return TCL_OK;
@@ -480,7 +561,7 @@ GridBboxCommand(tkwin, interp, objc, objv)
row2 = endY;
column2 = endX;
}
-
+
if (column > column2) {
int temp = column;
column = column2, column2 = temp;
@@ -489,35 +570,35 @@ GridBboxCommand(tkwin, interp, objc, objv)
int temp = row;
row = row2, row2 = temp;
}
-
+
if (column > 0 && column < endX) {
x = gridPtr->columnPtr[column-1].offset;
} else if (column > 0) {
x = gridPtr->columnPtr[endX-1].offset;
}
-
+
if (row > 0 && row < endY) {
y = gridPtr->rowPtr[row-1].offset;
} else if (row > 0) {
y = gridPtr->rowPtr[endY-1].offset;
}
-
+
if (column2 < 0) {
width = 0;
} else if (column2 >= endX) {
width = gridPtr->columnPtr[endX-1].offset - x;
} else {
width = gridPtr->columnPtr[column2].offset - x;
- }
-
+ }
+
if (row2 < 0) {
height = 0;
} else if (row2 >= endY) {
height = gridPtr->rowPtr[endY-1].offset - y;
} else {
height = gridPtr->rowPtr[row2].offset - y;
- }
-
+ }
+
Tcl_SetObjResult(interp, NewQuadObj(interp,
x + gridPtr->startX, y + gridPtr->startY, width, height));
return TCL_OK;
@@ -552,7 +633,7 @@ GridForgetRemoveCommand(tkwin, interp, objc, objv)
int i;
char *string = Tcl_GetString(objv[1]);
char c = string[0];
-
+
for (i = 2; i < objc; i++) {
if (TkGetWindowFromObj(interp, tkwin, objv[i], &slave) != TCL_OK) {
return TCL_ERROR;
@@ -560,11 +641,11 @@ GridForgetRemoveCommand(tkwin, interp, objc, objv)
slavePtr = GetGrid(slave);
if (slavePtr->masterPtr != NULL) {
-
+
/*
* For "forget", reset all the settings to their defaults
*/
-
+
if (c == 'f') {
slavePtr->column = slavePtr->row = -1;
slavePtr->numCols = 1;
@@ -619,7 +700,7 @@ GridInfoCommand(tkwin, interp, objc, objv)
register Gridder *slavePtr;
Tk_Window slave;
char buffer[64 + TCL_INTEGER_SPACE * 4];
-
+
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "window");
return TCL_ERROR;
@@ -632,7 +713,7 @@ GridInfoCommand(tkwin, interp, objc, objv)
Tcl_ResetResult(interp);
return TCL_OK;
}
-
+
Tcl_AppendElement(interp, "-in");
Tcl_AppendElement(interp, Tk_PathName(slavePtr->masterPtr->tkwin));
sprintf(buffer, " -column %d -row %d -columnspan %d -rowspan %d",
@@ -679,36 +760,36 @@ GridLocationCommand(tkwin, interp, objc, objv)
int x, y; /* Offset in pixels, from edge of master. */
int i, j; /* Corresponding column and row indeces. */
int endX, endY; /* end of grid */
-
+
if (objc != 5) {
Tcl_WrongNumArgs(interp, 2, objv, "master x y");
return TCL_ERROR;
}
-
+
if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
return TCL_ERROR;
}
-
+
if (Tk_GetPixelsFromObj(interp, master, objv[3], &x) != TCL_OK) {
return TCL_ERROR;
}
if (Tk_GetPixelsFromObj(interp, master, objv[4], &y) != TCL_OK) {
return TCL_ERROR;
}
-
+
masterPtr = GetGrid(master);
if (masterPtr->masterDataPtr == NULL) {
Tcl_SetObjResult(interp, NewPairObj(interp, -1, -1));
return TCL_OK;
}
gridPtr = masterPtr->masterDataPtr;
-
- /*
+
+ /*
* Update any pending requests. This is not always the
* steady state value, as more configure events could be in
* the pipeline, but its as close as its easy to get.
*/
-
+
while (masterPtr->flags & REQUESTED_RELAYOUT) {
Tcl_CancelIdleCall(ArrangeGrid, (ClientData) masterPtr);
ArrangeGrid ((ClientData) masterPtr);
@@ -716,7 +797,7 @@ GridLocationCommand(tkwin, interp, objc, objv)
SetGridSize(masterPtr);
endX = MAX(gridPtr->columnEnd, gridPtr->columnMax);
endY = MAX(gridPtr->rowEnd, gridPtr->rowMax);
-
+
slotPtr = masterPtr->masterDataPtr->columnPtr;
if (x < masterPtr->masterDataPtr->startX) {
i = -1;
@@ -726,7 +807,7 @@ GridLocationCommand(tkwin, interp, objc, objv)
/* null body */
}
}
-
+
slotPtr = masterPtr->masterDataPtr->rowPtr;
if (y < masterPtr->masterDataPtr->startY) {
j = -1;
@@ -736,7 +817,7 @@ GridLocationCommand(tkwin, interp, objc, objv)
/* null body */
}
}
-
+
Tcl_SetObjResult(interp, NewPairObj(interp, i, j));
return TCL_OK;
}
@@ -768,7 +849,7 @@ GridPropagateCommand(tkwin, interp, objc, objv)
Tk_Window master;
Gridder *masterPtr;
int propagate, old;
-
+
if (objc > 4) {
Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?");
return TCL_ERROR;
@@ -786,9 +867,9 @@ GridPropagateCommand(tkwin, interp, objc, objv)
if (Tcl_GetBooleanFromObj(interp, objv[3], &propagate) != TCL_OK) {
return TCL_ERROR;
}
-
+
/* Only request a relayout if the propagation bit changes */
-
+
old = !(masterPtr->flags & DONT_PROPAGATE);
if (propagate != old) {
if (propagate) {
@@ -796,12 +877,12 @@ GridPropagateCommand(tkwin, interp, objc, objv)
} else {
masterPtr->flags |= DONT_PROPAGATE;
}
-
+
/*
* Re-arrange the master to allow new geometry information to
* propagate upwards to the master's master.
*/
-
+
if (masterPtr->abortPtr != NULL) {
*masterPtr->abortPtr = 1;
}
@@ -854,20 +935,20 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv)
"-minsize", "-pad", "-uniform", "-weight", (char *) NULL };
enum options { ROWCOL_MINSIZE, ROWCOL_PAD, ROWCOL_UNIFORM, ROWCOL_WEIGHT };
int index;
-
+
if (((objc % 2 != 0) && (objc > 6)) || (objc < 4)) {
Tcl_WrongNumArgs(interp, 2, objv, "master index ?-option value...?");
return TCL_ERROR;
}
-
+
if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) {
return TCL_ERROR;
}
-
+
if (Tcl_ListObjGetElements(interp, objv[3], &lObjc, &lObjv) != TCL_OK) {
return TCL_ERROR;
}
-
+
string = Tcl_GetString(objv[1]);
masterPtr = GetGrid(master);
slotType = (*string == 'c') ? COLUMN : ROW;
@@ -885,16 +966,17 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv)
return TCL_ERROR;
}
ok = CheckSlotData(masterPtr, slot, slotType, /* checkOnly */ 1);
- if (ok == TCL_OK) {
- slotPtr = (slotType == COLUMN) ?
- masterPtr->masterDataPtr->columnPtr :
- masterPtr->masterDataPtr->rowPtr;
- }
+ if (ok == TCL_OK) {
+ slotPtr = (slotType == COLUMN) ?
+ masterPtr->masterDataPtr->columnPtr :
+ masterPtr->masterDataPtr->rowPtr;
+ }
+
/*
* Return all of the options for this row or column. If the
* request is out of range, return all 0's.
*/
-
+
if (objc == 4) {
int minsize = 0, pad = 0, weight = 0;
Tk_Uid uniform = NULL;
@@ -906,7 +988,7 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv)
weight = slotPtr[slot].weight;
uniform = slotPtr[slot].uniform;
}
-
+
Tcl_ListObjAppendElement(interp, res,
Tcl_NewStringObj("-minsize", -1));
Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(minsize));
@@ -928,7 +1010,7 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv)
* If only one option is given, with no value, the
* current value is returned.
*/
-
+
if (Tcl_GetIndexFromObj(interp, objv[4], optionStrings,
"option", 0, &index) != TCL_OK) {
return TCL_ERROR;
@@ -942,10 +1024,10 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv)
} else if (index == ROWCOL_UNIFORM) {
Tk_Uid value;
value = (ok == TCL_OK) ? slotPtr[slot].uniform : "";
- Tcl_SetObjResult(interp,
+ Tcl_SetObjResult(interp,
Tcl_NewStringObj(value == NULL ? "" : value, -1));
} else if (index == ROWCOL_PAD) {
- Tcl_SetObjResult(interp,
+ Tcl_SetObjResult(interp,
Tcl_NewIntObj((ok == TCL_OK) ? slotPtr[slot].pad : 0));
}
return TCL_OK;
@@ -969,7 +1051,7 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv)
slavePtr = GetGrid(slave);
if (slavePtr->masterPtr != masterPtr) {
Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ",
+ Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ",
Tcl_GetString(objv[1]), ": the window \"",
Tcl_GetString(lObjv[j]),
"\" is not managed by \"", Tcl_GetString(objv[2]),
@@ -978,7 +1060,7 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv)
}
} else {
Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ",
+ Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ",
Tcl_GetString(objv[1]), ": illegal index \"",
Tcl_GetString(lObjv[j]), "\"", (char *) NULL);
return TCL_ERROR;
@@ -998,7 +1080,7 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv)
for (slot = first; slot <= last; slot++) {
ok = CheckSlotData(masterPtr, slot, slotType, /*checkOnly*/ 0);
if (ok != TCL_OK) {
- Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ",
+ Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ",
Tcl_GetString(objv[1]), ": \"",
Tcl_GetString(lObjv[j]),
"\" is out of range", (char *) NULL);
@@ -1007,7 +1089,7 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv)
slotPtr = (slotType == COLUMN) ?
masterPtr->masterDataPtr->columnPtr :
masterPtr->masterDataPtr->rowPtr;
-
+
/*
* Loop through each option value pair, setting the values as
* required.
@@ -1048,7 +1130,7 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv)
!= TCL_OK) {
return TCL_ERROR;
} else if (size < 0) {
- Tcl_AppendResult(interp, "invalid arg \"",
+ Tcl_AppendResult(interp, "invalid arg \"",
Tcl_GetString(objv[i]),
"\": should be non-negative", (char *) NULL);
return TCL_ERROR;
@@ -1063,12 +1145,12 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv)
}
} while ((allSlaves == 1) && (slavePtr != NULL));
}
-
+
/*
* We changed a property, re-arrange the table,
* and check for constraint shrinkage.
*/
-
+
if (slotType == ROW) {
int last = masterPtr->masterDataPtr->rowMax - 1;
while ((last >= 0) && (slotPtr[last].weight == 0)
@@ -1126,7 +1208,7 @@ GridSizeCommand(tkwin, interp, objc, objv)
Tk_Window master;
Gridder *masterPtr;
GridMaster *gridPtr; /* pointer to grid data */
-
+
if (objc != 3) {
Tcl_WrongNumArgs(interp, 2, objv, "window");
return TCL_ERROR;
@@ -1136,7 +1218,7 @@ GridSizeCommand(tkwin, interp, objc, objv)
return TCL_ERROR;
}
masterPtr = GetGrid(master);
-
+
if (masterPtr->masterDataPtr != NULL) {
SetGridSize(masterPtr);
gridPtr = masterPtr->masterDataPtr;
@@ -1184,12 +1266,12 @@ GridSlavesCommand(tkwin, interp, objc, objv)
enum options { SLAVES_COLUMN, SLAVES_ROW };
int index;
Tcl_Obj *res;
-
+
if ((objc < 3) || ((objc % 2) == 0)) {
Tcl_WrongNumArgs(interp, 2, objv, "window ?-option value...?");
return TCL_ERROR;
}
-
+
for (i = 3; i < objc; i += 2) {
if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0,
&index) != TCL_OK) {
@@ -1313,8 +1395,7 @@ GridLostSlaveProc(clientData, tkwin)
* the minsize specified for that slot.
*
* Results:
- * The initial offset of the layout,
- * if all the weights are zero, else 0.
+ * The size used by the layout.
*
* Side effects:
* The slot offsets are modified to shrink the layout.
@@ -1343,12 +1424,11 @@ AdjustOffsets(size, slots, slotPtr)
*/
if (diff == 0) {
- return(0);
+ return size;
}
/*
- * If all the weights are zero, center the layout in its master if
- * there is extra space, else clip on the bottom/right.
+ * If all the weights are zero, there is nothing more to do.
*/
for (slot=0; slot < slots; slot++) {
@@ -1356,7 +1436,7 @@ AdjustOffsets(size, slots, slotPtr)
}
if (totalWeight == 0 ) {
- return(diff > 0 ? diff/2 : 0);
+ return slotPtr[slots-1].offset;
}
/*
@@ -1369,7 +1449,7 @@ AdjustOffsets(size, slots, slotPtr)
weight += slotPtr[slot].weight;
slotPtr[slot].offset += diff * weight / totalWeight;
}
- return(0);
+ return size;
}
/*
@@ -1389,8 +1469,7 @@ AdjustOffsets(size, slots, slotPtr)
/*
* If the requested size is less than the minimum required size,
- * set the slot sizes to their minimum values, then clip on the
- * bottom/right.
+ * set the slot sizes to their minimum values.
*/
if (size <= minSize) {
@@ -1405,7 +1484,7 @@ AdjustOffsets(size, slots, slotPtr)
}
slotPtr[slot].offset = offset;
}
- return(0);
+ return minSize;
}
/*
@@ -1464,7 +1543,7 @@ AdjustOffsets(size, slots, slotPtr)
}
diff -= newDiff;
}
- return(0);
+ return size;
}
/*
@@ -1552,11 +1631,12 @@ ArrangeGrid(clientData)
* are to be re-layed out. */
{
register Gridder *masterPtr = (Gridder *) clientData;
- register Gridder *slavePtr;
+ register Gridder *slavePtr;
GridMaster *slotPtr = masterPtr->masterDataPtr;
int abort;
int width, height; /* requested size of layout, in pixels */
int realWidth, realHeight; /* actual size layout should take-up */
+ int usedX, usedY;
masterPtr->flags &= ~REQUESTED_RELAYOUT;
@@ -1578,7 +1658,7 @@ ArrangeGrid(clientData)
/*
* Abort any nested call to ArrangeGrid for this window, since
* we'll do everything necessary here, and set up so this call
- * can be aborted if necessary.
+ * can be aborted if necessary.
*/
if (masterPtr->abortPtr != NULL) {
@@ -1599,7 +1679,7 @@ ArrangeGrid(clientData)
Tk_InternalBorderRight(masterPtr->tkwin);
height += Tk_InternalBorderTop(masterPtr->tkwin) +
Tk_InternalBorderBottom(masterPtr->tkwin);
-
+
if (width < Tk_MinReqWidth(masterPtr->tkwin)) {
width = Tk_MinReqWidth(masterPtr->tkwin);
}
@@ -1623,9 +1703,8 @@ ArrangeGrid(clientData)
/*
* If the currently requested layout size doesn't match the master's
* window size, then adjust the slot offsets according to the
- * weights. If all of the weights are zero, center the layout in
- * its master. I haven't decided what to do if the master is smaller
- * than the requested size.
+ * weights. If all of the weights are zero, place the layout according
+ * to the anchor value.
*/
realWidth = Tk_Width(masterPtr->tkwin) -
@@ -1634,12 +1713,12 @@ ArrangeGrid(clientData)
realHeight = Tk_Height(masterPtr->tkwin) -
Tk_InternalBorderTop(masterPtr->tkwin) -
Tk_InternalBorderBottom(masterPtr->tkwin);
- slotPtr->startX = AdjustOffsets(realWidth,
+ usedX = AdjustOffsets(realWidth,
MAX(slotPtr->columnEnd,slotPtr->columnMax), slotPtr->columnPtr);
- slotPtr->startY = AdjustOffsets(realHeight,
+ usedY = AdjustOffsets(realHeight,
MAX(slotPtr->rowEnd,slotPtr->rowMax), slotPtr->rowPtr);
- slotPtr->startX += Tk_InternalBorderLeft(masterPtr->tkwin);
- slotPtr->startY += Tk_InternalBorderTop(masterPtr->tkwin);
+ TkComputeAnchor(masterPtr->masterDataPtr->anchor, masterPtr->tkwin,
+ 0, 0, usedX, usedY, &slotPtr->startX, &slotPtr->startY);
/*
* Now adjust the actual size of the slave to its cavity by
@@ -1684,12 +1763,12 @@ ArrangeGrid(clientData)
if (abort) {
break;
}
-
+
/*
* Don't map the slave if the master isn't mapped: wait
* until the master gets mapped later.
*/
-
+
if (Tk_IsMapped(masterPtr->tkwin)) {
Tk_MapWindow(slavePtr->tkwin);
}
@@ -1730,7 +1809,7 @@ ArrangeGrid(clientData)
*/
static int
-ResolveConstraints(masterPtr, slotType, maxOffset)
+ResolveConstraints(masterPtr, slotType, maxOffset)
Gridder *masterPtr; /* The geometry master for this grid. */
int slotType; /* Either ROW or COLUMN. */
int maxOffset; /* The actual maximum size of this layout
@@ -1834,12 +1913,12 @@ ResolveConstraints(masterPtr, slotType, maxOffset)
* contribute to the minimum size of each slot directly, but can cause
* slots to grow if their size exceeds the the sizes of the slots they
* span.
- *
+ *
* Bin all slaves whose spans are > 1 by their right edges. This
* allows the computation on minimum and maximum possible layout
* sizes at each slot boundary, without the need to re-sort the slaves.
*/
-
+
switch (slotType) {
case COLUMN:
for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
@@ -2032,7 +2111,7 @@ ResolveConstraints(masterPtr, slotType, maxOffset)
* this span. */
int have; /* The actual amount of space that will
* be taken up by this span. */
- int weight; /* Cumulative weights of the columns in
+ int weight; /* Cumulative weights of the columns in
* this span. */
int noWeights = 0; /* True if the span has no weights. */
@@ -2077,13 +2156,13 @@ ResolveConstraints(masterPtr, slotType, maxOffset)
/*
* It might not be possible to give the span all of the space
- * available on this pass without violating the size constraints
+ * available on this pass without violating the size constraints
* of one or more of the internal slot boundaries.
* Try to determine the maximum amount of space that when added to
* the entire span, would cause a slot boundary to have its possible
* range reduced to one value, and reduce the amount of extra
* space allocated on this pass accordingly.
- *
+ *
* The calculation is done cumulatively to avoid accumulating
* roundoff errors.
*/
@@ -2102,7 +2181,7 @@ ResolveConstraints(masterPtr, slotType, maxOffset)
((prevMinOffset + layoutPtr[slot].minSize + grow)
> layoutPtr[slot].maxOffset)) {
int newHave;
- /*
+ /*
* There is not enough room to grow that much.
* Calculate how much this slot can grow and how much
* "have" that corresponds to.
@@ -2121,7 +2200,7 @@ ResolveConstraints(masterPtr, slotType, maxOffset)
newHave = newHave / totalWeight * totalWeight;
}
if (newHave <= 0) {
- /*
+ /*
* We can end up with a "have" of 0 here if
* the previous slots have taken all the space.
* In that case we cannot guess an appropriate
@@ -2152,7 +2231,7 @@ ResolveConstraints(masterPtr, slotType, maxOffset)
prevMinOffset += layoutPtr[slot].minSize + grow;
if (prevMinOffset < layoutPtr[slot].minOffset) {
prevMinOffset = layoutPtr[slot].minOffset;
- }
+ }
}
/* Quit the loop if the for loop ran all the way */
if (slot > end) break;
@@ -2184,7 +2263,7 @@ ResolveConstraints(masterPtr, slotType, maxOffset)
*/
for (slot=end; slot > start; slot--) {
- layoutPtr[slot-1].maxOffset =
+ layoutPtr[slot-1].maxOffset =
layoutPtr[slot].maxOffset-layoutPtr[slot].minSize;
}
}
@@ -2370,7 +2449,7 @@ CheckSlotData(masterPtr, slot, slotType, checkOnly)
if (checkOnly == CHECK_ONLY) {
return (end < slot) ? TCL_ERROR : TCL_OK;
} else {
- numSlot = (slotType == ROW) ? masterPtr->masterDataPtr->rowSpace
+ numSlot = (slotType == ROW) ? masterPtr->masterDataPtr->rowSpace
: masterPtr->masterDataPtr->columnSpace;
if (slot >= numSlot) {
int newNumSlot = slot + PREALLOC ;
@@ -2441,6 +2520,7 @@ InitMasterData(masterPtr)
gridPtr->rowSpace = TYPICAL_SIZE;
gridPtr->startX = 0;
gridPtr->startY = 0;
+ gridPtr->anchor = GRID_DEFAULT_ANCHOR;
memset((VOID *) gridPtr->columnPtr, 0, size);
memset((VOID *) gridPtr->rowPtr, 0, size);
@@ -2682,7 +2762,7 @@ ConfigureSlaves(interp, tkwin, objc, objv)
prevChar = firstChar;
string = Tcl_GetStringFromObj(objv[i], (int *) &length);
firstChar = string[0];
-
+
if (firstChar == '.') {
numWindows++;
continue;
@@ -2788,7 +2868,7 @@ ConfigureSlaves(interp, tkwin, objc, objv)
* programmer will want it to retain its old configuration information.
* If the programmer doesn't want this behavior, then the
* defaults can be reestablished by hand, without having to worry
- * about keeping track of the old state.
+ * about keeping track of the old state.
*/
for (i = numWindows; i < objc; i += 2) {
@@ -2800,7 +2880,7 @@ ConfigureSlaves(interp, tkwin, objc, objv)
if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK ||
tmp < 0) {
Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "bad column value \"",
+ Tcl_AppendResult(interp, "bad column value \"",
Tcl_GetString(objv[i+1]),
"\": must be a non-negative integer", (char *)NULL);
return TCL_ERROR;
@@ -2965,7 +3045,7 @@ ConfigureSlaves(interp, tkwin, objc, objv)
if (masterPtr->masterPtr == slavePtr) {
Tcl_AppendResult(interp, "can't put ", Tcl_GetString(objv[j]),
" inside ", Tk_PathName(masterPtr->tkwin),
- ", would cause management loop.",
+ ", would cause management loop.",
(char *) NULL);
Unlink(slavePtr);
return TCL_ERROR;
@@ -3045,7 +3125,7 @@ ConfigureSlaves(interp, tkwin, objc, objv)
* Find the implied grid location of the ^
*/
- if (lastWindow == NULL) {
+ if (lastWindow == NULL) {
if (masterPtr->masterDataPtr != NULL) {
SetGridSize(masterPtr);
lastRow = masterPtr->masterDataPtr->rowEnd - 2;
diff --git a/tests/grid.test b/tests/grid.test
index 2c13a38..187f061 100644
--- a/tests/grid.test
+++ b/tests/grid.test
@@ -5,7 +5,7 @@
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.
#
-# RCS: @(#) $Id: grid.test,v 1.22 2003/09/18 20:34:07 pspjuth Exp $
+# RCS: @(#) $Id: grid.test,v 1.23 2004/01/09 22:23:26 pspjuth Exp $
package require tcltest 2.1
eval tcltest::configure $argv
@@ -34,6 +34,7 @@ proc grid_reset {{test ?} {top .}} {
grid rowconfigure . $i -weight 0 -minsize 0 -pad 0 -uniform ""
}
grid propagate . 1
+ grid anchor . nw
update
}
@@ -46,7 +47,7 @@ test grid-1.1 {basic argument checking} {
test grid-1.2 {basic argument checking} {
list [catch {grid foo bar} msg] $msg
-} {1 {bad option "foo": must be bbox, columnconfigure, configure, forget, info, location, propagate, remove, rowconfigure, size, or slaves}}
+} {1 {bad option "foo": must be anchor, bbox, columnconfigure, configure, forget, info, location, propagate, remove, rowconfigure, size, or slaves}}
test grid-1.3 {basic argument checking} {
button .b
@@ -1261,6 +1262,7 @@ test grid-16.1 {layout centering} {
grid .$i -row $i -column $i -sticky nswe
}
grid propagate . 0
+ grid anchor . center
. configure -width 300 -height 250
update
grid bbox .
@@ -1691,6 +1693,51 @@ test grid-20.2 {recalculate size after removal (forget)} {
} {1 1}
grid_reset 20.2
+test grid-21.1 {anchor} {
+ list [catch {grid anchor . 1 xxx} msg] $msg
+} {1 {wrong # args: should be "grid anchor window ?anchor?"}}
+grid_reset 21.1
+
+test grid-21.2 {anchor} {
+ list [catch {grid anchor .} msg] $msg
+} {0 nw}
+grid_reset 21.2
+
+test grid-21.3 {anchor} {
+ list [catch {grid anchor . se;grid anchor .} msg] $msg
+} {0 se}
+grid_reset 21.3
+
+test grid-21.4 {anchor} {
+ list [catch {grid anchor .x} msg] $msg
+} {1 {bad window path name ".x"}}
+grid_reset 21.4
+
+test grid-21.5 {anchor} {
+ list [catch {grid anchor . x} msg] $msg
+} {1 {bad anchor "x": must be n, ne, e, se, s, sw, w, nw, or center}}
+grid_reset 21.5
+
+test grid-21.6 {anchor} {
+ foreach i {0 1 2} {
+ frame .$i -bg gray -width 75 -height 50 -bd 2 -relief ridge
+ grid .$i -row $i -column $i -sticky nswe
+ }
+ grid propagate . 0
+ . configure -width 300 -height 250
+
+ set res {}
+ foreach a {n ne e se s sw w nw center} {
+ grid anchor . $a
+ update
+ lappend res [grid bbox .]
+ }
+ set res
+} [list {37 0 225 150} {75 0 225 150} {75 50 225 150} {75 100 225 150} \
+ {37 100 225 150} {0 100 225 150} {0 50 225 150} {0 0 225 150} \
+ {37 50 225 150}]
+grid_reset 21.6
+
# cleanup
cleanupTests
return