655 lines
18 KiB
C
655 lines
18 KiB
C
/*
|
|
* 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_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;
|
|
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);
|
|
}
|
|
|