summaryrefslogtreecommitdiffstats
path: root/tk8.6/generic/ttk/ttkFrame.c
diff options
context:
space:
mode:
Diffstat (limited to 'tk8.6/generic/ttk/ttkFrame.c')
-rw-r--r--tk8.6/generic/ttk/ttkFrame.c653
1 files changed, 653 insertions, 0 deletions
diff --git a/tk8.6/generic/ttk/ttkFrame.c b/tk8.6/generic/ttk/ttkFrame.c
new file mode 100644
index 0000000..3e50a7f
--- /dev/null
+++ b/tk8.6/generic/ttk/ttkFrame.c
@@ -0,0 +1,653 @@
+/*
+ * Copyright (c) 2004, Joe English
+ *
+ * ttk::frame and ttk::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_TAKEFOCUS_FALSE,
+ WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
+};
+
+static const Ttk_Ensemble FrameCommands[] = {
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ { 0,0,0 }
+};
+
+/*
+ * 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 TtkCoreConfigure(interp, recordPtr, mask);
+}
+
+static WidgetSpec FrameWidgetSpec = {
+ "TFrame", /* className */
+ sizeof(Frame), /* recordSize */
+ FrameOptionSpecs, /* optionSpecs */
+ FrameCommands, /* subcommands */
+ TtkNullInitialize, /* initializeProc */
+ TtkNullCleanup, /* cleanupProc */
+ FrameConfigure, /* configureProc */
+ TtkNullPostConfigure, /* postConfigureProc */
+ TtkWidgetGetLayout, /* getLayoutProc */
+ FrameSize, /* sizeProc */
+ TtkWidgetDoLayout, /* layoutProc */
+ TtkWidgetDisplay /* displayProc */
+};
+
+TTK_BEGIN_LAYOUT(FrameLayout)
+ TTK_NODE("Frame.border", TTK_FILL_BOTH)
+TTK_END_LAYOUT
+
+/* ======================================================================
+ * +++ 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_SetObjResult(interp, Tcl_ObjPrintf(
+ "Bad label anchor specification %s", Tcl_GetString(objPtr)));
+ Tcl_SetErrorCode(interp, "TTK", "LABEL", "ANCHOR", 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;
+ Tk_Window labelWidget;
+
+ Ttk_Manager *mgr;
+ Ttk_Layout labelLayout; /* Sublayout for label */
+ 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,
+ -1, Tk_Offset(Labelframe,label.labelWidget),
+ 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->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);
+ } else {
+ if (style->labelAnchor & (TTK_PACK_TOP|TTK_PACK_BOTTOM)) {
+ style->labelMargins =
+ Ttk_MakePadding(DEFAULT_LABELINSET,0,DEFAULT_LABELINSET,0);
+ } else {
+ style->labelMargins =
+ Ttk_MakePadding(0,DEFAULT_LABELINSET,0,DEFAULT_LABELINSET);
+ }
+ }
+ 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)
+{
+ Tk_Window labelWidget = lframePtr->label.labelWidget;
+ Ttk_Layout labelLayout = lframePtr->label.labelLayout;
+
+ if (labelWidget) {
+ *widthPtr = Tk_ReqWidth(labelWidget);
+ *heightPtr = Tk_ReqHeight(labelWidget);
+ } else if (labelLayout) {
+ Ttk_LayoutSize(labelLayout, 0, 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;
+}
+
+/*
+ * LabelframeGetLayout --
+ * Getlayout widget hook.
+ */
+
+static Ttk_Layout LabelframeGetLayout(
+ Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)
+{
+ Labelframe *lf = recordPtr;
+ Ttk_Layout frameLayout = TtkWidgetGetLayout(interp, theme, recordPtr);
+ Ttk_Layout labelLayout;
+
+ if (!frameLayout) {
+ return NULL;
+ }
+
+ labelLayout = Ttk_CreateSublayout(
+ interp, theme, frameLayout, ".Label", lf->core.optionTable);
+
+ if (labelLayout) {
+ if (lf->label.labelLayout) {
+ Ttk_FreeLayout(lf->label.labelLayout);
+ }
+ Ttk_RebindSublayout(labelLayout, recordPtr);
+ lf->label.labelLayout = labelLayout;
+ }
+
+ return frameLayout;
+}
+
+/*
+ * LabelframeDoLayout --
+ * Labelframe layout hook.
+ *
+ * Side effects: Computes labelParcel.
+ */
+
+static void LabelframeDoLayout(void *recordPtr)
+{
+ Labelframe *lframePtr = recordPtr;
+ WidgetCore *corePtr = &lframePtr->core;
+ int lw, lh; /* Label width and height */
+ LabelframeStyle style;
+ Ttk_Box borderParcel = Ttk_WinBox(lframePtr->core.tkwin);
+ Ttk_Box labelParcel;
+
+ /*
+ * 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:
+ */
+ Ttk_PlaceLayout(corePtr->layout, corePtr->state, borderParcel);
+ if (lframePtr->label.labelLayout) {
+ Ttk_PlaceLayout(
+ lframePtr->label.labelLayout, corePtr->state, labelParcel);
+ }
+ /* labelWidget placed in LabelframePlaceSlaves GM hook */
+ lframePtr->label.labelParcel = labelParcel;
+}
+
+static void LabelframeDisplay(void *recordPtr, Drawable d)
+{
+ Labelframe *lframePtr = recordPtr;
+ Ttk_DrawLayout(lframePtr->core.layout, lframePtr->core.state, d);
+ if (lframePtr->label.labelLayout) {
+ Ttk_DrawLayout(lframePtr->label.labelLayout, lframePtr->core.state, d);
+ }
+}
+
+/* +++ Labelframe geometry manager hooks.
+ */
+
+/* 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);
+ }
+}
+
+static int LabelRequest(void *managerData, int index, int width, int height)
+{
+ return 1;
+}
+
+/* LabelRemoved --
+ * Unset the -labelwidget option.
+ *
+ * <<NOTE-LABELREMOVED>>:
+ * This routine is also called when the widget voluntarily forgets
+ * the slave in LabelframeConfigure.
+ */
+static void LabelRemoved(void *managerData, int slaveIndex)
+{
+ Labelframe *lframe = managerData;
+ lframe->label.labelWidget = 0;
+}
+
+static Ttk_ManagerSpec LabelframeManagerSpec = {
+ { "labelframe", Ttk_GeometryRequestProc, Ttk_LostSlaveProc },
+ LabelframeSize,
+ LabelframePlaceSlaves,
+ LabelRequest,
+ LabelRemoved
+};
+
+/* LabelframeInitialize --
+ * Initialization hook.
+ */
+static void 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.labelLayout = 0;
+ lframe->label.labelParcel = Ttk_MakeBox(-1,-1,-1,-1);
+}
+
+/* LabelframeCleanup --
+ * Cleanup hook.
+ */
+static void LabelframeCleanup(void *recordPtr)
+{
+ Labelframe *lframe = recordPtr;
+ Ttk_DeleteManager(lframe->label.mgr);
+ if (lframe->label.labelLayout) {
+ Ttk_FreeLayout(lframe->label.labelLayout);
+ }
+}
+
+/* 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 = lframePtr->label.labelWidget;
+ Ttk_PositionSpec unused;
+
+ /* Validate options:
+ */
+ if (mask & LABELWIDGET_CHANGED && labelWidget != NULL) {
+ 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);
+ /* Restore labelWidget field (see <<NOTE-LABELREMOVED>>)
+ */
+ lframePtr->label.labelWidget = labelWidget;
+ }
+
+ if (labelWidget) {
+ Ttk_InsertSlave(lframePtr->label.mgr, 0, labelWidget, NULL);
+ RaiseLabelWidget(lframePtr);
+ }
+ }
+
+ if (mask & GEOMETRY_CHANGED) {
+ Ttk_ManagerSizeChanged(lframePtr->label.mgr);
+ Ttk_ManagerLayoutChanged(lframePtr->label.mgr);
+ }
+
+ return TCL_OK;
+}
+
+static WidgetSpec LabelframeWidgetSpec = {
+ "TLabelframe", /* className */
+ sizeof(Labelframe), /* recordSize */
+ LabelframeOptionSpecs, /* optionSpecs */
+ FrameCommands, /* subcommands */
+ LabelframeInitialize, /* initializeProc */
+ LabelframeCleanup, /* cleanupProc */
+ LabelframeConfigure, /* configureProc */
+ TtkNullPostConfigure, /* postConfigureProc */
+ LabelframeGetLayout, /* getLayoutProc */
+ LabelframeSize, /* sizeProc */
+ LabelframeDoLayout, /* layoutProc */
+ LabelframeDisplay /* displayProc */
+};
+
+TTK_BEGIN_LAYOUT(LabelframeLayout)
+ TTK_NODE("Labelframe.border", TTK_FILL_BOTH)
+TTK_END_LAYOUT
+
+TTK_BEGIN_LAYOUT(LabelSublayout)
+ TTK_GROUP("Label.fill", TTK_FILL_BOTH,
+ TTK_NODE("Label.text", TTK_FILL_BOTH))
+TTK_END_LAYOUT
+
+/* ======================================================================
+ * +++ Initialization.
+ */
+
+MODULE_SCOPE
+void TtkFrame_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme theme = Ttk_GetDefaultTheme(interp);
+
+ Ttk_RegisterLayout(theme, "TFrame", FrameLayout);
+ Ttk_RegisterLayout(theme, "TLabelframe", LabelframeLayout);
+ Ttk_RegisterLayout(theme, "Label", LabelSublayout);
+
+ RegisterWidget(interp, "ttk::frame", &FrameWidgetSpec);
+ RegisterWidget(interp, "ttk::labelframe", &LabelframeWidgetSpec);
+}
+