summaryrefslogtreecommitdiffstats
path: root/tk8.6/generic/ttk/ttkPanedwindow.c
diff options
context:
space:
mode:
Diffstat (limited to 'tk8.6/generic/ttk/ttkPanedwindow.c')
-rw-r--r--tk8.6/generic/ttk/ttkPanedwindow.c976
1 files changed, 0 insertions, 976 deletions
diff --git a/tk8.6/generic/ttk/ttkPanedwindow.c b/tk8.6/generic/ttk/ttkPanedwindow.c
deleted file mode 100644
index adc2aef..0000000
--- a/tk8.6/generic/ttk/ttkPanedwindow.c
+++ /dev/null
@@ -1,976 +0,0 @@
-/*
- * Copyright (c) 2005, Joe English. Freely redistributable.
- *
- * ttk::panedwindow widget implementation.
- *
- * TODO: track active/pressed sash.
- */
-
-#include <string.h>
-#include <tk.h>
-#include "ttkManager.h"
-#include "ttkTheme.h"
-#include "ttkWidget.h"
-
-/*------------------------------------------------------------------------
- * +++ Layout algorithm.
- *
- * (pos=x/y, size=width/height, depending on -orient=horizontal/vertical)
- *
- * Each pane carries two pieces of state: the request size and the
- * position of the following sash. (The final pane has no sash,
- * its sash position is used as a sentinel value).
- *
- * Pane geometry is determined by the sash positions.
- * When resizing, sash positions are computed from the request sizes,
- * the available space, and pane weights (see PlaceSashes()).
- * This ensures continuous resize behavior (that is: changing
- * the size by X pixels then changing the size by Y pixels
- * gives the same result as changing the size by X+Y pixels
- * in one step).
- *
- * The request size is initially set to the slave window's requested size.
- * When the user drags a sash, each pane's request size is set to its
- * actual size. This ensures that panes "stay put" on the next resize.
- *
- * If reqSize == 0, use 0 for the weight as well. This ensures that
- * "collapsed" panes stay collapsed during a resize, regardless of
- * their nominal -weight.
- *
- * +++ Invariants.
- *
- * #sash = #pane - 1
- * pos(pane[0]) = 0
- * pos(sash[i]) = pos(pane[i]) + size(pane[i]), 0 <= i <= #sash
- * pos(pane[i+1]) = pos(sash[i]) + size(sash[i]), 0 <= i < #sash
- * pos(sash[#sash]) = size(pw) // sentinel value, constraint
- *
- * size(pw) = sum(size(pane(0..#pane))) + sum(size(sash(0..#sash)))
- * size(pane[i]) >= 0, for 0 <= i < #pane
- * size(sash[i]) >= 0, for 0 <= i < #sash
- * ==> pos(pane[i]) <= pos(sash[i]) <= pos(pane[i+1]), for 0 <= i < #sash
- *
- * Assumption: all sashes are the same size.
- */
-
-/*------------------------------------------------------------------------
- * +++ Widget record.
- */
-
-typedef struct {
- Tcl_Obj *orientObj;
- int orient;
- int width;
- int height;
- Ttk_Manager *mgr;
- Tk_OptionTable paneOptionTable;
- Ttk_Layout sashLayout;
- int sashThickness;
-} PanedPart;
-
-typedef struct {
- WidgetCore core;
- PanedPart paned;
-} Paned;
-
-/* @@@ NOTE: -orient is readonly 'cause dynamic oriention changes NYI
- */
-static Tk_OptionSpec PanedOptionSpecs[] = {
- {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "vertical",
- Tk_Offset(Paned,paned.orientObj), Tk_Offset(Paned,paned.orient),
- 0,(ClientData)ttkOrientStrings,READONLY_OPTION|STYLE_CHANGED },
- {TK_OPTION_INT, "-width", "width", "Width", "0",
- -1,Tk_Offset(Paned,paned.width),
- 0,0,GEOMETRY_CHANGED },
- {TK_OPTION_INT, "-height", "height", "Height", "0",
- -1,Tk_Offset(Paned,paned.height),
- 0,0,GEOMETRY_CHANGED },
-
- WIDGET_TAKEFOCUS_FALSE,
- WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
-};
-
-/*------------------------------------------------------------------------
- * +++ Slave pane record.
- */
-typedef struct {
- int reqSize; /* Pane request size */
- int sashPos; /* Folowing sash position */
- int weight; /* Pane -weight, for resizing */
-} Pane;
-
-static Tk_OptionSpec PaneOptionSpecs[] = {
- {TK_OPTION_INT, "-weight", "weight", "Weight", "0",
- -1,Tk_Offset(Pane,weight), 0,0,GEOMETRY_CHANGED },
- {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0}
-};
-
-/* CreatePane --
- * Create a new pane record.
- */
-static Pane *CreatePane(Tcl_Interp *interp, Paned *pw, Tk_Window slaveWindow)
-{
- Tk_OptionTable optionTable = pw->paned.paneOptionTable;
- void *record = ckalloc(sizeof(Pane));
- Pane *pane = record;
-
- memset(record, 0, sizeof(Pane));
- if (Tk_InitOptions(interp, record, optionTable, slaveWindow) != TCL_OK) {
- ckfree(record);
- return NULL;
- }
-
- pane->reqSize
- = pw->paned.orient == TTK_ORIENT_HORIZONTAL
- ? Tk_ReqWidth(slaveWindow) : Tk_ReqHeight(slaveWindow);
-
- return pane;
-}
-
-/* DestroyPane --
- * Free pane record.
- */
-static void DestroyPane(Paned *pw, Pane *pane)
-{
- void *record = pane;
- Tk_FreeConfigOptions(record, pw->paned.paneOptionTable, pw->core.tkwin);
- ckfree(record);
-}
-
-/* ConfigurePane --
- * Set pane options.
- */
-static int ConfigurePane(
- Tcl_Interp *interp, Paned *pw, Pane *pane, Tk_Window slaveWindow,
- int objc, Tcl_Obj *const objv[])
-{
- Ttk_Manager *mgr = pw->paned.mgr;
- Tk_SavedOptions savedOptions;
- int mask = 0;
-
- if (Tk_SetOptions(interp, (void*)pane, pw->paned.paneOptionTable,
- objc, objv, slaveWindow, &savedOptions, &mask) != TCL_OK)
- {
- return TCL_ERROR;
- }
-
- /* Sanity-check:
- */
- if (pane->weight < 0) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "-weight must be nonnegative", -1));
- Tcl_SetErrorCode(interp, "TTK", "PANE", "WEIGHT", NULL);
- goto error;
- }
-
- /* Done.
- */
- Tk_FreeSavedOptions(&savedOptions);
- Ttk_ManagerSizeChanged(mgr);
- return TCL_OK;
-
-error:
- Tk_RestoreSavedOptions(&savedOptions);
- return TCL_ERROR;
-}
-
-
-/*------------------------------------------------------------------------
- * +++ Sash adjustment.
- */
-
-/* ShoveUp --
- * Place sash i at specified position, recursively shoving
- * previous sashes upwards as needed, until hitting the top
- * of the window. If that happens, shove back down.
- *
- * Returns: final position of sash i.
- */
-
-static int ShoveUp(Paned *pw, int i, int pos)
-{
- Pane *pane = Ttk_SlaveData(pw->paned.mgr, i);
- int sashThickness = pw->paned.sashThickness;
-
- if (i == 0) {
- if (pos < 0)
- pos = 0;
- } else {
- Pane *prevPane = Ttk_SlaveData(pw->paned.mgr, i-1);
- if (pos < prevPane->sashPos + sashThickness)
- pos = ShoveUp(pw, i-1, pos - sashThickness) + sashThickness;
- }
- return pane->sashPos = pos;
-}
-
-/* ShoveDown --
- * Same as ShoveUp, but going in the opposite direction
- * and stopping at the sentinel sash.
- */
-static int ShoveDown(Paned *pw, int i, int pos)
-{
- Pane *pane = Ttk_SlaveData(pw->paned.mgr,i);
- int sashThickness = pw->paned.sashThickness;
-
- if (i == Ttk_NumberSlaves(pw->paned.mgr) - 1) {
- pos = pane->sashPos; /* Sentinel value == master window size */
- } else {
- Pane *nextPane = Ttk_SlaveData(pw->paned.mgr,i+1);
- if (pos + sashThickness > nextPane->sashPos)
- pos = ShoveDown(pw, i+1, pos + sashThickness) - sashThickness;
- }
- return pane->sashPos = pos;
-}
-
-/* PanedSize --
- * Compute the requested size of the paned widget
- * from the individual pane request sizes.
- *
- * Used as the WidgetSpec sizeProc and the ManagerSpec sizeProc.
- */
-static int PanedSize(void *recordPtr, int *widthPtr, int *heightPtr)
-{
- Paned *pw = recordPtr;
- int nPanes = Ttk_NumberSlaves(pw->paned.mgr);
- int nSashes = nPanes - 1;
- int sashThickness = pw->paned.sashThickness;
- int width = 0, height = 0;
- int index;
-
- if (pw->paned.orient == TTK_ORIENT_HORIZONTAL) {
- for (index = 0; index < nPanes; ++index) {
- Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
- Tk_Window slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, index);
-
- if (height < Tk_ReqHeight(slaveWindow))
- height = Tk_ReqHeight(slaveWindow);
- width += pane->reqSize;
- }
- width += nSashes * sashThickness;
- } else {
- for (index = 0; index < nPanes; ++index) {
- Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
- Tk_Window slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, index);
-
- if (width < Tk_ReqWidth(slaveWindow))
- width = Tk_ReqWidth(slaveWindow);
- height += pane->reqSize;
- }
- height += nSashes * sashThickness;
- }
-
- *widthPtr = pw->paned.width > 0 ? pw->paned.width : width;
- *heightPtr = pw->paned.height > 0 ? pw->paned.height : height;
- return 1;
-}
-
-/* AdjustPanes --
- * Set pane request sizes from sash positions.
- *
- * NOTE:
- * AdjustPanes followed by PlaceSashes (called during relayout)
- * will leave the sashes in the same place, as long as available size
- * remains contant.
- */
-static void AdjustPanes(Paned *pw)
-{
- int sashThickness = pw->paned.sashThickness;
- int pos = 0;
- int index;
-
- for (index = 0; index < Ttk_NumberSlaves(pw->paned.mgr); ++index) {
- Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
- int size = pane->sashPos - pos;
- pane->reqSize = size >= 0 ? size : 0;
- pos = pane->sashPos + sashThickness;
- }
-}
-
-/* PlaceSashes --
- * Set sash positions from pane request sizes and available space.
- * The sentinel sash position is set to the available space.
- *
- * Allocate pane->reqSize pixels to each pane, and distribute
- * the difference = available size - requested size according
- * to pane->weight.
- *
- * If there's still some left over, squeeze panes from the bottom up
- * (This can happen if all weights are zero, or if one or more panes
- * are too small to absorb the required shrinkage).
- *
- * Notes:
- * This doesn't distribute the remainder pixels as evenly as it could
- * when more than one pane has weight > 1.
- */
-static void PlaceSashes(Paned *pw, int width, int height)
-{
- Ttk_Manager *mgr = pw->paned.mgr;
- int nPanes = Ttk_NumberSlaves(mgr);
- int sashThickness = pw->paned.sashThickness;
- int available = pw->paned.orient == TTK_ORIENT_HORIZONTAL ? width : height;
- int reqSize = 0, totalWeight = 0;
- int difference, delta, remainder, pos, i;
-
- if (nPanes == 0)
- return;
-
- /* Compute total required size and total available weight:
- */
- for (i = 0; i < nPanes; ++i) {
- Pane *pane = Ttk_SlaveData(mgr, i);
- reqSize += pane->reqSize;
- totalWeight += pane->weight * (pane->reqSize != 0);
- }
-
- /* Compute difference to be redistributed:
- */
- difference = available - reqSize - sashThickness*(nPanes-1);
- if (totalWeight != 0) {
- delta = difference / totalWeight;
- remainder = difference % totalWeight;
- if (remainder < 0) {
- --delta;
- remainder += totalWeight;
- }
- } else {
- delta = remainder = 0;
- }
- /* ASSERT: 0 <= remainder < totalWeight */
-
- /* Place sashes:
- */
- pos = 0;
- for (i = 0; i < nPanes; ++i) {
- Pane *pane = Ttk_SlaveData(mgr, i);
- int weight = pane->weight * (pane->reqSize != 0);
- int size = pane->reqSize + delta * weight;
-
- if (weight > remainder)
- weight = remainder;
- remainder -= weight;
- size += weight;
-
- if (size < 0)
- size = 0;
-
- pane->sashPos = (pos += size);
- pos += sashThickness;
- }
-
- /* Handle emergency shrink/emergency stretch:
- * Set sentinel sash position to end of widget,
- * shove preceding sashes up.
- */
- ShoveUp(pw, nPanes - 1, available);
-}
-
-/* PlacePanes --
- * Places slave panes based on sash positions.
- */
-static void PlacePanes(Paned *pw)
-{
- int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL;
- int width = Tk_Width(pw->core.tkwin), height = Tk_Height(pw->core.tkwin);
- int sashThickness = pw->paned.sashThickness;
- int pos = 0;
- int index;
-
- for (index = 0; index < Ttk_NumberSlaves(pw->paned.mgr); ++index) {
- Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
- int size = pane->sashPos - pos;
-
- if (size > 0) {
- if (horizontal) {
- Ttk_PlaceSlave(pw->paned.mgr, index, pos, 0, size, height);
- } else {
- Ttk_PlaceSlave(pw->paned.mgr, index, 0, pos, width, size);
- }
- } else {
- Ttk_UnmapSlave(pw->paned.mgr, index);
- }
-
- pos = pane->sashPos + sashThickness;
- }
-}
-
-/*------------------------------------------------------------------------
- * +++ Manager specification.
- */
-
-static void PanedPlaceSlaves(void *managerData)
-{
- Paned *pw = managerData;
- PlaceSashes(pw, Tk_Width(pw->core.tkwin), Tk_Height(pw->core.tkwin));
- PlacePanes(pw);
-}
-
-static void PaneRemoved(void *managerData, int index)
-{
- Paned *pw = managerData;
- Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
- DestroyPane(pw, pane);
-}
-
-static int AddPane(
- Tcl_Interp *interp, Paned *pw,
- int destIndex, Tk_Window slaveWindow,
- int objc, Tcl_Obj *const objv[])
-{
- Pane *pane;
- if (!Ttk_Maintainable(interp, slaveWindow, pw->core.tkwin)) {
- return TCL_ERROR;
- }
- if (Ttk_SlaveIndex(pw->paned.mgr, slaveWindow) >= 0) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "%s already added", Tk_PathName(slaveWindow)));
- Tcl_SetErrorCode(interp, "TTK", "PANE", "PRESENT", NULL);
- return TCL_ERROR;
- }
-
- pane = CreatePane(interp, pw, slaveWindow);
- if (!pane) {
- return TCL_ERROR;
- }
- if (ConfigurePane(interp, pw, pane, slaveWindow, objc, objv) != TCL_OK) {
- DestroyPane(pw, pane);
- return TCL_ERROR;
- }
-
- Ttk_InsertSlave(pw->paned.mgr, destIndex, slaveWindow, pane);
- return TCL_OK;
-}
-
-/* PaneRequest --
- * Only update pane request size if slave is currently unmapped.
- * Geometry requests from mapped slaves are not directly honored
- * in order to avoid unexpected pane resizes (esp. while the
- * user is dragging a sash [#1325286]).
- */
-static int PaneRequest(void *managerData, int index, int width, int height)
-{
- Paned *pw = managerData;
- Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
- Tk_Window slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, index);
- int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL;
-
- if (!Tk_IsMapped(slaveWindow)) {
- pane->reqSize = horizontal ? width : height;
- }
- return 1;
-}
-
-static Ttk_ManagerSpec PanedManagerSpec = {
- { "panedwindow", Ttk_GeometryRequestProc, Ttk_LostSlaveProc },
- PanedSize,
- PanedPlaceSlaves,
- PaneRequest,
- PaneRemoved
-};
-
-/*------------------------------------------------------------------------
- * +++ Event handler.
- *
- * <<NOTE-PW-LEAVE-NOTIFYINFERIOR>>
- * Tk does not execute binding scripts for <Leave> events when
- * the pointer crosses from a parent to a child. This widget
- * needs to know when that happens, though, so it can reset
- * the cursor.
- *
- * This event handler generates an <<EnteredChild>> virtual event
- * on LeaveNotify/NotifyInferior.
- */
-
-static const unsigned PanedEventMask = LeaveWindowMask;
-static void PanedEventProc(ClientData clientData, XEvent *eventPtr)
-{
- WidgetCore *corePtr = clientData;
- if ( eventPtr->type == LeaveNotify
- && eventPtr->xcrossing.detail == NotifyInferior)
- {
- TtkSendVirtualEvent(corePtr->tkwin, "EnteredChild");
- }
-}
-
-/*------------------------------------------------------------------------
- * +++ Initialization and cleanup hooks.
- */
-
-static void PanedInitialize(Tcl_Interp *interp, void *recordPtr)
-{
- Paned *pw = recordPtr;
-
- Tk_CreateEventHandler(pw->core.tkwin,
- PanedEventMask, PanedEventProc, recordPtr);
- pw->paned.mgr = Ttk_CreateManager(&PanedManagerSpec, pw, pw->core.tkwin);
- pw->paned.paneOptionTable = Tk_CreateOptionTable(interp,PaneOptionSpecs);
- pw->paned.sashLayout = 0;
- pw->paned.sashThickness = 1;
-}
-
-static void PanedCleanup(void *recordPtr)
-{
- Paned *pw = recordPtr;
-
- if (pw->paned.sashLayout)
- Ttk_FreeLayout(pw->paned.sashLayout);
- Tk_DeleteEventHandler(pw->core.tkwin,
- PanedEventMask, PanedEventProc, recordPtr);
- Ttk_DeleteManager(pw->paned.mgr);
-}
-
-/* Post-configuration hook.
- */
-static int PanedPostConfigure(Tcl_Interp *interp, void *clientData, int mask)
-{
- Paned *pw = clientData;
-
- if (mask & GEOMETRY_CHANGED) {
- /* User has changed -width or -height.
- * Recalculate sash positions based on requested size.
- */
- Tk_Window tkwin = pw->core.tkwin;
- PlaceSashes(pw,
- pw->paned.width > 0 ? pw->paned.width : Tk_Width(tkwin),
- pw->paned.height > 0 ? pw->paned.height : Tk_Height(tkwin));
- }
-
- return TCL_OK;
-}
-
-/*------------------------------------------------------------------------
- * +++ Layout management hooks.
- */
-static Ttk_Layout PanedGetLayout(
- Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr)
-{
- Paned *pw = recordPtr;
- Ttk_Layout panedLayout = TtkWidgetGetLayout(interp, themePtr, recordPtr);
-
- if (panedLayout) {
- int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL;
- const char *layoutName =
- horizontal ? ".Vertical.Sash" : ".Horizontal.Sash";
- Ttk_Layout sashLayout = Ttk_CreateSublayout(
- interp, themePtr, panedLayout, layoutName, pw->core.optionTable);
-
- if (sashLayout) {
- int sashWidth, sashHeight;
-
- Ttk_LayoutSize(sashLayout, 0, &sashWidth, &sashHeight);
- pw->paned.sashThickness = horizontal ? sashWidth : sashHeight;
-
- if (pw->paned.sashLayout)
- Ttk_FreeLayout(pw->paned.sashLayout);
- pw->paned.sashLayout = sashLayout;
- } else {
- Ttk_FreeLayout(panedLayout);
- return 0;
- }
- }
-
- return panedLayout;
-}
-
-/*------------------------------------------------------------------------
- * +++ Drawing routines.
- */
-
-/* SashLayout --
- * Place the sash sublayout after the specified pane,
- * in preparation for drawing.
- */
-static Ttk_Layout SashLayout(Paned *pw, int index)
-{
- Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
- int thickness = pw->paned.sashThickness,
- height = Tk_Height(pw->core.tkwin),
- width = Tk_Width(pw->core.tkwin),
- sashPos = pane->sashPos;
-
- Ttk_PlaceLayout(
- pw->paned.sashLayout, pw->core.state,
- pw->paned.orient == TTK_ORIENT_HORIZONTAL
- ? Ttk_MakeBox(sashPos, 0, thickness, height)
- : Ttk_MakeBox(0, sashPos, width, thickness));
-
- return pw->paned.sashLayout;
-}
-
-static void DrawSash(Paned *pw, int index, Drawable d)
-{
- Ttk_DrawLayout(SashLayout(pw, index), pw->core.state, d);
-}
-
-static void PanedDisplay(void *recordPtr, Drawable d)
-{
- Paned *pw = recordPtr;
- int i, nSashes = Ttk_NumberSlaves(pw->paned.mgr) - 1;
-
- TtkWidgetDisplay(recordPtr, d);
- for (i = 0; i < nSashes; ++i) {
- DrawSash(pw, i, d);
- }
-}
-
-/*------------------------------------------------------------------------
- * +++ Widget commands.
- */
-
-/* $pw add window [ options ... ]
- */
-static int PanedAddCommand(
- void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
-{
- Paned *pw = recordPtr;
- Tk_Window slaveWindow;
-
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "window");
- return TCL_ERROR;
- }
-
- slaveWindow = Tk_NameToWindow(
- interp, Tcl_GetString(objv[2]), pw->core.tkwin);
-
- if (!slaveWindow) {
- return TCL_ERROR;
- }
-
- return AddPane(interp, pw, Ttk_NumberSlaves(pw->paned.mgr), slaveWindow,
- objc - 3, objv + 3);
-}
-
-/* $pw insert $index $slave ?-option value ...?
- * Insert new slave, or move existing one.
- */
-static int PanedInsertCommand(
- void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
-{
- Paned *pw = recordPtr;
- int nSlaves = Ttk_NumberSlaves(pw->paned.mgr);
- int srcIndex, destIndex;
- Tk_Window slaveWindow;
-
- if (objc < 4) {
- Tcl_WrongNumArgs(interp, 2,objv, "index slave ?-option value ...?");
- return TCL_ERROR;
- }
-
- slaveWindow = Tk_NameToWindow(
- interp, Tcl_GetString(objv[3]), pw->core.tkwin);
- if (!slaveWindow) {
- return TCL_ERROR;
- }
-
- if (!strcmp(Tcl_GetString(objv[2]), "end")) {
- destIndex = Ttk_NumberSlaves(pw->paned.mgr);
- } else if (TCL_OK != Ttk_GetSlaveIndexFromObj(
- interp,pw->paned.mgr,objv[2],&destIndex))
- {
- return TCL_ERROR;
- }
-
- srcIndex = Ttk_SlaveIndex(pw->paned.mgr, slaveWindow);
- if (srcIndex < 0) { /* New slave: */
- return AddPane(interp, pw, destIndex, slaveWindow, objc-4, objv+4);
- } /* else -- move existing slave: */
-
- if (destIndex >= nSlaves)
- destIndex = nSlaves - 1;
- Ttk_ReorderSlave(pw->paned.mgr, srcIndex, destIndex);
-
- return objc == 4 ? TCL_OK :
- ConfigurePane(interp, pw,
- Ttk_SlaveData(pw->paned.mgr, destIndex),
- Ttk_SlaveWindow(pw->paned.mgr, destIndex),
- objc-4,objv+4);
-}
-
-/* $pw forget $pane
- */
-static int PanedForgetCommand(
- void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
-{
- Paned *pw = recordPtr;
- int paneIndex;
-
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2,objv, "pane");
- return TCL_ERROR;
- }
-
- if (TCL_OK != Ttk_GetSlaveIndexFromObj(
- interp, pw->paned.mgr, objv[2], &paneIndex))
- {
- return TCL_ERROR;
- }
- Ttk_ForgetSlave(pw->paned.mgr, paneIndex);
-
- return TCL_OK;
-}
-
-/* $pw identify ?what? $x $y --
- * Return index of sash at $x,$y
- */
-static int PanedIdentifyCommand(
- void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
-{
- static const char *whatTable[] = { "element", "sash", NULL };
- enum { IDENTIFY_ELEMENT, IDENTIFY_SASH };
- int what = IDENTIFY_SASH;
- Paned *pw = recordPtr;
- int sashThickness = pw->paned.sashThickness;
- int nSashes = Ttk_NumberSlaves(pw->paned.mgr) - 1;
- int x, y, pos;
- int index;
-
- if (objc < 4 || objc > 5) {
- Tcl_WrongNumArgs(interp, 2,objv, "?what? x y");
- return TCL_ERROR;
- }
-
- if ( Tcl_GetIntFromObj(interp, objv[objc-2], &x) != TCL_OK
- || Tcl_GetIntFromObj(interp, objv[objc-1], &y) != TCL_OK
- || (objc == 5 && Tcl_GetIndexFromObjStruct(interp, objv[2], whatTable,
- sizeof(char *), "option", 0, &what) != TCL_OK)
- ) {
- return TCL_ERROR;
- }
-
- pos = pw->paned.orient == TTK_ORIENT_HORIZONTAL ? x : y;
- for (index = 0; index < nSashes; ++index) {
- Pane *pane = Ttk_SlaveData(pw->paned.mgr, index);
- if (pane->sashPos <= pos && pos <= pane->sashPos + sashThickness) {
- /* Found it. */
- switch (what) {
- case IDENTIFY_SASH:
- Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
- return TCL_OK;
- case IDENTIFY_ELEMENT:
- {
- Ttk_Element element =
- Ttk_IdentifyElement(SashLayout(pw, index), x, y);
- if (element) {
- Tcl_SetObjResult(interp,
- Tcl_NewStringObj(Ttk_ElementName(element), -1));
- }
- return TCL_OK;
- }
- }
- }
- }
-
- return TCL_OK; /* nothing found - return empty string */
-}
-
-/* $pw pane $pane ?-option ?value -option value ...??
- * Query/modify pane options.
- */
-static int PanedPaneCommand(
- void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
-{
- Paned *pw = recordPtr;
- int paneIndex;
- Tk_Window slaveWindow;
- Pane *pane;
-
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2,objv, "pane ?-option value ...?");
- return TCL_ERROR;
- }
-
- if (TCL_OK != Ttk_GetSlaveIndexFromObj(
- interp,pw->paned.mgr,objv[2],&paneIndex))
- {
- return TCL_ERROR;
- }
-
- pane = Ttk_SlaveData(pw->paned.mgr, paneIndex);
- slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, paneIndex);
-
- switch (objc) {
- case 3:
- return TtkEnumerateOptions(interp, pane, PaneOptionSpecs,
- pw->paned.paneOptionTable, slaveWindow);
- case 4:
- return TtkGetOptionValue(interp, pane, objv[3],
- pw->paned.paneOptionTable, slaveWindow);
- default:
- return ConfigurePane(interp, pw, pane, slaveWindow, objc-3,objv+3);
- }
-}
-
-/* $pw panes --
- * Return list of managed panes.
- */
-static int PanedPanesCommand(
- void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
-{
- Paned *pw = recordPtr;
- Ttk_Manager *mgr = pw->paned.mgr;
- Tcl_Obj *panes;
- int i;
-
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, "");
- return TCL_ERROR;
- }
-
- panes = Tcl_NewListObj(0, NULL);
- for (i = 0; i < Ttk_NumberSlaves(mgr); ++i) {
- const char *pathName = Tk_PathName(Ttk_SlaveWindow(mgr,i));
- Tcl_ListObjAppendElement(interp, panes, Tcl_NewStringObj(pathName,-1));
- }
- Tcl_SetObjResult(interp, panes);
-
- return TCL_OK;
-}
-
-
-/* $pw sashpos $index ?$newpos?
- * Query or modify sash position.
- */
-static int PanedSashposCommand(
- void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
-{
- Paned *pw = recordPtr;
- int sashIndex, position = -1;
- Pane *pane;
-
- if (objc < 3 || objc > 4) {
- Tcl_WrongNumArgs(interp, 2,objv, "index ?newpos?");
- return TCL_ERROR;
- }
- if (Tcl_GetIntFromObj(interp, objv[2], &sashIndex) != TCL_OK) {
- return TCL_ERROR;
- }
- if (sashIndex < 0 || sashIndex >= Ttk_NumberSlaves(pw->paned.mgr) - 1) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "sash index %d out of range", sashIndex));
- Tcl_SetErrorCode(interp, "TTK", "PANE", "SASH_INDEX", NULL);
- return TCL_ERROR;
- }
-
- pane = Ttk_SlaveData(pw->paned.mgr, sashIndex);
-
- if (objc == 3) {
- Tcl_SetObjResult(interp, Tcl_NewIntObj(pane->sashPos));
- return TCL_OK;
- }
- /* else -- set new sash position */
-
- if (Tcl_GetIntFromObj(interp, objv[3], &position) != TCL_OK) {
- return TCL_ERROR;
- }
-
- if (position < pane->sashPos) {
- ShoveUp(pw, sashIndex, position);
- } else {
- ShoveDown(pw, sashIndex, position);
- }
-
- AdjustPanes(pw);
- Ttk_ManagerLayoutChanged(pw->paned.mgr);
-
- Tcl_SetObjResult(interp, Tcl_NewIntObj(pane->sashPos));
- return TCL_OK;
-}
-
-static const Ttk_Ensemble PanedCommands[] = {
- { "add", PanedAddCommand,0 },
- { "configure", TtkWidgetConfigureCommand,0 },
- { "cget", TtkWidgetCgetCommand,0 },
- { "forget", PanedForgetCommand,0 },
- { "identify", PanedIdentifyCommand,0 },
- { "insert", PanedInsertCommand,0 },
- { "instate", TtkWidgetInstateCommand,0 },
- { "pane", PanedPaneCommand,0 },
- { "panes", PanedPanesCommand,0 },
- { "sashpos", PanedSashposCommand,0 },
- { "state", TtkWidgetStateCommand,0 },
- { 0,0,0 }
-};
-
-/*------------------------------------------------------------------------
- * +++ Widget specification.
- */
-
-static WidgetSpec PanedWidgetSpec =
-{
- "TPanedwindow", /* className */
- sizeof(Paned), /* recordSize */
- PanedOptionSpecs, /* optionSpecs */
- PanedCommands, /* subcommands */
- PanedInitialize, /* initializeProc */
- PanedCleanup, /* cleanupProc */
- TtkCoreConfigure, /* configureProc */
- PanedPostConfigure, /* postConfigureProc */
- PanedGetLayout, /* getLayoutProc */
- PanedSize, /* sizeProc */
- TtkWidgetDoLayout, /* layoutProc */
- PanedDisplay /* displayProc */
-};
-
-/*------------------------------------------------------------------------
- * +++ Elements and layouts.
- */
-
-static const int DEFAULT_SASH_THICKNESS = 5;
-
-typedef struct {
- Tcl_Obj *thicknessObj;
-} SashElement;
-
-static Ttk_ElementOptionSpec SashElementOptions[] = {
- { "-sashthickness", TK_OPTION_INT,
- Tk_Offset(SashElement,thicknessObj), "5" },
- { NULL, 0, 0, NULL }
-};
-
-static void SashElementSize(
- void *clientData, void *elementRecord, Tk_Window tkwin,
- int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
-{
- SashElement *sash = elementRecord;
- int thickness = DEFAULT_SASH_THICKNESS;
- Tcl_GetIntFromObj(NULL, sash->thicknessObj, &thickness);
- *widthPtr = *heightPtr = thickness;
-}
-
-static Ttk_ElementSpec SashElementSpec = {
- TK_STYLE_VERSION_2,
- sizeof(SashElement),
- SashElementOptions,
- SashElementSize,
- TtkNullElementDraw
-};
-
-TTK_BEGIN_LAYOUT(PanedLayout)
- TTK_NODE("Panedwindow.background", 0)/* @@@ BUG: empty layouts don't work */
-TTK_END_LAYOUT
-
-TTK_BEGIN_LAYOUT(HorizontalSashLayout)
- TTK_NODE("Sash.hsash", TTK_FILL_X)
-TTK_END_LAYOUT
-
-TTK_BEGIN_LAYOUT(VerticalSashLayout)
- TTK_NODE("Sash.vsash", TTK_FILL_Y)
-TTK_END_LAYOUT
-
-/*------------------------------------------------------------------------
- * +++ Registration routine.
- */
-MODULE_SCOPE
-void TtkPanedwindow_Init(Tcl_Interp *interp)
-{
- Ttk_Theme themePtr = Ttk_GetDefaultTheme(interp);
- RegisterWidget(interp, "ttk::panedwindow", &PanedWidgetSpec);
-
- Ttk_RegisterElement(interp, themePtr, "hsash", &SashElementSpec, 0);
- Ttk_RegisterElement(interp, themePtr, "vsash", &SashElementSpec, 0);
-
- Ttk_RegisterLayout(themePtr, "TPanedwindow", PanedLayout);
- Ttk_RegisterLayout(themePtr, "Horizontal.Sash", HorizontalSashLayout);
- Ttk_RegisterLayout(themePtr, "Vertical.Sash", VerticalSashLayout);
-}
-