From fcd7a3968daa37ea2184e281645832703b9b541a Mon Sep 17 00:00:00 2001 From: jenglish Date: Sat, 9 Jun 2007 21:45:44 +0000 Subject: Ttk_Manager API overhaul: + Ttk_Manager no longer responsible for managing slave records + Ttk_Manager structure now opaque + Ttk_Slave structure now private + Pass Ttk_Manager * to Tk_GeomMgr hooks instead of Ttk_Slave * ttk::labelframe: Simplified -labelwidget management. ttk::noteboook 'insert' command didn't correctly maintain current tab. Changed documentation of ttk::panedwindow 'identify' command to match implementation. --- ChangeLog | 20 ++++ doc/ttk_panedwindow.n | 7 +- generic/ttk/ttkFrame.c | 77 +++++--------- generic/ttk/ttkManager.c | 179 +++++++++++--------------------- generic/ttk/ttkManager.h | 52 ++-------- generic/ttk/ttkNotebook.c | 177 +++++++++++++++++++++---------- generic/ttk/ttkPanedwindow.c | 240 ++++++++++++++++++++++++++++++------------- library/ttk/panedwindow.tcl | 6 +- tests/ttk/notebook.test | 45 +++++++- tests/ttk/panedwindow.test | 7 +- 10 files changed, 460 insertions(+), 350 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0b9c768..f256389 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2007-06-09 Joe English + + * generic/ttk/ttkManager.h, generic/ttk/ttkManager.c, + generic/ttk/ttkNotebook.c, generic/ttk/ttkPanedwindow.c, + generic/ttk/ttkFrame.c: Ttk_Manager API overhaul: + + Ttk_Manager no longer responsible for managing slave records + + Ttk_Manager structure now opaque + + Ttk_Slave structure now private + + Pass Ttk_Manager * to Tk_GeomMgr hooks instead of Ttk_Slave * + + * generic/ttk/ttkFrame.c: Simplified -labelwidget management. + + * doc/ttk_panedwindow.n, library/ttk/panedwindow.tcl: + Changed documentation of ttk::panedwindow 'identify' command + to match implementation. + + * generic/ttk/ttkNotebook.c, tests/ttk/notebook.test: + BUGFIX: ttk::noteboook 'insert' command didn't correctly + maintain current tab. + 2007-06-09 Daniel Steffen * macosx/tkMacOSXColor.c: fix issues with TK_{IF,ELSE,ENDIF} macros; diff --git a/doc/ttk_panedwindow.n b/doc/ttk_panedwindow.n index d823473..4928b15 100644 --- a/doc/ttk_panedwindow.n +++ b/doc/ttk_panedwindow.n @@ -4,7 +4,7 @@ '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" RCS: @(#) $Id: ttk_panedwindow.n,v 1.4 2007/05/03 23:55:30 dkf Exp $ +'\" RCS: @(#) $Id: ttk_panedwindow.n,v 1.5 2007/06/09 21:45:44 jenglish Exp $ '\" .so man.macros .TH ttk_panedwindow n 8.5 Tk "Tk Themed Widget" @@ -82,9 +82,8 @@ If \fInewpos\fR is specified, sets the sash position Returns the position of sash number \fIindex\fR. .TP \fIpathname\fR \fBidentify\fR \fIx y\fR -Returns a list consisting of the sash index at point \fIx,y\fR -and the name of the sash subelement at that point. -Returns the empty list if \fIx,y\fR is not over a sash. +Returns the index of the sash at point \fIx,y\fR, +or the empty string if \fIx,y\fR is not over a sash. .SH "SEE ALSO" ttk_widget(n), ttk_notebook(n), panedwindow(n) diff --git a/generic/ttk/ttkFrame.c b/generic/ttk/ttkFrame.c index ee5259f..08f1f7f 100644 --- a/generic/ttk/ttkFrame.c +++ b/generic/ttk/ttkFrame.c @@ -1,4 +1,4 @@ -/* $Id: ttkFrame.c,v 1.5 2007/01/11 14:49:47 jenglish Exp $ +/* $Id: ttkFrame.c,v 1.6 2007/06/09 21:45:44 jenglish Exp $ * Copyright (c) 2004, Joe English * * ttk::frame and ttk::labelframe widgets. @@ -234,10 +234,9 @@ typedef struct { Tcl_Obj *labelAnchorObj; Tcl_Obj *textObj; Tcl_Obj *underlineObj; - Tcl_Obj *labelWidgetObj; + Tk_Window labelWidget; Ttk_Manager *mgr; - Tk_Window labelWidget; /* Set in configureProc */ Ttk_Box labelParcel; /* Set in layoutProc */ } LabelframePart; @@ -262,7 +261,7 @@ static Tk_OptionSpec LabelframeOptionSpecs[] = "-1", Tk_Offset(Labelframe,label.underlineObj), -1, 0,0,0 }, {TK_OPTION_WINDOW, "-labelwidget", "labelWidget", "LabelWidget", NULL, - Tk_Offset(Labelframe,label.labelWidgetObj), -1, + -1, Tk_Offset(Labelframe,label.labelWidget), TK_OPTION_NULL_OK,0,LABELWIDGET_CHANGED|GEOMETRY_CHANGED }, WIDGET_INHERIT_OPTIONS(FrameOptionSpecs) @@ -454,47 +453,26 @@ static void LabelframePlaceSlaves(void *recordPtr) /* Labelframe geometry manager: */ -static void LabelAdded(Ttk_Manager *mgr, int slaveIndex) { /* no-op */ } -static void LabelRemoved(Ttk_Manager *mgr, int slaveIndex) { /* no-op */ } -static int LabelConfigured( - Tcl_Interp *interp, Ttk_Manager *mgr, Ttk_Slave *slave, unsigned mask) - { return TCL_OK; } - -/* LabelframeLostSlave -- - * Called when the labelWidget slave is involuntarily lost; - * unset the -labelwidget option. - * Notes: - * Do this here instead of in the SlaveRemoved hook, - * since the latter is also called when the widget voluntarily - * forgets the slave. The latter happens in the ConfigureProc - * at a time when the widget is in an inconsistent state. + +/* LabelRemoved -- + * Unset the -labelwidget option. + * + * <>: + * This routine is also called when the widget voluntarily forgets + * the slave in LabelframeConfigure. */ -static void LabelframeLostSlave(ClientData clientData, Tk_Window slaveWindow) +static void LabelRemoved(Ttk_Manager *mgr, int slaveIndex) { - Ttk_Slave *slave = clientData; - Labelframe *lframePtr = slave->manager->managerData; - - Tcl_DecrRefCount(lframePtr->label.labelWidgetObj); - lframePtr->label.labelWidgetObj = 0; - lframePtr->label.labelWidget = 0; - Ttk_LostSlaveProc(clientData, slaveWindow); + Labelframe *lframe = Ttk_ManagerData(mgr); + lframe->label.labelWidget = 0; } -static Tk_OptionSpec LabelOptionSpecs[] = { - {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0, 0,0} -}; - static Ttk_ManagerSpec LabelframeManagerSpec = { - { "labelframe", Ttk_GeometryRequestProc, LabelframeLostSlave }, - LabelOptionSpecs, 0, - + { "labelframe", Ttk_GeometryRequestProc, Ttk_LostSlaveProc }, LabelframeSize, LabelframePlaceSlaves, - - LabelAdded, - LabelRemoved, - LabelConfigured + LabelRemoved }; /* LabelframeInitialize -- @@ -546,22 +524,14 @@ static void RaiseLabelWidget(Labelframe *lframe) static int LabelframeConfigure(Tcl_Interp *interp,void *recordPtr,int mask) { Labelframe *lframePtr = recordPtr; - Tk_Window labelWidget = NULL; + Tk_Window labelWidget = lframePtr->label.labelWidget; Ttk_PositionSpec unused; - /* Validate -labelwidget option: + /* Validate options: */ - if (lframePtr->label.labelWidgetObj) { - const char *pathName = Tcl_GetString(lframePtr->label.labelWidgetObj); - if (pathName && *pathName) { - labelWidget = - Tk_NameToWindow(interp, pathName, lframePtr->core.tkwin); - if (!labelWidget) { - return TCL_ERROR; - } - if (!Ttk_Maintainable(interp, labelWidget, lframePtr->core.tkwin)) { - return TCL_ERROR; - } + if (mask & LABELWIDGET_CHANGED && labelWidget != NULL) { + if (!Ttk_Maintainable(interp, labelWidget, lframePtr->core.tkwin)) { + return TCL_ERROR; } } @@ -582,12 +552,13 @@ static int LabelframeConfigure(Tcl_Interp *interp,void *recordPtr,int mask) if (mask & LABELWIDGET_CHANGED) { if (Ttk_NumberSlaves(lframePtr->label.mgr) == 1) { Ttk_ForgetSlave(lframePtr->label.mgr, 0); + /* Restore labelWidget field (see <>) + */ + lframePtr->label.labelWidget = labelWidget; } - lframePtr->label.labelWidget = labelWidget; - if (labelWidget) { - Ttk_AddSlave(interp, lframePtr->label.mgr, labelWidget, 0, 0,0); + Ttk_InsertSlave(lframePtr->label.mgr, 0, labelWidget, NULL); RaiseLabelWidget(lframePtr); } } diff --git a/generic/ttk/ttkManager.c b/generic/ttk/ttkManager.c index 319e465..3c9d51c 100644 --- a/generic/ttk/ttkManager.c +++ b/generic/ttk/ttkManager.c @@ -1,8 +1,8 @@ -/* $Id: ttkManager.c,v 1.3 2007/01/11 19:59:26 jenglish Exp $ +/* $Id: ttkManager.c,v 1.4 2007/06/09 21:45:44 jenglish Exp $ * * Copyright 2005, Joe English. Freely redistributable. * - * Ttk widget set: support routines for geometry managers. + * Support routines for geometry managers. */ #include @@ -41,19 +41,38 @@ * in this case Tk does _not_ call the LostSlaveProc (documented behavior). * Tk doesn't handle case (3) either; to account for that we * register an event handler on the slave widget to track events. - * */ -/* ++ manager->flags bits: +/* ++ Data structures. */ -#define MGR_UPDATE_PENDING 0x1 -#define MGR_RESIZE_REQUIRED 0x2 -#define MGR_RELAYOUT_REQUIRED 0x4 +typedef struct +{ + Tk_Window slaveWindow; + Ttk_Manager *manager; + void *slaveData; + unsigned flags; +} Ttk_Slave; -/* ++ slave->flags bits: +/* slave->flags bits: */ #define SLAVE_MAPPED 0x1 /* slave to be mapped when master is */ +struct TtkManager_ +{ + Ttk_ManagerSpec *managerSpec; + void *managerData; + Tk_Window masterWindow; + unsigned flags; + int nSlaves; + Ttk_Slave **slaves; +}; + +/* manager->flags bits: + */ +#define MGR_UPDATE_PENDING 0x1 +#define MGR_RESIZE_REQUIRED 0x2 +#define MGR_RELAYOUT_REQUIRED 0x4 + static void ManagerIdleProc(void *); /* forward */ /* ++ ScheduleUpdate -- @@ -103,7 +122,7 @@ static void ManagerIdleProc(ClientData clientData) if (mgr->flags & MGR_RESIZE_REQUIRED) { RecomputeSize(mgr); - } + } if (mgr->flags & MGR_RELAYOUT_REQUIRED) { if (mgr->flags & MGR_UPDATE_PENDING) { /* RecomputeSize has scheduled another update; relayout later */ @@ -127,7 +146,7 @@ static void ManagerEventHandler(ClientData clientData, XEvent *eventPtr) Ttk_Manager *mgr = clientData; int i; - switch (eventPtr->type) + switch (eventPtr->type) { case ConfigureNotify: RecomputeLayout(mgr); @@ -159,7 +178,7 @@ static void SlaveEventHandler(ClientData clientData, XEvent *eventPtr) Ttk_Slave *slave = clientData; if (eventPtr->type == DestroyNotify) { slave->manager->managerSpec->tkGeomMgr.lostSlaveProc( - clientData, slave->slaveWindow); + slave->manager, slave->slaveWindow); } } @@ -167,40 +186,21 @@ static void SlaveEventHandler(ClientData clientData, XEvent *eventPtr) * +++ Slave initialization and cleanup. */ -static Ttk_Slave *CreateSlave( - Tcl_Interp *interp, Ttk_Manager *mgr, Tk_Window slaveWindow) +static Ttk_Slave *NewSlave( + Ttk_Manager *mgr, Tk_Window slaveWindow, void *slaveData) { Ttk_Slave *slave = (Ttk_Slave*)ckalloc(sizeof(*slave)); - int status; slave->slaveWindow = slaveWindow; slave->manager = mgr; slave->flags = 0; - slave->slaveData = ckalloc(mgr->managerSpec->slaveSize); - memset(slave->slaveData, 0, mgr->managerSpec->slaveSize); - - if (!mgr->slaveOptionTable) { - mgr->slaveOptionTable = - Tk_CreateOptionTable(interp, mgr->managerSpec->slaveOptionSpecs); - } - - status = Tk_InitOptions( - interp, slave->slaveData, mgr->slaveOptionTable, slaveWindow); - - if (status != TCL_OK) { - ckfree((ClientData)slave->slaveData); - ckfree((ClientData)slave); - return NULL; - } + slave->slaveData = slaveData; return slave; } static void DeleteSlave(Ttk_Slave *slave) { - Tk_FreeConfigOptions( - slave->slaveData, slave->manager->slaveOptionTable, slave->slaveWindow); - ckfree((ClientData)slave->slaveData); ckfree((ClientData)slave); } @@ -216,7 +216,6 @@ Ttk_Manager *Ttk_CreateManager( mgr->managerSpec = managerSpec; mgr->managerData = managerData; mgr->masterWindow = masterWindow; - mgr->slaveOptionTable= 0; mgr->nSlaves = 0; mgr->slaves = NULL; mgr->flags = 0; @@ -238,9 +237,6 @@ void Ttk_DeleteManager(Ttk_Manager *mgr) if (mgr->slaves) { ckfree((ClientData)mgr->slaves); } - if (mgr->slaveOptionTable) { - Tk_DeleteOptionTable(mgr->slaveOptionTable); - } Tk_CancelIdleCall(ManagerIdleProc, mgr); @@ -268,7 +264,7 @@ static void InsertSlave(Ttk_Manager *mgr, Ttk_Slave *slave, int index) mgr->slaves[index] = slave; Tk_ManageGeometry(slave->slaveWindow, - &mgr->managerSpec->tkGeomMgr, (ClientData)slave); + &mgr->managerSpec->tkGeomMgr, (ClientData)mgr); Tk_CreateEventHandler(slave->slaveWindow, SlaveEventMask, SlaveEventHandler, (ClientData)slave); @@ -281,7 +277,7 @@ static void InsertSlave(Ttk_Manager *mgr, Ttk_Slave *slave, int index) * * NOTES/ASSUMPTIONS: * - * [1] It's safe to call Tk_UnmapWindow / Tk_UnmaintainGeometry even if this + * [1] It's safe to call Tk_UnmapWindow / Tk_UnmaintainGeometry even if this * routine is called from the slave's DestroyNotify event handler. */ static void RemoveSlave(Ttk_Manager *mgr, int index) @@ -320,85 +316,31 @@ static void RemoveSlave(Ttk_Manager *mgr, int index) void Ttk_GeometryRequestProc(ClientData clientData, Tk_Window slaveWindow) { - Ttk_Slave *slave = clientData; - ScheduleUpdate(slave->manager, MGR_RESIZE_REQUIRED); + Ttk_Manager *mgr = clientData; + ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED); } void Ttk_LostSlaveProc(ClientData clientData, Tk_Window slaveWindow) { - Ttk_Slave *slave = clientData; - int index = Ttk_SlaveIndex(slave->manager, slave->slaveWindow); + Ttk_Manager *mgr = clientData; + int index = Ttk_SlaveIndex(mgr, slaveWindow); /* ASSERT: index >= 0 */ - RemoveSlave(slave->manager, index); + RemoveSlave(mgr, index); } /*------------------------------------------------------------------------ * +++ Public API. */ -/* ++ Ttk_AddSlave -- - * Create and configure new slave window, insert at specified index. - * - * Returns: - * TCL_OK or TCL_ERROR; in the case of TCL_ERROR, the slave - * is not added and an error message is left in interp. +/* ++ Ttk_InsertSlave -- + * Add a new slave window at the specified index. */ -int Ttk_AddSlave( - Tcl_Interp *interp, Ttk_Manager *mgr, Tk_Window slaveWindow, - int index, int objc, Tcl_Obj *CONST objv[]) +void Ttk_InsertSlave( + Ttk_Manager *mgr, int index, Tk_Window tkwin, void *slaveData) { - Ttk_Slave *slave; - - /* Sanity-checks: - */ - if (!Ttk_Maintainable(interp, slaveWindow, mgr->masterWindow)) { - return TCL_ERROR; - } - if (Ttk_SlaveIndex(mgr, slaveWindow) >= 0) { - Tcl_AppendResult(interp, - Tk_PathName(slaveWindow), " already added", - NULL); - return TCL_ERROR; - } - - /* Create, configure, and insert slave: - */ - slave = CreateSlave(interp, mgr, slaveWindow); - if (Ttk_ConfigureSlave(interp, mgr, slave, objc, objv) != TCL_OK) { - DeleteSlave(slave); - return TCL_ERROR; - } + Ttk_Slave *slave = NewSlave(mgr, tkwin, slaveData); InsertSlave(mgr, slave, index); - mgr->managerSpec->SlaveAdded(mgr, index); - return TCL_OK; -} - -/* ++ Ttk_ConfigureSlave -- - */ -int Ttk_ConfigureSlave( - Tcl_Interp *interp, Ttk_Manager *mgr, Ttk_Slave *slave, - int objc, Tcl_Obj *CONST objv[]) -{ - Tk_SavedOptions savedOptions; - int mask = 0; - - /* ASSERT: mgr->slaveOptionTable != NULL */ - - if (Tk_SetOptions(interp, slave->slaveData, mgr->slaveOptionTable, - objc, objv, slave->slaveWindow, &savedOptions, &mask) != TCL_OK) - { - return TCL_ERROR; - } - - if (mgr->managerSpec->SlaveConfigured(interp,mgr,slave,mask) != TCL_OK) { - Tk_RestoreSavedOptions(&savedOptions); - return TCL_ERROR; - } - - Tk_FreeSavedOptions(&savedOptions); - ScheduleUpdate(mgr, MGR_RELAYOUT_REQUIRED); - return TCL_OK; } /* ++ Ttk_ForgetSlave -- @@ -437,7 +379,7 @@ void Ttk_UnmapSlave(Ttk_Manager *mgr, int slaveIndex) Ttk_Slave *slave = mgr->slaves[slaveIndex]; Tk_UnmaintainGeometry(slave->slaveWindow, mgr->masterWindow); slave->flags &= ~SLAVE_MAPPED; - /* Contrary to documentation, Tk_UnmaintainGeometry doesn't always + /* Contrary to documentation, Tk_UnmaintainGeometry doesn't always * unmap the slave: */ Tk_UnmapWindow(slave->slaveWindow); @@ -458,9 +400,13 @@ void Ttk_ManagerSizeChanged(Ttk_Manager *mgr) /* +++ Accessors. */ -int Ttk_NumberSlaves(Ttk_Manager *mgr) +int Ttk_NumberSlaves(Ttk_Manager *mgr) { - return mgr->nSlaves; + return mgr->nSlaves; +} +void *Ttk_ManagerData(Ttk_Manager *mgr) +{ + return mgr->managerData; } void *Ttk_SlaveData(Ttk_Manager *mgr, int slaveIndex) { @@ -487,17 +433,16 @@ int Ttk_SlaveIndex(Ttk_Manager *mgr, Tk_Window slaveWindow) return -1; } -/* ++ Ttk_GetSlaveFromObj(interp, mgr, objPtr, indexPtr) -- +/* ++ Ttk_GetSlaveIndexFromObj(interp, mgr, objPtr, indexPtr) -- * Return the index of the slave specified by objPtr. * Slaves may be specified as an integer index or * as the name of the managed window. * * Returns: - * Pointer to slave; stores slave index in *indexPtr. - * On error, returns NULL and leaves an error message in interp. + * Standard Tcl completion code. Leaves an error message in case of error. */ -Ttk_Slave *Ttk_GetSlaveFromObj( +int Ttk_GetSlaveIndexFromObj( Tcl_Interp *interp, Ttk_Manager *mgr, Tcl_Obj *objPtr, int *indexPtr) { const char *string = Tcl_GetString(objPtr); @@ -512,10 +457,10 @@ Ttk_Slave *Ttk_GetSlaveFromObj( Tcl_AppendResult(interp, "Slave index ", Tcl_GetString(objPtr), " out of bounds", NULL); - return NULL; + return TCL_ERROR; } *indexPtr = slaveIndex; - return mgr->slaves[slaveIndex]; + return TCL_OK; } /* Try interpreting as a slave window name; @@ -529,15 +474,15 @@ Ttk_Slave *Ttk_GetSlaveFromObj( Tcl_AppendResult(interp, string, " is not managed by ", Tk_PathName(mgr->masterWindow), NULL); - return NULL; + return TCL_ERROR; } *indexPtr = slaveIndex; - return mgr->slaves[slaveIndex]; + return TCL_OK; } Tcl_ResetResult(interp); Tcl_AppendResult(interp, "Invalid slave specification ", string, NULL); - return NULL; + return TCL_ERROR; } /* ++ Ttk_ReorderSlave(mgr, fromIndex, toIndex) -- @@ -569,7 +514,7 @@ void Ttk_ReorderSlave(Ttk_Manager *mgr, int fromIndex, int toIndex) /* ++ Ttk_Maintainable(interp, slave, master) -- * Utility routine. Verifies that 'master' may be used to maintain * the geometry of 'slave' via Tk_MaintainGeometry: - * + * * + 'master' is either 'slave's parent -OR- * + 'master is a descendant of 'slave's parent. * + 'slave' is not a toplevel window @@ -596,7 +541,7 @@ int Ttk_Maintainable(Tcl_Interp *interp, Tk_Window slave, Tk_Window master) return 1; badWindow: - Tcl_AppendResult(interp, + Tcl_AppendResult(interp, "can't add ", Tk_PathName(slave), " as slave of ", Tk_PathName(master), NULL); diff --git a/generic/ttk/ttkManager.h b/generic/ttk/ttkManager.h index c03c3da..550fe62 100644 --- a/generic/ttk/ttkManager.h +++ b/generic/ttk/ttkManager.h @@ -1,10 +1,8 @@ -/* $Id: ttkManager.h,v 1.5 2007/01/11 14:49:47 jenglish Exp $ +/* $Id: ttkManager.h,v 1.6 2007/06/09 21:45:44 jenglish Exp $ * * Copyright (c) 2005, Joe English. Freely redistributable. * - * Ttk widget set: Geometry management utilities. - * - * TODO: opacify data structures. + * Geometry manager utilities. */ #ifndef _TTKMANAGER @@ -12,8 +10,7 @@ #include "ttkTheme.h" -typedef struct TtkManager_ Ttk_Manager; /* forward */ -typedef struct TtkSlave_ Ttk_Slave; /* forward */ +typedef struct TtkManager_ Ttk_Manager; /* * Geometry manager specification record: @@ -23,24 +20,16 @@ typedef struct TtkSlave_ Ttk_Slave; /* forward */ * PlaceSlaves sets the position and size of all managed slaves * by calling Ttk_PlaceSlave(). * - * SlaveAdded() is called after a new slave has been added. - * * SlaveRemoved() is called immediately before a slave is removed. * NB: the associated slave window may have been destroyed when this * routine is called. */ typedef struct { /* Manager hooks */ Tk_GeomMgr tkGeomMgr; /* "real" Tk Geometry Manager */ - Tk_OptionSpec *slaveOptionSpecs; /* slave record options */ - size_t slaveSize; /* size of slave record */ int (*RequestedSize)(void *managerData, int *widthPtr, int *heightPtr); void (*PlaceSlaves)(void *managerData); - - void (*SlaveAdded)(Ttk_Manager *, int slaveIndex); void (*SlaveRemoved)(Ttk_Manager *, int slaveIndex); - int (*SlaveConfigured)( - Tcl_Interp *, Ttk_Manager *, Ttk_Slave *, unsigned mask); } Ttk_ManagerSpec; /* @@ -49,25 +38,6 @@ typedef struct { /* Manager hooks */ MODULE_SCOPE void Ttk_GeometryRequestProc(ClientData, Tk_Window slave); MODULE_SCOPE void Ttk_LostSlaveProc(ClientData, Tk_Window slave); -struct TtkSlave_ -{ - Tk_Window slaveWindow; - Ttk_Manager *manager; - void *slaveData; - unsigned flags; /* private; see manager.c */ -}; - -struct TtkManager_ -{ - Ttk_ManagerSpec *managerSpec; - void *managerData; - Tk_Window masterWindow; - Tk_OptionTable slaveOptionTable; - unsigned flags; /* private; see manager.c */ - int nSlaves; - Ttk_Slave **slaves; -}; - /* * Public API: */ @@ -75,16 +45,11 @@ MODULE_SCOPE Ttk_Manager *Ttk_CreateManager( Ttk_ManagerSpec *, void *managerData, Tk_Window masterWindow); MODULE_SCOPE void Ttk_DeleteManager(Ttk_Manager *); -MODULE_SCOPE int Ttk_AddSlave( - Tcl_Interp *, Ttk_Manager *, Tk_Window, int position, - int objc, Tcl_Obj *CONST objv[]); +MODULE_SCOPE void Ttk_InsertSlave( + Ttk_Manager *, int position, Tk_Window, void *slaveData); MODULE_SCOPE void Ttk_ForgetSlave(Ttk_Manager *, int slaveIndex); -MODULE_SCOPE int Ttk_ConfigureSlave( - Tcl_Interp *interp, Ttk_Manager *, Ttk_Slave *, - int objc, Tcl_Obj *CONST objv[]); - MODULE_SCOPE void Ttk_ReorderSlave(Ttk_Manager *, int fromIndex, int toIndex); /* Rearrange slave positions */ @@ -104,7 +69,7 @@ MODULE_SCOPE void Ttk_ManagerLayoutChanged(Ttk_Manager *); MODULE_SCOPE int Ttk_SlaveIndex(Ttk_Manager *, Tk_Window); /* Returns: index in slave array of specified window, -1 if not found */ -MODULE_SCOPE Ttk_Slave *Ttk_GetSlaveFromObj( +MODULE_SCOPE int Ttk_GetSlaveIndexFromObj( Tcl_Interp *, Ttk_Manager *, Tcl_Obj *, int *indexPtr); /* Accessor functions: @@ -112,8 +77,11 @@ MODULE_SCOPE Ttk_Slave *Ttk_GetSlaveFromObj( MODULE_SCOPE int Ttk_NumberSlaves(Ttk_Manager *); /* Returns: number of managed slaves */ +MODULE_SCOPE void *Ttk_ManagerData(Ttk_Manager *); + /* Returns: client data associated with master */ + MODULE_SCOPE void *Ttk_SlaveData(Ttk_Manager *, int slaveIndex); - /* Returns: private data associated with slave */ + /* Returns: client data associated with slave */ MODULE_SCOPE Tk_Window Ttk_SlaveWindow(Ttk_Manager *, int slaveIndex); /* Returns: slave window */ diff --git a/generic/ttk/ttkNotebook.c b/generic/ttk/ttkNotebook.c index a9596b9..a90f465 100644 --- a/generic/ttk/ttkNotebook.c +++ b/generic/ttk/ttkNotebook.c @@ -1,4 +1,4 @@ -/* $Id: ttkNotebook.c,v 1.8 2007/01/11 19:59:26 jenglish Exp $ +/* $Id: ttkNotebook.c,v 1.9 2007/06/09 21:45:44 jenglish Exp $ * Copyright (c) 2004, Joe English * * NOTE-ACTIVE: activeTabIndex is not always correct (it's @@ -188,6 +188,67 @@ static void NotebookStyleOptions(Notebook *nb, NotebookStyle *nbstyle) * +++ Tab management. */ +static Tab *CreateTab(Tcl_Interp *interp, Notebook *nb, Tk_Window slaveWindow) +{ + Tk_OptionTable optionTable = nb->notebook.paneOptionTable; + void *record = ckalloc(sizeof(Tab)); + memset(record, 0, sizeof(Tab)); + + if (Tk_InitOptions(interp, record, optionTable, slaveWindow) != TCL_OK) { + ckfree(record); + return NULL; + } + + return record; +} + +static void DestroyTab(Notebook *nb, Tab *tab) +{ + void *record = tab; + Tk_FreeConfigOptions(record, nb->notebook.paneOptionTable, nb->core.tkwin); + ckfree(record); +} + +static int ConfigureTab( + Tcl_Interp *interp, Notebook *nb, Tab *tab, Tk_Window slaveWindow, + int objc, Tcl_Obj *CONST objv[]) +{ + Ttk_Sticky sticky = tab->sticky; + Ttk_Padding padding = tab->padding; + Tk_SavedOptions savedOptions; + int mask = 0; + + if (Tk_SetOptions(interp, (ClientData)tab, nb->notebook.paneOptionTable, + objc, objv, slaveWindow, &savedOptions, &mask) != TCL_OK) + { + return TCL_ERROR; + } + + /* Check options: + * @@@ TODO: validate -image option. + */ + if (Ttk_GetStickyFromObj(interp, tab->stickyObj, &sticky) != TCL_OK) + { + goto error; + } + if (Ttk_GetPaddingFromObj(interp, slaveWindow, tab->paddingObj, &padding) + != TCL_OK) + { + goto error; + } + + tab->sticky = sticky; + tab->padding = padding; + + Tk_FreeSavedOptions(&savedOptions); + Ttk_ManagerSizeChanged(nb->notebook.mgr); + + return TCL_OK; +error: + Tk_RestoreSavedOptions(&savedOptions); + return TCL_ERROR; +} + /* * IdentifyTab -- * Return the index of the tab at point x,y, @@ -605,17 +666,14 @@ static void SelectNearestTab(Notebook *nb) } } -/* TabAdded -- GM SlaveAdded hook. - */ -static void TabAdded(Ttk_Manager *mgr, int slaveIndex) { /* No-op */ } - /* TabRemoved -- GM SlaveRemoved hook. * Select the next tab if the current one is being removed. - * Adjust currentIndex to account for removed slave if needed. + * Adjust currentIndex to account for removed slave. */ static void TabRemoved(Ttk_Manager *mgr, int index) { - Notebook *nb = mgr->managerData; + Notebook *nb = Ttk_ManagerData(mgr); + Tab *tab = Ttk_SlaveData(mgr, index); if (index == nb->notebook.currentIndex) { SelectNearestTab(nb); @@ -625,44 +683,49 @@ static void TabRemoved(Ttk_Manager *mgr, int index) --nb->notebook.currentIndex; } + DestroyTab(nb, tab); + TtkRedisplayWidget(&nb->core); } -/* TabConfigured -- GM slaveConfigured hook. - */ -static int TabConfigured( - Tcl_Interp *interp, Ttk_Manager *mgr, Ttk_Slave *slave, unsigned mask) + +static int AddTab( + Tcl_Interp *interp, Notebook *nb, + int destIndex, Tk_Window slaveWindow, + int objc, Tcl_Obj *const objv[]) { - Tab *tab = slave->slaveData; - Ttk_Sticky sticky = tab->sticky; - Tk_Window tkwin = mgr->masterWindow; + Tab *tab; + if (!Ttk_Maintainable(interp, slaveWindow, nb->core.tkwin)) { + return TCL_ERROR; + } + if (Ttk_SlaveIndex(nb->notebook.mgr, slaveWindow) >= 0) { + Tcl_AppendResult(interp, + Tk_PathName(slaveWindow), " already added", + NULL); + return TCL_ERROR; + } - /* Check options: - * @@@ TODO: validate -image option. + /* Create and insert tab. */ - if (Ttk_GetStickyFromObj(interp, tab->stickyObj, &sticky) != TCL_OK) { + tab = CreateTab(interp, nb, slaveWindow); + if (!tab) { return TCL_ERROR; } - if (Ttk_GetPaddingFromObj(interp,tkwin,tab->paddingObj,&tab->padding) - != TCL_OK) - { + if (ConfigureTab(interp, nb, tab, slaveWindow, objc, objv) != TCL_OK) { + DestroyTab(nb, tab); return TCL_ERROR; } - tab->sticky = sticky; + Ttk_InsertSlave(nb->notebook.mgr, destIndex, slaveWindow, tab); return TCL_OK; } static Ttk_ManagerSpec NotebookManagerSpec = { { "notebook", Ttk_GeometryRequestProc, Ttk_LostSlaveProc }, - PaneOptionSpecs, sizeof(Tab), - NotebookSize, NotebookPlaceSlaves, - TabAdded, TabRemoved, - TabConfigured }; /*------------------------------------------------------------------------ @@ -736,13 +799,13 @@ static int FindTabIndex( /* ... or integer index or slave window name: */ - if (Ttk_GetSlaveFromObj( - interp, nb->notebook.mgr, objPtr, index_rtn) != NULL) + if (Ttk_GetSlaveIndexFromObj( + interp, nb->notebook.mgr, objPtr, index_rtn) == TCL_OK) { return TCL_OK; } - /* Nothing matched; Ttk_GetSlaveFromObj will have left error message. + /* Nothing matched; Ttk_GetSlaveIndexFromObj will have left error message. */ return TCL_ERROR; } @@ -777,7 +840,7 @@ static int NotebookAddCommand( Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], void *recordPtr) { Notebook *nb = recordPtr; - int index = nb->notebook.mgr->nSlaves; + int index = Ttk_NumberSlaves(nb->notebook.mgr); Tk_Window slaveWindow; if (objc <= 2 || objc % 2 != 1) { @@ -792,10 +855,8 @@ static int NotebookAddCommand( /* Create and initialize new tab: */ - if (TCL_OK != Ttk_AddSlave( - interp, nb->notebook.mgr, slaveWindow, index, objc-3,objv+3) ) - { - return TCL_ERROR; + if (AddTab(interp, nb, index, slaveWindow, objc-3,objv+3) != TCL_OK) { + return TCL_ERROR; } /* If no tab is currently selected (or if this is the first tab), @@ -818,6 +879,7 @@ static int NotebookInsertCommand( { Notebook *nb = recordPtr; int current = nb->notebook.currentIndex; + int nSlaves = Ttk_NumberSlaves(nb->notebook.mgr); int srcIndex, destIndex; int status = TCL_OK; @@ -828,26 +890,28 @@ static int NotebookInsertCommand( if (!strcmp(Tcl_GetString(objv[2]), "end")) { destIndex = Ttk_NumberSlaves(nb->notebook.mgr); - } else if (!Ttk_GetSlaveFromObj( + } else if (TCL_OK != Ttk_GetSlaveIndexFromObj( interp, nb->notebook.mgr, objv[2], &destIndex)) { return TCL_ERROR; } - if (!Ttk_GetSlaveFromObj(interp, nb->notebook.mgr, objv[3], &srcIndex)) { + if (TCL_OK != Ttk_GetSlaveIndexFromObj( + interp, nb->notebook.mgr, objv[3], &srcIndex)) + { /* Try adding new slave: */ Tk_Window slaveWindow = Tk_NameToWindow(interp,Tcl_GetString(objv[3]),nb->core.tkwin); + + /* Check validity. + */ if (!slaveWindow) { return TCL_ERROR; } - - if (Ttk_AddSlave(interp, nb->notebook.mgr, slaveWindow, - destIndex, objc - 4, objv + 4) != TCL_OK) - { + if (TCL_OK != AddTab(interp,nb,destIndex,slaveWindow,objc-4,objv+4)) { return TCL_ERROR; } - if (nb->notebook.currentIndex <= destIndex) { + if (nb->notebook.currentIndex >= destIndex) { ++nb->notebook.currentIndex; } return TCL_OK; @@ -855,8 +919,8 @@ static int NotebookInsertCommand( /* else - move existing slave: */ - if (destIndex >= nb->notebook.mgr->nSlaves) { - destIndex = nb->notebook.mgr->nSlaves - 1; + if (destIndex >= nSlaves) { + destIndex = nSlaves - 1; } Ttk_ReorderSlave(nb->notebook.mgr, srcIndex, destIndex); @@ -872,8 +936,10 @@ static int NotebookInsertCommand( } if (objc > 4) { - status = Ttk_ConfigureSlave(interp, nb->notebook.mgr, - nb->notebook.mgr->slaves[destIndex], objc-4,objv+4); + status = ConfigureTab(interp, nb, + Ttk_SlaveData(nb->notebook.mgr,destIndex), + Ttk_SlaveWindow(nb->notebook.mgr,destIndex), + objc-4,objv+4); } TtkRedisplayWidget(&nb->core); @@ -934,7 +1000,7 @@ static int NotebookIdentifyCommand( Ttk_RebindSublayout(tabLayout, tab); Ttk_PlaceLayout(tabLayout, state, tab->parcel); - node = Ttk_LayoutIdentify(tabLayout, x, y); + node = Ttk_LayoutIdentify(tabLayout, x, y); } if (node) { @@ -965,7 +1031,8 @@ static int NotebookIndexCommand( * Special-case for "end": */ if (!strcmp("end", Tcl_GetString(objv[2]))) { - Tcl_SetObjResult(interp, Tcl_NewIntObj(nb->notebook.mgr->nSlaves)); + int nSlaves = Ttk_NumberSlaves(nb->notebook.mgr); + Tcl_SetObjResult(interp, Tcl_NewIntObj(nSlaves)); return TCL_OK; } @@ -1021,7 +1088,7 @@ static int NotebookTabsCommand( } result = Tcl_NewListObj(0, NULL); - for (i = 0; i < mgr->nSlaves; ++i) { + for (i = 0; i < Ttk_NumberSlaves(mgr); ++i) { const char *pathName = Tk_PathName(Ttk_SlaveWindow(mgr,i)); Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(pathName,-1)); } @@ -1038,7 +1105,7 @@ static int NotebookTabCommand( Notebook *nb = recordPtr; Ttk_Manager *mgr = nb->notebook.mgr; int index; - Ttk_Slave *slave; + Tk_Window slaveWindow; Tab *tab; if (objc < 3) { @@ -1050,18 +1117,18 @@ static int NotebookTabCommand( return TCL_ERROR; } - slave = mgr->slaves[index]; tab = Ttk_SlaveData(mgr, index); + slaveWindow = Ttk_SlaveWindow(mgr, index); if (objc == 3) { return TtkEnumerateOptions(interp, tab, - PaneOptionSpecs, nb->notebook.paneOptionTable, nb->core.tkwin); + PaneOptionSpecs, nb->notebook.paneOptionTable, slaveWindow); } else if (objc == 4) { return TtkGetOptionValue(interp, tab, objv[3], - nb->notebook.paneOptionTable, nb->core.tkwin); + nb->notebook.paneOptionTable, slaveWindow); } /* else */ - if (Ttk_ConfigureSlave(interp, mgr, slave, objc - 3,objv + 3) != TCL_OK) { + if (ConfigureTab(interp, nb, tab, slaveWindow, objc-3,objv+3) != TCL_OK) { return TCL_ERROR; } @@ -1180,7 +1247,8 @@ static Ttk_Layout NotebookGetLayout( return notebookLayout; } -/* +++ Display routines. +/*------------------------------------------------------------------------ + * +++ Display routines. */ static void DisplayTab(Notebook *nb, int index, Drawable d) @@ -1199,6 +1267,7 @@ static void DisplayTab(Notebook *nb, int index, Drawable d) static void NotebookDisplay(void *clientData, Drawable d) { Notebook *nb = clientData; + int nSlaves = Ttk_NumberSlaves(nb->notebook.mgr); int index; /* Draw notebook background (base layout): @@ -1208,7 +1277,7 @@ static void NotebookDisplay(void *clientData, Drawable d) /* Draw tabs from left to right, but draw the current tab last * so it will overwrite its neighbors. */ - for (index = 0; index < nb->notebook.mgr->nSlaves; ++index) { + for (index = 0; index < nSlaves; ++index) { if (index != nb->notebook.currentIndex) { DisplayTab(nb, index, d); } diff --git a/generic/ttk/ttkPanedwindow.c b/generic/ttk/ttkPanedwindow.c index ccc376d..7de701c 100644 --- a/generic/ttk/ttkPanedwindow.c +++ b/generic/ttk/ttkPanedwindow.c @@ -1,4 +1,4 @@ -/* $Id: ttkPanedwindow.c,v 1.9 2007/01/11 14:49:47 jenglish Exp $ +/* $Id: ttkPanedwindow.c,v 1.10 2007/06/09 21:45:45 jenglish Exp $ * * Copyright (c) 2005, Joe English. Freely redistributable. * @@ -64,6 +64,7 @@ typedef struct { Tcl_Obj *orientObj; int orient; Ttk_Manager *mgr; + Tk_OptionTable paneOptionTable; Ttk_Layout sashLayout; int sashThickness; } PanedPart; @@ -98,6 +99,74 @@ static Tk_OptionSpec PaneOptionSpecs[] = { {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_AppendResult(interp, "-weight must be nonnegative", NULL); + goto error; + } + + /* Done. + */ + Tk_FreeSavedOptions(&savedOptions); + Ttk_ManagerSizeChanged(mgr); + return TCL_OK; + +error: + Tk_RestoreSavedOptions(&savedOptions); + return TCL_ERROR; +} + + /*------------------------------------------------------------------------ * +++ Layout algorithm. */ @@ -135,7 +204,7 @@ static int ShoveDown(Paned *pw, int i, int pos) Pane *pane = Ttk_SlaveData(pw->paned.mgr,i); int sashThickness = pw->paned.sashThickness; - if (i == pw->paned.mgr->nSlaves - 1) { + 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); @@ -146,8 +215,10 @@ static int ShoveDown(Paned *pw, int i, int pos) } /* PanedSize -- - * Compute the requested size of the paned widget. - * Used as both the WidgetSpec sizeProc and the ManagerSpec sizeProc. + * 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) { @@ -326,29 +397,39 @@ static void PanedPlaceSlaves(void *managerData) PlacePanes(pw); } -static void PaneAdded(Ttk_Manager *mgr, int index) +static void PaneRemoved(Ttk_Manager *mgr, int index) { + Paned *pw = Ttk_ManagerData(mgr); Pane *pane = Ttk_SlaveData(mgr, index); - Tk_Window slaveWindow = Ttk_SlaveWindow(mgr, index); - Paned *pw = mgr->managerData; - - /* See also: PanedGeometryRequestProc */ - pane->reqSize - = pw->paned.orient == TTK_ORIENT_HORIZONTAL - ? Tk_ReqWidth(slaveWindow) : Tk_ReqHeight(slaveWindow); + DestroyPane(pw, pane); } -static void PaneRemoved(Ttk_Manager *mgr, int i) { /*no-op*/ } - -static int PaneConfigured( - Tcl_Interp *interp, Ttk_Manager *mgr, Ttk_Slave *slave, unsigned mask) +static int AddPane( + Tcl_Interp *interp, Paned *pw, + int destIndex, Tk_Window slaveWindow, + int objc, Tcl_Obj *const objv[]) { - Pane *pane = slave->slaveData; - if (pane->weight < 0) { - Tcl_AppendResult(interp, "-weight must be nonnegative", NULL); - pane->weight = 0; + Pane *pane; + if (!Ttk_Maintainable(interp, slaveWindow, pw->core.tkwin)) { + return TCL_ERROR; + } + if (Ttk_SlaveIndex(pw->paned.mgr, slaveWindow) >= 0) { + Tcl_AppendResult(interp, + Tk_PathName(slaveWindow), " already added", + 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; } @@ -358,15 +439,15 @@ static int PaneConfigured( * in order to avoid unexpected pane resizes (esp. while the * user is dragging a sash [#1325286]). */ - static void PanedGeometryRequestProc( ClientData clientData, Tk_Window slaveWindow) { - Ttk_Slave *slave = clientData; - Pane *pane = slave->slaveData; - Paned *pw = slave->manager->managerData; + Ttk_Manager *mgr = clientData; + Paned *pw = Ttk_ManagerData(mgr); if (!Tk_IsMapped(slaveWindow)) { + int slaveIndex = Ttk_SlaveIndex(mgr, slaveWindow); /* ASSERT: != -1 */ + Pane *pane = Ttk_SlaveData(mgr, slaveIndex); pane->reqSize = pw->paned.orient == TTK_ORIENT_HORIZONTAL ? Tk_ReqWidth(slaveWindow) : Tk_ReqHeight(slaveWindow); @@ -379,12 +460,9 @@ static void PanedGeometryRequestProc( static Ttk_ManagerSpec PanedManagerSpec = { { "panedwindow", PanedGeometryRequestProc, Ttk_LostSlaveProc }, - PaneOptionSpecs, sizeof(Pane), PanedSize, PanedPlaceSlaves, - PaneAdded, - PaneRemoved, - PaneConfigured, + PaneRemoved }; /*------------------------------------------------------------------------ @@ -422,6 +500,7 @@ static int PanedInitialize(Tcl_Interp *interp, void *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; @@ -450,7 +529,7 @@ static Ttk_Layout PanedGetLayout( if (panedLayout) { int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL; - const char *layoutName = + const char *layoutName = horizontal ? ".Vertical.Sash" : ".Horizontal.Sash"; Ttk_Layout sashLayout = Ttk_CreateSublayout( interp, themePtr, panedLayout, layoutName, pw->core.optionTable); @@ -478,35 +557,39 @@ static Ttk_Layout PanedGetLayout( return panedLayout; } -static void PanedDisplay(void *recordPtr, Drawable d) +/*------------------------------------------------------------------------ + * +++ Drawing routines. + */ + +static void DrawSash(Paned *pw, Drawable d, Ttk_Box b) { - Paned *pw = recordPtr; - int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL; Ttk_Layout sashLayout = pw->paned.sashLayout; - int sashThickness = pw->paned.sashThickness; Ttk_State state = pw->core.state; - int nPanes = Ttk_NumberSlaves(pw->paned.mgr); + + Ttk_PlaceLayout(sashLayout, state, b); + Ttk_DrawLayout(sashLayout, state, d); +} + +static void PanedDisplay(void *recordPtr, Drawable d) +{ + Paned *pw = recordPtr; + int nPanes = Ttk_NumberSlaves(pw->paned.mgr), + horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL, + thickness = pw->paned.sashThickness, + height = Tk_Height(pw->core.tkwin), + width = Tk_Width(pw->core.tkwin); int i; TtkWidgetDisplay(recordPtr, d); /* Draw sashes: */ - if (horizontal) { - int height = Tk_Height(pw->core.tkwin); - for (i = 0; i < nPanes; ++i) { - Pane *pane = Ttk_SlaveData(pw->paned.mgr, i); - Ttk_PlaceLayout(sashLayout, state, - Ttk_MakeBox(pane->sashPos, 0, sashThickness, height)); - Ttk_DrawLayout(sashLayout, state, d); - } - } else { - int width = Tk_Width(pw->core.tkwin); - for (i = 0; i < nPanes; ++i) { - Pane *pane = Ttk_SlaveData(pw->paned.mgr, i); - Ttk_PlaceLayout(sashLayout, state, - Ttk_MakeBox(0, pane->sashPos, width, sashThickness)); - Ttk_DrawLayout(sashLayout, state, d); + for (i = 0; i < nPanes; ++i) { + Pane *pane = Ttk_SlaveData(pw->paned.mgr, i); + if (horizontal) { + DrawSash(pw, d, Ttk_MakeBox(pane->sashPos, 0, thickness, height)); + } else { + DrawSash(pw, d, Ttk_MakeBox(0, pane->sashPos, width, thickness)); } } } @@ -535,8 +618,8 @@ static int PanedAddCommand( return TCL_ERROR; } - return Ttk_AddSlave(interp, pw->paned.mgr, slaveWindow, - Ttk_NumberSlaves(pw->paned.mgr), objc - 3, objv + 3); + return AddPane(interp, pw, Ttk_NumberSlaves(pw->paned.mgr), slaveWindow, + objc - 3, objv + 3); } /* $pw insert $index $slave ?options...? @@ -546,6 +629,7 @@ static int PanedInsertCommand( Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], void *recordPtr) { Paned *pw = recordPtr; + int nSlaves = Ttk_NumberSlaves(pw->paned.mgr); int srcIndex, destIndex; Tk_Window slaveWindow; @@ -562,23 +646,26 @@ static int PanedInsertCommand( if (!strcmp(Tcl_GetString(objv[2]), "end")) { destIndex = Ttk_NumberSlaves(pw->paned.mgr); - } else if (!Ttk_GetSlaveFromObj(interp,pw->paned.mgr,objv[2],&destIndex)) { + } 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 Ttk_AddSlave(interp, pw->paned.mgr, slaveWindow, - destIndex, objc - 4, objv + 4); + return AddPane(interp, pw, destIndex, slaveWindow, objc-4, objv+4); } /* else -- move existing slave: */ - if (destIndex >= pw->paned.mgr->nSlaves) - destIndex = pw->paned.mgr->nSlaves - 1; + if (destIndex >= nSlaves) + destIndex = nSlaves - 1; Ttk_ReorderSlave(pw->paned.mgr, srcIndex, destIndex); return objc == 4 ? TCL_OK : - Ttk_ConfigureSlave(interp, pw->paned.mgr, - pw->paned.mgr->slaves[destIndex], objc-4,objv+4); + ConfigurePane(interp, pw, + Ttk_SlaveData(pw->paned.mgr, destIndex), + Ttk_SlaveWindow(pw->paned.mgr, destIndex), + objc-4,objv+4); } /* $pw forget $pane @@ -594,7 +681,9 @@ static int PanedForgetCommand( return TCL_ERROR; } - if (!Ttk_GetSlaveFromObj(interp, pw->paned.mgr, objv[2], &paneIndex)) { + if (TCL_OK != Ttk_GetSlaveIndexFromObj( + interp, pw->paned.mgr, objv[2], &paneIndex)) + { return TCL_ERROR; } Ttk_ForgetSlave(pw->paned.mgr, paneIndex); @@ -602,14 +691,15 @@ static int PanedForgetCommand( return TCL_OK; } -/* $pw identify $x $y - * @@@ TODO: implement as documented, or change documentation. +/* $pw identify $x $y -- + * Return index of sash at $x,$y */ static int PanedIdentifyCommand( Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], void *recordPtr) { Paned *pw = recordPtr; int sashThickness = pw->paned.sashThickness; + int nSashes = Ttk_NumberSlaves(pw->paned.mgr) - 1; int x, y, pos; int index; @@ -624,7 +714,7 @@ static int PanedIdentifyCommand( } pos = pw->paned.orient == TTK_ORIENT_HORIZONTAL ? x : y; - for (index = 0; index < pw->paned.mgr->nSlaves - 1; ++index) { + for (index = 0; index < nSashes; ++index) { Pane *pane = Ttk_SlaveData(pw->paned.mgr, index); if (pane->sashPos <= pos && pos <= pane->sashPos + sashThickness) { Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); @@ -632,7 +722,7 @@ static int PanedIdentifyCommand( } } - return TCL_OK; /* empty list */ + return TCL_OK; /* return empty string */ } /* $pw pane $pane ?-option ?value -option value ...?? @@ -643,28 +733,32 @@ static int PanedPaneCommand( { Paned *pw = recordPtr; int paneIndex; - Ttk_Slave *slave; + Tk_Window slaveWindow; + Pane *pane; if (objc < 3) { Tcl_WrongNumArgs(interp, 2,objv, "pane ?-option value...?"); return TCL_ERROR; } - slave = Ttk_GetSlaveFromObj(interp,pw->paned.mgr,objv[2],&paneIndex); - if (!slave) { + 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, slave->slaveData, PaneOptionSpecs, - pw->paned.mgr->slaveOptionTable, slave->slaveWindow); + return TtkEnumerateOptions(interp, pane, PaneOptionSpecs, + pw->paned.paneOptionTable, slaveWindow); case 4: - return TtkGetOptionValue(interp, slave->slaveData,objv[3], - pw->paned.mgr->slaveOptionTable, slave->slaveWindow); + return TtkGetOptionValue(interp, pane, objv[3], + pw->paned.paneOptionTable, slaveWindow); default: - return Ttk_ConfigureSlave( - interp, pw->paned.mgr, slave, objc-3,objv+3); + return ConfigurePane(interp, pw, pane, slaveWindow, objc-3,objv+3); } } @@ -745,7 +839,7 @@ static WidgetSpec PanedWidgetSpec = PanedInitialize, /* initializeProc */ PanedCleanup, /* cleanupProc */ TtkCoreConfigure, /* configureProc */ - TtkNullPostConfigure, /* postConfigureProc */ + TtkNullPostConfigure, /* postConfigureProc */ PanedGetLayout, /* getLayoutProc */ PanedSize, /* sizeProc */ TtkWidgetDoLayout, /* layoutProc */ diff --git a/library/ttk/panedwindow.tcl b/library/ttk/panedwindow.tcl index 15ec4f8..9cb046d 100644 --- a/library/ttk/panedwindow.tcl +++ b/library/ttk/panedwindow.tcl @@ -1,5 +1,5 @@ # -# $Id: panedwindow.tcl,v 1.3 2007/04/13 00:21:47 hobbs Exp $ +# $Id: panedwindow.tcl,v 1.4 2007/06/09 21:45:45 jenglish Exp $ # # Bindings for ttk::panedwindow widget. # @@ -33,8 +33,8 @@ bind TPanedwindow <> { ttk::panedwindow::ResetCursor %W } proc ttk::panedwindow::Press {w x y} { variable State - lassign [$w identify $x $y] sash element - if {![info exists sash] || $sash eq ""} { + set sash [$w identify $x $y] + if {$sash eq ""} { set State(pressed) 0 return } diff --git a/tests/ttk/notebook.test b/tests/ttk/notebook.test index ecb614a..d4c5e4c 100644 --- a/tests/ttk/notebook.test +++ b/tests/ttk/notebook.test @@ -1,5 +1,5 @@ # -# $Id: notebook.test,v 1.1 2006/10/31 01:42:27 hobbs Exp $ +# $Id: notebook.test,v 1.2 2007/06/09 21:45:45 jenglish Exp $ # package require Tk 8.5 @@ -380,6 +380,49 @@ test notebook-7.7d "insert - current tab undisturbed" -body { .nb index current } -result 4 +test notebook-7.8a "move tabs - current tab undisturbed - exhaustive" -body { + .nb select .nb.f0 + foreach i {0 1 2 3 4} { + .nb insert $i .nb.f$i + } + + foreach i {0 1 2 3 4} { + .nb select .nb.f$i + foreach j {0 1 2 3 4} { + foreach k {0 1 2 3 4} { + .nb insert $j $k + set current [lindex [.nb tabs] [.nb index current]] + if {$current != ".nb.f$i"} { + error "($i,$j,$k) current = $current" + } + .nb insert $k $j + if {[.nb tabs] ne [list .nb.f0 .nb.f1 .nb.f2 .nb.f3 .nb.f4]} { + error "swap $j $k; swap $k $j => [.nb tabs]" + } + } + } + } + .nb tabs +} -result [list .nb.f0 .nb.f1 .nb.f2 .nb.f3 .nb.f4] + +test notebook-7.8b "insert new - current tab undisturbed - exhaustive" -body { + foreach i {0 1 2 3 4} { + .nb select .nb.f$i + foreach j {0 1 2 3 4} { +.nb select .nb.f$i + .nb insert $j [frame .nb.newf] + set current [lindex [.nb tabs] [.nb index current]] + if {$current != ".nb.f$i"} { + puts stderr "new tab at $j, current = $current, expect .nb.f$i" + } + destroy .nb.newf + if {[.nb tabs] ne [list .nb.f0 .nb.f1 .nb.f2 .nb.f3 .nb.f4]} { + error "tabs disturbed" + } + } + } +} + test notebook-7.end "insert - cleanup" -body { destroy .nb } diff --git a/tests/ttk/panedwindow.test b/tests/ttk/panedwindow.test index 190e6b5..47764a2 100644 --- a/tests/ttk/panedwindow.test +++ b/tests/ttk/panedwindow.test @@ -1,5 +1,5 @@ # -# $Id: panedwindow.test,v 1.2 2006/11/07 03:45:28 jenglish Exp $ +# $Id: panedwindow.test,v 1.3 2007/06/09 21:45:45 jenglish Exp $ # package require Tk 8.5 @@ -156,10 +156,11 @@ test panedwindow-4.2 "forget forgotten" -body { # proc checkorder {winlist} { set pos -1 + set positions [list] foreach win $winlist { - set nextpos [winfo y $win] + lappend positions [set nextpos [winfo y $win]] if {$nextpos <= $pos} { - error "window $win out of order" + error "window $win out of order ($positions)" } set pos $nextpos } -- cgit v0.12