summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog22
-rw-r--r--doc/panedwindow.n246
-rw-r--r--generic/tkInt.h6
-rw-r--r--generic/tkPanedWindow.c2780
-rw-r--r--generic/tkWindow.c3
-rw-r--r--library/panedwindow.tcl136
-rw-r--r--mac/tkMacDefault.h36
-rw-r--r--tests/panedwindow.test2380
-rw-r--r--unix/Makefile.in10
-rw-r--r--unix/tkUnixDefault.h36
-rw-r--r--win/Makefile.in3
-rw-r--r--win/makefile.vc4
-rw-r--r--win/tkWinDefault.h36
13 files changed, 5688 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 956a829..27caaf9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2002-02-21 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * doc/panedwindow.n:
+ * generic/tkPanedWindow.c:
+ * generic/tkInt.h:
+ * generic/tkWindow.c:
+ * library/panedwindow.tcl:
+ * mac/tkMacDefault.h:
+ * tests/panedwindow.test:
+ * unix/Makefile.in:
+ * unix/tkUnixDefault.h:
+ * win/Makefile.in:
+ * win/makefile.vc:
+ * win/tkWinDefault.h: added implementation of TIP #41, panedwindow
+ widget. [Patch #512503] (melski)
+
+ * generic/tkOption.c (ReadOptionFile): fixed Tcl_Seek casting to
+ remove warnings (we expect no option files with be > 2GB).
+
+ * unix/configure: regenerated
+ * unix/tcl.m4: updated to sync with Tcl's tcl.m4
+
2002-02-19 Don Porter <dgp@users.sourceforge.net>
* changes: First draft of updated changes for 8.4a4 release.
diff --git a/doc/panedwindow.n b/doc/panedwindow.n
new file mode 100644
index 0000000..1679e3c
--- /dev/null
+++ b/doc/panedwindow.n
@@ -0,0 +1,246 @@
+'\"
+'\" Copyright (c) 1992 The Regents of the University of California.
+'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+'\" RCS: @(#) $Id: panedwindow.n,v 1.1 2002/02/22 02:41:16 hobbs Exp $
+'\"
+.so man.macros
+.TH panedwindow n 8.4 Tk "Tk Built-In Commands"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+panedwindow \- Create and manipulate panedwindow widgets
+.SH SYNOPSIS
+\fBpanedwindow\fR \fIpathName \fR?\fIoptions\fR?
+.SO
+\-background \-height \-width
+\-borderwidth \-orient
+\-cursor \-relief
+.SE
+.SH "WIDGET-SPECIFIC OPTIONS"
+.OP \-handlepad handlePad HandlePad
+When sash handles are drawn, specifies the distance from the top or
+left end of the sash (depending on the orientation of the widget) at
+which to draw the handle. May be any value accepted by \fBTk_GetPixels\fR.
+.OP \-handlesize handleSize HandleSize
+Specifies the side length of a sash handle. Handles are always
+drawn as squares. May be any value accepted by \fBTk_GetPixels\fR.
+.OP \-opaqueresize opaqueResize OpaqueResize
+Specifies whether panes should be resized as a sash is moved (true),
+or if resizing should be deferred until the sash is placed (false).
+.OP \-sashcursor sashCursor SashCursor
+Mouse cursor to use when over a sash. If null,
+\fBsb_h_double_arrow\fR will be used for horizontal panedwindows, and
+\fBsb_v_double_arrow\fR will be used for vertical panedwindows.
+.OP \-sashpad sashPad SashPad
+Specifies the amount of padding to leave of each side of a sash. May
+be any value accepted by \fBTk_GetPixels\fR.
+.OP \-sashrelief sashRelief SashRelief
+Relief to use when drawing a sash. May be any of the standard Tk
+relief values.
+.OP \-sashwidth sashWidth SashWidth
+Specifies the width of each sash. May be any value accepted by
+\fBTk_GetPixels\fR.
+.OP \-showhandle showHandle ShowHandle
+Specifies whether sash handles should be shown. May be any valid Tcl
+boolean value.
+.BE
+
+.SH DESCRIPTION
+.PP
+The \fBpanedwindow\fR command creates a new window (given by the
+\fIpathName\fR argument) and makes it into a panedwindow widget.
+Additional options, described above, may be specified on the command
+line or in the option database to configure aspects of the panedwindow
+such as its default background color and relief. The
+\fBpanedwindow\fR command returns the path name of the new window.
+.PP
+A panedwindow widget contains any number of panes, arranged
+horizontally or vertically, according to the value of the
+\fB\-orient\fR option. Each pane contains one widget, and each pair of
+panes is separated by a moveable (via mouse movements) sash. Moving a
+sash causes the widgets on either side of the sash to be resized.
+
+.SH "WIDGET COMMAND"
+.PP
+The \fBpanedwindow\fR command creates a new Tcl command whose name is
+the same as the path name of the panedwindow's window. This command
+may be used to invoke various operations on the widget. It has the
+following general form:
+.CS
+\fIpathName option \fR?\fIarg arg ...\fR?
+.CE
+\fIPathName\fR is the name of the command, which is the same as
+the panedwindow widget's path name. \fIOption\fR and the \fIarg\fRs
+determine the exact behavior of the command. The following
+commands are possible for panedwindow widgets:
+.TP
+\fIpathName \fBadd \fIwindow ?window ...? ?option value ...?\fR
+Add one or more windows to the panedwindow, each in a separate pane.
+The arguments consist of the names of one or more windows
+followed by pairs of arguments that specify how to manage the windows.
+\fIOption\fR may have any of the values accepted by the
+\fBconfigure\fR subcommand.
+.TP
+\fIpathName \fBcget \fIoption\fR
+Returns the current value of the configuration option given by
+\fIoption\fR. \fIOption\fR may have any of the values accepted by the
+\fBpanedwindow\fR command.
+.TP
+\fIpathName \fBconfigure \fI?option? ?value option value ...?\fR
+Query or modify the configuration options of the widget. If no
+\fIoption\fR is specified, returns a list describing all of the
+available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string. \fIOption\fR may have
+any of the values accepted by the \fBpanedwindow\fR command.
+.TP
+\fIpathName \fBforget \fIwindow ?window ...?\fR
+Remove the pane containing \fIwindow\fR from the panedwindow. All
+geometry management options for \fIwindow\fR will be forgotten.
+.TP
+\fIpathName \fBidentify \fIx y\fR
+Identify the panedwindow component underneath the point given by
+\fIx\fR and \fIy\fR, in window coordinates. If the point is over a
+sash or a sash handle, the result is a two element list containing the
+index of the sash or handle, and a word indicating whether it is over
+a sash or a handle, such as {0 sash} or {2 handle}. If the point is
+over any other part of the panedwindow, the result is an empty list.
+.TP
+\fIpathName \fBproxy \fI?args?\fR
+This command is used to query and change the position of the sash
+proxy, used for rubberband-style pane resizing. It can take any of
+the following forms:
+.RS
+.TP
+\fIpathName \fBproxy coord\fR
+Return a list containing the x and y coordinates of the most recent
+proxy location.
+.TP
+\fIpathname \fBproxy forget\fR
+Remove the proxy from the display.
+.TP
+\fIpathName \fBproxy place \fIx y\fR
+Place the proxy at the given \fIx\fR and \fIy\fR coordinates.
+.RE
+.TP
+\fIpathName \fBsash \fI?args?\fR
+This command is used to query and change the position of sashes in the
+panedwindow. It can take any of the following forms:
+.RS
+.TP
+\fIpathName \fBsash coord \fIindex\fR
+Return the current x and y coordinate pair for the sash given by
+\fIindex\fR. \fIIndex\fR must be an integer between 0 and 1 less than
+the number of panes in the panedwindow. The coordinates given are
+those of the top left corner of the region containing the sash.
+\fIpathName \fBsash dragto \fIindex x y\fR
+This command computes the difference between the given coordinates and the
+coordinates given to the last \fBsash coord\fR command for the given
+sash. It then moves that sash the computed difference. The return
+value is the empty string.
+.TP
+\fIpathName \fBsash mark \fIindex x y\fR
+Records \fIx\fR and \fIy\fR for the sash given by \fIindex\fR; used in
+conjunction with later dragto commands to move the sash.
+.TP
+\fIpathName \fBsash place \fIindex x y\fR
+Place the sash given by \fIindex\fR at the given coordinates.
+.RE
+.TP
+\fIpathName \fBpanecget \fIwindow option\fR
+Query a management option for \fIwindow\fR. \fIOption\fR may be any
+value allowed by the \fBpaneconfigure\fR subcommand.
+.TP
+\fIpathName \fBpaneconfigure \fIwindow ?option? ?value option value ...?\fR
+Query or modify the management options for \fIwindow\fR. If no
+\fIoption\fR is specified, returns a list describing all of the
+available options for \fIpathName\fR (see \fBTk_ConfigureInfo\fR for
+information on the format of this list). If \fIoption\fR is specified
+with no \fIvalue\fR, then the command returns a list describing the
+one named option (this list will be identical to the corresponding
+sublist of the value returned if no \fIoption\fR is specified). If
+one or more \fIoption\-value\fR pairs are specified, then the command
+modifies the given widget option(s) to have the given value(s); in
+this case the command returns an empty string. The following options
+are supported:
+.RS
+.TP
+\fB\-after \fIwindow\fR
+Insert the window after the window specified. \fIwindow\fR should be the
+name of a window already managed by \fIpathName\fR.
+.TP
+\fB\-before \fIwindow\fR
+Insert the window before the window specified. \fIwindow\fR should be
+the name of a window already managed by \fIpathName\fR.
+.TP
+\fB\-height \fIsize\fR
+Specify a height for the window. The height will be the outer
+dimension of the window including its border, if any. If \fIsize\fR
+is an empty string, or if \fB\-height\fR is not specified, then the
+height requested internally by the window will be used initially; the
+height may later be adjusted by the movement of sashes in the
+panedwindow. \fISize\fR may be any value accepted by \fBTk_GetPixels\fR.
+.TP
+\fB\-minsize \fIn\fR
+Specifies that the size of the window cannot be made less than
+\fIn\fR. This constraint only affects the size of the widget in the
+paned dimension -- the x dimension for horizontal panedwindows, the y
+dimension for vertical panedwindows. May be any value accepted by
+\fBTk_GetPixels\fR.
+.TP
+\fB\-padx \fIn\fR
+Specifies a non-negative value indicating how much extra space to
+leave on each side of the window in the X-direction. The value may
+have any of the forms accepted by \fBTk_GetPixels\fR.
+.TP
+\fB\-pady \fIn\fR
+Specifies a non-negative value indicating how much extra space to
+leave on each side of the window in the Y-direction. The value may
+have any of the forms accepted by \fBTk_GetPixels\fR.
+.TP
+\fB\-sticky \fIstyle\fR
+If a window's pane is larger than the requested dimensions of the
+window, this option may be used to position (or stretch) the window
+within its pane. \fIStyle\fR is a string that contains zero or more
+of the characters \fBn\fP, \fBs\fP, \fBe\fP or \fBw\fP. The string
+can optionally contains spaces or commas, but they are ignored. Each
+letter refers to a side (north, south, east, or west) that the window
+will "stick" to. If both \fBn\fP and \fBs\fP (or \fBe\fP and \fBw\fP)
+are specified, the window will be stretched to fill the entire height
+(or width) of its cavity.
+.TP
+\fB\-width \fIsize\fR
+Specify a width for the window. The width will be the outer
+dimension of the window including its border, if any. If \fIsize\fR
+is an empty string, or if \fB\-width\fR is not specified, then the
+width requested internally by the window will be used initially; the
+width may later be adjusted by the movement of sashes in the
+panedwindow. \fISize\fR may be any value accepted by \fBTk_GetPixels\fR.
+.RE
+.TP
+\fIpathName \fBpanes\fR
+Returns an ordered list of the widgets managed by \fIpathName\fR.
+
+.SH "RESIZING PANES"
+
+A pane is resized by grabbing the sash (or sash handle if present) and
+dragging with the mouse. This is accomplished via mouse motion
+bindings on the widget. When a sash is moved, the sizes of the panes
+on each side of the sash, and thus the widgets in those panes, are
+adjusted.
+.PP
+When a pane is resized from outside (eg, it is packed to expand and
+fill, and the containing toplevel is resized), space is added to the final
+(rightmost or bottommost) pane in the window.
+
+.SH KEYWORDS
+panedwindow, widget, geometry management
diff --git a/generic/tkInt.h b/generic/tkInt.h
index c5c085d..30772bc 100644
--- a/generic/tkInt.h
+++ b/generic/tkInt.h
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: $Id: tkInt.h,v 1.41 2002/01/15 20:48:30 dgp Exp $
+ * RCS: $Id: tkInt.h,v 1.42 2002/02/22 02:41:16 hobbs Exp $
*/
#ifndef _TKINT
@@ -983,6 +983,10 @@ EXTERN int Tk_MessageBoxObjCmd _ANSI_ARGS_((ClientData clientData,
EXTERN int Tk_MessageObjCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *CONST objv[]));
+EXTERN int Tk_PanedWindowObjCmd _ANSI_ARGS_((
+ ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
EXTERN int Tk_OptionObjCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *CONST objv[]));
diff --git a/generic/tkPanedWindow.c b/generic/tkPanedWindow.c
new file mode 100644
index 0000000..d3a64b5
--- /dev/null
+++ b/generic/tkPanedWindow.c
@@ -0,0 +1,2780 @@
+/*
+ * tkPanedWindow.c --
+ *
+ * This module implements "paned window" widgets that are object
+ * based. A "paned window" is a widget that manages the geometry for
+ * some number of other widgets, placing a movable "sash" between them,
+ * which can be used to alter the relative sizes of adjacent widgets.
+ *
+ * Copyright (c) 1997 Sun Microsystems, Inc.
+ * Copyright (c) 2000 Ajuba Solutions.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id: tkPanedWindow.c,v 1.1 2002/02/22 02:41:17 hobbs Exp $
+ */
+
+#include "tkPort.h"
+#include "default.h"
+#include "tkInt.h"
+
+#if ((TCL_MAJOR_VERSION > 8) || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 4))
+#define TCL_84
+#endif
+
+/*
+ * We need to have TK_OPTION_CUSTOM, et al defined to compile with any
+ * stubs-enable version of Tk, but we'll only allow the widget to
+ * be created in 8.4+. These are taken from 8.4+ tk.h.
+ */
+#ifndef TCL_84
+
+/*
+ * Generating code for accessing these parts of the stub table when
+ * compiling against a core older than 8.4a2 is a hassle because
+ * we have to write up some macros hiding some very hackish pointer
+ * arithmetics to get at these fields. We assume that pointer to
+ * functions are always of the same size.
+ */
+
+#define STUB_BASE ((char*)(&(tkStubsPtr->tk_GetAnchorFromObj))) /*field 200*/
+#define procPtrSize (sizeof(Tcl_DriverBlockModeProc *))
+#define IDX(n) (((n)-200) * procPtrSize)
+#define SLOT(n) (STUB_BASE + IDX(n))
+
+typedef Tk_Window (tk_CreateAnonymousWindow) _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window parent, char * screenName)); /* 241 */
+#define Tk_CreateAnonymousWindow (*((tk_CreateAnonymousWindow**) (SLOT(241))))
+
+#define TK_OPTION_CUSTOM (TK_OPTION_END + 1)
+typedef int (Tk_CustomOptionSetProc) _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj **value, char *widgRec,
+ int offset, char *saveInternalPtr, int flags));
+typedef Tcl_Obj *(Tk_CustomOptionGetProc) _ANSI_ARGS_((ClientData clientData,
+ Tk_Window tkwin, char *widgRec, int offset));
+typedef void (Tk_CustomOptionRestoreProc) _ANSI_ARGS_((ClientData clientData,
+ Tk_Window tkwin, char *internalPtr, char *saveInternalPtr));
+typedef void (Tk_CustomOptionFreeProc) _ANSI_ARGS_((ClientData clientData,
+ Tk_Window tkwin, char *internalPtr));
+
+typedef struct Tk_ObjCustomOption {
+ char *name; /* Name of the custom option. */
+ Tk_CustomOptionSetProc *setProc; /* Function to use to set a record's
+ * option value from a Tcl_Obj */
+ Tk_CustomOptionGetProc *getProc; /* Function to use to get a Tcl_Obj
+ * representation from an internal
+ * representation of an option. */
+ Tk_CustomOptionRestoreProc *restoreProc; /* Function to use to restore a
+ * saved value for the internal
+ * representation. */
+ Tk_CustomOptionFreeProc *freeProc; /* Function to use to free the internal
+ * representation of an option. */
+ ClientData clientData; /* Arbitrary one-word value passed to
+ * the handling procs. */
+} Tk_ObjCustomOption;
+
+#endif
+
+/* Flag values for "sticky"ness The 16 combinations subsume the packer's
+ * notion of anchor and fill.
+ *
+ * STICK_NORTH This window sticks to the top of its cavity.
+ * STICK_EAST This window sticks to the right edge of its cavity.
+ * STICK_SOUTH This window sticks to the bottom of its cavity.
+ * STICK_WEST This window sticks to the left edge of its cavity.
+ */
+
+#define STICK_NORTH 1
+#define STICK_EAST 2
+#define STICK_SOUTH 4
+#define STICK_WEST 8
+/*
+ * The following table defines the legal values for the -orient option.
+ */
+
+static char *orientStrings[] = {
+ "horizontal", "vertical", (char *) NULL
+};
+
+enum orient { ORIENT_HORIZONTAL, ORIENT_VERTICAL };
+
+typedef struct {
+ Tk_OptionTable pwOptions; /* Token for paned window option table. */
+ Tk_OptionTable slaveOpts; /* Token for slave cget option table. */
+} OptionTables;
+
+/*
+ * One structure of the following type is kept for each window
+ * managed by a paned window widget.
+ */
+
+typedef struct Slave {
+ Tk_Window tkwin; /* Window being managed. */
+
+ int minSize; /* Minimum size of this pane, on the
+ * relevant axis, in pixels. */
+ int padx; /* Additional padding requested for
+ * slave, in the x dimension. */
+ int pady; /* Additional padding requested for
+ * slave, in the y dimension. */
+ Tcl_Obj *widthPtr, *heightPtr; /* Tcl_Obj rep's of slave width/height,
+ * to allow for null values. */
+ int width; /* Slave width. */
+ int height; /* Slave height. */
+ int sticky; /* Sticky string. */
+ int x, y; /* Coordinates of the widget. */
+ int paneWidth, paneHeight; /* Pane dimensions (may be different
+ * from slave width/height). */
+ int sashx, sashy; /* Coordinates of the sash of the
+ * right or bottom of this pane. */
+ int markx, marky; /* Coordinates of the last mark set
+ * for the sash. */
+ int handlex, handley; /* Coordinates of the sash handle. */
+ struct PanedWindow *masterPtr; /* Paned window managing the window. */
+ Tk_Window after; /* Placeholder for parsing options. */
+ Tk_Window before; /* Placeholder for parsing options. */
+} Slave;
+
+/*
+ * A data structure of the following type is kept for each paned window
+ * widget managed by this file:
+ */
+
+typedef struct PanedWindow {
+ Tk_Window tkwin; /* Window that embodies the paned window. */
+ Tk_Window proxywin; /* Window for the resizing proxy. */
+ Display *display; /* X's token for the window's display. */
+ Tcl_Interp *interp; /* Interpreter associated with widget. */
+ Tcl_Command widgetCmd; /* Token for square's widget command. */
+ Tk_OptionTable optionTable; /* Token representing the configuration
+ * specifications. */
+ Tk_OptionTable slaveOpts; /* Token for slave cget table. */
+ Tk_3DBorder background; /* Background color. */
+ int borderWidth; /* Value of -borderwidth option. */
+ int relief; /* 3D border effect (TK_RELIEF_RAISED, etc) */
+ Tcl_Obj *widthPtr; /* Tcl_Obj rep for width. */
+ Tcl_Obj *heightPtr; /* Tcl_Obj rep for height. */
+ int width, height; /* Width and height of the widget. */
+ enum orient orient; /* Orientation of the widget. */
+ Tk_Cursor cursor; /* Current cursor for window, or None. */
+ int resizeOpaque; /* Boolean indicating whether resize should be
+ * opaque or rubberband style. */
+
+ int sashRelief; /* Relief used to draw sash. */
+ int sashWidth; /* Width of each sash, in pixels. */
+ Tcl_Obj *sashWidthPtr; /* Tcl_Obj rep for sash width. */
+ int sashPad; /* Additional padding around each sash. */
+ Tcl_Obj *sashPadPtr; /* Tcl_Obj rep for sash padding. */
+ int showHandle; /* Boolean indicating whether sash handles
+ * should be drawn. */
+ int handleSize; /* Size of one side of a sash handle (handles
+ * are square), in pixels. */
+ int handlePad; /* Distance from border to draw handle. */
+ Tcl_Obj *handleSizePtr; /* Tcl_Obj rep for handle size. */
+ Tk_Cursor sashCursor; /* Cursor used when mouse is above a sash. */
+
+ GC gc; /* Graphics context for copying from
+ * off-screen pixmap onto screen. */
+ int proxyx, proxyy; /* Proxy x,y coordinates. */
+ Slave **slaves; /* Pointer to array of Slaves. */
+ int numSlaves; /* Number of slaves. */
+ int sizeofSlaves; /* Number of elements in the slaves array. */
+ int flags; /* Flags for widget; see below. */
+} PanedWindow;
+
+/*
+ * Flags used for paned windows:
+ *
+ * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has
+ * been queued to redraw this window.
+ *
+ * WIDGET_DELETED: Non-zero means that the paned window has
+ * been, or is in the process of being, deleted.
+ */
+
+#define REDRAW_PENDING 0x0001
+#define WIDGET_DELETED 0x0002
+#define REQUESTED_RELAYOUT 0x0004
+#define RECOMPUTE_GEOMETRY 0x0008
+#define PROXY_REDRAW_PENDING 0x0010
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+int Tk_PanedWindowObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]));
+static void PanedWindowCmdDeletedProc _ANSI_ARGS_((ClientData clientData));
+static int ConfigurePanedWindow _ANSI_ARGS_((Tcl_Interp *interp,
+ PanedWindow *pwPtr, int objc, Tcl_Obj *CONST objv[]));
+static void DestroyPanedWindow _ANSI_ARGS_((PanedWindow *pwPtr));
+static void DisplayPanedWindow _ANSI_ARGS_((ClientData clientData));
+static void PanedWindowEventProc _ANSI_ARGS_((ClientData clientData,
+ XEvent *eventPtr));
+static void ProxyWindowEventProc _ANSI_ARGS_((ClientData clientData,
+ XEvent *eventPtr));
+static void DisplayProxyWindow _ANSI_ARGS_((ClientData clientData));
+void PanedWindowWorldChanged _ANSI_ARGS_((ClientData instanceData));
+static int PanedWindowWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *, int objc, Tcl_Obj * CONST objv[]));
+static void PanedWindowLostSlaveProc _ANSI_ARGS_((ClientData clientData,
+ Tk_Window tkwin));
+static void PanedWindowReqProc _ANSI_ARGS_((ClientData clientData,
+ Tk_Window tkwin));
+static void ArrangePanes _ANSI_ARGS_((ClientData clientData));
+static void Unlink _ANSI_ARGS_((Slave *slavePtr));
+static Slave * GetPane _ANSI_ARGS_((PanedWindow *pwPtr, Tk_Window tkwin));
+static void SlaveStructureProc _ANSI_ARGS_((ClientData clientData,
+ XEvent *eventPtr));
+static int PanedWindowSashCommand _ANSI_ARGS_((PanedWindow *pwPtr,
+ Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]));
+static int PanedWindowProxyCommand _ANSI_ARGS_((PanedWindow *pwPtr,
+ Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]));
+static void ComputeGeometry _ANSI_ARGS_((PanedWindow *pwPtr));
+static int ConfigureSlaves _ANSI_ARGS_((PanedWindow *pwPtr,
+ Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]));
+static void DestroyOptionTables _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp));
+static int SetSticky _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj **value, char *recordPtr, int internalOffset,
+ char *oldInternalPtr, int flags));
+static Tcl_Obj *GetSticky _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin,
+ char *recordPtr, int internalOffset));
+static void RestoreSticky _ANSI_ARGS_((ClientData clientData,
+ Tk_Window tkwin, char *internalPtr,
+ char *oldInternalPtr));
+static void AdjustForSticky _ANSI_ARGS_((int sticky, int cavityWidth,
+ int cavityHeight, int *xPtr, int *yPtr,
+ int *slaveWidthPtr, int *slaveHeightPtr));
+static void MoveSash _ANSI_ARGS_((PanedWindow *pwPtr, int sash, int diff));
+static int ObjectIsEmpty _ANSI_ARGS_((Tcl_Obj *objPtr));
+static char * ComputeSlotAddress _ANSI_ARGS_((char *recordPtr, int offset));
+static int PanedWindowIdentifyCoords _ANSI_ARGS_((PanedWindow *pwPtr,
+ Tcl_Interp *interp, int x, int y));
+
+static Tk_GeomMgr panedWindowMgrType = {
+ "panedwindow", /* name */
+ PanedWindowReqProc, /* requestProc */
+ PanedWindowLostSlaveProc, /* lostSlaveProc */
+};
+
+/*
+ * Information used for objv parsing.
+ */
+
+#define GEOMETRY 0x0001
+
+/*
+ * The following structure contains pointers to functions used for processing
+ * the custom "-sticky" option for slave windows.
+ */
+
+static Tk_ObjCustomOption stickyOption = {
+ "sticky", /* name */
+ SetSticky, /* setProc */
+ GetSticky, /* getProc */
+ RestoreSticky, /* restoreProc */
+ (Tk_CustomOptionFreeProc *)NULL, /* freeProc */
+ 0
+};
+
+static Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_PANEDWINDOW_BG_COLOR, -1, Tk_Offset(PanedWindow, background), 0,
+ (ClientData) DEF_PANEDWINDOW_BG_MONO},
+ {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth"},
+ {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-background"},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_PANEDWINDOW_BORDERWIDTH, -1, Tk_Offset(PanedWindow, borderWidth),
+ 0, 0, GEOMETRY},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_PANEDWINDOW_CURSOR, -1, Tk_Offset(PanedWindow, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-handlepad", "handlePad", "HandlePad",
+ DEF_PANEDWINDOW_HANDLEPAD, -1, Tk_Offset(PanedWindow, handlePad),
+ 0, 0},
+ {TK_OPTION_PIXELS, "-handlesize", "handleSize", "HandleSize",
+ DEF_PANEDWINDOW_HANDLESIZE, Tk_Offset(PanedWindow, handleSizePtr),
+ Tk_Offset(PanedWindow, handleSize), 0, 0, GEOMETRY},
+ {TK_OPTION_PIXELS, "-height", "height", "Height",
+ DEF_PANEDWINDOW_HEIGHT, Tk_Offset(PanedWindow, heightPtr),
+ Tk_Offset(PanedWindow, height), TK_OPTION_NULL_OK, 0, GEOMETRY},
+ {TK_OPTION_BOOLEAN, "-opaqueresize", "opaqueResize", "OpaqueResize",
+ DEF_PANEDWINDOW_OPAQUERESIZE, -1,
+ Tk_Offset(PanedWindow, resizeOpaque), 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient",
+ DEF_PANEDWINDOW_ORIENT, -1, Tk_Offset(PanedWindow, orient),
+ 0, (ClientData) orientStrings, GEOMETRY},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_PANEDWINDOW_RELIEF, -1, Tk_Offset(PanedWindow, relief), 0, 0, 0},
+ {TK_OPTION_CURSOR, "-sashcursor", "sashCursor", "Cursor",
+ DEF_PANEDWINDOW_SASHCURSOR, -1, Tk_Offset(PanedWindow, sashCursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-sashpad", "sashPad", "SashPad",
+ DEF_PANEDWINDOW_SASHPAD, -1, Tk_Offset(PanedWindow, sashPad),
+ 0, 0, GEOMETRY},
+ {TK_OPTION_RELIEF, "-sashrelief", "sashRelief", "Relief",
+ DEF_PANEDWINDOW_SASHRELIEF, -1, Tk_Offset(PanedWindow, sashRelief),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-sashwidth", "sashWidth", "Width",
+ DEF_PANEDWINDOW_SASHWIDTH, Tk_Offset(PanedWindow, sashWidthPtr),
+ Tk_Offset(PanedWindow, sashWidth), 0, 0, GEOMETRY},
+ {TK_OPTION_BOOLEAN, "-showhandle", "showHandle", "ShowHandle",
+ DEF_PANEDWINDOW_SHOWHANDLE, -1, Tk_Offset(PanedWindow, showHandle),
+ 0, 0, GEOMETRY},
+ {TK_OPTION_PIXELS, "-width", "width", "Width",
+ DEF_PANEDWINDOW_WIDTH, Tk_Offset(PanedWindow, widthPtr),
+ Tk_Offset(PanedWindow, width), TK_OPTION_NULL_OK, 0, GEOMETRY},
+ {TK_OPTION_END}
+};
+
+static Tk_OptionSpec slaveOptionSpecs[] = {
+ {TK_OPTION_WINDOW, "-after", (char *) NULL, (char *) NULL,
+ DEF_PANEDWINDOW_PANE_AFTER, -1, Tk_Offset(Slave, after),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_WINDOW, "-before", (char *) NULL, (char *) NULL,
+ DEF_PANEDWINDOW_PANE_BEFORE, -1, Tk_Offset(Slave, before),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-height", (char *) NULL, (char *) NULL,
+ DEF_PANEDWINDOW_PANE_HEIGHT, Tk_Offset(Slave, heightPtr),
+ Tk_Offset(Slave, height), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-minsize", (char *) NULL, (char *) NULL,
+ DEF_PANEDWINDOW_PANE_MINSIZE, -1, Tk_Offset(Slave, minSize), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", (char *) NULL, (char *) NULL,
+ DEF_PANEDWINDOW_PANE_PADX, -1, Tk_Offset(Slave, padx), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", (char *) NULL, (char *) NULL,
+ DEF_PANEDWINDOW_PANE_PADY, -1, Tk_Offset(Slave, pady), 0, 0, 0},
+ {TK_OPTION_CUSTOM, "-sticky", (char *) NULL, (char *) NULL,
+ DEF_PANEDWINDOW_PANE_STICKY, -1, Tk_Offset(Slave, sticky), 0,
+ (ClientData) &stickyOption, 0},
+ {TK_OPTION_PIXELS, "-width", (char *) NULL, (char *) NULL,
+ DEF_PANEDWINDOW_PANE_WIDTH, Tk_Offset(Slave, widthPtr),
+ Tk_Offset(Slave, width), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_END}
+};
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_PanedWindowObjCmd --
+ *
+ * This procedure is invoked to process the "panedwindow" Tcl
+ * command. It creates a new "panedwindow" widget.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * A new widget is created and configured.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_PanedWindowObjCmd(clientData, interp, objc, objv)
+ ClientData clientData; /* NULL. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj * CONST objv[]; /* Argument objects. */
+{
+ PanedWindow *pwPtr;
+ Tk_Window tkwin, parent;
+ OptionTables *pwOpts;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");
+ return TCL_ERROR;
+ }
+
+ tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
+ Tcl_GetStringFromObj(objv[1], NULL), (char *) NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+
+ pwOpts = (OptionTables *)
+ Tcl_GetAssocData(interp, "PanedWindowOptionTables", NULL);
+ if (pwOpts == NULL) {
+ /*
+ * The first time this procedure is invoked, the option tables will
+ * be NULL. We then create the option tables from the templates
+ * and store a pointer to the tables as the command's clinical so
+ * we'll have easy access to it in the future.
+ */
+ pwOpts = (OptionTables *) ckalloc(sizeof(OptionTables));
+ /* Set up an exit handler to free the optionTables struct */
+ Tcl_SetAssocData(interp, "PanedWindowOptionTables",
+ DestroyOptionTables, (ClientData) pwOpts);
+
+ /* Create the paned window option tables. */
+ pwOpts->pwOptions = Tk_CreateOptionTable(interp, optionSpecs);
+ pwOpts->slaveOpts = Tk_CreateOptionTable(interp, slaveOptionSpecs);
+ }
+
+ Tk_SetClass(tkwin, "PanedWindow");
+
+ /*
+ * Allocate and initialize the widget record.
+ */
+
+ pwPtr = (PanedWindow *) ckalloc(sizeof(PanedWindow));
+ memset((void *)pwPtr, 0, (sizeof(PanedWindow)));
+ pwPtr->tkwin = tkwin;
+ pwPtr->display = Tk_Display(tkwin);
+ pwPtr->interp = interp;
+ pwPtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(pwPtr->tkwin), PanedWindowWidgetObjCmd,
+ (ClientData) pwPtr, PanedWindowCmdDeletedProc);
+ pwPtr->optionTable = pwOpts->pwOptions;
+ pwPtr->slaveOpts = pwOpts->slaveOpts;
+ pwPtr->relief = TK_RELIEF_RAISED;
+ pwPtr->gc = None;
+ pwPtr->cursor = None;
+ pwPtr->sashCursor = None;
+
+ if (Tk_InitOptions(interp, (char *) pwPtr, pwOpts->pwOptions,
+ tkwin) != TCL_OK) {
+ Tk_DestroyWindow(pwPtr->tkwin);
+ ckfree((char *) pwPtr);
+ return TCL_ERROR;
+ }
+
+ Tk_CreateEventHandler(pwPtr->tkwin, ExposureMask|StructureNotifyMask,
+ PanedWindowEventProc, (ClientData) pwPtr);
+
+ /*
+ * Find the toplevel ancestor of the panedwindow, and make a proxy
+ * win as a child of that window; this way the proxy can always float
+ * above slaves in the panedwindow.
+ */
+ parent = Tk_Parent(pwPtr->tkwin);
+ while (!(Tk_IsTopLevel(parent))) {
+ parent = Tk_Parent(parent);
+ if (parent == NULL) {
+ parent = pwPtr->tkwin;
+ break;
+ }
+ }
+
+ pwPtr->proxywin = Tk_CreateAnonymousWindow(interp, parent, (char *) NULL);
+ Tk_CreateEventHandler(pwPtr->proxywin, ExposureMask, ProxyWindowEventProc,
+ (ClientData) pwPtr);
+
+ if (ConfigurePanedWindow(interp, pwPtr, objc - 2, objv + 2) != TCL_OK) {
+ Tk_DestroyWindow(pwPtr->tkwin);
+ Tk_DestroyWindow(pwPtr->proxywin);
+ ckfree((char *) pwPtr);
+ return TCL_ERROR;
+ }
+
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), Tk_PathName(pwPtr->tkwin), -1);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PanedWindowWidgetObjCmd --
+ *
+ * This procedure is invoked to process the Tcl command
+ * that corresponds to a widget managed by this module.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+PanedWindowWidgetObjCmd(clientData, interp, objc, objv)
+ ClientData clientData; /* Information about square widget. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj * CONST objv[]; /* Argument objects. */
+{
+ PanedWindow *pwPtr = (PanedWindow *) clientData;
+ int result = TCL_OK;
+ static CONST char *optionStrings[] = {"add", "cget", "configure", "forget",
+ "identify", "panecget",
+ "paneconfigure", "panes",
+ "proxy", "sash", (char *) NULL};
+ enum options { PW_ADD, PW_CGET, PW_CONFIGURE, PW_FORGET, PW_IDENTIFY,
+ PW_PANECGET, PW_PANECONFIGURE, PW_PANES, PW_PROXY,
+ PW_SASH };
+ Tcl_Obj *resultObj;
+ int index, count, i, x, y;
+ Tk_Window tkwin;
+ Slave *slavePtr;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "command",
+ 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ Tcl_Preserve((ClientData) pwPtr);
+
+ switch ((enum options) index) {
+ case PW_ADD: {
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "widget ?widget ...?");
+ result = TCL_ERROR;
+ break;
+ }
+
+ return ConfigureSlaves(pwPtr, interp, objc, objv);
+ break;
+ }
+
+ case PW_CGET: {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ result = TCL_ERROR;
+ break;
+ }
+ resultObj = Tk_GetOptionValue(interp, (char *) pwPtr,
+ pwPtr->optionTable, objv[2], pwPtr->tkwin);
+ if (resultObj == NULL) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, resultObj);
+ }
+ break;
+ }
+
+ case PW_CONFIGURE: {
+ resultObj = NULL;
+ if (objc <= 3) {
+ resultObj = Tk_GetOptionInfo(interp, (char *) pwPtr,
+ pwPtr->optionTable,
+ (objc == 3) ? objv[2] : (Tcl_Obj *) NULL,
+ pwPtr->tkwin);
+ if (resultObj == NULL) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, resultObj);
+ }
+ } else {
+ result = ConfigurePanedWindow(interp, pwPtr, objc - 2,
+ objv + 2);
+ }
+ break;
+ }
+
+ case PW_FORGET: {
+ Tk_Window slave;
+ int i;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "widget ?widget ...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Clean up each window named in the arg list.
+ */
+ for (count = 0, i = 2; i < objc; i++) {
+ slave = Tk_NameToWindow(interp, Tcl_GetString(objv[i]),
+ pwPtr->tkwin);
+ if (slave == NULL) {
+ continue;
+ }
+ slavePtr = GetPane(pwPtr, slave);
+ if ((slavePtr != NULL) && (slavePtr->masterPtr != NULL)) {
+ count++;
+ Tk_ManageGeometry(slave, (Tk_GeomMgr *) NULL,
+ (ClientData) NULL);
+ Tk_UnmaintainGeometry(slavePtr->tkwin, pwPtr->tkwin);
+ Tk_DeleteEventHandler(slavePtr->tkwin, StructureNotifyMask,
+ SlaveStructureProc, (ClientData) slavePtr);
+ Tk_UnmapWindow(slavePtr->tkwin);
+ Unlink(slavePtr);
+ }
+ if (count != 0) {
+ ComputeGeometry(pwPtr);
+ }
+ }
+ break;
+ }
+
+ case PW_IDENTIFY: {
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "x y");
+ result = TCL_ERROR;
+ break;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ return PanedWindowIdentifyCoords(pwPtr, interp, x, y);
+ break;
+ }
+
+ case PW_PANECGET: {
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "pane option");
+ result = TCL_ERROR;
+ break;
+ }
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]),
+ pwPtr->tkwin);
+ if (tkwin == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ resultObj = NULL;
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ if (pwPtr->slaves[i]->tkwin == tkwin) {
+ resultObj = Tk_GetOptionValue(interp,
+ (char *) pwPtr->slaves[i], pwPtr->slaveOpts,
+ objv[3], tkwin);
+ }
+ }
+ if (i == pwPtr->numSlaves) {
+ Tcl_SetResult(interp, "not managed by this window",
+ TCL_STATIC);
+ }
+ if (resultObj == NULL) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, resultObj);
+ }
+ break;
+ }
+
+ case PW_PANECONFIGURE: {
+ resultObj = NULL;
+ if (objc <= 4) {
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]),
+ pwPtr->tkwin);
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ if (pwPtr->slaves[i]->tkwin == tkwin) {
+ resultObj = Tk_GetOptionInfo(interp,
+ (char *) pwPtr->slaves[i],
+ pwPtr->slaveOpts,
+ (objc == 4) ? objv[3] : (Tcl_Obj *) NULL,
+ pwPtr->tkwin);
+ if (resultObj == NULL) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetObjResult(interp, resultObj);
+ }
+ break;
+ }
+ }
+ } else {
+ result = ConfigureSlaves(pwPtr, interp, objc, objv);
+ }
+ break;
+ }
+
+ case PW_PANES: {
+ resultObj = Tcl_NewObj();
+
+ Tcl_IncrRefCount(resultObj);
+
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ Tcl_ListObjAppendElement(interp, resultObj,
+ Tcl_NewStringObj(Tk_PathName(pwPtr->slaves[i]->tkwin),
+ -1));
+ }
+ Tcl_SetObjResult(interp, resultObj);
+ Tcl_DecrRefCount(resultObj);
+ break;
+ }
+
+ case PW_PROXY: {
+ return PanedWindowProxyCommand(pwPtr, interp, objc, objv);
+ break;
+ }
+
+ case PW_SASH: {
+ return PanedWindowSashCommand(pwPtr, interp, objc, objv);
+ break;
+ }
+ }
+ Tcl_Release((ClientData) pwPtr);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureSlaves --
+ *
+ * Add or alter the configuration options of a slave in a paned
+ * window.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Depends on options; may add a slave to the paned window, may
+ * alter the geometry management options of a slave.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureSlaves(pwPtr, interp, objc, objv)
+ PanedWindow *pwPtr; /* Information about paned window. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj * CONST objv[]; /* Argument objects. */
+{
+ int i, firstOptionArg, j, found, doubleBw, index, numNewSlaves, haveLoc;
+ int insertIndex;
+ Tk_Window tkwin = NULL, ancestor, parent;
+ Slave *slavePtr, **inserts, **new;
+ Slave options;
+ char *arg;
+
+ /*
+ * Find the non-window name arguments; these are the configure options
+ * for the slaves. Also validate that the window names given are
+ * legitimate (ie, they are real windows, they are not the panedwindow
+ * itself, etc.).
+ */
+ for (i = 2; i < objc; i++) {
+ arg = Tcl_GetString(objv[i]);
+ if (arg[0] == '-') {
+ break;
+ } else {
+ tkwin = Tk_NameToWindow(interp, arg, pwPtr->tkwin);
+ if (tkwin == NULL) {
+ /*
+ * Just a plain old bad window; Tk_NameToWindow filled in an
+ * error message for us.
+ */
+ return TCL_ERROR;
+ } else if (tkwin == pwPtr->tkwin) {
+ /*
+ * A panedwindow cannot manage itself.
+ */
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "can't add ", arg, " to itself",
+ (char *) NULL);
+ return TCL_ERROR;
+ } else if (Tk_IsTopLevel(tkwin)) {
+ /*
+ * A panedwindow cannot manage a toplevel.
+ */
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "can't add toplevel ", arg, " to ",
+ Tk_PathName(pwPtr->tkwin), (char *) NULL);
+ return TCL_ERROR;
+ } else {
+ /*
+ * Make sure the panedwindow is the parent of the slave,
+ * or a descendant of the slave's parent.
+ */
+ parent = Tk_Parent(tkwin);
+ for (ancestor = pwPtr->tkwin;;ancestor = Tk_Parent(ancestor)) {
+ if (ancestor == parent) {
+ break;
+ }
+ if (Tk_IsTopLevel(ancestor)) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "can't add ", arg,
+ " to ", Tk_PathName(pwPtr->tkwin),
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ }
+ }
+ firstOptionArg = i;
+
+ /*
+ * Pre-parse the configuration options, to get the before/after specifiers
+ * into an easy-to-find location (a local variable). Also, check the
+ * return from Tk_SetOptions once, here, so we can save a little bit of
+ * extra testing in the for loop below.
+ */
+ memset((void *)&options, 0, sizeof(Slave));
+ if (Tk_SetOptions(interp, (char *) &options, pwPtr->slaveOpts,
+ objc - firstOptionArg, objv + firstOptionArg,
+ pwPtr->tkwin, NULL, NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * If either -after or -before was given, find the numerical index that
+ * corresponds to the given window. If both -after and -before are
+ * given, the option precedence is: -after, then -before.
+ */
+ index = -1;
+ haveLoc = 0;
+ if (options.after != None) {
+ tkwin = options.after;
+ haveLoc = 1;
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ if (options.after == pwPtr->slaves[i]->tkwin) {
+ index = i + 1;
+ break;
+ }
+ }
+ } else if (options.before != None) {
+ tkwin = options.before;
+ haveLoc = 1;
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ if (options.before == pwPtr->slaves[i]->tkwin) {
+ index = i;
+ break;
+ }
+ }
+ }
+
+ /*
+ * If a window was given for -after/-before, but it's not a window
+ * managed by the panedwindow, throw an error
+ */
+ if (haveLoc && index == -1) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "window \"", Tk_PathName(tkwin),
+ "\" is not managed by ", Tk_PathName(pwPtr->tkwin),
+ (char *) NULL);
+ Tk_FreeConfigOptions((char *) &options, pwPtr->slaveOpts,
+ pwPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Allocate an array to hold, in order, the pointers to the slave
+ * structures corresponding to the windows specified. Some of those
+ * structures may already have existed, some may be new.
+ */
+ inserts = (Slave **)ckalloc(sizeof(Slave *) * (firstOptionArg - 2));
+ insertIndex = 0;
+
+ /*
+ * Populate the inserts array, creating new slave structures as necessary,
+ * applying the options to each structure as we go, and, if necessary,
+ * marking the spot in the original slaves array as empty (for pre-existing
+ * slave structures).
+ */
+ for (i = 0, numNewSlaves = 0; i < firstOptionArg - 2; i++) {
+ /*
+ * We don't check that tkwin is NULL here, because the pre-pass above
+ * guarantees that the input at this stage is good.
+ */
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i + 2]),
+ pwPtr->tkwin);
+
+ found = 0;
+ for (j = 0; j < pwPtr->numSlaves; j++) {
+ if (pwPtr->slaves[j] != NULL && pwPtr->slaves[j]->tkwin == tkwin) {
+ Tk_SetOptions(interp, (char *) pwPtr->slaves[j],
+ pwPtr->slaveOpts, objc - firstOptionArg,
+ objv + firstOptionArg, pwPtr->tkwin, NULL, NULL);
+ found = 1;
+
+ /*
+ * If the slave is supposed to move, add it to the inserts
+ * array now; otherwise, leave it where it is.
+ */
+
+ if (index != -1) {
+ inserts[insertIndex++] = pwPtr->slaves[j];
+ pwPtr->slaves[j] = NULL;
+ }
+ break;
+ }
+ }
+
+ if (found) {
+ continue;
+ }
+
+ /*
+ * Make sure this slave wasn't already put into the inserts array,
+ * ie, when the user specifies the same window multiple times in
+ * a single add commaned.
+ */
+ for (j = 0; j < insertIndex; j++) {
+ if (inserts[j]->tkwin == tkwin) {
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ continue;
+ }
+
+ /*
+ * Create a new slave structure and initialize it. All slaves
+ * start out with their "natural" dimensions.
+ */
+
+ slavePtr = (Slave *) ckalloc(sizeof(Slave));
+ memset(slavePtr, 0, sizeof(Slave));
+ Tk_InitOptions(interp, (char *)slavePtr, pwPtr->slaveOpts,
+ pwPtr->tkwin);
+ Tk_SetOptions(interp, (char *)slavePtr, pwPtr->slaveOpts,
+ objc - firstOptionArg, objv + firstOptionArg,
+ pwPtr->tkwin, NULL, NULL);
+ slavePtr->tkwin = tkwin;
+ slavePtr->masterPtr = pwPtr;
+ doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width;
+ if (slavePtr->width > 0) {
+ slavePtr->paneWidth = slavePtr->width;
+ } else {
+ slavePtr->paneWidth = Tk_ReqWidth(tkwin) + doubleBw;
+ }
+ if (slavePtr->height > 0) {
+ slavePtr->paneHeight = slavePtr->height;
+ } else {
+ slavePtr->paneHeight = Tk_ReqHeight(tkwin) + doubleBw;
+ }
+
+ /*
+ * Set up the geometry management callbacks for this slave.
+ */
+
+ Tk_CreateEventHandler(slavePtr->tkwin, StructureNotifyMask,
+ SlaveStructureProc, (ClientData) slavePtr);
+ Tk_ManageGeometry(slavePtr->tkwin, &panedWindowMgrType,
+ (ClientData) slavePtr);
+ inserts[insertIndex++] = slavePtr;
+ numNewSlaves++;
+ }
+
+ /*
+ * Allocate the new slaves array, then copy the slaves into it, in
+ * order.
+ */
+ new = (Slave **)ckalloc(sizeof(Slave *) * (pwPtr->numSlaves+numNewSlaves));
+ memset(new, 0, sizeof(Slave *) * (pwPtr->numSlaves + numNewSlaves));
+ if (index == -1) {
+ /*
+ * If none of the existing slaves have to be moved, just copy the old
+ * and append the new.
+ */
+ memcpy((void *)&(new[0]), pwPtr->slaves,
+ sizeof(Slave *) * pwPtr->numSlaves);
+ memcpy((void *)&(new[pwPtr->numSlaves]), inserts,
+ sizeof(Slave *) * numNewSlaves);
+ } else {
+ /*
+ * If some of the existing slaves were moved, the old slaves array
+ * will be partially populated, with some valid and some invalid
+ * entries. Walk through it, copying valid entries to the new slaves
+ * array as we go; when we get to the insert location for the new
+ * slaves, copy the inserts array over, then finish off the old slaves
+ * array.
+ */
+ for (i = 0, j = 0; i < index; i++) {
+ if (pwPtr->slaves[i] != NULL) {
+ new[j] = pwPtr->slaves[i];
+ j++;
+ }
+ }
+
+ memcpy((void *)&(new[j]), inserts, sizeof(Slave *) * (insertIndex));
+ j += firstOptionArg - 2;
+
+ for (i = index; i < pwPtr->numSlaves; i++) {
+ if (pwPtr->slaves[i] != NULL) {
+ new[j] = pwPtr->slaves[i];
+ j++;
+ }
+ }
+ }
+
+ /*
+ * Make the new slaves array the paned window's slave array, and clean up.
+ */
+ ckfree((void *)pwPtr->slaves);
+ ckfree((void *)inserts);
+ pwPtr->slaves = new;
+
+ /*
+ * Set the paned window's slave count to the new value.
+ */
+ pwPtr->numSlaves += numNewSlaves;
+
+ Tk_FreeConfigOptions((char *) &options, pwPtr->slaveOpts, pwPtr->tkwin);
+
+ ComputeGeometry(pwPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PanedWindowSashCommand --
+ *
+ * Implementation of the panedwindow sash subcommand. See the user
+ * documentation for details on what it does.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Depends on the arguments.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PanedWindowSashCommand(pwPtr, interp, objc, objv)
+ PanedWindow *pwPtr; /* Pointer to paned window information. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj * CONST objv[]; /* Argument objects. */
+{
+ static CONST char *sashOptionStrings[] = { "coord", "dragto", "mark",
+ "place", (char *) NULL };
+ enum sashOptions { SASH_COORD, SASH_DRAGTO, SASH_MARK, SASH_PLACE };
+ int index, sash, x, y, diff;
+ Tcl_Obj *coords[2];
+ Slave *slavePtr;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[2], sashOptionStrings,
+ "option", 0, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ Tcl_ResetResult(interp);
+ switch ((enum sashOptions) index) {
+ case SASH_COORD: {
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[3], &sash) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (sash >= pwPtr->numSlaves - 1) {
+ Tcl_ResetResult(interp);
+ Tcl_SetResult(interp, "invalid sash index", TCL_STATIC);
+ return TCL_ERROR;
+ }
+ slavePtr = pwPtr->slaves[sash];
+
+ coords[0] = Tcl_NewIntObj(slavePtr->sashx);
+ coords[1] = Tcl_NewIntObj(slavePtr->sashy);
+ Tcl_SetListObj(Tcl_GetObjResult(interp), 2, coords);
+ break;
+ }
+
+ case SASH_MARK: {
+ if (objc != 6 && objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index ?x y?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[3], &sash) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (sash >= pwPtr->numSlaves - 1) {
+ Tcl_ResetResult(interp);
+ Tcl_SetResult(interp, "invalid sash index", TCL_STATIC);
+ return TCL_ERROR;
+ }
+
+ if (objc == 6) {
+ if (Tcl_GetIntFromObj(interp, objv[4], &x) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[5], &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ pwPtr->slaves[sash]->markx = x;
+ pwPtr->slaves[sash]->marky = y;
+ } else {
+ coords[0] = Tcl_NewIntObj(pwPtr->slaves[sash]->markx);
+ coords[1] = Tcl_NewIntObj(pwPtr->slaves[sash]->marky);
+ Tcl_SetListObj(Tcl_GetObjResult(interp), 2, coords);
+ }
+
+ break;
+ }
+
+ case SASH_DRAGTO:
+ case SASH_PLACE: {
+ if (objc != 6) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index x y");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[3], &sash) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (sash >= pwPtr->numSlaves - 1) {
+ Tcl_ResetResult(interp);
+ Tcl_SetResult(interp, "invalid sash index", TCL_STATIC);
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[4], &x) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[5], &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ slavePtr = pwPtr->slaves[sash];
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ if (index == SASH_PLACE) {
+ diff = x - pwPtr->slaves[sash]->sashx;
+ } else {
+ diff = x - pwPtr->slaves[sash]->markx;
+ }
+ } else {
+ if (index == SASH_PLACE) {
+ diff = y - pwPtr->slaves[sash]->sashy;
+ } else {
+ diff = y - pwPtr->slaves[sash]->marky;
+ }
+ }
+
+ MoveSash(pwPtr, sash, diff);
+ ComputeGeometry(pwPtr);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigurePanedWindow --
+ *
+ * This procedure is called to process an argv/argc list in
+ * conjunction with the Tk option database to configure (or
+ * reconfigure) a paned window widget.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If TCL_ERROR is
+ * returned, then the interp's result contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as colors, border width,
+ * etc. get set for pwPtr; old resources get freed,
+ * if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigurePanedWindow(interp, pwPtr, objc, objv)
+ Tcl_Interp *interp; /* Used for error reporting. */
+ PanedWindow *pwPtr; /* Information about widget. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument values. */
+{
+ Tk_SavedOptions savedOptions;
+ int typemask = 0;
+
+ if (Tk_SetOptions(interp, (char *) pwPtr, pwPtr->optionTable, objc, objv,
+ pwPtr->tkwin, &savedOptions, &typemask) != TCL_OK) {
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
+ }
+
+ Tk_FreeSavedOptions(&savedOptions);
+
+ PanedWindowWorldChanged((ClientData) pwPtr);
+
+ /*
+ * If an option that affects geometry has changed, make a relayout
+ * request.
+ */
+
+ if (typemask & GEOMETRY) {
+ ComputeGeometry(pwPtr);
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PanedWindowWorldChanged --
+ *
+ * This procedure is invoked anytime a paned window's world has
+ * changed in some way that causes the widget to have to recompute
+ * graphics contexts and geometry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Paned window will be relayed out and redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+PanedWindowWorldChanged(instanceData)
+ ClientData instanceData; /* Information about the paned window. */
+{
+ XGCValues gcValues;
+ GC newGC;
+ PanedWindow *pwPtr = (PanedWindow *) instanceData;
+
+ /*
+ * Allocated a graphics context for drawing the paned window widget
+ * elements (background, sashes, etc.).
+ */
+
+ gcValues.background = Tk_3DBorderColor(pwPtr->background)->pixel;
+ newGC = Tk_GetGC(pwPtr->tkwin, GCBackground, &gcValues);
+ if (pwPtr->gc != None) {
+ Tk_FreeGC(pwPtr->display, pwPtr->gc);
+ }
+ pwPtr->gc = newGC;
+
+ /*
+ * Issue geometry size requests to Tk.
+ */
+
+ Tk_SetInternalBorder(pwPtr->tkwin, pwPtr->borderWidth);
+ if (pwPtr->width > 0 || pwPtr->height > 0) {
+ Tk_GeometryRequest(pwPtr->tkwin, pwPtr->width, pwPtr->height);
+ }
+
+ /*
+ * Arrange for the window to be redrawn, if neccessary.
+ */
+
+ if (Tk_IsMapped(pwPtr->tkwin) && !(pwPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayPanedWindow, (ClientData) pwPtr);
+ pwPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PanedWindowEventProc --
+ *
+ * This procedure is invoked by the Tk dispatcher for various
+ * events on paned windows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get
+ * cleaned up. When it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+PanedWindowEventProc(clientData, eventPtr)
+ ClientData clientData; /* Information about window. */
+ XEvent *eventPtr; /* Information about event. */
+{
+ PanedWindow *pwPtr = (PanedWindow *) clientData;
+
+ if (eventPtr->type == Expose) {
+ if (pwPtr->tkwin != NULL && !(pwPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayPanedWindow, (ClientData) pwPtr);
+ pwPtr->flags |= REDRAW_PENDING;
+ }
+ } else if (eventPtr->type == ConfigureNotify) {
+ pwPtr->flags |= REQUESTED_RELAYOUT;
+ if (pwPtr->tkwin != NULL && !(pwPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayPanedWindow, (ClientData) pwPtr);
+ pwPtr->flags |= REDRAW_PENDING;
+ }
+ } else if (eventPtr->type == DestroyNotify) {
+ DestroyPanedWindow(pwPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PanedWindowCmdDeletedProc --
+ *
+ * This procedure is invoked when a widget command is deleted. If
+ * the widget isn't already in the process of being destroyed,
+ * this command destroys it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+PanedWindowCmdDeletedProc(clientData)
+ ClientData clientData; /* Pointer to widget record for widget. */
+{
+ PanedWindow *pwPtr = (PanedWindow *) clientData;
+
+ /*
+ * This procedure could be invoked either because the window was
+ * destroyed and the command was then deleted or because the command was
+ * deleted, and then this procedure destroys the widget. The
+ * WIDGET_DELETED flag distinguishes these cases.
+ */
+
+ if (!(pwPtr->flags & WIDGET_DELETED)) {
+ Tk_DestroyWindow(pwPtr->tkwin);
+ Tk_DestroyWindow(pwPtr->proxywin);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayPanedWindow --
+ *
+ * This procedure redraws the contents of a paned window widget.
+ * It is invoked as a do-when-idle handler, so it only runs
+ * when there's nothing else for the application to do.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information appears on the screen.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayPanedWindow(clientData)
+ ClientData clientData; /* Information about window. */
+{
+ PanedWindow *pwPtr = (PanedWindow *) clientData;
+ Pixmap pixmap;
+ Tk_Window tkwin = pwPtr->tkwin;
+ int i, sashWidth, sashHeight;
+
+ pwPtr->flags &= ~REDRAW_PENDING;
+ if ((pwPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+
+ if (pwPtr->flags & REQUESTED_RELAYOUT) {
+ ArrangePanes(clientData);
+ }
+
+ /*
+ * Create a pixmap for double-buffering, if necessary.
+ */
+
+ pixmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
+ Tk_Width(tkwin), Tk_Height(tkwin),
+ DefaultDepthOfScreen(Tk_Screen(tkwin)));
+
+ /*
+ * Redraw the widget's background and border.
+ */
+ Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background, 0, 0,
+ Tk_Width(tkwin), Tk_Height(tkwin), pwPtr->borderWidth,
+ pwPtr->relief);
+
+ /*
+ * Set up boilerplate geometry values for sashes (width, height, common
+ * coordinates).
+ */
+
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ sashHeight = Tk_Height(tkwin) - (2 * Tk_InternalBorderWidth(tkwin));
+ sashWidth = pwPtr->sashWidth;
+ } else {
+ sashWidth = Tk_Width(tkwin) - (2 * Tk_InternalBorderWidth(tkwin));
+ sashHeight = pwPtr->sashWidth;
+ }
+
+ /*
+ * Draw the sashes.
+ */
+ for (i = 0; i < pwPtr->numSlaves - 1; i++) {
+ Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background,
+ pwPtr->slaves[i]->sashx, pwPtr->slaves[i]->sashy,
+ sashWidth, sashHeight, 1, pwPtr->sashRelief);
+
+ if (pwPtr->showHandle) {
+ Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background,
+ pwPtr->slaves[i]->handlex, pwPtr->slaves[i]->handley,
+ pwPtr->handleSize, pwPtr->handleSize, 1,
+ TK_RELIEF_RAISED);
+ }
+ }
+
+ /*
+ * Copy the information from the off-screen pixmap onto the screen,
+ * then delete the pixmap.
+ */
+
+ XCopyArea(Tk_Display(tkwin), pixmap, Tk_WindowId(tkwin), pwPtr->gc,
+ 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin),
+ 0, 0);
+ Tk_FreePixmap(Tk_Display(tkwin), pixmap);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyPanedWindow --
+ *
+ * This procedure is invoked by PanedWindowEventProc to free the
+ * internal structure of a paned window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the paned window is freed up.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyPanedWindow(pwPtr)
+ PanedWindow *pwPtr; /* Info about paned window widget. */
+{
+ int i;
+
+ /*
+ * First mark the widget as in the process of being deleted,
+ * so that any code that causes calls to other paned window procedures
+ * will abort.
+ */
+
+ pwPtr->flags |= WIDGET_DELETED;
+
+ /*
+ * Cancel idle callbacks for redrawing the widget and for rearranging
+ * the panes.
+ */
+ if (pwPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayPanedWindow, (ClientData) pwPtr);
+ }
+
+ /*
+ * Clean up the slave list; foreach slave:
+ * o Cancel the slave's structure notification callback
+ * o Cancel geometry management for the slave.
+ * o Free memory for the slave
+ */
+
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ Tk_DeleteEventHandler(pwPtr->slaves[i]->tkwin, StructureNotifyMask,
+ SlaveStructureProc, (ClientData) pwPtr->slaves[i]);
+ Tk_ManageGeometry(pwPtr->slaves[i]->tkwin, NULL, NULL);
+ Tk_FreeConfigOptions((char *)pwPtr->slaves[i], pwPtr->slaveOpts,
+ pwPtr->tkwin);
+ ckfree((void *)pwPtr->slaves[i]);
+ pwPtr->slaves[i] = NULL;
+ }
+
+ /*
+ * Remove the widget command from the interpreter.
+ */
+
+ Tcl_DeleteCommandFromToken(pwPtr->interp, pwPtr->widgetCmd);
+
+ /*
+ * Let Tk_FreeConfigOptions clean up the rest.
+ */
+
+ Tk_FreeConfigOptions((char *) pwPtr, pwPtr->optionTable, pwPtr->tkwin);
+ pwPtr->tkwin = NULL;
+
+ Tcl_EventuallyFree((ClientData) pwPtr, TCL_DYNAMIC);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PanedWindowReqProc --
+ *
+ * This procedure is invoked by Tk_GeometryRequest for
+ * windows managed by a paned window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Arranges for tkwin, and all its managed siblings, to
+ * be re-arranged at the next idle point.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+PanedWindowReqProc(clientData, tkwin)
+ ClientData clientData; /* Paned window's information about
+ * window that got new preferred
+ * geometry. */
+ Tk_Window tkwin; /* Other Tk-related information
+ * about the window. */
+{
+ Slave *panePtr = (Slave *) clientData;
+ PanedWindow *pwPtr = (PanedWindow *) (panePtr->masterPtr);
+ ComputeGeometry(pwPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PanedWindowLostSlaveProc --
+ *
+ * This procedure is invoked by Tk whenever some other geometry
+ * claims control over a slave that used to be managed by us.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Forgets all information about the slave. Causes geometry to
+ * be recomputed for the panedwindow.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+PanedWindowLostSlaveProc(clientData, tkwin)
+ ClientData clientData; /* Grid structure for slave window that
+ * was stolen away. */
+ Tk_Window tkwin; /* Tk's handle for the slave window. */
+{
+ register Slave *slavePtr = (Slave *) clientData;
+ PanedWindow *pwPtr = (PanedWindow *) (slavePtr->masterPtr);
+ if (pwPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin, pwPtr->tkwin);
+ }
+ Unlink(slavePtr);
+ Tk_DeleteEventHandler(slavePtr->tkwin, StructureNotifyMask,
+ SlaveStructureProc, (ClientData) slavePtr);
+ Tk_UnmapWindow(slavePtr->tkwin);
+ slavePtr->tkwin = NULL;
+ ckfree((void *)slavePtr);
+ ComputeGeometry(pwPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ArrangePanes --
+ *
+ * This procedure is invoked (using the Tcl_DoWhenIdle
+ * mechanism) to re-layout a set of windows managed by
+ * a paned window. It is invoked at idle time so that a
+ * series of pane requests can be merged into a single
+ * layout operation.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The slaves of masterPtr may get resized or moved.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ArrangePanes(clientData)
+ ClientData clientData; /* Structure describing parent whose slaves
+ * are to be re-layed out. */
+{
+ register PanedWindow *pwPtr = (PanedWindow *) clientData;
+ register Slave *slavePtr;
+ int i, slaveWidth, slaveHeight, slaveX, slaveY, paneWidth, paneHeight;
+ int doubleBw;
+
+ pwPtr->flags &= ~REQUESTED_RELAYOUT;
+
+ /*
+ * If the parent has no slaves anymore, then don't do anything
+ * at all: just leave the parent's size as-is. Otherwise there is
+ * no way to "relinquish" control over the parent so another geometry
+ * manager can take over.
+ */
+
+ if (pwPtr->numSlaves == 0) {
+ return;
+ }
+
+ Tcl_Preserve((ClientData) pwPtr);
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ slavePtr = pwPtr->slaves[i];
+
+ /*
+ * Compute the size of this slave. The algorithm (assuming a
+ * horizontal paned window) is:
+ *
+ * 1. Get "base" dimensions. If a width or height is specified
+ * for this slave, use those values; else use the
+ * ReqWidth/ReqHeight.
+ * 2. Using base dimensions, pane dimensions, and sticky values,
+ * determine the x and y, and actual width and height of the
+ * widget.
+ */
+
+ doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width;
+ slaveWidth = (slavePtr->width > 0 ? slavePtr->width :
+ Tk_ReqWidth(slavePtr->tkwin) + doubleBw);
+ slaveHeight = (slavePtr->height > 0 ? slavePtr->height :
+ Tk_ReqHeight(slavePtr->tkwin) + doubleBw);
+
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ paneWidth = slavePtr->paneWidth;
+ if (i == pwPtr->numSlaves - 1 && Tk_IsMapped(pwPtr->tkwin)) {
+ if (Tk_Width(pwPtr->tkwin) > Tk_ReqWidth(pwPtr->tkwin)) {
+ paneWidth += Tk_Width(pwPtr->tkwin) -
+ Tk_ReqWidth(pwPtr->tkwin) -
+ Tk_InternalBorderWidth(pwPtr->tkwin);
+ }
+ }
+ paneHeight = Tk_Height(pwPtr->tkwin) - (2 * slavePtr->pady) -
+ (2 * Tk_InternalBorderWidth(pwPtr->tkwin));
+ } else {
+ paneHeight = slavePtr->paneHeight;
+ if (i == pwPtr->numSlaves - 1 && Tk_IsMapped(pwPtr->tkwin)) {
+ if (Tk_Height(pwPtr->tkwin) > Tk_ReqHeight(pwPtr->tkwin)) {
+ paneHeight += Tk_Height(pwPtr->tkwin) -
+ Tk_ReqHeight(pwPtr->tkwin) -
+ Tk_InternalBorderWidth(pwPtr->tkwin);
+ }
+ }
+ paneWidth = Tk_Width(pwPtr->tkwin) - (2 * slavePtr->padx) -
+ (2 * Tk_InternalBorderWidth(pwPtr->tkwin));
+ }
+
+ if (slaveWidth > paneWidth) {
+ slaveWidth = paneWidth;
+ }
+ if (slaveHeight > paneHeight) {
+ slaveHeight = paneHeight;
+ }
+
+ slaveX = slavePtr->x;
+ slaveY = slavePtr->y;
+ AdjustForSticky(slavePtr->sticky, paneWidth, paneHeight,
+ &slaveX, &slaveY, &slaveWidth, &slaveHeight);
+
+ slaveX += slavePtr->padx;
+ slaveY += slavePtr->pady;
+
+ /*
+ * Now put the window in the proper spot.
+ */
+ if ((slaveWidth <= 0) || (slaveHeight <= 0)) {
+ Tk_UnmaintainGeometry(slavePtr->tkwin, pwPtr->tkwin);
+ Tk_UnmapWindow(slavePtr->tkwin);
+ } else {
+ Tk_MaintainGeometry(slavePtr->tkwin, pwPtr->tkwin,
+ slaveX, slaveY, slaveWidth, slaveHeight);
+ }
+ }
+ Tcl_Release((ClientData) pwPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Unlink --
+ *
+ * Remove a slave from a paned window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The paned window will be scheduled for re-arranging and redrawing.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+Unlink(slavePtr)
+ register Slave *slavePtr; /* Window to unlink. */
+{
+ register PanedWindow *masterPtr;
+ int i, j;
+
+ masterPtr = slavePtr->masterPtr;
+ if (masterPtr == NULL) {
+ return;
+ }
+
+ /*
+ * Find the specified slave in the panedwindow's list of slaves, then
+ * remove it from that list.
+ */
+
+ for (i = 0; i < masterPtr->numSlaves; i++) {
+ if (masterPtr->slaves[i] == slavePtr) {
+ for (j = i; j < masterPtr->numSlaves - 1; j++) {
+ masterPtr->slaves[j] = masterPtr->slaves[j + 1];
+ }
+ break;
+ }
+ }
+
+ masterPtr->flags |= REQUESTED_RELAYOUT;
+ if (!(masterPtr->flags & REDRAW_PENDING)) {
+ masterPtr->flags |= REDRAW_PENDING;
+ Tcl_DoWhenIdle(DisplayPanedWindow, (ClientData) masterPtr);
+ }
+
+ /*
+ * Set the slave's masterPtr to NULL, so that we can tell that the
+ * slave is no longer attached to any panedwindow.
+ */
+ slavePtr->masterPtr = NULL;
+
+ masterPtr->numSlaves--;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetPane --
+ *
+ * Given a token to a Tk window, find the pane that corresponds to
+ * that token in a given paned window.
+ *
+ * Results:
+ * Pointer to the slave structure, or NULL if the window is not
+ * managed by this paned window.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Slave *
+GetPane(pwPtr, tkwin)
+ PanedWindow *pwPtr; /* Pointer to the paned window info. */
+ Tk_Window tkwin; /* Window to search for. */
+{
+ int i;
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ if (pwPtr->slaves[i]->tkwin == tkwin) {
+ return pwPtr->slaves[i];
+ }
+ }
+ return NULL;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SlaveStructureProc --
+ *
+ * This procedure is invoked whenever StructureNotify events
+ * occur for a window that's managed by a paned window. This
+ * procedure's only purpose is to clean up when windows are
+ * deleted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The paned window slave structure associated with the window
+ * is freed, and the slave is disassociated from the paned
+ * window which managed it.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+SlaveStructureProc(clientData, eventPtr)
+ ClientData clientData; /* Pointer to record describing window item. */
+ XEvent *eventPtr; /* Describes what just happened. */
+{
+ Slave *slavePtr = (Slave *) clientData;
+ PanedWindow *pwPtr = slavePtr->masterPtr;
+
+ if (eventPtr->type == DestroyNotify) {
+ Unlink(slavePtr);
+ slavePtr->tkwin = NULL;
+ ckfree((void *)slavePtr);
+ ComputeGeometry(pwPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ComputeGeometry --
+ *
+ * Compute geometry for the paned window, including coordinates of
+ * all slave windows and each sash.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Recomputes geometry information for a paned window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ComputeGeometry(pwPtr)
+ PanedWindow *pwPtr; /* Pointer to the Paned Window structure. */
+{
+ int i, x, y, doubleBw, internalBw;
+ int reqWidth, reqHeight, sashWidth, sxOff, syOff, hxOff, hyOff, dim;
+ Slave *slavePtr;
+
+ pwPtr->flags |= REQUESTED_RELAYOUT;
+
+ x = y = internalBw = Tk_InternalBorderWidth(pwPtr->tkwin);
+ reqWidth = reqHeight = 0;
+
+ /*
+ * Sashes and handles share space on the display. To simplify
+ * processing below, precompute the x and y offsets of the handles and
+ * sashes within the space occupied by their combination; later, just add
+ * those offsets blindly (avoiding the extra showHandle, etc, checks).
+ */
+ sxOff = syOff = hxOff = hyOff = 0;
+ if (pwPtr->showHandle && pwPtr->handleSize > pwPtr->sashWidth) {
+ sashWidth = pwPtr->handleSize;
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ sxOff = (pwPtr->handleSize - pwPtr->sashWidth) / 2;
+ hyOff = pwPtr->handlePad;
+ } else {
+ syOff = (pwPtr->handleSize - pwPtr->sashWidth) / 2;
+ hxOff = pwPtr->handlePad;
+ }
+ } else {
+ sashWidth = pwPtr->sashWidth;
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ hxOff = (pwPtr->handleSize - pwPtr->sashWidth) / 2;
+ hyOff = pwPtr->handlePad;
+ } else {
+ hyOff = (pwPtr->handleSize - pwPtr->sashWidth) / 2;
+ hxOff = pwPtr->handlePad;
+ }
+ }
+
+ for (i = 0; i < pwPtr->numSlaves; i++) {
+ slavePtr = pwPtr->slaves[i];
+ /*
+ * First set the coordinates for the top left corner of the slave's
+ * parcel.
+ */
+ slavePtr->x = x;
+ slavePtr->y = y;
+
+ /*
+ * Make sure the pane's paned dimension is at least minsize.
+ * This check may be redundant, since the only way to change a pane's
+ * size is by moving a sash, and that code checks the minsize.
+ */
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ if (slavePtr->paneWidth < slavePtr->minSize) {
+ slavePtr->paneWidth = slavePtr->minSize;
+ }
+ } else {
+ if (slavePtr->paneHeight < slavePtr->minSize) {
+ slavePtr->paneHeight = slavePtr->minSize;
+ }
+ }
+
+ /*
+ * Compute the location of the sash at the right or bottom of the
+ * parcel.
+ */
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ x += slavePtr->paneWidth + (2 * slavePtr->padx) + pwPtr->sashPad;
+ } else {
+ y += slavePtr->paneHeight + (2 * slavePtr->pady) + pwPtr->sashPad;
+ }
+ slavePtr->sashx = x + sxOff;
+ slavePtr->sashy = y + syOff;
+ slavePtr->handlex = x + hxOff;
+ slavePtr->handley = y + hyOff;
+
+ /*
+ * Compute the location of the next parcel.
+ */
+
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ x += sashWidth + pwPtr->sashPad;
+ } else {
+ y += sashWidth + pwPtr->sashPad;
+ }
+
+ /*
+ * Find the maximum height/width of the slaves, for computing the
+ * requested height/width of the paned window.
+ */
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ /*
+ * If the slave has an explicit height set, use that; otherwise,
+ * use the slave's requested height.
+ */
+ if (slavePtr->height > 0) {
+ dim = slavePtr->height;
+ } else {
+ doubleBw = (2 * Tk_Changes(slavePtr->tkwin)->border_width);
+ dim = Tk_ReqHeight(slavePtr->tkwin) + doubleBw;
+ }
+ dim += (2 * slavePtr->pady);
+ if (dim > reqHeight) {
+ reqHeight = dim;
+ }
+ } else {
+ /*
+ * If the slave has an explicit width set use that; otherwise,
+ * use the slave's requested width.
+ */
+ if (slavePtr->width > 0) {
+ dim = slavePtr->width;
+ } else {
+ doubleBw = (2 * Tk_Changes(slavePtr->tkwin)->border_width);
+ dim = Tk_ReqWidth(slavePtr->tkwin) + doubleBw;
+ }
+ dim += (2 * slavePtr->padx);
+ if (dim > reqWidth) {
+ reqWidth = dim;
+ }
+ }
+ }
+
+ /*
+ * The loop above should have left x (or y) equal to the sum of the
+ * widths (or heights) of the widgets, plus the size of one sash and
+ * the sash padding for each widget, plus the width of the left (or top)
+ * border of the paned window.
+ *
+ * The requested width (or height) is therefore x (or y) minus the size of
+ * one sash and padding, plus the width of the right (or bottom) border
+ * of the paned window.
+ *
+ * The height (or width) is equal to the maximum height (or width) of
+ * the slaves, plus the width of the border of the top and bottom (or left
+ * and right) of the paned window.
+ */
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ reqWidth = x - (sashWidth + (2 * pwPtr->sashPad)) + internalBw;
+ reqHeight += 2 * internalBw;
+ } else {
+ reqHeight = y - (sashWidth + (2 * pwPtr->sashPad)) + internalBw;
+ reqWidth += 2 * internalBw;
+ }
+ if (pwPtr->width <= 0 && pwPtr->height <= 0) {
+ Tk_GeometryRequest(pwPtr->tkwin, reqWidth, reqHeight);
+ }
+ if (Tk_IsMapped(pwPtr->tkwin) && !(pwPtr->flags & REDRAW_PENDING)) {
+ pwPtr->flags |= REDRAW_PENDING;
+ Tcl_DoWhenIdle(DisplayPanedWindow, (ClientData) pwPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyOptionTables --
+ *
+ * This procedure is registered as an exit callback when the paned window
+ * command is first called. It cleans up the OptionTables structure
+ * allocated by that command.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyOptionTables(clientData, interp)
+ ClientData clientData; /* Pointer to the OptionTables struct */
+ Tcl_Interp *interp; /* Pointer to the calling interp */
+{
+ ckfree((char *)clientData);
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetSticky -
+ *
+ * Converts an internal boolean combination of "sticky" bits into a
+ * a Tcl string obj containing zero or mor of n, s, e, or w.
+ *
+ * Results:
+ * Tcl_Obj containing the string representation of the sticky value.
+ *
+ * Side effects:
+ * Creates a new Tcl_Obj.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj *
+GetSticky(clientData, tkwin, recordPtr, internalOffset)
+ ClientData clientData;
+ Tk_Window tkwin;
+ char *recordPtr; /* Pointer to widget record. */
+ int internalOffset; /* Offset within *recordPtr containing the
+ * sticky value. */
+{
+ int sticky = *(int *)(recordPtr + internalOffset);
+ static char buffer[5];
+ int count = 0;
+
+ if (sticky & STICK_NORTH) {
+ buffer[count++] = 'n';
+ }
+ if (sticky & STICK_EAST) {
+ buffer[count++] = 'e';
+ }
+ if (sticky & STICK_SOUTH) {
+ buffer[count++] = 's';
+ }
+ if (sticky & STICK_WEST) {
+ buffer[count++] = 'w';
+ }
+ buffer[count] = '\0';
+
+ return Tcl_NewStringObj(buffer, -1);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetSticky --
+ *
+ * Converts a Tcl_Obj representing a widgets stickyness into an
+ * integer value.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * May store the integer value into the internal representation
+ * pointer. May change the pointer to the Tcl_Obj to NULL to indicate
+ * that the specified string was empty and that is acceptable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetSticky(clientData, interp, tkwin, value, recordPtr, internalOffset,
+ oldInternalPtr, flags)
+ ClientData clientData;
+ Tcl_Interp *interp; /* Current interp; may be used for errors. */
+ Tk_Window tkwin; /* Window for which option is being set. */
+ Tcl_Obj **value; /* Pointer to the pointer to the value object.
+ * We use a pointer to the pointer because
+ * we may need to return a value (NULL). */
+ char *recordPtr; /* Pointer to storage for the widget record. */
+ int internalOffset; /* Offset within *recordPtr at which the
+ internal value is to be stored. */
+ char *oldInternalPtr; /* Pointer to storage for the old value. */
+ int flags; /* Flags for the option, set Tk_SetOptions. */
+{
+ int sticky = 0;
+ char c, *string, *internalPtr;
+
+ internalPtr = ComputeSlotAddress(recordPtr, internalOffset);
+
+ if (flags & TK_OPTION_NULL_OK && ObjectIsEmpty(*value)) {
+ *value = NULL;
+ } else {
+ /*
+ * Convert the sticky specifier into an integer value.
+ */
+
+ string = Tcl_GetString(*value);
+
+ while ((c = *string++) != '\0') {
+ switch (c) {
+ case 'n': case 'N': sticky |= STICK_NORTH; break;
+ case 'e': case 'E': sticky |= STICK_EAST; break;
+ case 's': case 'S': sticky |= STICK_SOUTH; break;
+ case 'w': case 'W': sticky |= STICK_WEST; break;
+ case ' ': case ',': case '\t': case '\r': case '\n': break;
+ default: {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad stickyness value \"",
+ Tcl_GetString(*value), "\": must be a string ",
+ "containing zero or more of n, e, s, and w",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ }
+
+ if (internalPtr != NULL) {
+ *((int *) oldInternalPtr) = *((int *) internalPtr);
+ *((int *) internalPtr) = sticky;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RestoreSticky --
+ *
+ * Restore a sticky option value from a saved value.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Restores the old value.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RestoreSticky(clientData, tkwin, internalPtr, oldInternalPtr)
+ ClientData clientData;
+ Tk_Window tkwin;
+ char *internalPtr; /* Pointer to storage for value. */
+ char *oldInternalPtr; /* Pointer to old value. */
+{
+ *(int *)internalPtr = *(int *)oldInternalPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AdjustForSticky --
+ *
+ * Given the x,y coords of the top-left corner of a pane, the
+ * dimensions of that pane, and the dimensions of a slave, compute
+ * the x,y coords and actual dimensions of the slave based on the slave's
+ * sticky value.
+ *
+ * Results:
+ * No direct return; sets the x, y, slaveWidth and slaveHeight to
+ * correct values.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+AdjustForSticky(sticky, cavityWidth, cavityHeight, xPtr, yPtr,
+ slaveWidthPtr, slaveHeightPtr)
+ int sticky; /* Sticky value; see top of file for definition. */
+ int cavityWidth; /* Width of the cavity. */
+ int cavityHeight; /* Height of the cavity. */
+ int *xPtr, *yPtr; /* Initially, coordinates of the top-left
+ * corner of cavity; also return values for
+ * actual x, y coords of slave. */
+ int *slaveWidthPtr; /* Slave width. */
+ int *slaveHeightPtr; /* Slave height. */
+{
+ int diffx=0; /* Cavity width - slave width. */
+ int diffy=0; /* Cavity hight - slave height. */
+
+ if (cavityWidth > *slaveWidthPtr) {
+ diffx = cavityWidth - *slaveWidthPtr;
+ }
+
+ if (cavityHeight > *slaveHeightPtr) {
+ diffy = cavityHeight - *slaveHeightPtr;
+ }
+
+ if ((sticky & STICK_EAST) && (sticky & STICK_WEST)) {
+ *slaveWidthPtr += diffx;
+ }
+ if ((sticky & STICK_NORTH) && (sticky & STICK_SOUTH)) {
+ *slaveHeightPtr += diffy;
+ }
+ if (!(sticky & STICK_WEST)) {
+ *xPtr += (sticky & STICK_EAST) ? diffx : diffx/2;
+ }
+ if (!(sticky & STICK_NORTH)) {
+ *yPtr += (sticky & STICK_SOUTH) ? diffy : diffy/2;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MoveSash --
+ *
+ * Move the sash given by index the amount given.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Recomputes the sizes of the panes in a panedwindow.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MoveSash(pwPtr, sash, diff)
+ PanedWindow *pwPtr;
+ int sash;
+ int diff;
+{
+ int diffConsumed = 0, i, extra, maxCoord, currCoord;
+ int *lengthPtr, newLength;
+ Slave *slave;
+
+ if (diff > 0) {
+ /*
+ * Growing the pane, at the expense of panes to the right.
+ */
+
+
+ /*
+ * First check that moving the sash the requested distance will not
+ * leave it off the screen. If necessary, clip the requested diff
+ * to the maximum possible while remaining visible.
+ */
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ if (Tk_IsMapped(pwPtr->tkwin)) {
+ maxCoord = Tk_Width(pwPtr->tkwin);
+ } else {
+ maxCoord = Tk_ReqWidth(pwPtr->tkwin);
+ }
+ extra = Tk_Width(pwPtr->tkwin) - Tk_ReqWidth(pwPtr->tkwin);
+ currCoord = pwPtr->slaves[sash]->sashx;
+ } else {
+ if (Tk_IsMapped(pwPtr->tkwin)) {
+ maxCoord = Tk_Height(pwPtr->tkwin);
+ } else {
+ maxCoord = Tk_ReqHeight(pwPtr->tkwin);
+ }
+ extra = Tk_Height(pwPtr->tkwin) - Tk_ReqHeight(pwPtr->tkwin);
+ currCoord = pwPtr->slaves[sash]->sashy;
+ }
+
+ maxCoord -= (pwPtr->borderWidth + pwPtr->sashWidth + pwPtr->sashPad);
+ if (currCoord + diff >= maxCoord) {
+ diff = maxCoord - currCoord;
+ }
+
+ for (i = sash + 1; i < pwPtr->numSlaves; i++) {
+ if (diffConsumed == diff) {
+ break;
+ }
+ slave = pwPtr->slaves[i];
+
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ lengthPtr = &(slave->paneWidth);
+ } else {
+ lengthPtr = &(slave->paneHeight);
+ }
+
+ /*
+ * Remove as much space from this pane as possible (constrained
+ * by the minsize value and the visible dimensions of the window).
+ */
+
+ if (i == pwPtr->numSlaves - 1 && extra > 0) {
+ /*
+ * The last pane may have some additional "virtual" space,
+ * if the width (or height) of the paned window is bigger
+ * than the requested width (or height).
+ *
+ * That extra space is not included in the paneWidth
+ * (or paneHeight) value, so we have to handle the last
+ * pane specially.
+ */
+ newLength = (*lengthPtr + extra) - (diff - diffConsumed);
+ if (newLength < slave->minSize) {
+ newLength = slave->minSize;
+ }
+ if (newLength < 0) {
+ newLength = 0;
+ }
+ diffConsumed += (*lengthPtr + extra) - newLength;
+ if (newLength < *lengthPtr) {
+ *lengthPtr = newLength;
+ }
+ } else {
+ newLength = *lengthPtr - (diff - diffConsumed);
+ if (newLength < slave->minSize) {
+ newLength = slave->minSize;
+ }
+ if (newLength < 0) {
+ newLength = 0;
+ }
+ diffConsumed += *lengthPtr - newLength;
+ *lengthPtr = newLength;
+ }
+ }
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ pwPtr->slaves[sash]->paneWidth += diffConsumed;
+ } else {
+ pwPtr->slaves[sash]->paneHeight += diffConsumed;
+ }
+ } else if (diff < 0) {
+ /*
+ * Shrinking the pane; additional space is given to the pane to the
+ * right.
+ */
+ for (i = sash; i >= 0; i--) {
+ if (diffConsumed == diff) {
+ break;
+ }
+ /*
+ * Remove as much space from this pane as possible.
+ */
+ slave = pwPtr->slaves[i];
+
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ lengthPtr = &(slave->paneWidth);
+ } else {
+ lengthPtr = &(slave->paneHeight);
+ }
+
+ newLength = *lengthPtr + (diff - diffConsumed);
+ if (newLength < slave->minSize) {
+ newLength = slave->minSize;
+ }
+ if (newLength < 0) {
+ newLength = 0;
+ }
+ diffConsumed -= *lengthPtr - newLength;
+ *lengthPtr = newLength;
+ }
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ pwPtr->slaves[sash + 1]->paneWidth -= diffConsumed;
+ } else {
+ pwPtr->slaves[sash + 1]->paneHeight -= diffConsumed;
+ }
+ }
+
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ProxyWindowEventProc --
+ *
+ * This procedure is invoked by the Tk dispatcher for various
+ * events on paned window proxy windows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get
+ * cleaned up. When it gets exposed, it is redisplayed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ProxyWindowEventProc(clientData, eventPtr)
+ ClientData clientData; /* Information about window. */
+ XEvent *eventPtr; /* Information about event. */
+{
+ PanedWindow *pwPtr = (PanedWindow *) clientData;
+
+ if (eventPtr->type == Expose) {
+ if (pwPtr->proxywin != NULL &&!(pwPtr->flags & PROXY_REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayProxyWindow, (ClientData) pwPtr);
+ pwPtr->flags |= PROXY_REDRAW_PENDING;
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DisplayProxyWindow --
+ *
+ * This procedure redraws a paned window proxy window.
+ * It is invoked as a do-when-idle handler, so it only runs
+ * when there's nothing else for the application to do.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information appears on the screen.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DisplayProxyWindow(clientData)
+ ClientData clientData; /* Information about window. */
+{
+ PanedWindow *pwPtr = (PanedWindow *) clientData;
+ Pixmap pixmap;
+ Tk_Window tkwin = pwPtr->proxywin;
+ pwPtr->flags &= ~PROXY_REDRAW_PENDING;
+ if ((tkwin == NULL) || !Tk_IsMapped(tkwin)) {
+ return;
+ }
+
+ /*
+ * Create a pixmap for double-buffering, if necessary.
+ */
+
+ pixmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
+ Tk_Width(tkwin), Tk_Height(tkwin),
+ DefaultDepthOfScreen(Tk_Screen(tkwin)));
+
+ /*
+ * Redraw the widget's background and border.
+ */
+ Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background, 0, 0,
+ Tk_Width(tkwin), Tk_Height(tkwin), 2, pwPtr->sashRelief);
+
+ /*
+ * Copy the pixmap to the display.
+ */
+ XCopyArea(Tk_Display(tkwin), pixmap, Tk_WindowId(tkwin), pwPtr->gc,
+ 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin),
+ 0, 0);
+ Tk_FreePixmap(Tk_Display(tkwin), pixmap);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PanedWindowProxyCommand --
+ *
+ * Handles the panedwindow proxy subcommand. See the user
+ * documentation for details.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * May map or unmap the proxy sash.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PanedWindowProxyCommand(pwPtr, interp, objc, objv)
+ PanedWindow *pwPtr; /* Pointer to paned window information. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj * CONST objv[]; /* Argument objects. */
+{
+ static CONST char *optionStrings[] = { "coord", "forget", "place",
+ (char *) NULL };
+ enum options { PROXY_COORD, PROXY_FORGET, PROXY_PLACE };
+ int index, x, y, sashWidth, sashHeight;
+ Tcl_Obj *coords[2];
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[2], optionStrings, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ switch ((enum options) index) {
+ case PROXY_COORD:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+
+ coords[0] = Tcl_NewIntObj(pwPtr->proxyx);
+ coords[1] = Tcl_NewIntObj(pwPtr->proxyy);
+ Tcl_SetListObj(Tcl_GetObjResult(interp), 2, coords);
+ break;
+
+ case PROXY_FORGET:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ return TCL_ERROR;
+ }
+ if (Tk_IsMapped(pwPtr->proxywin)) {
+ Tk_UnmapWindow(pwPtr->proxywin);
+ Tk_UnmaintainGeometry(pwPtr->proxywin, pwPtr->tkwin);
+ }
+ break;
+
+ case PROXY_PLACE: {
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "x y");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ if (x < 0) {
+ x = 0;
+ }
+ y = Tk_InternalBorderWidth(pwPtr->tkwin);
+ sashWidth = pwPtr->sashWidth;
+ sashHeight = Tk_Height(pwPtr->tkwin) -
+ (2 * Tk_InternalBorderWidth(pwPtr->tkwin));
+ } else {
+ if (y < 0) {
+ y = 0;
+ }
+ x = Tk_InternalBorderWidth(pwPtr->tkwin);
+ sashHeight = pwPtr->sashWidth;
+ sashWidth = Tk_Width(pwPtr->tkwin) -
+ (2 * Tk_InternalBorderWidth(pwPtr->tkwin));
+ }
+
+ /*
+ * Stash the proxy coordinates for future "proxy coord" calls.
+ */
+
+ pwPtr->proxyx = x;
+ pwPtr->proxyy = y;
+
+ /*
+ * Make sure the proxy window is higher in the stacking order
+ * than the slaves, so that it will be visible when drawn.
+ * It would be more correct to push the proxy window just high
+ * enough to appear above the highest slave, but it's much easier
+ * to just force it all the way to the top of the stacking order.
+ */
+
+ Tk_RestackWindow(pwPtr->proxywin, Above, NULL);
+
+ /*
+ * Let Tk_MaintainGeometry take care of placing the window at
+ * the right coordinates.
+ */
+ Tk_MaintainGeometry(pwPtr->proxywin, pwPtr->tkwin,
+ x, y, sashWidth, sashHeight);
+ break;
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ObjectIsEmpty --
+ *
+ * This procedure tests whether the string value of an object is
+ * empty.
+ *
+ * Results:
+ * The return value is 1 if the string value of objPtr has length
+ * zero, and 0 otherwise.
+ *
+ * Side effects:
+ * May cause object shimmering, since this function can force a
+ * conversion to a string object.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ObjectIsEmpty(objPtr)
+ Tcl_Obj *objPtr; /* Object to test. May be NULL. */
+{
+ int length;
+
+ if (objPtr == NULL) {
+ return 1;
+ }
+ if (objPtr->bytes != NULL) {
+ return (objPtr->length == 0);
+ }
+ Tcl_GetStringFromObj(objPtr, &length);
+ return (length == 0);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ComputeInternalPointer --
+ *
+ * Given a pointer to the start of a record and the offset of a slot
+ * within that record, compute the address of that slot.
+ *
+ * Results:
+ * If offset is non-negative, returns the computed address; else,
+ * returns NULL.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+ComputeSlotAddress(recordPtr, offset)
+ char *recordPtr; /* Pointer to the start of a record. */
+ int offset; /* Offset of a slot within that record; may be < 0. */
+{
+ if (offset >= 0) {
+ return recordPtr + offset;
+ } else {
+ return NULL;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PanedWindowIdentifyCoords --
+ *
+ * Given a pair of x,y coordinates, identify the panedwindow component
+ * at that point, if any.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * Modifies the interpreter's result to contain either an empty list,
+ * or a two element list of the form {sash n} or {handle n} to indicate
+ * that the point lies within the n'th sash or handle.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+PanedWindowIdentifyCoords(pwPtr, interp, x, y)
+ PanedWindow *pwPtr; /* Information about the widget. */
+ Tcl_Interp *interp; /* Interpreter in which to store result. */
+ int x, y; /* Coordinates of the point to identify. */
+{
+ Tcl_Obj *list;
+ int i, sashHeight, sashWidth, thisx, thisy;
+ int found, isHandle, lpad, rpad, tpad, bpad;
+ list = Tcl_NewObj();
+
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ if (Tk_IsMapped(pwPtr->tkwin)) {
+ sashHeight = Tk_Height(pwPtr->tkwin);
+ } else {
+ sashHeight = Tk_ReqHeight(pwPtr->tkwin);
+ }
+ sashHeight -= 2 * Tk_InternalBorderWidth(pwPtr->tkwin);
+ if (pwPtr->showHandle && pwPtr->handleSize > pwPtr->sashWidth) {
+ sashWidth = pwPtr->handleSize;
+ lpad = (pwPtr->handleSize - pwPtr->sashWidth) / 2;
+ rpad = pwPtr->handleSize - lpad;
+ lpad += pwPtr->sashPad;
+ rpad += pwPtr->sashPad;
+ } else {
+ sashWidth = pwPtr->sashWidth;
+ lpad = rpad = pwPtr->sashPad;
+ }
+ tpad = bpad = 0;
+ } else {
+ if (pwPtr->showHandle && pwPtr->handleSize > pwPtr->sashWidth) {
+ sashHeight = pwPtr->handleSize;
+ tpad = (pwPtr->handleSize - pwPtr->sashWidth) / 2;
+ bpad = pwPtr->handleSize - tpad;
+ tpad += pwPtr->sashPad;
+ bpad += pwPtr->sashPad;
+ } else {
+ sashHeight = pwPtr->sashWidth;
+ tpad = bpad = pwPtr->sashPad;
+ }
+ if (Tk_IsMapped(pwPtr->tkwin)) {
+ sashWidth = Tk_Width(pwPtr->tkwin);
+ } else {
+ sashWidth = Tk_ReqWidth(pwPtr->tkwin);
+ }
+ sashWidth -= 2 * Tk_InternalBorderWidth(pwPtr->tkwin);
+ lpad = rpad = 0;
+ }
+
+ isHandle = 0;
+ found = -1;
+ for (i = 0; i < pwPtr->numSlaves - 1; i++) {
+ thisx = pwPtr->slaves[i]->sashx;
+ thisy = pwPtr->slaves[i]->sashy;
+
+ if (((thisx - lpad) <= x && x <= (thisx + rpad + sashWidth)) &&
+ ((thisy - tpad) <= y && y <= (thisy + bpad + sashHeight))) {
+ found = i;
+
+ /*
+ * Determine if the point is over the handle or the sash.
+ */
+ if (pwPtr->showHandle) {
+ thisx = pwPtr->slaves[i]->handlex;
+ thisy = pwPtr->slaves[i]->handley;
+ if (pwPtr->orient == ORIENT_HORIZONTAL) {
+ if (thisy <= y && y <= (thisy + pwPtr->handleSize)) {
+ isHandle = 1;
+ }
+ } else {
+ if (thisx <= x && x <= (thisx + pwPtr->handleSize)) {
+ isHandle = 1;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ /*
+ * Set results.
+ */
+ if (found != -1) {
+ Tcl_ListObjAppendElement(interp, list, Tcl_NewIntObj(found));
+ if (isHandle) {
+ Tcl_ListObjAppendElement(interp, list,
+ Tcl_NewStringObj("handle", -1));
+ } else {
+ Tcl_ListObjAppendElement(interp, list,
+ Tcl_NewStringObj("sash", -1));
+ }
+ }
+
+ Tcl_SetObjResult(interp, list);
+ return TCL_OK;
+}
diff --git a/generic/tkWindow.c b/generic/tkWindow.c
index c77e482..0c82898 100644
--- a/generic/tkWindow.c
+++ b/generic/tkWindow.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWindow.c,v 1.41 2002/01/25 21:09:37 dgp Exp $
+ * RCS: @(#) $Id: tkWindow.c,v 1.42 2002/02/22 02:41:17 hobbs Exp $
*/
#include "tkPort.h"
@@ -143,6 +143,7 @@ static TkCmd commands[] = {
{"listbox", NULL, Tk_ListboxObjCmd, 1, 0},
{"menubutton", NULL, Tk_MenubuttonObjCmd, 1, 0},
{"message", NULL, Tk_MessageObjCmd, 1, 0},
+ {"panedwindow", NULL, Tk_PanedWindowObjCmd, 1, 0},
{"radiobutton", NULL, Tk_RadiobuttonObjCmd, 1, 0},
{"scale", NULL, Tk_ScaleObjCmd, 1, 0},
{"scrollbar", Tk_ScrollbarCmd, NULL, 1, 1},
diff --git a/library/panedwindow.tcl b/library/panedwindow.tcl
new file mode 100644
index 0000000..a232f89
--- /dev/null
+++ b/library/panedwindow.tcl
@@ -0,0 +1,136 @@
+# panedwindow.tcl --
+#
+# This file defines the default bindings for Tk panedwindow widgets and
+# provides procedures that help in implementing those bindings.
+#
+# RCS: @(#) $Id: panedwindow.tcl,v 1.1 2002/02/22 02:41:17 hobbs Exp $
+#
+
+bind PanedWindow <Button-1> { ::tk::panedwindow::MarkSash %W %x %y 1 }
+bind PanedWindow <Button-2> { ::tk::panedwindow::MarkSash %W %x %y 0 }
+
+bind PanedWindow <B1-Motion> { ::tk::panedwindow::DragSash %W %x %y 1 }
+bind PanedWindow <B2-Motion> { ::tk::panedwindow::DragSash %W %x %y 0 }
+
+bind PanedWindow <ButtonRelease-1> {::tk::panedwindow::ReleaseSash %W %x %y 1}
+bind PanedWindow <ButtonRelease-2> {::tk::panedwindow::ReleaseSash %W %x %y 0}
+
+bind PanedWindow <Motion> { ::tk::panedwindow::Motion %W %x %y }
+
+bind PanedWindow <Leave> { ::tk::panedwindow::Leave %W }
+
+# Initialize namespace
+namespace eval ::tk::panedwindow {}
+
+# ::tk::panedwindow::MarkSash --
+#
+# ADD COMMENTS HERE
+#
+# Arguments:
+# args comments
+# Results:
+# Returns ...
+#
+proc ::tk::panedwindow::MarkSash {w x y proxy} {
+ set what [$w identify $x $y]
+ if { [llength $what] == 2 } {
+ foreach {index which} $what break
+ if { !$::tk_strictMotif || [string equal $which "handle"] } {
+ if {!$proxy} { $w sash mark $index $x $y }
+ set ::tk::Priv(sash) $index
+ }
+ }
+}
+
+# ::tk::panedwindow::DragSash --
+#
+# ADD COMMENTS HERE
+#
+# Arguments:
+# args comments
+# Results:
+# Returns ...
+#
+proc ::tk::panedwindow::DragSash {w x y proxy} {
+ if { [info exists ::tk::Priv(sash)] } {
+ if {$proxy} {
+ $w proxy place $x $y
+ } else {
+ $w sash dragto $::tk::Priv(sash) $x $y
+ $w sash mark $::tk::Priv(sash) $x $y
+ }
+ }
+}
+
+# ::tk::panedwindow::ReleaseSash --
+#
+# ADD COMMENTS HERE
+#
+# Arguments:
+# args comments
+# Results:
+# Returns ...
+#
+proc ::tk::panedwindow::ReleaseSash {w proxy} {
+ if { [info exists ::tk::Priv(sash)] } {
+ if {$proxy} {
+ foreach {x y} [$w proxy coord] break
+ $w sash place $::tk::Priv(sash) $x $y
+ unset ::tk::Priv(sash)
+ $w proxy forget
+ } else {
+ unset ::tk::Priv(sash)
+ }
+ }
+}
+
+# ::tk::panedwindow::Motion --
+#
+# ADD COMMENTS HERE
+#
+# Arguments:
+# args comments
+# Results:
+# Returns ...
+#
+proc ::tk::panedwindow::Motion {w x y} {
+ variable ::tk::Priv
+ set id [$w identify $x $y]
+ if { [llength $id] == 2 } {
+ if { !$::tk_strictMotif || [string equal [lindex $id 1] "handle"] } {
+ if { ![info exists Priv(panecursor)] } {
+ set Priv(panecursor) [$w cget -cursor]
+ }
+ if { [string equal [$w cget -sashcursor] ""] } {
+ if { [string equal [$w cget -orient] "horizontal"] } {
+ $w configure -cursor sb_h_double_arrow
+ } else {
+ $w configure -cursor sb_v_double_arrow
+ }
+ } else {
+ $w configure -cursor [$w cget -sashcursor]
+ }
+ return
+ }
+ }
+ if { [info exists Priv(panecursor)] } {
+ $w configure -cursor $Priv(panecursor)
+ unset Priv(panecursor)
+ }
+}
+
+# ::tk::panedwindow::Leave --
+#
+# ADD COMMENTS HERE
+#
+# Arguments:
+# args comments
+# Results:
+# Returns ...
+#
+proc ::tk::panedwindow::Leave {w} {
+ if { [info exists ::tk::Priv(panecursor)] } {
+ $w configure -cursor $::tk::Priv(panecursor)
+ unset ::tk::Priv(panecursor)
+ }
+}
diff --git a/mac/tkMacDefault.h b/mac/tkMacDefault.h
index 0c78e71..8e43b37 100644
--- a/mac/tkMacDefault.h
+++ b/mac/tkMacDefault.h
@@ -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: tkMacDefault.h,v 1.12 2001/11/13 00:19:05 hobbs Exp $
+ * RCS: @(#) $Id: tkMacDefault.h,v 1.13 2002/02/22 02:41:17 hobbs Exp $
*/
#ifndef _TKMACDEFAULT
@@ -360,6 +360,40 @@
#define DEF_MESSAGE_WIDTH "0"
/*
+ * Defaults for panedwindows
+ */
+
+#define DEF_PANEDWINDOW_BG_COLOR NORMAL_BG
+#define DEF_PANEDWINDOW_BG_MONO WHITE
+#define DEF_PANEDWINDOW_BORDERWIDTH "2"
+#define DEF_PANEDWINDOW_CURSOR ""
+#define DEF_PANEDWINDOW_HANDLEPAD "8"
+#define DEF_PANEDWINDOW_HANDLESIZE "8"
+#define DEF_PANEDWINDOW_HEIGHT ""
+#define DEF_PANEDWINDOW_OPAQUERESIZE "0"
+#define DEF_PANEDWINDOW_ORIENT "horizontal"
+#define DEF_PANEDWINDOW_RELIEF "raised"
+#define DEF_PANEDWINDOW_SASHCURSOR ""
+#define DEF_PANEDWINDOW_SASHPAD "2"
+#define DEF_PANEDWINDOW_SASHRELIEF "raised"
+#define DEF_PANEDWINDOW_SASHWIDTH "2"
+#define DEF_PANEDWINDOW_SHOWHANDLE "0"
+#define DEF_PANEDWINDOW_WIDTH ""
+
+/*
+ * Defaults for panedwindow panes
+ */
+
+#define DEF_PANEDWINDOW_PANE_AFTER ""
+#define DEF_PANEDWINDOW_PANE_BEFORE ""
+#define DEF_PANEDWINDOW_PANE_HEIGHT ""
+#define DEF_PANEDWINDOW_PANE_MINSIZE "0"
+#define DEF_PANEDWINDOW_PANE_PADX "0"
+#define DEF_PANEDWINDOW_PANE_PADY "0"
+#define DEF_PANEDWINDOW_PANE_STICKY "nsew"
+#define DEF_PANEDWINDOW_PANE_WIDTH ""
+
+/*
* Defaults for scales:
*/
diff --git a/tests/panedwindow.test b/tests/panedwindow.test
new file mode 100644
index 0000000..0177231
--- /dev/null
+++ b/tests/panedwindow.test
@@ -0,0 +1,2380 @@
+# This file is a Tcl script to test entry widgets in Tk. It is
+# organized in the standard fashion for Tcl tests.
+#
+# Copyright (c) 1994 The Regents of the University of California.
+# Copyright (c) 1994-1997 Sun Microsystems, Inc.
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# All rights reserved.
+#
+# RCS: @(#) $Id: panedwindow.test,v 1.1 2002/02/22 02:41:17 hobbs Exp $
+
+if {[info tclversion] < 8.4} {
+ puts "panedwindow requires Tk 8.4"
+ exit
+}
+
+if {[lsearch [namespace children] ::tcltest] == -1} {
+ source [file join [pwd] [file dirname [info script]] defs.tcl]
+}
+
+foreach i [winfo children .] {
+ destroy $i
+}
+
+wm geometry . {}
+raise .
+
+set i 1
+panedwindow .p
+foreach test {
+ {-background "#ff0000" "#ff0000" non-existent
+ {unknown color name "non-existent"}}
+ {-bd 4 4 badValue {bad screen distance "badValue"}}
+ {-bg "#ff0000" "#ff0000" non-existent {unknown color name "non-existent"}}
+ {-borderwidth 1.3 1 badValue {bad screen distance "badValue"}}
+ {-cursor arrow arrow badValue {bad cursor spec "badValue"}}
+ {-handlesize 20 20 badValue {bad screen distance "badValue"}}
+ {-height 20 20 badValue {bad screen distance "badValue"}}
+ {-opaqueresize true 1 foo {expected boolean value but got "foo"}}
+ {-orient horizontal horizontal badValue
+ {bad orient "badValue": must be horizontal or vertical}}
+ {-relief groove groove 1.5 {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}}
+ {-sashcursor arrow arrow badValue {bad cursor spec "badValue"}}
+ {-sashpad 1.3 1 badValue {bad screen distance "badValue"}}
+ {-sashrelief groove groove 1.5 {bad relief "1.5": must be flat, groove, raised, ridge, solid, or sunken}}
+ {-sashwidth 10 10 badValue {bad screen distance "badValue"}}
+ {-showhandle true 1 foo {expected boolean value but got "foo"}}
+ {-width 402 402 badValue {bad screen distance "badValue"}}
+} {
+ set name [lindex $test 0]
+ test panedwindow-1.$i {configuration options} {
+ .p configure $name [lindex $test 1]
+ list [lindex [.p configure $name] 4] [.p cget $name]
+ } [list [lindex $test 2] [lindex $test 2]]
+ incr i
+ if {[lindex $test 3] != ""} {
+ test entry-1.$i {configuration options} {
+ list [catch {.p configure $name [lindex $test 3]} msg] $msg
+ } [list 1 [lindex $test 4]]
+ }
+ .p configure $name [lindex [.p configure $name] 3]
+ incr i
+}
+.p add [button .b]
+.p add [button .c]
+foreach test {
+ {-after .c .c badValue {bad window path name "badValue"}}
+ {-before .c .c badValue {bad window path name "badValue"}}
+ {-height 10 10 badValue {bad screen distance "badValue"}}
+ {-minsize 10 10 badValue {bad screen distance "badValue"}}
+ {-padx 1.3 1 badValue {bad screen distance "badValue"}}
+ {-pady 1.3 1 badValue {bad screen distance "badValue"}}
+ {-sticky nsew nesw abcd {bad stickyness value "abcd": must be a string containing zero or more of n, e, s, and w}}
+ {-width 10 10 badValue {bad screen distance "badValue"}}
+} {
+ set name [lindex $test 0]
+ test panedwindow-1.$i {configuration options} {
+ .p paneconfigure .b $name [lindex $test 1]
+ list [lindex [.p paneconfigure .b $name] 4] [.p panecget .b $name]
+ } [list [lindex $test 2] [lindex $test 2]]
+ incr i
+ if {[lindex $test 3] != ""} {
+ test entry-1.$i {configuration options} {
+ list [catch {.p paneconfigure .b $name [lindex $test 3]} msg] $msg
+ } [list 1 [lindex $test 4]]
+ }
+ .p paneconfigure .b $name [lindex [.p paneconfigure .b $name] 3]
+ incr i
+}
+destroy .p .b .c
+
+test panedwindow-2.1 {panedwindow widget command} {
+ panedwindow .p
+ set result [list [catch {.p foo} msg] $msg]
+ destroy .p
+ set result
+} {1 {bad command "foo": must be add, cget, configure, forget, identify, panecget, paneconfigure, panes, proxy, or sash}}
+
+test panedwindow-3.1 {panedwindow panes subcommand} {
+ panedwindow .p
+ .p add [button .b]
+ .p add [button .c]
+ set result [list [.p panes]]
+ .p forget .b
+ lappend result [.p panes]
+ destroy .p .b .c
+ set result
+} [list [list .b .c] [list .c]]
+
+test panedwindow-4.1 {forget subcommand} {
+ panedwindow .p
+ set result [list [catch {.p forget} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "wrong # args: should be \".p forget widget ?widget ...?\""]
+test panedwindow-4.2 {forget subcommand, forget one from start} {
+ panedwindow .p
+ .p add [button .b]
+ .p add [button .c]
+ set result [list [.p panes]]
+ .p forget .b
+ lappend result [.p panes]
+ destroy .p .b .c
+ set result
+} [list {.b .c} .c]
+test panedwindow-4.3 {forget subcommand, forget one from end} {
+ panedwindow .p
+ .p add [button .b]
+ .p add [button .c]
+ .p add [button .d]
+ set result [list [.p panes]]
+ .p forget .d
+ update
+ lappend result [.p panes]
+ destroy .p .b .c .d
+ set result
+} [list {.b .c .d} {.b .c}]
+test panedwindow-4.4 {forget subcommand, forget multiple} {
+ panedwindow .p
+ .p add [button .b]
+ .p add [button .c]
+ .p add [button .d]
+ set result [list [.p panes]]
+ .p forget .b .c
+ update
+ lappend result [.p panes]
+ destroy .p .b .c .d
+ set result
+} [list {.b .c .d} .d]
+test panedwindow-4.5 {forget subcommand, panes are unmapped} {
+ panedwindow .p
+ .p add [button .b]
+ .p add [button .c]
+ pack .p
+ update
+
+ set result [list [winfo ismapped .b] [winfo ismapped .c]]
+ .p forget .b
+ update
+
+ lappend result [winfo ismapped .b] [winfo ismapped .c]
+ destroy .p .b .c
+
+ set result
+} [list 1 1 0 1]
+test panedwindow-4.6 {forget subcommand, changes reqsize of panedwindow} {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false
+ .p add [frame .f -width 20 -height 20] [frame .g -width 20 -height 20]
+ set result [list [winfo reqwidth .p]]
+ .p forget .f
+ lappend result [winfo reqwidth .p]
+ destroy .p .f .g
+ set result
+} [list 44 20]
+
+test panedwindow-5.1 {sash subcommand} {
+ panedwindow .p
+ set result [list [catch {.p sash} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "wrong # args: should be \".p sash option ?arg ...?\""]
+test panedwindow-5.2 {sash subcommand} {
+ panedwindow .p
+ set result [list [catch {.p sash foo} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "bad option \"foo\": must be coord, dragto, mark, or place"]
+
+test panedwindow-6.1 {sash coord subcommand, errors} {
+ panedwindow .p
+ set result [list [catch {.p sash coord} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "wrong # args: should be \".p sash coord index\""]
+test panedwindow-6.2 {sash coord subcommand, errors} {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4
+ set result [list [catch {.p sash coord 0} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "invalid sash index"]
+test panedwindow-6.3 {sash coord subcommand, errors} {
+ panedwindow .p
+ set result [list [catch {.p sash coord foo} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "expected integer but got \"foo\""]
+test panedwindow-6.4 {sash coord subcommand sashes correctly placed} {
+ panedwindow .p -borderwidth 0 -sashpad 2 -sashwidth 4 -showhandle false
+ .p add [frame .p.f -width 20 -height 20] \
+ [frame .p.f2 -width 20 -height 20] \
+ [frame .p.f3 -width 20 -height 20]
+ set result [.p sash coord 0]
+ destroy .p .p.f .p.f2 .p.f3
+ set result
+} [list 22 0]
+test panedwindow-6.5 {sash coord subcommand sashes correctly placed} {
+ panedwindow .p -borderwidth 0 -sashpad 2 -sashwidth 4 -showhandle false
+ .p add [frame .p.f -width 20 -height 20] \
+ [frame .p.f2 -width 20 -height 20] \
+ [frame .p.f3 -width 20 -height 20]
+ set result [.p sash coord 1]
+ destroy .p .p.f .p.f2 .p.f3
+ set result
+} [list 50 0]
+test panedwindow-6.6 {sash coord subcommand, sashes correctly placed} {
+ panedwindow .p -borderwidth 0 -sashpad 2 -sashwidth 4 -orient vertical \
+ -showhandle false
+ .p add [frame .p.f -width 20 -height 20] \
+ [frame .p.f2 -width 20 -height 20] \
+ [frame .p.f3 -width 20 -height 20]
+ set result [.p sash coord 0]
+ destroy .p .p.f .p.f2 .p.f3
+ set result
+} [list 0 22]
+test panedwindow-6.7 {sash coord subcommand, sashes correctly placed} {
+ panedwindow .p -borderwidth 0 -sashpad 2 -sashwidth 4 -orient vertical \
+ -showhandle false
+ .p add [frame .p.f -width 20 -height 20] \
+ [frame .p.f2 -width 20 -height 20] \
+ [frame .p.f3 -width 20 -height 20]
+ set result [.p sash coord 1]
+ destroy .p .p.f .p.f2 .p.f3
+ set result
+} [list 0 50]
+
+test panedwindow-8.1 {sash mark subcommand, errors} {
+ panedwindow .p
+ set result [list [catch {.p sash mark} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "wrong # args: should be \".p sash mark index ?x y?\""]
+test panedwindow-8.2 {sash mark subcommand, errors} {
+ panedwindow .p
+ set result [list [catch {.p sash mark foo} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "expected integer but got \"foo\""]
+test panedwindow-8.3 {sash mark subcommand, errors} {
+ panedwindow .p
+ set result [list [catch {.p sash mark 0 foo bar} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "invalid sash index"]
+test panedwindow-8.4 {sash mark subcommand, errors} {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ set result [list [catch {.p sash mark 0 foo bar} msg] $msg]
+ destroy .p .b .c
+ set result
+} [list 1 "expected integer but got \"foo\""]
+test panedwindow-8.5 {sash mark subcommand, errors} {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ set result [list [catch {.p sash mark 0 0 bar} msg] $msg]
+ destroy .p .b .c
+ set result
+} [list 1 "expected integer but got \"bar\""]
+test panedwindow-8.6 {sash mark subcommand, mark defaults to 0 0} {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ set result [.p sash mark 0]
+ destroy .p .b .c
+ set result
+} [list 0 0]
+test panedwindow-8.7 {sash mark subcommand, set mark} {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ .p sash mark 0 10 10
+ set result [.p sash mark 0]
+ destroy .p .b .c
+ set result
+} [list 10 10]
+
+test panedwindow-9.1 {sash dragto subcommand, errors} {
+ panedwindow .p
+ set result [list [catch {.p sash dragto} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "wrong # args: should be \".p sash dragto index x y\""]
+test panedwindow-9.2 {sash dragto subcommand, errors} {
+ panedwindow .p
+ set result [list [catch {.p sash dragto foo bar baz} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "expected integer but got \"foo\""]
+test panedwindow-9.3 {sash dragto subcommand, errors} {
+ panedwindow .p
+ set result [list [catch {.p sash dragto 0 foo bar} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "invalid sash index"]
+test panedwindow-9.4 {sash dragto subcommand, errors} {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ set result [list [catch {.p sash dragto 0 foo bar} msg] $msg]
+ destroy .p .b .c
+ set result
+} [list 1 "expected integer but got \"foo\""]
+test panedwindow-9.5 {sash dragto subcommand, errors} {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ set result [list [catch {.p sash dragto 0 0 bar} msg] $msg]
+ destroy .p .b .c
+ set result
+} [list 1 "expected integer but got \"bar\""]
+
+test panedwindow-10.1 {sash mark/sash dragto interaction} {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false
+ .p add [frame .f -width 20 -height 20] [button .c]
+ .p sash mark 0 10 10
+ .p sash dragto 0 20 10
+ set result [.p sash coord 0]
+ destroy .p .f .c
+ set result
+} [list 30 0]
+test panedwindow-10.2 {sash mark/sash dragto interaction} {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -orient vertical \
+ -showhandle false
+ .p add [frame .p.f -width 20 -height 20] [button .p.c]
+ .p sash mark 0 10 10
+ .p sash dragto 0 10 20
+ set result [.p sash coord 0]
+ destroy .p .p.f .p.c
+ set result
+} [list 0 30]
+test panedwindow-10.3 {sash mark/sash dragto, respects minsize} {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false
+ .p add [frame .f -width 20 -height 20] [button .c] -minsize 15
+ .p sash mark 0 20 10
+ .p sash dragto 0 10 10
+ set result [.p sash coord 0]
+ destroy .p .f .c
+ set result
+} [list 15 0]
+
+test panedwindow-11.1 {sash place subcommand, errors} {
+ panedwindow .p
+ set result [list [catch {.p sash place} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "wrong # args: should be \".p sash place index x y\""]
+test panedwindow-11.2 {sash place subcommand, errors} {
+ panedwindow .p
+ set result [list [catch {.p sash place foo bar baz} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "expected integer but got \"foo\""]
+test panedwindow-11.3 {sash place subcommand, errors} {
+ panedwindow .p
+ set result [list [catch {.p sash place 0 foo bar} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "invalid sash index"]
+test panedwindow-11.4 {sash place subcommand, errors} {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ set result [list [catch {.p sash place 0 foo bar} msg] $msg]
+ destroy .p .b .c
+ set result
+} [list 1 "expected integer but got \"foo\""]
+test panedwindow-11.5 {sash place subcommand, errors} {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ set result [list [catch {.p sash place 0 0 bar} msg] $msg]
+ destroy .p .b .c
+ set result
+} [list 1 "expected integer but got \"bar\""]
+test panedwindow-11.6 {sash place subcommand, moves sash} {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 20] [button .c]
+ .p sash place 0 10 0
+ set result [.p sash coord 0]
+ destroy .p .f .c
+ set result
+} [list 10 0]
+test panedwindow-11.7 {sash place subcommand, moves sash} {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -orient vertical
+ .p add [frame .f -width 20 -height 20] [button .c]
+ .p sash place 0 0 10
+ set result [.p sash coord 0]
+ destroy .p .f .c
+ set result
+} [list 0 10]
+test panedwindow-11.8 {sash place subcommand, respects minsize} {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false
+ .p add [frame .f -width 20 -height 20] [button .c] -minsize 15
+ .p sash place 0 10 0
+ set result [.p sash coord 0]
+ destroy .p .f .c
+ set result
+} [list 15 0]
+
+test panedwindow-12.1 {moving sash changes size of pane to left} {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 4 -showhandle false
+ .p add [frame .f -width 20 -height 20] [button .c] -sticky nsew
+ .p sash place 0 30 0
+ pack .p
+ update
+ set result [winfo width .f]
+ destroy .p .f .c
+ set result
+} 30
+test panedwindow-12.2 {moving sash changes size of pane to right} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 20] [frame .f2 -width 20 -height 20]
+ pack .p
+ update
+ set result [winfo width .f2]
+ .p sash place 0 30 0
+ update
+ lappend result [winfo width .f2]
+ destroy .p .f .f2
+ set result
+} {20 10}
+test panedwindow-12.3 {moving sash does not change reqsize of panedwindow} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 20] [frame .f2 -width 20 -height 20]
+ .p sash place 0 30 0
+ set result [winfo reqwidth .p]
+ destroy .p .f .f2
+ set result
+} 44
+test panedwindow-12.4 {moving sash changes size of pane above} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ .p add [frame .f -width 20 -height 10] [button .c] -sticky nsew
+ .p sash place 0 0 20
+ pack .p
+ update
+ set result [winfo height .f]
+ destroy .p .f .c
+ set result
+} 20
+test panedwindow-12.5 {moving sash changes size of pane below} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ .p add [frame .f -width 20 -height 10] [frame .f2 -width 20 -height 10]
+ pack .p
+ update
+ set result [winfo height .f2]
+ .p sash place 0 0 15
+ update
+ lappend result [winfo height .f2]
+ destroy .p .f .f2
+ set result
+} {10 5}
+test panedwindow-12.6 {moving sash does not change reqsize of panedwindow} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ .p add [frame .f -width 20 -height 10] [frame .f2 -width 20 -height 10]
+ set result [winfo reqheight .p]
+ .p sash place 0 0 20
+ lappend result [winfo reqheight .p]
+ destroy .p .f .f2
+ set result
+} [list 24 24]
+test panedwindow-12.7 {moving sash does not alter reqsize of widget} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ .p add [frame .f -width 20 -height 10] [frame .f2 -width 20 -height 10]
+ set result [winfo reqheight .f]
+ .p sash place 0 0 20
+ lappend result [winfo reqheight .f]
+ destroy .p .f .f2
+ set result
+} [list 10 10]
+test panedwindow-12.8 {moving sash restricted to minsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 20] [button .c] -minsize 15
+ .p sash place 0 10 0
+ pack .p
+ update
+ set result [winfo width .f]
+ destroy .p .f .c
+ set result
+} 15
+test panedwindow-12.10 {moving sash restricted to minsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ .p add [frame .f -width 20 -height 30] [button .c] -minsize 10
+ .p sash place 0 0 5
+ pack .p
+ update
+ set result [winfo height .f]
+ destroy .p .f .c
+ set result
+} 10
+test panedwindow-12.12 {moving sash in unmapped window restricted to reqsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20]
+ set result [list [.p sash coord 0]]
+ .p sash place 0 100 0
+ lappend result [.p sash coord 0]
+ destroy .p .f .f2
+ set result
+} [list {20 0} {40 0}]
+test panedwindow-12.13 {moving sash right pushes other sashes} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20] \
+ [frame .f3 -width 20 -height 30]
+ .p sash place 0 80 0
+ set result [list [.p sash coord 0] [.p sash coord 1]]
+ destroy .p .f .f2 .f3
+ set result
+} {{60 0} {64 0}}
+test panedwindow-12.14 {moving sash left pushes other sashes} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20] \
+ [frame .f3 -width 20 -height 30]
+ .p sash place 1 0 0
+ set result [list [.p sash coord 0] [.p sash coord 1]]
+ destroy .p .f .f2 .f3
+ set result
+} {{0 0} {4 0}}
+test panedwindow-12.15 {move sash in mapped window restricted to visible win} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20] \
+ [frame .f3 -width 20 -height 30]
+ place .p -width 50
+ update
+ .p sash place 1 100 0
+ update
+ set result [.p sash coord 1]
+ destroy .p .f .f2 .f3
+ set result
+} {46 0}
+test panedwindow-12.16 {move sash in mapped window restricted to visible win} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20] \
+ [frame .f3 -width 20 -height 30]
+ place .p -width 100
+ update
+ .p sash place 1 200 0
+ update
+ set result [.p sash coord 1]
+ destroy .p .f .f2 .f3
+ set result
+} {96 0}
+test panedwindow-12.17 {moving sash into "virtual" space on \
+ last pane increases reqsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .f -width 20 -height 30] [frame .f2 -width 20 -height 20] \
+ [frame .f3 -width 20 -height 30]
+ place .p -width 100
+ set result [winfo reqwidth .p]
+ update
+ .p sash place 1 200 0
+ update
+ lappend result [winfo reqwidth .p]
+ destroy .p .f .f2 .f3
+ set result
+} {68 100}
+
+test panedwindow-13.1 {horizontal panedwindow lays out widgets properly} {
+ panedwindow .p -showhandle false -borderwidth 2 -sashpad 2 -sashwidth 2
+ foreach win {.p.f .p.f2 .p.f3} {.p add [frame $win -width 20 -height 10]}
+ pack .p
+ update
+ set result {}
+ foreach w [.p panes] {lappend result [winfo x $w] [winfo y $w]}
+ destroy .p .p.f .p.f2 .p.f3
+ set result
+} [list 2 2 28 2 54 2]
+test panedwindow-13.2 {vertical panedwindow lays out widgets properly} {
+ panedwindow .p -showhandle false -borderwidth 2 -sashpad 2 -sashwidth 2 \
+ -orient vertical
+ foreach win {.p.f .p.f2 .p.f3} {.p add [frame $win -width 20 -height 10]}
+ pack .p
+ update
+ set result {}
+ foreach w [.p panes] {lappend result [winfo x $w] [winfo y $w]}
+ destroy .p .p.f .p.f2 .p.f3
+ set result
+} [list 2 2 2 18 2 34]
+test panedwindow-13.3 {horizontal panedwindow lays out widgets properly} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ foreach {win color} {.p.f blue .p.f2 green} {
+ .p add [frame $win -width 20 -height 20 -bg $color] -padx 10 -pady 5 \
+ -sticky ""
+ }
+ pack .p
+ update
+ set result [list [winfo reqwidth .p] [winfo reqheight .p]]
+ foreach win {.p.f .p.f2} {lappend result [winfo x $win] [winfo y $win]}
+ .p paneconfigure .p.f -padx 0 -pady 0
+ update
+ lappend result [winfo reqwidth .p] [winfo reqheight .p]
+ foreach win {.p.f .p.f2} {lappend result [winfo x $win] [winfo y $win]}
+ destroy .p .p.f .p.f2
+ set result
+} [list 80 30 10 5 50 5 60 30 0 5 30 5]
+test panedwindow-13.4 {vertical panedwindow lays out widgets properly} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0 \
+ -orient vertical
+ foreach win {.p.f .p.f2} {
+ .p add [frame $win -width 20 -height 20] -padx 10 -pady 5 -sticky ""
+ }
+ pack .p
+ update
+ set result [list [winfo reqwidth .p] [winfo reqheight .p]]
+ foreach win {.p.f .p.f2} {lappend result [winfo x $win] [winfo y $win]}
+ .p paneconfigure .p.f -padx 0 -pady 0
+ update
+ lappend result [winfo reqwidth .p] [winfo reqheight .p]
+ foreach win {.p.f .p.f2} {lappend result [winfo x $win] [winfo y $win]}
+ destroy .p .p.f .p.f2
+ set result
+} [list 40 60 10 5 10 35 40 50 10 0 10 25]
+test panedwindow-13.5 {panedwindow respects reqsize of panes when possible} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -width 20 -height 20] -sticky ""
+ place .p -width 40
+ update
+ set result [list [winfo width .p.f]]
+ .p.f configure -width 30
+ update
+ lappend result [winfo width .p.f]
+ destroy .p .p.f
+ set result
+} [list 20 30]
+test panedwindow-13.6 {panedwindow takes explicit widget width over reqwidth} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -width 20 -height 20] -width 20 -sticky ""
+ place .p -width 40
+ update
+ set result [list [winfo width .p.f]]
+ .p.f configure -width 30
+ update
+ lappend result [winfo width .p.f]
+ destroy .p .p.f
+ set result
+} [list 20 20]
+test panedwindow-13.7 {horizontal panedwindow reqheight is max slave height} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ .p add [frame .p.f -width 20 -height 20] [frame .p.f2 -width 20 -height 20]
+ set result [winfo reqheight .p]
+ .p.f config -height 40
+ lappend result [winfo reqheight .p]
+ destroy .p .p.f .p.f2
+ set result
+} {20 40}
+test panedwindow-13.8 {horizontal panedwindow reqheight is max slave height} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ foreach win {.p.f .p.f2} {.p add [frame $win -width 20 -height 20]}
+ .p paneconfigure .p.f -height 15
+ set result [winfo reqheight .p]
+ .p.f config -height 40
+ lappend result [winfo reqheight .p]
+ destroy .p .p.f .p.f2
+ set result
+} {20 20}
+test panedwindow-13.9 {panedwindow pane width overrides widget width} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4
+ foreach win {.p.f .p.f2} {.p add [frame $win -width 20 -height 20]}
+ .p sash place 0 10 0
+ pack .p
+ update
+ set result [winfo width .p.f]
+ .p paneconfigure .p.f -width 30
+ lappend result [winfo width .p.f]
+ destroy .p .p.f .p.f2
+ set result
+} [list 10 10]
+test panedwindow-13.10 {panedwindow respects reqsize of panes when possible} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -width 20 -height 20] -sticky ""
+ place .p -height 40
+ update
+ set result [list [winfo height .p.f]]
+ .p.f configure -height 30
+ update
+ lappend result [winfo height .p.f]
+ destroy .p .p.f
+ set result
+} [list 20 30]
+test panedwindow-13.11 {panedwindow takes explicit height over reqheight} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -width 20 -height 20] -height 20 -sticky ""
+ place .p -height 40
+ update
+ set result [list [winfo height .p.f]]
+ .p.f configure -height 30
+ update
+ lappend result [winfo height .p.f]
+ destroy .p .p.f
+ set result
+} [list 20 20]
+test panedwindow-13.12 {vertical panedwindow reqwidth is max slave width} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ .p add [frame .p.f -width 20 -height 20] [frame .p.f2 -width 20 -height 20]
+ set result [winfo reqwidth .p]
+ .p.f config -width 40
+ lappend result [winfo reqwidth .p]
+ destroy .p .p.f .p.f2
+ set result
+} {20 40}
+test panedwindow-13.13 {vertical panedwindow reqwidth is max slave width} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ foreach win {.p.f .p.f2} {.p add [frame $win -width 20 -height 20]}
+ .p paneconfigure .p.f -width 15
+ set result [winfo reqwidth .p]
+ .p.f config -width 40
+ lappend result [winfo reqwidth .p]
+ destroy .p .p.f .p.f2
+ set result
+} {20 20}
+test panedwindow-13.14 {panedwindow pane height overrides widget width} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 4 \
+ -orient vertical
+ foreach win {.p.f .p.f2} {.p add [frame $win -width 20 -height 20]}
+ .p sash place 0 0 10
+ pack .p
+ update
+ set result [winfo height .p.f]
+ .p paneconfigure .p.f -height 30
+ lappend result [winfo height .p.f]
+ destroy .p .p.f .p.f2
+ set result
+} [list 10 10]
+
+
+test panedwindow-14.1 {PanestructureProc, widget yields managements} {
+ # Check that the panedwindow correctly yields geometry management of
+ # a slave when the slave is destroyed.
+
+ # This test should not cause a core dump, and it should not cause
+ # a memory leak.
+ panedwindow .p
+ .p add [button .b]
+ destroy .p
+ pack .b
+ destroy .b
+ set result ""
+} ""
+test panedwindow-14.2 {PanedWindowLostSlaveProc, widget yields management} {
+ # Check that the paned window correctly yields geometry management of
+ # a slave when some other geometry manager steals the slave from us.
+
+ # This test should not cause a core dump, and it should not cause a
+ # memory leak.
+ panedwindow .p
+ .p add [button .b]
+ pack .p
+ update
+ pack .b
+ update
+ set result [.p panes]
+ destroy .p .b
+ set result
+} {}
+
+set stickysets [list n s e w sn ns en ne wn nw esn nse nsw nsew ""]
+set stickygets [list n s e w ns ns ne ne nw nw nes nes nsw nesw ""]
+set i 0
+foreach s $stickysets g $stickygets {
+ test panedwindow-15.[incr i] {panedwindow sticky settings} {
+ panedwindow .p -showhandle false
+ .p add [button .b]
+ .p paneconfigure .b -sticky $s
+ set result [.p panecget .b -sticky]
+ destroy .p .b
+ set result
+ } $g
+}
+
+set i 0
+foreach s [list {} n s e w ns ew nw ne se sw nse nsw sew new news] \
+ x [list 10 10 10 20 0 10 0 0 20 20 0 20 0 0 0 0] \
+ y [list 10 0 20 10 10 0 10 0 0 20 20 0 0 20 0 0] \
+ w [list 20 20 20 20 20 20 40 20 20 20 20 20 20 40 40 40] \
+ h [list 20 20 20 20 20 40 20 20 20 20 20 40 40 20 20 40] {
+ test panedwindow-16.[incr i] {panedwindow sticky works} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ .p add [frame .p.f -height 20 -width 20 -bg red] -sticky $s
+ place .p -width 40 -height 40
+ update
+ set result [list $s [winfo x .p.f] [winfo y .p.f] \
+ [winfo width .p.f] [winfo height .p.f]]
+ destroy .p .p.f
+ set result
+ } [list $s $x $y $w $h]
+}
+
+test panedwindow-17.1 {setting minsize when pane is too small snaps width} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .p.f -height 20 -width 20 -bg red]
+ set result [winfo reqwidth .p]
+ .p paneconfigure .p.f -minsize 40
+ lappend result [winfo reqwidth .p]
+ destroy .p .p.f .p.f2
+ set result
+} [list 20 40]
+
+test panedwindow-18.1 {MoveSash, move right} {
+ set result {}
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Get the requested width of the paned window
+ lappend result [winfo reqwidth .p]
+
+ .p sash place 0 30 0
+
+ # Get the reqwidth again, to make sure it hasn't changed
+ lappend result [winfo reqwidth .p]
+
+ # Check that the sash moved
+ lappend result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 42 42 {30 0}]
+test panedwindow-18.2 {MoveSash, move right (unmapped) clipped by reqwidth} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 0 100 0
+
+ # Get the new sash coord; it should be clipped by the reqwidth of
+ # the panedwindow.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 40 0]
+test panedwindow-18.3 {MoveSash, move right (mapped, width < reqwidth) clipped by width} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Put the panedwindow up on the display and give it a width < reqwidth
+ place .p -x 0 -y 0 -width 32
+ update
+
+ .p sash place 0 100 0
+
+ # Get the new sash coord; it should be clipped by the visible width of
+ # the panedwindow.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 30 0]
+test panedwindow-18.4 {MoveSash, move right (mapped, width > reqwidth) clipped by width} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Put the panedwindow up on the display and give it a width > reqwidth
+ place .p -x 0 -y 0 -width 102
+ update
+
+ .p sash place 0 200 0
+
+ # Get the new sash coord; it should be clipped by the visible width of
+ # the panedwindow.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 100 0]
+test panedwindow-18.5 {MoveSash, move right respects minsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 100 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 30 0]
+test panedwindow-18.6 {MoveSash, move right respects minsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 100 0
+
+ # Get the new sash coord; it should have moved as far as possible.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 40 0]
+test panedwindow-18.7 {MoveSash, move right pushes other sashes} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 0 100 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ set result [.p sash coord 1]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 62 0]
+test panedwindow-18.8 {MoveSash, move right pushes other sashes, respects minsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 100 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ set result [.p sash coord 1]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 52 0]
+test panedwindow-18.9 {MoveSash, move right respects minsize, exludes pad} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize 10 -padx 5
+ }
+
+ .p sash place 0 100 0
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 50 0]
+test panedwindow-18.10 {MoveSash, move right, negative minsize becomes 0} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize -50
+ }
+
+ .p sash place 0 50 0
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ set result [list [.p sash coord 0] [.p sash coord 1]]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list [list 50 0] [list 52 0]]
+test panedwindow-18.11 {MoveSash, move left} {
+ set result {}
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Get the requested width of the paned window
+ lappend result [winfo reqwidth .p]
+
+ .p sash place 0 10 0
+
+ # Get the reqwidth again, to make sure it hasn't changed
+ lappend result [winfo reqwidth .p]
+
+ # Check that the sash moved
+ lappend result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 42 42 {10 0}]
+test panedwindow-18.12 {MoveSash, move left, can't move outside of window} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 0 -100 0
+
+ # Get the new sash coord; it should be clipped by the reqwidth of
+ # the panedwindow.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 0 0]
+test panedwindow-18.13 {MoveSash, move left respects minsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 0 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 10 0]
+test panedwindow-18.14 {MoveSash, move left respects minsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible.
+ set result [.p sash coord 1]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 22 0]
+test panedwindow-18.15 {MoveSash, move left pushes other sashes} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 0 0]
+test panedwindow-18.16 {MoveSash, move left pushes other sashes, respects minsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 10 0]
+test panedwindow-18.17 {MoveSash, move left respects minsize, exludes pad} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize 10 -padx 5
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ set result [.p sash coord 1]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 42 0]
+test panedwindow-18.18 {MoveSash, move left, negative minsize becomes 0} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ foreach w {.f1 .f2 .f3} c {red blue green} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize -50
+ }
+
+ .p sash place 1 10 0
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ set result [list [.p sash coord 0] [.p sash coord 1]]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list [list 8 0] [list 10 0]]
+
+test panedwindow-19.1 {MoveSash, move down} {
+ set result {}
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Get the requested width of the paned window
+ lappend result [winfo reqheight .p]
+
+ .p sash place 0 0 30
+
+ # Get the reqwidth again, to make sure it hasn't changed
+ lappend result [winfo reqheight .p]
+
+ # Check that the sash moved
+ lappend result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 42 42 {0 30}]
+test panedwindow-19.2 {MoveSash, move down (unmapped) clipped by reqheight} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 0 0 100
+
+ # Get the new sash coord; it should be clipped by the reqheight of
+ # the panedwindow.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 0 40]
+test panedwindow-19.3 {MoveSash, move down (mapped, height < reqheight) clipped by height} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Put the panedwindow up on the display and give it a height < reqheight
+ place .p -x 0 -y 0 -height 32
+ update
+
+ .p sash place 0 0 100
+
+ # Get the new sash coord; it should be clipped by the visible height of
+ # the panedwindow.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 0 30]
+test panedwindow-19.4 {MoveSash, move down (mapped, height > reqheight) clipped by height} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Put the panedwindow up on the display and give it a width > reqwidth
+ place .p -x 0 -y 0 -height 102
+ update
+
+ .p sash place 0 0 200
+
+ # Get the new sash coord; it should be clipped by the visible width of
+ # the panedwindow.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 0 100]
+test panedwindow-19.5 {MoveSash, move down respects minsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 0 100
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 0 30]
+test panedwindow-19.6 {MoveSash, move down respects minsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 0 100
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 0 40]
+test panedwindow-19.7 {MoveSash, move down pushes other sashes} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 0 0 100
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ set result [.p sash coord 1]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 0 62]
+test panedwindow-19.8 {MoveSash, move down pushes other sashes, respects minsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 0 100
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ set result [.p sash coord 1]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 0 52]
+test panedwindow-19.9 {MoveSash, move down respects minsize, exludes pad} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize 10 -pady 5
+ }
+
+ .p sash place 0 0 100
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 0 50]
+test panedwindow-19.10 {MoveSash, move right, negative minsize becomes 0} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize -50
+ }
+
+ .p sash place 0 0 50
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ set result [list [.p sash coord 0] [.p sash coord 1]]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list [list 0 50] [list 0 52]]
+test panedwindow-19.11 {MoveSash, move up} {
+ set result {}
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ # Get the requested width of the paned window
+ lappend result [winfo reqheight .p]
+
+ .p sash place 0 0 10
+
+ # Get the reqwidth again, to make sure it hasn't changed
+ lappend result [winfo reqheight .p]
+
+ # Check that the sash moved
+ lappend result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 42 42 {0 10}]
+test panedwindow-19.12 {MoveSash, move up, can't move outside of window} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 0 0 -100
+
+ # Get the new sash coord; it should be clipped by the reqwidth of
+ # the panedwindow.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 0 0]
+test panedwindow-19.13 {MoveSash, move up respects minsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 0 0 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2
+
+ set result
+} [list 0 10]
+test panedwindow-19.14 {MoveSash, move up respects minsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible.
+ set result [.p sash coord 1]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 0 22]
+test panedwindow-19.15 {MoveSash, move up pushes other sashes} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 0 0]
+test panedwindow-19.16 {MoveSash, move up pushes other sashes, respects minsize} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] -sticky nsew -minsize 10
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible while
+ # respecting minsizes.
+ set result [.p sash coord 0]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 0 10]
+test panedwindow-19.17 {MoveSash, move up respects minsize, exludes pad} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize 10 -pady 5
+ }
+
+ .p sash place 1 0 0
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ set result [.p sash coord 1]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list 0 42]
+test panedwindow-19.18 {MoveSash, move up, negative minsize becomes 0} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} c {red blue green} {
+ .p add [frame $w -height 20 -width 20 -bg $c] \
+ -sticky nsew -minsize -50
+ }
+
+ .p sash place 1 0 10
+
+ # Get the new sash coord; it should have moved as far as possible,
+ # respecting minsizes.
+ set result [list [.p sash coord 0] [.p sash coord 1]]
+
+ # Cleanup
+ destroy .p .f1 .f2 .f3
+
+ set result
+} [list [list 0 8] [list 0 10]]
+
+# The following tests check that the panedwindow is correctly computing its
+# geometry based on the various configuration options that can affect the
+# geometry.
+
+test panedwindow-20.1 {ComputeGeometry, reqheight taken from widgets} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue]
+ }
+ set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]
+ .f3 configure -height 40
+ lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]
+ destroy .p .f1 .f2 .f3
+ set result
+} [list [list 60 20] [list 60 40]]
+test panedwindow-20.2 {ComputeGeometry, reqheight taken from widgets} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue]
+ }
+ set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]
+ .p paneconfigure .f3 -height 40
+ lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]
+ destroy .p .f1 .f2 .f3
+ set result
+} [list [list 60 20] [list 60 40]]
+test panedwindow-20.3 {ComputeGeometry, reqheight taken from widgets} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -pady 20
+ }
+ set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]
+ .p paneconfigure .f3 -height 40
+ lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]
+ destroy .p .f1 .f2 .f3
+ set result
+} [list [list 60 60] [list 60 80]]
+test panedwindow-20.4 {ComputeGeometry, reqwidth taken from widgets} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue]
+ }
+ set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]
+ .f3 configure -width 40
+ lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]
+ destroy .p .f1 .f2 .f3
+ set result
+} [list [list 20 60] [list 40 60]]
+test panedwindow-20.5 {ComputeGeometry, reqwidth taken from widgets} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue]
+ }
+ set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]
+ .p paneconfigure .f3 -width 40
+ lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]
+ destroy .p .f1 .f2 .f3
+ set result
+} [list [list 20 60] [list 40 60]]
+test panedwindow-20.6 {ComputeGeometry, reqwidth taken from widgets} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 0 \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] -padx 20
+ }
+ set result [list [list [winfo reqwidth .p] [winfo reqheight .p]]]
+ .p paneconfigure .f3 -width 40
+ lappend result [list [winfo reqwidth .p] [winfo reqheight .p]]
+ destroy .p .f1 .f2 .f3
+ set result
+} [list [list 60 60] [list 80 60]]
+
+set i 6
+foreach bd {0 2} {
+ foreach sp {0 5} {
+ foreach sw {0 3} {
+ foreach h {0 1} {
+ test panedwindow-20.[incr i]-$bd-$sp-$sw-$h \
+ {ComputeGeometry, one slave, reqsize set properly} {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth $bd -sashpad $sp \
+ -sashwidth $sw -handlesize 6 -showhandle $h
+ .p add [frame .p.f -width 20 -height 20 -bg red] -padx $h \
+ -sticky ""
+ set result [list [winfo reqwidth .p] [winfo reqheight .p]]
+ destroy .p .p.f
+ set result
+ } [list [expr {(2 * $bd) + 20 + (2 * $h)}] \
+ [expr {(2 * $bd) + 20}]]
+
+ test panedwindow-20.[incr i]-$bd-$sp-$sw-$h \
+ {ComputeGeometry, three panes, reqsize set properly} {
+ panedwindow .p -borderwidth $bd -sashpad $sp \
+ -sashwidth $sw -handlesize 6 -showhandle $h
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ set result [list [winfo reqwidth .p] [winfo reqheight .p]]
+ destroy .p .p.f1 .p.f2 .p.f3
+ set result
+ } [list [expr {(2 * $bd) + ($h?12:(2*$sw)) + (4*$sp) + 60}] \
+ [expr {(2 * $bd) + 20}]]
+
+ test panedwindow-20.[incr i]-$bd-$sp-$sw-$h \
+ {ComputeGeometry, sash coords} {
+ panedwindow .p -borderwidth $bd -sashpad $sp \
+ -sashwidth $sw -handlesize 6 -showhandle $h
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ set result [list [.p sash coord 0] [.p sash coord 1]]
+ destroy .p .f1 .f2 .f3
+ set result
+ } [list [list [expr {$bd+20+($h?(6-$sw)/2:0)+$sp}] $bd] \
+ [list [expr {$bd+40+($h?6+(6-$sw)/2:$sw)+(3*$sp)}] \
+ $bd]]
+
+ test panedwindow-20.[incr i]-$bd-$sp-$sw-$h \
+ {ComputeGeometry/ArrangePanes, slave coords} {
+ panedwindow .p -borderwidth $bd -sashpad $sp \
+ -sashwidth $sw -handlesize 6 -showhandle $h
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 3 -padx 11
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ destroy .p .p.f1 .p.f2 .p.f3
+ set result
+ } [list [list [expr {$bd+11}] [expr {$bd+3}] 20 20] \
+ [list [expr {$bd+53+($h?6:$sw)+(2*$sp)}] \
+ [expr {$bd+3}] 20 20] \
+ [list [expr {$bd+95+($h?12:2*$sw)+(4*$sp)}] \
+ [expr {$bd+3}] 20 20]]
+
+ test panedwindow-20.[incr i]-$bd-$sp-$sw-$h \
+ {ComputeGeometry, one slave, vertical} {
+ # With just one slave, sashpad and sashwidth should not
+ # affect the panedwindow's geometry, since no sash should
+ # ever be drawn.
+ panedwindow .p -borderwidth $bd -sashpad $sp \
+ -orient vertical -sashwidth $sw -handlesize 6 \
+ -showhandle $h
+ .p add [frame .f -width 20 -height 20 -bg red] -pady $h \
+ -sticky ""
+ set result [list [winfo reqwidth .p] [winfo reqheight .p]]
+ destroy .p .f
+ set result
+ } [list [expr {(2 * $bd) + 20}] \
+ [expr {(2 * $bd) + 20 + (2 * $h)}]]
+
+ test panedwindow-20.[incr i]-$bd-$sp-$sw-$h \
+ {ComputeGeometry, three panes, vertical} {
+ panedwindow .p -borderwidth $bd -sashpad $sp \
+ -sashwidth $sw -handlesize 6 -showhandle $h \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ set result [list [winfo reqwidth .p] [winfo reqheight .p]]
+ destroy .p .f1 .f2 .f3
+ set result
+ } [list [expr {(2 * $bd) + 20}] \
+ [expr {(2 * $bd) + ($h?12:(2*$sw)) + (4*$sp) + 60}]]
+
+ test panedwindow-20.[incr i]-$bd-$sp-$sw-$h \
+ {ComputeGeometry, sash coords, vertical} {
+ panedwindow .p -borderwidth $bd -sashpad $sp \
+ -sashwidth $sw -handlesize 6 -showhandle $h \
+ -orient vertical
+ foreach w {.f1 .f2 .f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky ""
+ }
+ set result [list [.p sash coord 0] [.p sash coord 1]]
+ destroy .p .f1 .f2 .f3
+ set result
+ } [list [list $bd [expr {$bd+20+($h?(6-$sw)/2:0)+$sp}]] \
+ [list $bd \
+ [expr {$bd+40+($h?6+(6-$sw)/2:$sw)+(3*$sp)}]]]
+
+ test panedwindow-20.[incr i]-$bd-$sp-$sw-$h \
+ {ComputeGeometry/ArrangePanes, slave coords, vert} {
+ panedwindow .p -borderwidth $bd -sashpad $sp \
+ -sashwidth $sw -handlesize 6 -showhandle $h \
+ -orient vertical
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ .p add [frame $w -width 20 -height 20 -bg blue] \
+ -sticky nsew -pady 11 -padx 3
+ }
+ pack .p
+ update
+ set result {}
+ foreach w {.p.f1 .p.f2 .p.f3} {
+ lappend result [list [winfo x $w] [winfo y $w] \
+ [winfo width $w] [winfo height $w]]
+ }
+ destroy .p .p.f1 .p.f2 .p.f3
+ set result
+ } [list [list [expr {$bd+3}] [expr {$bd+11}] 20 20] \
+ [list [expr {$bd+3}] \
+ [expr {$bd+53+($h?6:$sw)+(2*$sp)}] 20 20] \
+ [list [expr {$bd+3}] \
+ [expr {$bd+95+($h?12:2*$sw)+(4*$sp)}] 20 20]]
+ }
+ }
+ }
+}
+
+test panedwindow-21.1 {destroyed widgets are removed from panedwindow} {
+ panedwindow .p
+ .p add [frame .f -width 20 -height 20 -bg blue]
+ destroy .f
+ set result [.p panes]
+ destroy .p
+ set result
+} {}
+test panedwindow-21.2 {destroyed slave causes geometry recomputation} {
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .f -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 20 -bg red]
+ destroy .f
+ set result [winfo reqwidth .p]
+ destroy .p .f2
+ set result
+} 20
+
+test panedwindow-22.1 {ArrangePanes, extra space is given to the last pane} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 20 -bg red] -sticky nsew
+ place .p -width 100 -x 0 -y 0
+ update
+ set result [winfo width .f2]
+ destroy .p .f1 .f2
+ set result
+} 78
+test panedwindow-22.2 {ArrangePanes, extra space is given to the last pane} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 20 -bg red] -sticky nsew
+ place .p -height 100 -x 0 -y 0
+ update
+ set result [winfo height .f2]
+ destroy .p .f1 .f2
+ set result
+} 78
+test panedwindow-22.3 {ArrangePanes, explicit height/width are preferred} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 20 -bg red] -sticky ""
+ .p paneconfigure .f1 -width 10 -height 15
+ pack .p
+ update
+ set result [list [winfo width .f1] [winfo height .f1]]
+ destroy .p .f1 .f2
+ set result
+} {10 15}
+test panedwindow-22.4 {ArrangePanes, panes clipped by size of pane} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 20 -bg red]
+ .p sash place 0 10 0
+ pack .p
+ update
+ set result [list [winfo width .f1] [winfo height .f1]]
+ destroy .p .f1 .f2
+ set result
+} {10 20}
+test panedwindow-22.5 {ArrangePanes, panes clipped by size of pane} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 20 -bg red]
+ .p sash place 0 0 10
+ pack .p
+ update
+ set result [list [winfo width .f1] [winfo height .f1]]
+ destroy .p .f1 .f2
+ set result
+} {20 10}
+test panedwindow-22.6 {ArrangePanes, height of pane taken from total height} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .p.f1 -width 20 -height 20 -bg blue] \
+ [frame .p.f2 -width 20 -height 40 -bg red] -sticky ""
+ pack .p
+ update
+ set result [list [winfo y .p.f1]]
+ destroy .p .p.f1 .p.f2
+ set result
+} 10
+test panedwindow-22.8 {ArrangePanes, width of pane taken from total width} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 \
+ -orient vertical
+ .p add [frame .p.f1 -width 20 -height 20 -bg blue] \
+ [frame .p.f2 -width 40 -height 40 -bg red] -sticky ""
+ pack .p
+ update
+ set result [list [winfo x .p.f1]]
+ destroy .p .p.f1 .p.f2
+ set result
+} 10
+test panedwindow-22.9 {ArrangePanes, panes with width <= 0 are unmapped} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 40 -bg red]
+ pack .p
+ update
+ set result [winfo ismapped .f1]
+ .p sash place 0 0 0
+ update
+ lappend result [winfo ismapped .f1]
+ destroy .p .f1 .f2
+ set result
+} {1 0}
+test panedwindow-22.10 {ArrangePanes, panes with width <= 0 are unmapped} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .p.f1 -width 20 -height 20 -bg blue] \
+ [frame .p.f2 -width 20 -height 40 -bg red]
+ pack .p
+ update
+ set result [winfo ismapped .p.f1]
+ .p sash place 0 0 0
+ update
+ lappend result [winfo ismapped .p.f1]
+ destroy .p .p.f1 .p.f2
+ set result
+} {1 0}
+test panedwindow-22.11 {ArrangePanes, panes with width <= 0 are unmapped} {
+ panedwindow .p -showhandle false -borderwidth 0 -sashpad 0 -sashwidth 2 -orient vertical
+ .p add [frame .p.f1 -width 20 -height 20 -bg blue] \
+ [frame .p.f2 -width 20 -height 40 -bg red]
+ pack .p
+ update
+ set result [winfo ismapped .p.f1]
+ .p sash place 0 0 0
+ update
+ lappend result [winfo ismapped .p.f1]
+ destroy .p .p.f1 .p.f2
+ set result
+} {1 0}
+
+test panedwindow-23.1 {PanedWindowReqProc, react to slave geometry changes} {
+ # Basically just want to make sure that the PanedWindowReqProc is called
+ panedwindow .p -borderwidth 0 -sashpad 0 -sashwidth 2
+ .p add [frame .f1 -width 20 -height 20 -bg blue] \
+ [frame .f2 -width 20 -height 40 -bg red]
+ set result [winfo reqheight .p]
+ .f1 configure -height 80
+ lappend result [winfo reqheight .p]
+ destroy .p .f1 .f2
+ set result
+} {40 80}
+
+test panedwindow-24.1 {ConfigurePanes, can't add panedwindow to itself} {
+ panedwindow .p
+ set result [list [catch {.p add .p} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "can't add .p to itself"]
+test panedwindow-24.2 {ConfigurePanes, bad window throws error} {
+ panedwindow .p
+ set result [list [catch {.p add .b} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "bad window path name \".b\""]
+test panedwindow-24.3 {ConfigurePanes, bad window aborts processing} {
+ panedwindow .p
+ button .b
+ catch {.p add .b .a}
+ set result [.p panes]
+ destroy .p .b
+ set result
+} {}
+test panedwindow-24.4 {ConfigurePanes, bad option aborts processing} {
+ panedwindow .p
+ button .b
+ catch {.p add .b -sticky foobar}
+ set result [.p panes]
+ destroy .p .b
+ set result
+} {}
+test panedwindow-24.5 {ConfigurePanes, after win isn't managed by panedwin} {
+ panedwindow .p
+ button .b
+ button .c
+ set result [list [catch {.p add .b -after .c} msg] $msg]
+ destroy .p .b .c
+ set result
+} [list 1 "window \".c\" is not managed by .p"]
+test panedwindow-24.6 {ConfigurePanes, before win isn't managed by panedwin} {
+ panedwindow .p
+ button .b
+ button .c
+ set result [list [catch {.p add .b -before .c} msg] $msg]
+ destroy .p .b .c
+ set result
+} [list 1 "window \".c\" is not managed by .p"]
+test panedwindow-24.7 {ConfigurePanes, -after {} is a no-op} {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ .p paneconfigure .b -after {}
+ set result [.p panes]
+ destroy .p .b .c
+ set result
+} {.b .c}
+test panedwindow-24.8 {ConfigurePanes, -before {} is a no-op} {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ .p paneconfigure .b -before {}
+ set result [.p panes]
+ destroy .p .b .c
+ set result
+} {.b .c}
+test panedwindow-24.9 {ConfigurePanes, new panes are added} {
+ panedwindow .p
+ .p add [button .b] [button .c]
+ set result [.p panes]
+ destroy .p .b .c
+ set result
+} {.b .c}
+test panedwindow-24.10 {ConfigurePanes, options applied to all panes} {
+ panedwindow .p
+ .p add [button .b] [button .c] -sticky ne -height 5 -width 5 -minsize 10
+ set result {}
+ foreach w {.b .c} {
+ set val {}
+ foreach option {-sticky -height -width -minsize} {
+ lappend val $option [.p panecget $w $option]
+ }
+ lappend result $w $val
+ }
+ destroy .p .b .c
+ set result
+} [list .b {-sticky ne -height 5 -width 5 -minsize 10} \
+ .c {-sticky ne -height 5 -width 5 -minsize 10}]
+test panedwindow-24.11 {ConfigurePanes, existing panes are reconfigured} {
+ panedwindow .p
+ .p add [button .b] -sticky nw -height 10
+ .p add .b [button .c] -sticky se -height 2
+ set result [list [.p panes] \
+ [.p panecget .b -sticky] [.p panecget .b -height] \
+ [.p panecget .c -sticky] [.p panecget .c -height]]
+ destroy .p .b .c
+ set result
+} [list {.b .c} es 2 es 2]
+test panedwindow-24.12 {ConfigurePanes, widgets added to end by default} {
+ panedwindow .p
+ .p add [button .b]
+ .p add [button .c]
+ .p add [button .d]
+ set result [.p panes]
+ destroy .p .b .c .d
+ set result
+} {.b .c .d}
+test panedwindow-24.13 {ConfigurePanes, -after, single addition} {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+
+ .p add .a .b
+ .p add .c -after .a
+ set result [.p panes]
+ destroy .p .a .b .c
+ set result
+} {.a .c .b}
+test panedwindow-24.14 {ConfigurePanes, -after, multiple additions} {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b
+ .p add .c .d -after .a
+ set result [.p panes]
+ destroy .p .a .b .c .d
+ set result
+} {.a .c .d .b}
+test panedwindow-24.15 {ConfigurePanes, -after, relocates existing widget} {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b .c .d
+ .p add .d -after .a
+ set result [.p panes]
+ destroy .p .a .b .c .d
+ set result
+} {.a .d .b .c}
+test panedwindow-24.16 {ConfigurePanes, -after, relocates existing widgets} {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b .c .d
+ .p add .b .d -after .a
+ set result [.p panes]
+ destroy .p .a .b .c .d
+ set result
+} {.a .b .d .c}
+test panedwindow-24.17 {ConfigurePanes, -after, relocates existing widgets} {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b .c .d
+ .p add .d .a -after .b
+ set result [.p panes]
+ destroy .p .a .b .c .d
+ set result
+} {.b .d .a .c}
+test panedwindow-24.18 {ConfigurePanes, -after, relocates existing widgets} {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b .c .d
+ .p add .d .a -after .a
+ set result [.p panes]
+ destroy .p .a .b .c .d
+ set result
+} {.d .a .b .c}
+test panedwindow-24.19 {ConfigurePanes, -after, after last window} {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b .c
+ .p add .d -after .c
+ set result [.p panes]
+ destroy .p .a .b .c .d
+ set result
+} {.a .b .c .d}
+test panedwindow-24.20 {ConfigurePanes, -before, before first window} {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b .c
+ .p add .d -before .a
+ set result [.p panes]
+ destroy .p .a .b .c .d
+ set result
+} {.d .a .b .c}
+test panedwindow-24.21 {ConfigurePanes, -before, relocate existing windows} {
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+ button .d
+
+ .p add .a .b .c
+ .p add .d .b -before .a
+ set result [.p panes]
+ destroy .p .a .b .c .d
+ set result
+} {.d .b .a .c}
+test panedwindow-24.22 {ConfigurePanes, slave specified multiple times} {
+ # This test should not cause a core dump
+
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+
+ .p add .a .a .b .c
+ set result [.p panes]
+ destroy .p .a .b .c
+ set result
+} {.a .b .c}
+test panedwindow-22.23 {ConfigurePanes, slave specified multiple times} {
+ # This test should not cause a core dump
+
+ panedwindow .p
+ button .a
+ button .b
+ button .c
+
+ .p add .a .a .b .c
+ .p add .a .b .a -after .c
+ set result [.p panes]
+ destroy .p .a .b .c
+ set result
+} {.c .a .b}
+test panedwindow-22.24 {ConfigurePanes, panedwindow cannot manage toplevels} {
+ panedwindow .p
+ toplevel .t
+ set result [list [catch {.p add .t} msg] $msg]
+ destroy .p .t
+ set result
+} [list 1 "can't add toplevel .t to .p"]
+test panedwindow-22.25 {ConfigurePanes, restrict possible panes} {
+ panedwindow .p
+ frame .f
+ button .f.b
+ set result [list [catch {.p add .f.b} msg] $msg]
+ destroy .p .f .f.b
+ set result
+} [list 1 "can't add .f.b to .p"]
+test panedwindow-22.26 {ConfigurePanes, restrict possible panes} {
+ frame .f
+ panedwindow .f.p
+ button .b
+ set result [list [catch {.f.p add .b} msg] $msg]
+ destroy .f.p .f .b
+ set result
+} [list 0 ""]
+test panedwindow-22.27 {ConfigurePanes, restrict possible panes} {
+ panedwindow .p
+ button .p.b
+ set result [list [catch {.p add .p.b} msg] $msg]
+ destroy .p .p.b
+ set result
+} [list 0 ""]
+test panedwindow-22.28 {ConfigurePanes, restrict possible panes} {
+ frame .f
+ frame .f.f
+ frame .f.f.f
+ panedwindow .f.f.f.p
+ button .b
+ set result [list [catch {.f.f.f.p add .b} msg] $msg]
+ destroy .f .f.f .f.f.f .f.f.f.p .b
+ set result
+} [list 0 ""]
+
+test panedwindow-26.1 {DestroyPanedWindow} {
+ # This test should not result in any memory leaks.
+ panedwindow .p
+ foreach w {.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o .q .r .s .t} {
+ .p add [button $w]
+ }
+ foreach w {.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o .p .q .r .s .t} {
+ destroy $w
+ }
+ set result {}
+} {}
+
+test panedwindow-27.1 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 0 0]
+ destroy .p .f .f2
+ set result
+} {}
+test panedwindow-27.2 {PanedWindowIdentifyCoords, padding is included} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 20 0]
+ destroy .p .f .f2
+ set result
+} {0 sash}
+test panedwindow-27.3 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 22 0]
+ destroy .p .f .f2
+ set result
+} {0 sash}
+test panedwindow-27.4 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 24 0]
+ destroy .p .f .f2
+ set result
+} {0 sash}
+test panedwindow-27.5 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 26 0]
+ destroy .p .f .f2
+ set result
+} {0 sash}
+test panedwindow-27.6 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 26 -1]
+ destroy .p .f .f2
+ set result
+} {}
+test panedwindow-27.7 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 26 100]
+ destroy .p .f .f2
+ set result
+} {}
+test panedwindow-27.8 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 6
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 22 4]
+ destroy .p .f .f2
+ set result
+} {0 sash}
+test panedwindow-27.9 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 6
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 22 5]
+ destroy .p .f .f2
+ set result
+} {0 handle}
+test panedwindow-27.10 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 8
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 20 5]
+ destroy .p .f .f2
+ set result
+} {0 handle}
+test panedwindow-27.11 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 8
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 20 0]
+ destroy .p .f .f2
+ set result
+} {0 sash}
+test panedwindow-27.12 {PanedWindowIdentifyCoords} {
+ panedwindow .p -showhandle false -bd 0 -sashwidth 2 -sashpad 2
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20] \
+ [frame .f3 -bg green -width 20 -height 20]
+ set result [.p identify 48 0]
+ destroy .p .f .f2 .f3
+ set result
+} {1 sash}
+test panedwindow-27.13 {identify subcommand errors} {
+ panedwindow .p -borderwidth 0 -sashpad 2 -sashwidth 4
+ set result [list [catch {.p identify} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "wrong # args: should be \".p identify x y\""]
+test panedwindow-27.14 {identify subcommand errors} {
+ panedwindow .p
+ set result [list [catch {.p identify foo bar} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "expected integer but got \"foo\""]
+test panedwindow-27.14 {identify subcommand errors} {
+ panedwindow .p
+ set result [list [catch {.p identify 0 bar} msg] $msg]
+ destroy .p
+ set result
+} [list 1 "expected integer but got \"bar\""]
+test panedwindow-27.15 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 0 0]
+ destroy .p .f .f2
+ set result
+} {}
+test panedwindow-27.16 {PanedWindowIdentifyCoords, padding is included} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 0 20]
+ destroy .p .f .f2
+ set result
+} {0 sash}
+test panedwindow-27.17 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 0 22]
+ destroy .p .f .f2
+ set result
+} {0 sash}
+test panedwindow-27.18 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 0 24]
+ destroy .p .f .f2
+ set result
+} {0 sash}
+test panedwindow-27.19 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 0 26]
+ destroy .p .f .f2
+ set result
+} {0 sash}
+test panedwindow-27.20 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify -1 26]
+ destroy .p .f .f2
+ set result
+} {}
+test panedwindow-27.21 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 100 26]
+ destroy .p .f .f2
+ set result
+} {}
+test panedwindow-27.22 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 6 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 4 22]
+ destroy .p .f .f2
+ set result
+} {0 sash}
+test panedwindow-27.23 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 6 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 5 22]
+ destroy .p .f .f2
+ set result
+} {0 handle}
+test panedwindow-27.24 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 8 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 5 20]
+ destroy .p .f .f2
+ set result
+} {0 handle}
+test panedwindow-27.25 {PanedWindowIdentifyCoords} {
+ panedwindow .p -bd 0 -sashwidth 2 -sashpad 2 -showhandle 1 -handlepad 5 \
+ -handlesize 8 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20]
+ set result [.p identify 0 20]
+ destroy .p .f .f2
+ set result
+} {0 sash}
+test panedwindow-27.26 {PanedWindowIdentifyCoords} {
+ panedwindow .p -showhandle false -bd 0 -sashwidth 2 -sashpad 2 -orient vertical
+ .p add [frame .f -bg red -width 20 -height 20] \
+ [frame .f2 -bg blue -width 20 -height 20] \
+ [frame .f3 -bg green -width 20 -height 20]
+ set result [.p identify 0 48]
+ destroy .p .f .f2 .f3
+ set result
+} {1 sash}
+
+
+# cleanup
+::tcltest::cleanupTests
+return
diff --git a/unix/Makefile.in b/unix/Makefile.in
index f12d87d..43daf62 100644
--- a/unix/Makefile.in
+++ b/unix/Makefile.in
@@ -5,7 +5,7 @@
# "autoconf" program (constructs like "@foo@" will get replaced in the
# actual Makefile.
#
-# RCS: @(#) $Id: Makefile.in,v 1.62 2002/01/29 08:04:37 mdejong Exp $
+# RCS: @(#) $Id: Makefile.in,v 1.63 2002/02/22 02:41:17 hobbs Exp $
# Current Tk version; used in various names.
@@ -265,8 +265,8 @@ TCLTEST_OBJS = ${TCL_BIN_DIR}/tclTest.o ${TCL_BIN_DIR}/tclThreadTest.o \
TKTEST_OBJS = $(TCLTEST_OBJS) tkTestInit.o tkTest.o tkSquare.o
WIDGOBJS = tkButton.o tkEntry.o tkFrame.o tkListbox.o \
- tkMenu.o tkMenubutton.o tkMenuDraw.o tkMessage.o tkScale.o \
- tkScrollbar.o
+ tkMenu.o tkMenubutton.o tkMenuDraw.o tkMessage.o \
+ tkPanedWindow.o tkScale.o tkScrollbar.o
CANVOBJS = tkCanvas.o tkCanvArc.o tkCanvBmap.o tkCanvImg.o \
tkCanvLine.o tkCanvPoly.o tkCanvPs.o tkCanvText.o \
@@ -316,6 +316,7 @@ SRCS = \
$(GENERIC_DIR)/tkListbox.c $(GENERIC_DIR)/tkMenu.c \
$(GENERIC_DIR)/tkMenubutton.c $(GENERIC_DIR)/tkMenuDraw.c \
$(GENERIC_DIR)/tkMessage.c \
+ $(GENERIC_DIR)/tkPanedWindow.c \
$(GENERIC_DIR)/tkScale.c $(GENERIC_DIR)/tkScrollbar.c \
$(GENERIC_DIR)/tkCanvas.c $(GENERIC_DIR)/tkCanvArc.c \
$(GENERIC_DIR)/tkCanvBmap.c $(GENERIC_DIR)/tkCanvImg.c \
@@ -781,6 +782,9 @@ tkMenuDraw.o: $(GENERIC_DIR)/tkMenuDraw.c
tkMessage.o: $(GENERIC_DIR)/tkMessage.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkMessage.c
+tkPanedWindow.o: $(GENERIC_DIR)/tkPanedWindow.c
+ $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkPanedWindow.c
+
tkScale.o: $(GENERIC_DIR)/tkScale.c
$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tkScale.c
diff --git a/unix/tkUnixDefault.h b/unix/tkUnixDefault.h
index 76ae654..1428d59 100644
--- a/unix/tkUnixDefault.h
+++ b/unix/tkUnixDefault.h
@@ -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: tkUnixDefault.h,v 1.12 2001/11/13 00:19:05 hobbs Exp $
+ * RCS: @(#) $Id: tkUnixDefault.h,v 1.13 2002/02/22 02:41:17 hobbs Exp $
*/
#ifndef _TKUNIXDEFAULT
@@ -354,6 +354,40 @@
#define DEF_MESSAGE_WIDTH "0"
/*
+ * Defaults for panedwindows
+ */
+
+#define DEF_PANEDWINDOW_BG_COLOR NORMAL_BG
+#define DEF_PANEDWINDOW_BG_MONO WHITE
+#define DEF_PANEDWINDOW_BORDERWIDTH "2"
+#define DEF_PANEDWINDOW_CURSOR ""
+#define DEF_PANEDWINDOW_HANDLEPAD "8"
+#define DEF_PANEDWINDOW_HANDLESIZE "8"
+#define DEF_PANEDWINDOW_HEIGHT ""
+#define DEF_PANEDWINDOW_OPAQUERESIZE "0"
+#define DEF_PANEDWINDOW_ORIENT "horizontal"
+#define DEF_PANEDWINDOW_RELIEF "raised"
+#define DEF_PANEDWINDOW_SASHCURSOR ""
+#define DEF_PANEDWINDOW_SASHPAD "2"
+#define DEF_PANEDWINDOW_SASHRELIEF "raised"
+#define DEF_PANEDWINDOW_SASHWIDTH "2"
+#define DEF_PANEDWINDOW_SHOWHANDLE "1"
+#define DEF_PANEDWINDOW_WIDTH ""
+
+/*
+ * Defaults for panedwindow panes
+ */
+
+#define DEF_PANEDWINDOW_PANE_AFTER ""
+#define DEF_PANEDWINDOW_PANE_BEFORE ""
+#define DEF_PANEDWINDOW_PANE_HEIGHT ""
+#define DEF_PANEDWINDOW_PANE_MINSIZE "0"
+#define DEF_PANEDWINDOW_PANE_PADX "0"
+#define DEF_PANEDWINDOW_PANE_PADY "0"
+#define DEF_PANEDWINDOW_PANE_STICKY "nsew"
+#define DEF_PANEDWINDOW_PANE_WIDTH ""
+
+/*
* Defaults for scales:
*/
diff --git a/win/Makefile.in b/win/Makefile.in
index 958b347..3d1b0da 100644
--- a/win/Makefile.in
+++ b/win/Makefile.in
@@ -4,7 +4,7 @@
# "autoconf" program (constructs like "@foo@" will get replaced in the
# actual Makefile.
#
-# RCS: @(#) $Id: Makefile.in,v 1.47 2001/12/19 07:45:52 mdejong Exp $
+# RCS: @(#) $Id: Makefile.in,v 1.48 2002/02/22 02:41:17 hobbs Exp $
TCLVERSION = @TCL_VERSION@
VERSION = @TK_VERSION@
@@ -319,6 +319,7 @@ TK_OBJS = \
tkMenubutton.$(OBJEXT) \
tkMenuDraw.$(OBJEXT) \
tkMessage.$(OBJEXT) \
+ tkPanedWindow.$(OBJEXT) \
tkObj.$(OBJEXT) \
tkOldConfig.$(OBJEXT) \
tkOption.$(OBJEXT) \
diff --git a/win/makefile.vc b/win/makefile.vc
index 50240b9..b7cb202 100644
--- a/win/makefile.vc
+++ b/win/makefile.vc
@@ -12,7 +12,7 @@
# Copyright (c) 2001 Tomasoft Engineering.
#
#------------------------------------------------------------------------------
-# RCS: @(#) $Id: makefile.vc,v 1.50 2002/02/01 23:20:29 davygrvy Exp $
+# RCS: @(#) $Id: makefile.vc,v 1.51 2002/02/22 02:41:17 hobbs Exp $
#------------------------------------------------------------------------------
!if "$(MSVCDIR)" == ""
@@ -331,6 +331,7 @@ TKOBJS = \
$(TMP_DIR)\tkMenubutton.obj \
$(TMP_DIR)\tkMenuDraw.obj \
$(TMP_DIR)\tkMessage.obj \
+ $(TMP_DIR)\tkPanedWindow.obj \
$(TMP_DIR)\tkObj.obj \
$(TMP_DIR)\tkOldConfig.obj \
$(TMP_DIR)\tkOption.obj \
@@ -651,6 +652,7 @@ $(GENERICDIR)/tkListbox.c: $(GENERICDIR)/default.h
$(GENERICDIR)/tkMenu.c: $(GENERICDIR)/default.h
$(GENERICDIR)/tkMenubutton.c: $(GENERICDIR)/default.h
$(GENERICDIR)/tkMessage.c: $(GENERICDIR)/default.h
+$(GENERICDIR)/tkPanedWindow.c: $(GENERICDIR)/default.h
$(GENERICDIR)/tkScale.c: $(GENERICDIR)/default.h
$(GENERICDIR)/tkScrollbar.c: $(GENERICDIR)/default.h
$(GENERICDIR)/tkText.c: $(GENERICDIR)/default.h
diff --git a/win/tkWinDefault.h b/win/tkWinDefault.h
index 8379b9c..2648401 100644
--- a/win/tkWinDefault.h
+++ b/win/tkWinDefault.h
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWinDefault.h,v 1.12 2001/11/13 00:19:05 hobbs Exp $
+ * RCS: @(#) $Id: tkWinDefault.h,v 1.13 2002/02/22 02:41:17 hobbs Exp $
*/
#ifndef _TKWINDEFAULT
@@ -359,6 +359,40 @@
#define DEF_MESSAGE_WIDTH "0"
/*
+ * Defaults for panedwindows
+ */
+
+#define DEF_PANEDWINDOW_BG_COLOR NORMAL_BG
+#define DEF_PANEDWINDOW_BG_MONO WHITE
+#define DEF_PANEDWINDOW_BORDERWIDTH "2"
+#define DEF_PANEDWINDOW_CURSOR ""
+#define DEF_PANEDWINDOW_HANDLEPAD "8"
+#define DEF_PANEDWINDOW_HANDLESIZE "8"
+#define DEF_PANEDWINDOW_HEIGHT ""
+#define DEF_PANEDWINDOW_OPAQUERESIZE "0"
+#define DEF_PANEDWINDOW_ORIENT "horizontal"
+#define DEF_PANEDWINDOW_RELIEF "raised"
+#define DEF_PANEDWINDOW_SASHCURSOR ""
+#define DEF_PANEDWINDOW_SASHPAD "2"
+#define DEF_PANEDWINDOW_SASHRELIEF "raised"
+#define DEF_PANEDWINDOW_SASHWIDTH "2"
+#define DEF_PANEDWINDOW_SHOWHANDLE "0"
+#define DEF_PANEDWINDOW_WIDTH ""
+
+/*
+ * Defaults for panedwindow panes
+ */
+
+#define DEF_PANEDWINDOW_PANE_AFTER ""
+#define DEF_PANEDWINDOW_PANE_BEFORE ""
+#define DEF_PANEDWINDOW_PANE_HEIGHT ""
+#define DEF_PANEDWINDOW_PANE_MINSIZE "0"
+#define DEF_PANEDWINDOW_PANE_PADX "0"
+#define DEF_PANEDWINDOW_PANE_PADY "0"
+#define DEF_PANEDWINDOW_PANE_STICKY "nsew"
+#define DEF_PANEDWINDOW_PANE_WIDTH ""
+
+/*
* Defaults for scales:
*/