summaryrefslogtreecommitdiffstats
path: root/generic/tkPack.c
diff options
context:
space:
mode:
authordrh <drh@sqlite.org>2001-02-12 18:06:47 (GMT)
committerdrh <drh@sqlite.org>2001-02-12 18:06:47 (GMT)
commit413e598de2e293d8046eaadcb0e4e30a9b9f49cc (patch)
treea7e13b5d6f5052a80f4cc71760b9cbdc5b952852 /generic/tkPack.c
parent68371803a20c54dd7674dfb0e56673f3bf1218ae (diff)
downloadtk-413e598de2e293d8046eaadcb0e4e30a9b9f49cc.zip
tk-413e598de2e293d8046eaadcb0e4e30a9b9f49cc.tar.gz
tk-413e598de2e293d8046eaadcb0e4e30a9b9f49cc.tar.bz2
Asymmetric padding in "pack" and "grid" geometry managers
Diffstat (limited to 'generic/tkPack.c')
-rw-r--r--generic/tkPack.c242
1 files changed, 179 insertions, 63 deletions
diff --git a/generic/tkPack.c b/generic/tkPack.c
index a178261..a6df7a9 100644
--- a/generic/tkPack.c
+++ b/generic/tkPack.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkPack.c,v 1.6 2000/04/10 22:43:12 ericm Exp $
+ * RCS: @(#) $Id: tkPack.c,v 1.7 2001/02/12 18:06:47 drh Exp $
*/
#include "tkPort.h"
@@ -24,7 +24,7 @@ typedef enum {TOP, BOTTOM, LEFT, RIGHT} Side;
* structure of the following type:
*/
-typedef struct /* Green Bay */ Packer {
+typedef struct Packer {
Tk_Window tkwin; /* Tk token for window. NULL means that
* the window has been deleted, but the
* packet hasn't had a chance to clean up
@@ -45,12 +45,15 @@ typedef struct /* Green Bay */ Packer {
* than window needs, this indicates how
* where to position window in frame. */
int padX, padY; /* Total additional pixels to leave around the
- * window (half of this space is left on each
- * side). This is space *outside* the window:
+ * 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). */
+ int padLeft, padTop; /* The part of padX or padY to use on the
+ * left or top of the widget, respectively.
+ * By default, this is half of padX or padY. */
int iPadX, iPadY; /* Total extra pixels to allocate inside the
- * window (half this amount will appear on
+ * window (half of this amount will appear on
* each side). */
int doubleBw; /* Twice the window's last known border
* width. If this changes, the window
@@ -136,6 +139,43 @@ static int YExpansion _ANSI_ARGS_((Packer *slavePtr,
/*
*--------------------------------------------------------------
*
+ * TkPrintPadAmount --
+ *
+ * This procedure generates a text value that describes one
+ * of the -padx, -pady, -ipadx, or -ipady configuration options.
+ * The text value generated is appended to the interpreter
+ * result.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+void
+TkPrintPadAmount(interp, switchName, halfSpace, allSpace)
+ Tcl_Interp *interp; /* The interpreter into which the result
+ * is written. */
+ char *switchName; /* One of "padx", "pady", "ipadx" or "ipady" */
+ int halfSpace; /* The left or top padding amount */
+ int allSpace; /* The total amount of padding */
+{
+ char buffer[60 + 2*TCL_INTEGER_SPACE];
+ if (halfSpace*2 == allSpace) {
+ sprintf(buffer, " -%.10s %d", switchName, halfSpace);
+ } else {
+ sprintf(buffer, " -%.10s {%d %d}", switchName, halfSpace,
+ allSpace - halfSpace);
+ }
+ Tcl_AppendResult(interp, buffer, (char *)NULL);
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
* Tk_PackCmd --
*
* This procedure is invoked to process the "pack" Tcl command.
@@ -268,7 +308,6 @@ Tk_PackCmd(clientData, interp, argc, argv)
} else if ((c == 'i') && (strncmp(argv[1], "info", length) == 0)) {
register Packer *slavePtr;
Tk_Window slave;
- char buffer[64 + TCL_INTEGER_SPACE * 4];
static char *sideNames[] = {"top", "bottom", "left", "right"};
if (argc != 3) {
@@ -307,10 +346,11 @@ Tk_PackCmd(clientData, interp, argc, argv)
Tcl_AppendResult(interp, "both", (char *) NULL);
break;
}
- sprintf(buffer, " -ipadx %d -ipady %d -padx %d -pady %d",
- slavePtr->iPadX/2, slavePtr->iPadY/2, slavePtr->padX/2,
- slavePtr->padY/2);
- Tcl_AppendResult(interp, buffer, " -side ", sideNames[slavePtr->side],
+ TkPrintPadAmount(interp, "ipadx", slavePtr->iPadX/2, slavePtr->iPadX);
+ TkPrintPadAmount(interp, "ipady", slavePtr->iPadY/2, slavePtr->iPadY);
+ TkPrintPadAmount(interp, "padx", slavePtr->padLeft, slavePtr->padX);
+ TkPrintPadAmount(interp, "pady", slavePtr->padTop, slavePtr->padY);
+ Tcl_AppendResult(interp, " -side ", sideNames[slavePtr->side],
(char *) NULL);
} else if ((c == 'p') && (strncmp(argv[1], "propagate", length) == 0)) {
Tk_Window master;
@@ -518,6 +558,8 @@ ArrangePacking(clientData)
int abort; /* May get set to non-zero to abort this
* repacking operation. */
int borderX, borderY;
+ int borderTop, borderBtm;
+ int borderLeft, borderRight;
int maxWidth, maxHeight, tmp;
masterPtr->flags &= ~REQUESTED_REPACK;
@@ -678,9 +720,15 @@ ArrangePacking(clientData)
if (slavePtr->flags & OLD_STYLE) {
borderX = borderY = 0;
+ borderTop = borderBtm = 0;
+ borderLeft = borderRight = 0;
} else {
borderX = slavePtr->padX;
borderY = slavePtr->padY;
+ borderLeft = slavePtr->padLeft;
+ borderRight = borderX - borderLeft;
+ borderTop = slavePtr->padTop;
+ borderBtm = borderY - borderTop;
}
width = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->doubleBw
+ slavePtr->iPadX;
@@ -694,44 +742,42 @@ ArrangePacking(clientData)
|| (height > (frameHeight - borderY))) {
height = frameHeight - borderY;
}
- borderX /= 2;
- borderY /= 2;
switch (slavePtr->anchor) {
case TK_ANCHOR_N:
- x = frameX + (frameWidth - width)/2;
- y = frameY + borderY;
+ x = frameX + (borderLeft + frameWidth - width - borderRight)/2;
+ y = frameY + borderTop;
break;
case TK_ANCHOR_NE:
- x = frameX + frameWidth - width - borderX;
- y = frameY + borderY;
+ x = frameX + frameWidth - width - borderRight;
+ y = frameY + borderTop;
break;
case TK_ANCHOR_E:
- x = frameX + frameWidth - width - borderX;
- y = frameY + (frameHeight - height)/2;
+ x = frameX + frameWidth - width - borderRight;
+ y = frameY + (borderTop + frameHeight - height - borderBtm)/2;
break;
case TK_ANCHOR_SE:
- x = frameX + frameWidth - width - borderX;
- y = frameY + frameHeight - height - borderY;
+ x = frameX + frameWidth - width - borderRight;
+ y = frameY + frameHeight - height - borderBtm;
break;
case TK_ANCHOR_S:
- x = frameX + (frameWidth - width)/2;
- y = frameY + frameHeight - height - borderY;
+ x = frameX + (borderLeft + frameWidth - width - borderRight)/2;
+ y = frameY + frameHeight - height - borderBtm;
break;
case TK_ANCHOR_SW:
- x = frameX + borderX;
- y = frameY + frameHeight - height - borderY;
+ x = frameX + borderLeft;
+ y = frameY + frameHeight - height - borderBtm;
break;
case TK_ANCHOR_W:
- x = frameX + borderX;
- y = frameY + (frameHeight - height)/2;
+ x = frameX + borderLeft;
+ y = frameY + (borderTop + frameHeight - height - borderBtm)/2;
break;
case TK_ANCHOR_NW:
- x = frameX + borderX;
- y = frameY + borderY;
+ x = frameX + borderLeft;
+ y = frameY + borderTop;
break;
case TK_ANCHOR_CENTER:
- x = frameX + (frameWidth - width)/2;
- y = frameY + (frameHeight - height)/2;
+ x = frameX + (borderLeft + frameWidth - width - borderRight)/2;
+ y = frameY + (borderTop + frameHeight - height - borderBtm)/2;
break;
default:
panic("bad frame factor in ArrangePacking");
@@ -969,6 +1015,7 @@ GetPacker(tkwin)
packPtr->side = TOP;
packPtr->anchor = TK_ANCHOR_CENTER;
packPtr->padX = packPtr->padY = 0;
+ packPtr->padLeft = packPtr->padTop = 0;
packPtr->iPadX = packPtr->iPadY = 0;
packPtr->doubleBw = 2*Tk_Changes(tkwin)->border_width;
packPtr->abortPtr = NULL;
@@ -982,6 +1029,85 @@ GetPacker(tkwin)
/*
*--------------------------------------------------------------
*
+ * TkParsePadAmount --
+ *
+ * This procedure parses a padding specification and returns
+ * the appropriate padding values. A padding specification can
+ * be either a single pixel width, or a list of two pixel widths.
+ * If a single pixel width, the amount specified is used for
+ * padding on both sides. If two amounts are specified, then
+ * they specify the left/right or top/bottom padding.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * An error message is written to the interpreter is something
+ * is not right.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkParsePadAmount(interp, tkwin, padSpec, halfPtr, allPtr)
+ Tcl_Interp *interp; /* Interpreter for error reporting. */
+ Tk_Window tkwin; /* A window. Needed by Tk_GetPixels() */
+ char *padSpec; /* The argument to "-padx", "-pady", "-ipadx",
+ * or "-ipady". The thing to be parsed. */
+ int *halfPtr; /* Write the left/top part of padding here */
+ int *allPtr; /* Write the total padding here */
+{
+ char *secondPart; /* The second pixel amount of the list */
+ char *separator = 0; /* Separator between 1st and 2nd pixel widths */
+ int sepChar; /* Character used as the separator */
+ int firstInt, secondInt; /* The two components of the padding */
+
+ for (secondPart=padSpec;
+ (*secondPart != '\0') && !isspace(UCHAR(*secondPart));
+ secondPart++)
+ { /* Do nothing */ }
+ if (*secondPart != '\0') {
+ separator = secondPart;
+ sepChar = *secondPart;
+ *secondPart = '\0';
+ secondPart++;
+ while ( isspace(UCHAR(*secondPart)) ) {
+ secondPart++;
+ }
+ if (*secondPart == '\0'){
+ secondPart = 0;
+ *separator = sepChar;
+ }
+ } else {
+ secondPart = 0;
+ }
+ if ((Tk_GetPixels(interp, tkwin, padSpec, &firstInt) != TCL_OK) ||
+ (firstInt < 0)) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad pad value \"", padSpec,
+ "\": must be positive screen distance", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (secondPart) {
+ if ((Tk_GetPixels(interp, tkwin, secondPart, &secondInt) != TCL_OK) ||
+ (secondInt < 0)) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad 2nd pad value \"", secondPart,
+ "\": must be positive screen distance", (char *) NULL);
+ return TCL_ERROR;
+ }
+ *separator = sepChar;
+ } else {
+ secondInt = firstInt;
+ }
+ if (halfPtr != 0) *halfPtr = firstInt;
+ *allPtr = firstInt + secondInt;
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
* PackAfter --
*
* This procedure does most of the real work of adding
@@ -1013,7 +1139,7 @@ PackAfter(interp, prevPtr, masterPtr, argc, argv)
Tk_Window tkwin, ancestor, parent;
size_t length;
char **options;
- int index, tmp, optionCount, c;
+ int index, optionCount, c;
/*
* Iterate over all of the window specifiers, each consisting of
@@ -1072,6 +1198,7 @@ PackAfter(interp, prevPtr, masterPtr, argc, argv)
packPtr->side = TOP;
packPtr->anchor = TK_ANCHOR_CENTER;
packPtr->padX = packPtr->padY = 0;
+ packPtr->padLeft = packPtr->padTop = 0;
packPtr->iPadX = packPtr->iPadY = 0;
packPtr->flags &= ~(FILLX|FILLY|EXPAND);
packPtr->flags |= OLD_STYLE;
@@ -1111,27 +1238,24 @@ PackAfter(interp, prevPtr, masterPtr, argc, argv)
(char *) NULL);
goto error;
}
- if ((Tk_GetPixels(interp, tkwin, options[index+1], &tmp)
- != TCL_OK) || (tmp < 0)) {
- badPad:
- Tcl_AppendResult(interp, "bad pad value \"",
- options[index+1],
- "\": must be positive screen distance",
- (char *) NULL);
+ if (TkParsePadAmount(interp, tkwin, options[index+1],
+ &packPtr->padLeft, &packPtr->padX) != TCL_OK) {
goto error;
}
- packPtr->padX = tmp;
+ packPtr->padX /= 2;
+ packPtr->padLeft /= 2;
packPtr->iPadX = 0;
index++;
} else if ((c == 'p') && (strcmp(curOpt, "pady")) == 0) {
if (optionCount < (index+2)) {
goto missingPad;
}
- if ((Tk_GetPixels(interp, tkwin, options[index+1], &tmp)
- != TCL_OK) || (tmp < 0)) {
- goto badPad;
+ if (TkParsePadAmount(interp, tkwin, options[index+1],
+ &packPtr->padTop, &packPtr->padY) != TCL_OK) {
+ goto error;
}
- packPtr->padY = tmp;
+ packPtr->padY /= 2;
+ packPtr->padTop /= 2;
packPtr->iPadY = 0;
index++;
} else if ((c == 'f') && (length > 1)
@@ -1462,6 +1586,7 @@ ConfigureSlaves(interp, tkwin, argc, argv)
slavePtr->side = TOP;
slavePtr->anchor = TK_ANCHOR_CENTER;
slavePtr->padX = slavePtr->padY = 0;
+ slavePtr->padLeft = slavePtr->padTop = 0;
slavePtr->iPadX = slavePtr->iPadY = 0;
slavePtr->flags &= ~(FILLX|FILLY|EXPAND);
}
@@ -1561,34 +1686,25 @@ ConfigureSlaves(interp, tkwin, argc, argv)
positionGiven = 1;
}
} else if ((c == 'i') && (strcmp(argv[i], "-ipadx") == 0)) {
- if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK)
- || (tmp < 0)) {
- badPad:
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "bad pad value \"", argv[i+1],
- "\": must be positive screen distance",
- (char *) NULL);
+ if (TkParsePadAmount(interp, slave, argv[i+1],
+ 0, &slavePtr->iPadX) != TCL_OK) {
return TCL_ERROR;
}
- slavePtr->iPadX = tmp*2;
} else if ((c == 'i') && (strcmp(argv[i], "-ipady") == 0)) {
- if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK)
- || (tmp< 0)) {
- goto badPad;
+ if (TkParsePadAmount(interp, slave, argv[i+1],
+ 0, &slavePtr->iPadY) != TCL_OK) {
+ return TCL_ERROR;
}
- slavePtr->iPadY = tmp*2;
} else if ((c == 'p') && (strcmp(argv[i], "-padx") == 0)) {
- if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK)
- || (tmp< 0)) {
- goto badPad;
+ if (TkParsePadAmount(interp, slave, argv[i+1],
+ &slavePtr->padLeft, &slavePtr->padX) != TCL_OK) {
+ return TCL_ERROR;
}
- slavePtr->padX = tmp*2;
} else if ((c == 'p') && (strcmp(argv[i], "-pady") == 0)) {
- if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK)
- || (tmp< 0)) {
- goto badPad;
+ if (TkParsePadAmount(interp, slave, argv[i+1],
+ &slavePtr->padTop, &slavePtr->padY) != TCL_OK) {
+ return TCL_ERROR;
}
- slavePtr->padY = tmp*2;
} else if ((c == 's') && (strncmp(argv[i], "-side", length) == 0)) {
c = argv[i+1][0];
if ((c == 't') && (strcmp(argv[i+1], "top") == 0)) {