summaryrefslogtreecommitdiffstats
path: root/generic/ttk/ttkFrame.c
diff options
context:
space:
mode:
authorhobbs <hobbs>2006-10-31 01:42:25 (GMT)
committerhobbs <hobbs>2006-10-31 01:42:25 (GMT)
commit397a2c9832bf618f26be267501cf49ab06a562ec (patch)
tree61d5e957eccfcba57b0dd27ebc73db085385834e /generic/ttk/ttkFrame.c
parent18d330543869e240c2bd12fc9fbb8d5027f5cad6 (diff)
downloadtk-397a2c9832bf618f26be267501cf49ab06a562ec.zip
tk-397a2c9832bf618f26be267501cf49ab06a562ec.tar.gz
tk-397a2c9832bf618f26be267501cf49ab06a562ec.tar.bz2
* doc/ttk_Geometry.3, doc/ttk_Theme.3, doc/ttk_button.n:
* doc/ttk_checkbutton.n, doc/ttk_combobox.n, doc/ttk_dialog.n: * doc/ttk_entry.n, doc/ttk_frame.n, doc/ttk_image.n: * doc/ttk_intro.n, doc/ttk_label.n, doc/ttk_labelframe.n: * doc/ttk_menubutton.n, doc/ttk_notebook.n, doc/ttk_panedwindow.n: * doc/ttk_progressbar.n, doc/ttk_radiobutton.n, doc/ttk_scrollbar.n: * doc/ttk_separator.n, doc/ttk_sizegrip.n, doc/ttk_style.n: * doc/ttk_treeview.n, doc/ttk_widget.n,: * generic/ttk/ttk.decls, generic/ttk/ttkBlink.c: * generic/ttk/ttkButton.c, generic/ttk/ttkCache.c: * generic/ttk/ttkClamTheme.c, generic/ttk/ttkClassicTheme.c: * generic/ttk/ttkDecls.h, generic/ttk/ttkDefaultTheme.c: * generic/ttk/ttkElements.c, generic/ttk/ttkEntry.c: * generic/ttk/ttkFrame.c, generic/ttk/ttkImage.c: * generic/ttk/ttkInit.c, generic/ttk/ttkLabel.c: * generic/ttk/ttkLayout.c, generic/ttk/ttkManager.c: * generic/ttk/ttkManager.h, generic/ttk/ttkNotebook.c: * generic/ttk/ttkPanedwindow.c, generic/ttk/ttkProgress.c: * generic/ttk/ttkScale.c, generic/ttk/ttkScroll.c: * generic/ttk/ttkScrollbar.c, generic/ttk/ttkSeparator.c: * generic/ttk/ttkSquare.c, generic/ttk/ttkState.c: * generic/ttk/ttkStubInit.c, generic/ttk/ttkStubLib.c: * generic/ttk/ttkTagSet.c, generic/ttk/ttkTheme.c: * generic/ttk/ttkTheme.h, generic/ttk/ttkThemeInt.h: * generic/ttk/ttkTrace.c, generic/ttk/ttkTrack.c: * generic/ttk/ttkTreeview.c, generic/ttk/ttkWidget.c: * generic/ttk/ttkWidget.h: * library/demos/ttk_demo.tcl, library/demos/ttk_iconlib.tcl: * library/demos/ttk_repeater.tcl: * library/ttk/altTheme.tcl, library/ttk/aquaTheme.tcl: * library/ttk/button.tcl, library/ttk/clamTheme.tcl: * library/ttk/classicTheme.tcl, library/ttk/combobox.tcl: * library/ttk/cursors.tcl, library/ttk/defaults.tcl: * library/ttk/dialog.tcl, library/ttk/entry.tcl: * library/ttk/fonts.tcl, library/ttk/icons.tcl: * library/ttk/keynav.tcl, library/ttk/menubutton.tcl: * library/ttk/notebook.tcl, library/ttk/panedwindow.tcl: * library/ttk/progress.tcl, library/ttk/scale.tcl: * library/ttk/scrollbar.tcl, library/ttk/sizegrip.tcl: * library/ttk/treeview.tcl, library/ttk/ttk.tcl: * library/ttk/utils.tcl, library/ttk/winTheme.tcl: * library/ttk/xpTheme.tcl: * macosx/ttkMacOSXTheme.c: * tests/ttk/all.tcl, tests/ttk/bwidget.test, tests/ttk/combobox.test: * tests/ttk/entry.test, tests/ttk/image.test: * tests/ttk/labelframe.test, tests/ttk/layout.test: * tests/ttk/misc.test, tests/ttk/notebook.test: * tests/ttk/panedwindow.test, tests/ttk/progressbar.test: * tests/ttk/scrollbar.test, tests/ttk/treetags.test: * tests/ttk/treeview.test, tests/ttk/ttk.test, tests/ttk/validate.test: * win/ttkWinMonitor.c, win/ttkWinTheme.c, win/ttkWinXPTheme.c: First import of Ttk themed Tk widgets as branched from tile 0.7.8 * generic/tkInt.h, generic/tkWindow.c: add Ttk_Init call, copy tk classic widgets to ::tk namespace. * library/tk.tcl: add source of ttk/ttk.tcl, define $::ttk::library. * unix/Makefile.in, win/Makefile.in: add Ttk build bits * win/configure, win/configure.in: check for uxtheme.h (XP theme).
Diffstat (limited to 'generic/ttk/ttkFrame.c')
-rw-r--r--generic/ttk/ttkFrame.c620
1 files changed, 620 insertions, 0 deletions
diff --git a/generic/ttk/ttkFrame.c b/generic/ttk/ttkFrame.c
new file mode 100644
index 0000000..c0a9b6e
--- /dev/null
+++ b/generic/ttk/ttkFrame.c
@@ -0,0 +1,620 @@
+/* $Id: ttkFrame.c,v 1.1 2006/10/31 01:42:26 hobbs Exp $
+ * Copyright (c) 2004, Joe English
+ *
+ * Ttk widget set: frame and labelframe widgets
+ */
+
+#include <tk.h>
+
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+#include "ttkManager.h"
+
+/* ======================================================================
+ * +++ Frame widget:
+ */
+
+typedef struct
+{
+ Tcl_Obj *borderWidthObj;
+ Tcl_Obj *paddingObj;
+ Tcl_Obj *reliefObj;
+ Tcl_Obj *widthObj;
+ Tcl_Obj *heightObj;
+} FramePart;
+
+typedef struct
+{
+ WidgetCore core;
+ FramePart frame;
+} Frame;
+
+static Tk_OptionSpec FrameOptionSpecs[] =
+{
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", NULL,
+ Tk_Offset(Frame,frame.borderWidthObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+ {TK_OPTION_STRING, "-padding", "padding", "Pad", NULL,
+ Tk_Offset(Frame,frame.paddingObj), -1,
+ TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief", NULL,
+ Tk_Offset(Frame,frame.reliefObj), -1,
+ TK_OPTION_NULL_OK,0,0 },
+ {TK_OPTION_PIXELS, "-width", "width", "Width", "0",
+ Tk_Offset(Frame,frame.widthObj), -1,
+ 0,0,GEOMETRY_CHANGED },
+ {TK_OPTION_PIXELS, "-height", "height", "Height", "0",
+ Tk_Offset(Frame,frame.heightObj), -1,
+ 0,0,GEOMETRY_CHANGED },
+
+ WIDGET_INHERIT_OPTIONS(CoreOptionSpecs)
+};
+
+static WidgetCommandSpec FrameCommands[] =
+{
+ { "configure", WidgetConfigureCommand },
+ { "cget", WidgetCgetCommand },
+ { "instate", WidgetInstateCommand },
+ { "state", WidgetStateCommand },
+ { "identify", WidgetIdentifyCommand },
+ { NULL, NULL }
+};
+
+/*
+ * FrameMargins --
+ * Compute internal margins for a frame widget.
+ * This includes the -borderWidth, plus any additional -padding.
+ */
+static Ttk_Padding FrameMargins(Frame *framePtr)
+{
+ Ttk_Padding margins = Ttk_UniformPadding(0);
+
+ /* Check -padding:
+ */
+ if (framePtr->frame.paddingObj) {
+ Ttk_GetPaddingFromObj(NULL,
+ framePtr->core.tkwin, framePtr->frame.paddingObj, &margins);
+ }
+
+ /* Add padding for border:
+ */
+ if (framePtr->frame.borderWidthObj) {
+ int border = 0;
+ Tk_GetPixelsFromObj(NULL,
+ framePtr->core.tkwin, framePtr->frame.borderWidthObj, &border);
+ margins = Ttk_AddPadding(margins, Ttk_UniformPadding((short)border));
+ }
+
+ return margins;
+}
+
+/* FrameSize procedure --
+ * The frame doesn't request a size of its own by default,
+ * but it does have an internal border. See also <<NOTE-SIZE>>
+ */
+static int FrameSize(void *recordPtr, int *widthPtr, int *heightPtr)
+{
+ Frame *framePtr = recordPtr;
+ Ttk_SetMargins(framePtr->core.tkwin, FrameMargins(framePtr));
+ return 0;
+}
+
+/*
+ * FrameConfigure -- configure hook.
+ * <<NOTE-SIZE>> Usually the size of a frame is controlled by
+ * a geometry manager (pack, grid); the -width and -height
+ * options are only effective if geometry propagation is turned
+ * off or if the [place] GM is used for child widgets.
+ *
+ * To avoid geometry blinking, we issue a geometry request
+ * in the Configure hook instead of the Size hook, and only
+ * if -width and/or -height is nonzero and one of them
+ * or the other size-related options (-borderwidth, -padding)
+ * has been changed.
+ */
+
+static int FrameConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Frame *framePtr = recordPtr;
+ int width, height;
+
+ /*
+ * Make sure -padding resource, if present, is correct:
+ */
+ if (framePtr->frame.paddingObj) {
+ Ttk_Padding unused;
+ if (Ttk_GetPaddingFromObj(interp,
+ framePtr->core.tkwin,
+ framePtr->frame.paddingObj,
+ &unused) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ /* See <<NOTE-SIZE>>
+ */
+ if ( TCL_OK != Tk_GetPixelsFromObj(
+ interp,framePtr->core.tkwin,framePtr->frame.widthObj,&width)
+ || TCL_OK != Tk_GetPixelsFromObj(
+ interp,framePtr->core.tkwin,framePtr->frame.heightObj,&height)
+ )
+ {
+ return TCL_ERROR;
+ }
+
+ if ((width > 0 || height > 0) && (mask & GEOMETRY_CHANGED)) {
+ Tk_GeometryRequest(framePtr->core.tkwin, width, height);
+ }
+
+ return CoreConfigure(interp, recordPtr, mask);
+}
+
+/* public */
+WidgetSpec FrameWidgetSpec =
+{
+ "TFrame", /* className */
+ sizeof(Frame), /* recordSize */
+ FrameOptionSpecs, /* optionSpecs */
+ FrameCommands, /* subcommands */
+ NullInitialize, /* initializeProc */
+ NullCleanup, /* cleanupProc */
+ FrameConfigure, /* configureProc */
+ NullPostConfigure, /* postConfigureProc */
+ WidgetGetLayout, /* getLayoutProc */
+ FrameSize, /* sizeProc */
+ WidgetDoLayout, /* layoutProc */
+ WidgetDisplay /* displayProc */
+};
+
+/* ======================================================================
+ * +++ Labelframe widget:
+ */
+
+#define DEFAULT_LABELINSET 8
+#define DEFAULT_BORDERWIDTH 2
+
+int TtkGetLabelAnchorFromObj(
+ Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_PositionSpec *anchorPtr)
+{
+ const char *string = Tcl_GetString(objPtr);
+ char c = *string++;
+ Ttk_PositionSpec flags = 0;
+
+ /* First character determines side:
+ */
+ switch (c) {
+ case 'w' : flags = TTK_PACK_LEFT; break;
+ case 'e' : flags = TTK_PACK_RIGHT; break;
+ case 'n' : flags = TTK_PACK_TOP; break;
+ case 's' : flags = TTK_PACK_BOTTOM; break;
+ default : goto error;
+ }
+
+ /* Remaining characters are as per -sticky:
+ */
+ while ((c = *string++) != '\0') {
+ switch (c) {
+ case 'w' : flags |= TTK_STICK_W; break;
+ case 'e' : flags |= TTK_STICK_E; break;
+ case 'n' : flags |= TTK_STICK_N; break;
+ case 's' : flags |= TTK_STICK_S; break;
+ default : goto error;
+ }
+ }
+
+ *anchorPtr = flags;
+ return TCL_OK;
+
+error:
+ if (interp) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp,
+ "Bad label anchor specification ", Tcl_GetString(objPtr),
+ NULL);
+ }
+ return TCL_ERROR;
+}
+
+/* LabelAnchorSide --
+ * Returns the side corresponding to a LabelAnchor value.
+ */
+static Ttk_Side LabelAnchorSide(Ttk_PositionSpec flags)
+{
+ if (flags & TTK_PACK_LEFT) return TTK_SIDE_LEFT;
+ else if (flags & TTK_PACK_RIGHT) return TTK_SIDE_RIGHT;
+ else if (flags & TTK_PACK_TOP) return TTK_SIDE_TOP;
+ else if (flags & TTK_PACK_BOTTOM) return TTK_SIDE_BOTTOM;
+ /*NOTREACHED*/
+ return TTK_SIDE_TOP;
+}
+
+/*
+ * Labelframe widget record:
+ */
+typedef struct {
+ Tcl_Obj *labelAnchorObj;
+ Tcl_Obj *textObj;
+ Tcl_Obj *underlineObj;
+ Tcl_Obj *labelWidgetObj;
+
+ Ttk_Manager *mgr;
+ Tk_Window labelWidget; /* Set in configureProc */
+ Ttk_Box labelParcel; /* Set in layoutProc */
+} LabelframePart;
+
+typedef struct
+{
+ WidgetCore core;
+ FramePart frame;
+ LabelframePart label;
+} Labelframe;
+
+#define LABELWIDGET_CHANGED 0x100
+
+static Tk_OptionSpec LabelframeOptionSpecs[] =
+{
+ {TK_OPTION_STRING, "-labelanchor", "labelAnchor", "LabelAnchor",
+ "nw", Tk_Offset(Labelframe, label.labelAnchorObj),-1,
+ 0,0,GEOMETRY_CHANGED},
+ {TK_OPTION_STRING, "-text", "text", "Text", "",
+ Tk_Offset(Labelframe,label.textObj), -1,
+ 0,0,GEOMETRY_CHANGED },
+ {TK_OPTION_INT, "-underline", "underline", "Underline",
+ "-1", Tk_Offset(Labelframe,label.underlineObj), -1,
+ 0,0,0 },
+ {TK_OPTION_WINDOW, "-labelwidget", "labelWidget", "LabelWidget", NULL,
+ Tk_Offset(Labelframe,label.labelWidgetObj), -1,
+ TK_OPTION_NULL_OK,0,LABELWIDGET_CHANGED|GEOMETRY_CHANGED },
+
+ WIDGET_INHERIT_OPTIONS(FrameOptionSpecs)
+};
+
+/*
+ * Labelframe style parameters:
+ */
+typedef struct
+{
+ int borderWidth; /* border width */
+ Ttk_Padding padding; /* internal padding */
+ Ttk_PositionSpec labelAnchor; /* corner/side to place label */
+ Ttk_Padding labelMargins; /* extra space around label */
+ int labelOutside; /* true=>place label outside border */
+} LabelframeStyle;
+
+static void LabelframeStyleOptions(Labelframe *lf, LabelframeStyle *style)
+{
+ Ttk_Layout layout = lf->core.layout;
+ Tcl_Obj *objPtr;
+
+ style->borderWidth = DEFAULT_BORDERWIDTH;
+ style->padding = Ttk_UniformPadding(0);
+ style->labelAnchor = TTK_PACK_TOP | TTK_STICK_W;
+ style->labelMargins =
+ Ttk_MakePadding(DEFAULT_LABELINSET,0,DEFAULT_LABELINSET,0);
+ style->labelOutside = 0;
+
+ if ((objPtr = Ttk_QueryOption(layout, "-borderwidth", 0)) != NULL) {
+ Tk_GetPixelsFromObj(NULL, lf->core.tkwin, objPtr, &style->borderWidth);
+ }
+ if ((objPtr = Ttk_QueryOption(layout, "-padding", 0)) != NULL) {
+ Ttk_GetPaddingFromObj(NULL, lf->core.tkwin, objPtr, &style->padding);
+ }
+ if ((objPtr = Ttk_QueryOption(layout,"-labelanchor", 0)) != NULL) {
+ TtkGetLabelAnchorFromObj(NULL, objPtr, &style->labelAnchor);
+ }
+ if ((objPtr = Ttk_QueryOption(layout,"-labelmargins", 0)) != NULL) {
+ Ttk_GetBorderFromObj(NULL, objPtr, &style->labelMargins);
+ }
+ if ((objPtr = Ttk_QueryOption(layout,"-labeloutside", 0)) != NULL) {
+ Tcl_GetBooleanFromObj(NULL, objPtr, &style->labelOutside);
+ }
+
+ return;
+}
+
+/* LabelframeLabelSize --
+ * Extract the requested width and height of the labelframe's label:
+ * taken from the label widget if specified, otherwise the text label.
+ */
+static void
+LabelframeLabelSize(Labelframe *lframePtr, int *widthPtr, int *heightPtr)
+{
+ WidgetCore *corePtr = &lframePtr->core;
+ Tk_Window labelWidget = lframePtr->label.labelWidget;
+ Ttk_LayoutNode *textNode = Ttk_LayoutFindNode(corePtr->layout, "text");
+
+ if (labelWidget) {
+ *widthPtr = Tk_ReqWidth(labelWidget);
+ *heightPtr = Tk_ReqHeight(labelWidget);
+ } else if (textNode) {
+ Ttk_LayoutNodeReqSize(corePtr->layout, textNode, widthPtr, heightPtr);
+ } else {
+ *widthPtr = *heightPtr = 0;
+ }
+}
+
+/*
+ * LabelframeSize --
+ * Like the frame, this doesn't request a size of its own
+ * but it does have internal padding and a minimum size.
+ */
+static int LabelframeSize(void *recordPtr, int *widthPtr, int *heightPtr)
+{
+ Labelframe *lframePtr = recordPtr;
+ WidgetCore *corePtr = &lframePtr->core;
+ Ttk_Padding margins;
+ LabelframeStyle style;
+ int labelWidth, labelHeight;
+
+ LabelframeStyleOptions(lframePtr, &style);
+
+ /* Compute base margins (See also: FrameMargins)
+ */
+ margins = Ttk_AddPadding(
+ style.padding, Ttk_UniformPadding((short)style.borderWidth));
+
+ /* Adjust margins based on label size and position:
+ */
+ LabelframeLabelSize(lframePtr, &labelWidth, &labelHeight);
+ labelWidth += Ttk_PaddingWidth(style.labelMargins);
+ labelHeight += Ttk_PaddingHeight(style.labelMargins);
+
+ switch (LabelAnchorSide(style.labelAnchor)) {
+ case TTK_SIDE_LEFT: margins.left += labelWidth; break;
+ case TTK_SIDE_RIGHT: margins.right += labelWidth; break;
+ case TTK_SIDE_TOP: margins.top += labelHeight; break;
+ case TTK_SIDE_BOTTOM: margins.bottom += labelHeight; break;
+ }
+
+ Ttk_SetMargins(corePtr->tkwin,margins);
+
+ /* Request minimum size based on border width and label size:
+ */
+ Tk_SetMinimumRequestSize(corePtr->tkwin,
+ labelWidth + 2*style.borderWidth,
+ labelHeight + 2*style.borderWidth);
+
+ return 0;
+}
+
+/*
+ * LabelframeDoLayout --
+ * Labelframe layout hook.
+ *
+ * Side effects: Computes labelParcel.
+ */
+
+static void LabelframeDoLayout(void *recordPtr)
+{
+ Labelframe *lframePtr = recordPtr;
+ WidgetCore *corePtr = &lframePtr->core;
+ Ttk_Box borderParcel = Ttk_WinBox(corePtr->tkwin);
+ Ttk_LayoutNode
+ *textNode = Ttk_LayoutFindNode(corePtr->layout, "text"),
+ *borderNode = Ttk_LayoutFindNode(corePtr->layout, "border");
+ int lw, lh; /* Label width and height */
+ LabelframeStyle style;
+ Ttk_Box labelParcel;
+
+ /*
+ * Do base layout:
+ */
+ Ttk_PlaceLayout(corePtr->layout,corePtr->state,borderParcel);
+
+ /*
+ * Compute label parcel:
+ */
+ LabelframeStyleOptions(lframePtr, &style);
+ LabelframeLabelSize(lframePtr, &lw, &lh);
+ lw += Ttk_PaddingWidth(style.labelMargins);
+ lh += Ttk_PaddingHeight(style.labelMargins);
+
+ labelParcel = Ttk_PadBox(
+ Ttk_PositionBox(&borderParcel, lw, lh, style.labelAnchor),
+ style.labelMargins);
+
+ if (!style.labelOutside) {
+ /* Move border edge so it's over label:
+ */
+ switch (LabelAnchorSide(style.labelAnchor)) {
+ case TTK_SIDE_LEFT: borderParcel.x -= lw / 2;
+ case TTK_SIDE_RIGHT: borderParcel.width += lw/2; break;
+ case TTK_SIDE_TOP: borderParcel.y -= lh / 2;
+ case TTK_SIDE_BOTTOM: borderParcel.height += lh / 2; break;
+ }
+ }
+
+ /*
+ * Place border and label:
+ */
+ if (borderNode) {
+ Ttk_PlaceLayoutNode(corePtr->layout, borderNode, borderParcel);
+ }
+ if (textNode) {
+ Ttk_PlaceLayoutNode(corePtr->layout, textNode, labelParcel);
+ }
+ /* labelWidget placed in LabelframePlaceSlaves GM hook */
+ lframePtr->label.labelParcel = labelParcel;
+}
+
+/* LabelframePlaceSlaves --
+ * Sets the position and size of the labelwidget.
+ */
+static void LabelframePlaceSlaves(void *recordPtr)
+{
+ Labelframe *lframe = recordPtr;
+
+ if (Ttk_NumberSlaves(lframe->label.mgr) == 1) {
+ Ttk_Box b;
+ LabelframeDoLayout(recordPtr);
+ b = lframe->label.labelParcel;
+ /* ASSERT: slave #0 is lframe->label.labelWidget */
+ Ttk_PlaceSlave(lframe->label.mgr, 0, b.x,b.y,b.width,b.height);
+ }
+}
+
+/* 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.
+ */
+static void LabelframeLostSlave(ClientData clientData, Tk_Window slaveWindow)
+{
+ 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);
+}
+
+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,
+
+ LabelframeSize,
+ LabelframePlaceSlaves,
+
+ LabelAdded,
+ LabelRemoved,
+ LabelConfigured
+};
+
+/* LabelframeInitialize --
+ * Initialization hook.
+ */
+static int LabelframeInitialize(Tcl_Interp *interp, void *recordPtr)
+{
+ Labelframe *lframe = recordPtr;
+
+ lframe->label.mgr = Ttk_CreateManager(
+ &LabelframeManagerSpec, lframe, lframe->core.tkwin);
+ lframe->label.labelWidget = 0;
+ lframe->label.labelParcel = Ttk_MakeBox(-1,-1,-1,-1);
+
+ return TCL_OK;
+}
+
+/* LabelframeCleanup --
+ * Cleanup hook.
+ */
+static void LabelframeCleanup(void *recordPtr)
+{
+ Labelframe *lframe = recordPtr;
+ Ttk_DeleteManager(lframe->label.mgr);
+}
+
+/* RaiseLabelWidget --
+ * Raise the -labelwidget to ensure that the labelframe doesn't
+ * obscure it (if it's not a direct child), or bring it to
+ * the top of the stacking order (if it is).
+ */
+static void RaiseLabelWidget(Labelframe *lframe)
+{
+ Tk_Window parent = Tk_Parent(lframe->label.labelWidget);
+ Tk_Window sibling = NULL;
+ Tk_Window w = lframe->core.tkwin;
+
+ while (w && w != parent) {
+ sibling = w;
+ w = Tk_Parent(w);
+ }
+
+ Tk_RestackWindow(lframe->label.labelWidget, Above, sibling);
+}
+
+/* LabelframeConfigure --
+ * Configuration hook.
+ */
+static int LabelframeConfigure(Tcl_Interp *interp,void *recordPtr,int mask)
+{
+ Labelframe *lframePtr = recordPtr;
+ Tk_Window labelWidget = NULL;
+ Ttk_PositionSpec unused;
+
+ /* Validate -labelwidget option:
+ */
+ 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 (TtkGetLabelAnchorFromObj(
+ interp, lframePtr->label.labelAnchorObj, &unused) != TCL_OK)
+ {
+ return TCL_ERROR;
+ }
+
+ /* Base class configuration:
+ */
+ if (FrameConfigure(interp, recordPtr, mask) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /* Update -labelwidget changes, if any:
+ */
+ if (mask & LABELWIDGET_CHANGED) {
+ if (Ttk_NumberSlaves(lframePtr->label.mgr) == 1) {
+ Ttk_ForgetSlave(lframePtr->label.mgr, 0);
+ }
+
+ lframePtr->label.labelWidget = labelWidget;
+
+ if (labelWidget) {
+ Ttk_AddSlave(interp, lframePtr->label.mgr, labelWidget, 0, 0,0);
+ RaiseLabelWidget(lframePtr);
+ }
+ }
+
+ if (mask & GEOMETRY_CHANGED) {
+ Ttk_ManagerSizeChanged(lframePtr->label.mgr);
+ Ttk_ManagerLayoutChanged(lframePtr->label.mgr);
+ }
+
+ return TCL_OK;
+}
+
+/* public */
+WidgetSpec LabelframeWidgetSpec =
+{
+ "TLabelframe", /* className */
+ sizeof(Labelframe), /* recordSize */
+ LabelframeOptionSpecs, /* optionSpecs */
+ FrameCommands, /* subcommands */
+ LabelframeInitialize, /* initializeProc */
+ LabelframeCleanup, /* cleanupProc */
+ LabelframeConfigure, /* configureProc */
+ NullPostConfigure, /* postConfigureProc */
+ WidgetGetLayout, /* getLayoutProc */
+ LabelframeSize, /* sizeProc */
+ LabelframeDoLayout, /* layoutProc */
+ WidgetDisplay /* displayProc */
+};
+