From fc6975170b18c3a343d4c0333631e36f621ec9c9 Mon Sep 17 00:00:00 2001 From: pspjuth Date: Thu, 18 Sep 2003 18:22:22 +0000 Subject: Implementation of TIP#147, "Make Grid's Column/Row Configure Easier". --- ChangeLog | 6 ++ doc/grid.n | 28 +++--- generic/tkGrid.c | 280 +++++++++++++++++++++++++++++++++---------------------- tests/grid.test | 61 +++++++++++- 4 files changed, 251 insertions(+), 124 deletions(-) diff --git a/ChangeLog b/ChangeLog index eaa8e47..86907e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2003-09-18 Peter Spjuth + * doc/grid.n: + * tests/grid.test: + * generic/tkGrid.c: Implementation of TIP#147, + "Make Grid's Column/Row Configure Easier". + 2003-09-17 Don Porter * generic/tkImage.c: Stopped [image create] from generating an diff --git a/doc/grid.n b/doc/grid.n index c6c3b17..07c1ddd 100644 --- a/doc/grid.n +++ b/doc/grid.n @@ -4,10 +4,10 @@ '\" 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.5 2001/09/30 19:01:58 pspjuth Exp $ +'\" RCS: @(#) $Id: grid.n,v 1.6 2003/09/18 18:22:22 pspjuth Exp $ '\" .so man.macros -.TH grid n 8.4 Tk "Tk Built-In Commands" +.TH grid n 8.5 Tk "Tk Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME @@ -46,12 +46,16 @@ indicated is returned. \fBgrid columnconfigure \fImaster index \fR?\fI\-option value...\fR? Query or set the column properties of the \fIindex\fP column of the geometry master, \fImaster\fP. -.VS 8.4 The valid options are \fB\-minsize\fP, \fB\-weight\fP, \fB\-uniform\fP and \fB-pad\fP. -.VE If one or more options are provided, then \fIindex\fP may be given as -a list of column indeces to which the configuration options will operate on. +a list of column indices to which the configuration options will operate on. +.VS 8.5 +Indices may be integers, window names or the keyword \fIall\fP. For \fIall\fP +the options apply to all columns currently occupied be slave windows. For +a window name, that window must be a slave of this master and the options +apply to all columns currently occupied be the slave. +.VE The \fB\-minsize\fP option sets the minimum size, in screen units, that will be permitted for this column. The \fB\-weight\fP option (an integer value) @@ -61,14 +65,12 @@ columns. A weight of zero (0) indicates the column will not deviate from its requested size. A column whose weight is two will grow at twice the rate as a column of weight one when extra space is allocated to the layout. -.VS 8.4 The \fB-uniform\fP option, when a non-empty value is supplied, places the column in a \fIuniform group\fP with other columns that have the same value for \fB-uniform\fP. The space for columns belonging to a uniform group is allocated so that their sizes are always in strict proportion to their \fB-weight\fP values. See ``THE GRID ALGORITHM'' below for further details. -.VE The \fB-pad\fP option specifies the number of screen units that will be added to the largest window contained completely in that column when the grid geometry manager requests a size from the containing window. @@ -204,12 +206,16 @@ Propagation is enabled by default. \fBgrid rowconfigure \fImaster index \fR?\fI\-option value...\fR? Query or set the row properties of the \fIindex\fP row of the geometry master, \fImaster\fP. -.VS 8.4 The valid options are \fB\-minsize\fP, \fB\-weight\fP, \fB\-uniform\fP and \fB-pad\fP. -.VE If one or more options are provided, then \fIindex\fP may be given as -a list of row indeces to which the configuration options will operate on. +a list of row indices to which the configuration options will operate on. +.VS 8.5 +Indices may be integers, window names or the keyword \fIall\fP. For \fIall\fP +the options apply to all rows currently occupied be slave windows. For +a window name, that window must be a slave of this master and the options +apply to all rows currently occupied be the slave. +.VE The \fB\-minsize\fP option sets the minimum size, in screen units, that will be permitted for this row. The \fB\-weight\fP option (an integer value) @@ -219,14 +225,12 @@ rows. A weight of zero (0) indicates the row will not deviate from its requested size. A row whose weight is two will grow at twice the rate as a row of weight one when extra space is allocated to the layout. -.VS 8.4 The \fB-uniform\fP option, when a non-empty value is supplied, places the row in a \fIuniform group\fP with other rows that have the same value for \fB-uniform\fP. The space for rows belonging to a uniform group is allocated so that their sizes are always in strict proportion to their \fB-weight\fP values. See ``THE GRID ALGORITHM'' below for further details. -.VE The \fB-pad\fP option specifies the number of screen units that will be added to the largest window contained completely in that row when the grid geometry manager requests a size from the containing window. diff --git a/generic/tkGrid.c b/generic/tkGrid.c index 0b6ac23..9a8ca90 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.27 2003/09/16 21:47:15 pspjuth Exp $ + * RCS: @(#) $Id: tkGrid.c,v 1.28 2003/09/18 18:22:22 pspjuth Exp $ */ #include "tkInt.h" @@ -838,17 +838,17 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv) int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { - Tk_Window master; + Tk_Window master, slave; Gridder *masterPtr; + Gridder *slavePtr; SlotInfo *slotPtr = NULL; int slot; /* the column or row number */ int slotType; /* COLUMN or ROW */ int size; /* the configuration value */ - int checkOnly; /* check the size only */ int lObjc; /* Number of items in index list */ Tcl_Obj **lObjv; /* array of indices */ int ok; /* temporary TCL result code */ - int i, j; + int i, j, first, last; char *string; static CONST char *optionStrings[] = { "-minsize", "-pad", "-uniform", "-weight", (char *) NULL }; @@ -869,30 +869,26 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv) } string = Tcl_GetString(objv[1]); - checkOnly = ((objc == 4) || (objc == 5)); masterPtr = GetGrid(master); slotType = (*string == 'c') ? COLUMN : ROW; - if (checkOnly && lObjc > 1) { - Tcl_AppendResult(interp, Tcl_GetString(objv[3]), - " must be a single element.", (char *) NULL); - return TCL_ERROR; - } - for (j = 0; j < lObjc; j++) { - if (Tcl_GetIntFromObj(interp, lObjv[j], &slot) != TCL_OK) { + + if ((objc == 4) || (objc == 5)) { + if (lObjc != 1) { + Tcl_AppendResult(interp, Tcl_GetString(objv[3]), + " must be a single element.", (char *) NULL); return TCL_ERROR; } - ok = CheckSlotData(masterPtr, slot, slotType, checkOnly); - if ((ok != TCL_OK) && ((objc < 4) || (objc > 5))) { - Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", - Tcl_GetString(objv[1]), ": \"", Tcl_GetString(lObjv[j]), - "\" is out of range", (char *) NULL); + if (Tcl_GetIntFromObj(interp, lObjv[0], &slot) != TCL_OK) { + Tcl_AppendResult(interp, + " (when retreiving options only integer indices are allowed)", + (char *) NULL); return TCL_ERROR; - } else if (ok == TCL_OK) { - slotPtr = (slotType == COLUMN) ? - masterPtr->masterDataPtr->columnPtr : - masterPtr->masterDataPtr->rowPtr; } - + ok = CheckSlotData(masterPtr, slot, slotType, /* checkOnly */ 1); + 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. @@ -902,7 +898,7 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv) int minsize = 0, pad = 0, weight = 0; Tk_Uid uniform = NULL; Tcl_Obj *res = Tcl_NewListObj(0, NULL); - + if (ok == TCL_OK) { minsize = slotPtr[slot].minSize; pad = slotPtr[slot].pad; @@ -926,114 +922,178 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv) Tcl_SetObjResult(interp, res); return TCL_OK; } - + /* - * Loop through each option value pair, setting the values as - * required. If only one option is given, with no value, the + * If only one option is given, with no value, the * current value is returned. */ - for (i = 4; i < objc; i += 2) { - if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObj(interp, objv[4], optionStrings, + "option", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == ROWCOL_MINSIZE) { + Tcl_SetObjResult(interp, + Tcl_NewIntObj((ok == TCL_OK) ? slotPtr[slot].minSize : 0)); + } else if (index == ROWCOL_WEIGHT) { + Tcl_SetObjResult(interp, + Tcl_NewIntObj((ok == TCL_OK) ? slotPtr[slot].weight : 0)); + } else if (index == ROWCOL_UNIFORM) { + Tk_Uid value; + value = (ok == TCL_OK) ? slotPtr[slot].uniform : ""; + Tcl_SetObjResult(interp, + Tcl_NewStringObj(value == NULL ? "" : value, -1)); + } else if (index == ROWCOL_PAD) { + Tcl_SetObjResult(interp, + Tcl_NewIntObj((ok == TCL_OK) ? slotPtr[slot].pad : 0)); + } + return TCL_OK; + } + + for (j = 0; j < lObjc; j++) { + int allSlaves = 0; + if (Tcl_GetIntFromObj(interp, lObjv[j], &slot) == TCL_OK) { + first = slot; + last = slot; + slavePtr = NULL; + } else if (strcmp(Tcl_GetString(lObjv[j]), "all") == 0) { + slavePtr = masterPtr->slavePtr; + if (slavePtr == NULL) { + continue; + } + allSlaves = 1; + } else if (TkGetWindowFromObj(interp, tkwin, lObjv[j], &slave) + == TCL_OK) { + /* Is it gridded in this master? */ + slavePtr = GetGrid(slave); + if (slavePtr->masterPtr != masterPtr) { + Tcl_ResetResult(interp); + 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]), + "\"", (char *) NULL); return TCL_ERROR; } - if (index == ROWCOL_MINSIZE) { - if (objc == 5) { - Tcl_SetObjResult(interp, Tcl_NewIntObj( - (ok == TCL_OK) ? slotPtr[slot].minSize : 0)); - } else if (Tk_GetPixelsFromObj(interp, master, objv[i+1], &size) - != TCL_OK) { - return TCL_ERROR; - } else { - slotPtr[slot].minSize = size; - } + } else { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", + Tcl_GetString(objv[1]), ": illegal index \"", + Tcl_GetString(lObjv[j]), "\"", (char *) NULL); + return TCL_ERROR; + } + + /* + * The outer loop is only to handle "all". + */ + do { + if (slavePtr != NULL) { + first = (slotType == COLUMN) ? + slavePtr->column : slavePtr->row; + last = first - 1 + ((slotType == COLUMN) ? + slavePtr->numCols : slavePtr->numRows); } - else if (index == ROWCOL_WEIGHT) { - int wt; - if (objc == 5) { - Tcl_SetObjResult(interp, Tcl_NewIntObj( - (ok == TCL_OK) ? slotPtr[slot].weight : 0)); - } else if (Tcl_GetIntFromObj(interp, objv[i+1], &wt) - != TCL_OK) { - return TCL_ERROR; - } else if (wt < 0) { - Tcl_AppendResult(interp, "invalid arg \"", - Tcl_GetString(objv[i]), - "\": should be non-negative", (char *) NULL); + + 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_GetString(objv[1]), ": \"", + Tcl_GetString(lObjv[j]), + "\" is out of range", (char *) NULL); return TCL_ERROR; - } else { - slotPtr[slot].weight = wt; } - } - else if (index == ROWCOL_UNIFORM) { - if (objc == 5) { - Tk_Uid value; - value = (ok == TCL_OK) ? slotPtr[slot].uniform : ""; - if (value == NULL) { - value = ""; + slotPtr = (slotType == COLUMN) ? + masterPtr->masterDataPtr->columnPtr : + masterPtr->masterDataPtr->rowPtr; + + /* + * Loop through each option value pair, setting the values as + * required. + */ + + for (i = 4; i < objc; i += 2) { + if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, + "option", 0, &index) != TCL_OK) { + return TCL_ERROR; } - Tcl_SetObjResult(interp, Tcl_NewStringObj(value, -1)); - } else { - slotPtr[slot].uniform = Tk_GetUid(Tcl_GetString(objv[i+1])); - if (slotPtr[slot].uniform != NULL && - slotPtr[slot].uniform[0] == 0) { - slotPtr[slot].uniform = NULL; + if (index == ROWCOL_MINSIZE) { + if (Tk_GetPixelsFromObj(interp, master, objv[i+1], + &size) != TCL_OK) { + return TCL_ERROR; + } else { + slotPtr[slot].minSize = size; + } + } else if (index == ROWCOL_WEIGHT) { + int wt; + if (Tcl_GetIntFromObj(interp, objv[i+1], &wt) != TCL_OK) { + return TCL_ERROR; + } else if (wt < 0) { + Tcl_AppendResult(interp, "invalid arg \"", + Tcl_GetString(objv[i]), + "\": should be non-negative", (char *) NULL); + return TCL_ERROR; + } else { + slotPtr[slot].weight = wt; + } + } else if (index == ROWCOL_UNIFORM) { + slotPtr[slot].uniform = Tk_GetUid(Tcl_GetString(objv[i+1])); + if (slotPtr[slot].uniform != NULL && + slotPtr[slot].uniform[0] == 0) { + slotPtr[slot].uniform = NULL; + } + } else if (index == ROWCOL_PAD) { + if (Tk_GetPixelsFromObj(interp, master, objv[i+1], &size) + != TCL_OK) { + return TCL_ERROR; + } else if (size < 0) { + Tcl_AppendResult(interp, "invalid arg \"", + Tcl_GetString(objv[i]), + "\": should be non-negative", (char *) NULL); + return TCL_ERROR; + } else { + slotPtr[slot].pad = size; + } } } } - else if (index == ROWCOL_PAD) { - if (objc == 5) { - Tcl_SetObjResult(interp, Tcl_NewIntObj( - (ok == TCL_OK) ? slotPtr[slot].pad : 0)); - } else if (Tk_GetPixelsFromObj(interp, master, objv[i+1], &size) - != TCL_OK) { - return TCL_ERROR; - } else if (size < 0) { - Tcl_AppendResult(interp, "invalid arg \"", - Tcl_GetString(objv[i]), - "\": should be non-negative", (char *) NULL); - return TCL_ERROR; - } else { - slotPtr[slot].pad = size; - } + if (slavePtr != NULL) { + slavePtr = slavePtr->nextPtr; } - } + } while ((allSlaves == 1) && (slavePtr != NULL)); } /* - * If we changed a property, re-arrange the table, + * We changed a property, re-arrange the table, * and check for constraint shrinkage. */ - if (objc != 5) { - if (slotType == ROW) { - int last = masterPtr->masterDataPtr->rowMax - 1; - while ((last >= 0) && (slotPtr[last].weight == 0) - && (slotPtr[last].pad == 0) - && (slotPtr[last].minSize == 0) - && (slotPtr[last].uniform == NULL)) { - last--; - } - masterPtr->masterDataPtr->rowMax = last+1; - } else { - int last = masterPtr->masterDataPtr->columnMax - 1; - while ((last >= 0) && (slotPtr[last].weight == 0) - && (slotPtr[last].pad == 0) - && (slotPtr[last].minSize == 0) - && (slotPtr[last].uniform == NULL)) { - last--; - } - masterPtr->masterDataPtr->columnMax = last + 1; - } - - if (masterPtr->abortPtr != NULL) { - *masterPtr->abortPtr = 1; - } - if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { - masterPtr->flags |= REQUESTED_RELAYOUT; - Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); + if (slotType == ROW) { + int last = masterPtr->masterDataPtr->rowMax - 1; + while ((last >= 0) && (slotPtr[last].weight == 0) + && (slotPtr[last].pad == 0) + && (slotPtr[last].minSize == 0) + && (slotPtr[last].uniform == NULL)) { + last--; + } + masterPtr->masterDataPtr->rowMax = last+1; + } else { + int last = masterPtr->masterDataPtr->columnMax - 1; + while ((last >= 0) && (slotPtr[last].weight == 0) + && (slotPtr[last].pad == 0) + && (slotPtr[last].minSize == 0) + && (slotPtr[last].uniform == NULL)) { + last--; } + masterPtr->masterDataPtr->columnMax = last + 1; + } + + if (masterPtr->abortPtr != NULL) { + *masterPtr->abortPtr = 1; + } + if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { + masterPtr->flags |= REQUESTED_RELAYOUT; + Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); } return TCL_OK; } diff --git a/tests/grid.test b/tests/grid.test index 063c9f8..c751db4 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.20 2003/09/16 21:47:15 pspjuth Exp $ +# RCS: @(#) $Id: grid.test,v 1.21 2003/09/18 18:22:22 pspjuth Exp $ package require tcltest 2.1 eval tcltest::configure $argv @@ -582,7 +582,7 @@ grid_reset 10.3 test grid-10.4 {column/row configure} { list [catch {grid columnconfigure . nine -weight} msg] $msg -} {1 {expected integer but got "nine"}} +} {1 {expected integer but got "nine" (when retreiving options only integer indices are allowed)}} grid_reset 10.4 test grid-10.5 {column/row configure} { @@ -687,6 +687,63 @@ test grid-10.20 {column/row configure} { } {foo} grid_reset 10.20 +test grid-10.21 {column/row configure} { + list [catch {grid columnconfigure . .b -weight 1} msg] $msg +} {1 {grid columnconfigure: illegal index ".b"}} +grid_reset 10.21 + +test grid-10.22 {column/row configure} { + button .b + list [catch {grid columnconfigure . .b -weight 1} msg] $msg +} {1 {grid columnconfigure: the window ".b" is not managed by "."}} +grid_reset 10.22 + +test grid-10.23 {column/row configure} { + button .b + grid .b -column 1 -columnspan 2 + grid columnconfigure . .b -weight 1 + set res {} + foreach i {0 1 2 3} { + lappend res [grid columnconfigure . $i -weight] + } + set res +} {0 1 1 0} +grid_reset 10.23 + +test grid-10.24 {column/row configure} { + button .b + button .c + button .d + grid .b -column 1 -columnspan 2 + grid .c -column 2 -columnspan 3 + grid .d -column 4 -columnspan 2 + grid columnconfigure . {.b .d} -weight 1 + grid columnconfigure . .c -weight 2 + set res {} + foreach i {0 1 2 3 4 5 6} { + lappend res [grid columnconfigure . $i -weight] + } + set res +} {0 1 2 2 2 1 0} +grid_reset 10.24 + +test grid-10.25 {column/row configure} { + button .b + button .c + button .d + grid .b -row 1 -rowspan 2 + grid .c -row 2 -rowspan 3 + grid .d -row 4 -rowspan 2 + grid rowconfigure . {7 all} -weight 1 + grid rowconfigure . {1 .d} -weight 2 + set res {} + foreach i {0 1 2 3 4 5 6 7} { + lappend res [grid rowconfigure . $i -weight] + } + set res +} {0 2 1 1 2 2 0 1} +grid_reset 10.25 + # auto-placement tests test grid-11.1 {default widget placement} { -- cgit v0.12