OSDN Git Service

Please enter the commit message for your changes. Lines starting
[eos/base.git] / util / src / TclTk / tk8.6.12 / generic / ttk / ttkFrame.c
1 /*
2  * Copyright (c) 2004, Joe English
3  *
4  * ttk::frame and ttk::labelframe widgets.
5  */
6
7 #include "tkInt.h"
8 #include "ttkTheme.h"
9 #include "ttkWidget.h"
10 #include "ttkManager.h"
11
12 /* ======================================================================
13  * +++ Frame widget:
14  */
15
16 typedef struct {
17     Tcl_Obj     *borderWidthObj;
18     Tcl_Obj     *paddingObj;
19     Tcl_Obj     *reliefObj;
20     Tcl_Obj     *widthObj;
21     Tcl_Obj     *heightObj;
22 } FramePart;
23
24 typedef struct {
25     WidgetCore  core;
26     FramePart   frame;
27 } Frame;
28
29 static Tk_OptionSpec FrameOptionSpecs[] = {
30     {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", NULL,
31         Tk_Offset(Frame,frame.borderWidthObj), -1,
32         TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
33     {TK_OPTION_STRING, "-padding", "padding", "Pad", NULL,
34         Tk_Offset(Frame,frame.paddingObj), -1,
35         TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
36     {TK_OPTION_RELIEF, "-relief", "relief", "Relief", NULL,
37         Tk_Offset(Frame,frame.reliefObj), -1,
38         TK_OPTION_NULL_OK,0,0 },
39     {TK_OPTION_PIXELS, "-width", "width", "Width", "0",
40         Tk_Offset(Frame,frame.widthObj), -1,
41         0,0,GEOMETRY_CHANGED },
42     {TK_OPTION_PIXELS, "-height", "height", "Height", "0",
43         Tk_Offset(Frame,frame.heightObj), -1,
44         0,0,GEOMETRY_CHANGED },
45
46     WIDGET_TAKEFOCUS_FALSE,
47     WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
48 };
49
50 static const Ttk_Ensemble FrameCommands[] = {
51     { "configure",      TtkWidgetConfigureCommand,0 },
52     { "cget",           TtkWidgetCgetCommand,0 },
53     { "instate",        TtkWidgetInstateCommand,0 },
54     { "state",          TtkWidgetStateCommand,0 },
55     { "identify",       TtkWidgetIdentifyCommand,0 },
56     { 0,0,0 }
57 };
58
59 /*
60  * FrameMargins --
61  *      Compute internal margins for a frame widget.
62  *      This includes the -borderWidth, plus any additional -padding.
63  */
64 static Ttk_Padding FrameMargins(Frame *framePtr)
65 {
66     Ttk_Padding margins = Ttk_UniformPadding(0);
67
68     /* Check -padding:
69      */
70     if (framePtr->frame.paddingObj) {
71         Ttk_GetPaddingFromObj(NULL,
72             framePtr->core.tkwin, framePtr->frame.paddingObj, &margins);
73     }
74
75     /* Add padding for border:
76      */
77     if (framePtr->frame.borderWidthObj) {
78         int border = 0;
79         Tk_GetPixelsFromObj(NULL,
80             framePtr->core.tkwin, framePtr->frame.borderWidthObj, &border);
81         margins = Ttk_AddPadding(margins, Ttk_UniformPadding((short)border));
82     }
83
84     return margins;
85 }
86
87 /* FrameSize procedure --
88  *      The frame doesn't request a size of its own by default,
89  *      but it does have an internal border.  See also <<NOTE-SIZE>>
90  */
91 static int FrameSize(
92     void *recordPtr,
93     TCL_UNUSED(int *),
94     TCL_UNUSED(int *))
95 {
96     Frame *framePtr = (Frame *)recordPtr;
97     Ttk_SetMargins(framePtr->core.tkwin, FrameMargins(framePtr));
98     return 0;
99 }
100
101 /*
102  * FrameConfigure -- configure hook.
103  *      <<NOTE-SIZE>> Usually the size of a frame is controlled by
104  *      a geometry manager (pack, grid); the -width and -height
105  *      options are only effective if geometry propagation is turned
106  *      off or if the [place] GM is used for child widgets.
107  *
108  *      To avoid geometry blinking, we issue a geometry request
109  *      in the Configure hook instead of the Size hook, and only
110  *      if -width and/or -height is nonzero and one of them
111  *      or the other size-related options (-borderwidth, -padding)
112  *      has been changed.
113  */
114
115 static int FrameConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
116 {
117     Frame *framePtr = (Frame *)recordPtr;
118     int width, height;
119
120     /*
121      * Make sure -padding resource, if present, is correct:
122      */
123     if (framePtr->frame.paddingObj) {
124         Ttk_Padding unused;
125         if (Ttk_GetPaddingFromObj(interp,
126                         framePtr->core.tkwin,
127                         framePtr->frame.paddingObj,
128                         &unused) != TCL_OK) {
129             return TCL_ERROR;
130         }
131     }
132
133     /* See <<NOTE-SIZE>>
134      */
135     if (  TCL_OK != Tk_GetPixelsFromObj(
136             interp,framePtr->core.tkwin,framePtr->frame.widthObj,&width)
137        || TCL_OK != Tk_GetPixelsFromObj(
138             interp,framePtr->core.tkwin,framePtr->frame.heightObj,&height)
139        )
140     {
141         return TCL_ERROR;
142     }
143
144     if ((width > 0 || height > 0) && (mask & GEOMETRY_CHANGED)) {
145         Tk_GeometryRequest(framePtr->core.tkwin, width, height);
146     }
147
148     return TtkCoreConfigure(interp, recordPtr, mask);
149 }
150
151 static WidgetSpec FrameWidgetSpec = {
152     "TFrame",                   /* className */
153     sizeof(Frame),              /* recordSize */
154     FrameOptionSpecs,           /* optionSpecs */
155     FrameCommands,              /* subcommands */
156     TtkNullInitialize,          /* initializeProc */
157     TtkNullCleanup,             /* cleanupProc */
158     FrameConfigure,             /* configureProc */
159     TtkNullPostConfigure,       /* postConfigureProc */
160     TtkWidgetGetLayout,         /* getLayoutProc */
161     FrameSize,                  /* sizeProc */
162     TtkWidgetDoLayout,          /* layoutProc */
163     TtkWidgetDisplay            /* displayProc */
164 };
165
166 TTK_BEGIN_LAYOUT(FrameLayout)
167     TTK_NODE("Frame.border", TTK_FILL_BOTH)
168 TTK_END_LAYOUT
169
170 /* ======================================================================
171  * +++ Labelframe widget:
172  */
173
174 #define DEFAULT_LABELINSET      8
175 #define DEFAULT_BORDERWIDTH     2
176
177 int TtkGetLabelAnchorFromObj(
178     Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_PositionSpec *anchorPtr)
179 {
180     const char *string = Tcl_GetString(objPtr);
181     char c = *string++;
182     Ttk_PositionSpec flags = 0;
183
184     /* First character determines side:
185      */
186     switch (c) {
187         case 'w' : flags = TTK_PACK_LEFT;       break;
188         case 'e' : flags = TTK_PACK_RIGHT;      break;
189         case 'n' : flags = TTK_PACK_TOP;        break;
190         case 's' : flags = TTK_PACK_BOTTOM;     break;
191         default  : goto error;
192     }
193
194     /* Remaining characters are as per -sticky:
195      */
196     while ((c = *string++) != '\0') {
197         switch (c) {
198             case 'w' : flags |= TTK_STICK_W; break;
199             case 'e' : flags |= TTK_STICK_E; break;
200             case 'n' : flags |= TTK_STICK_N; break;
201             case 's' : flags |= TTK_STICK_S; break;
202             default  : goto error;
203         }
204     }
205
206     *anchorPtr = flags;
207     return TCL_OK;
208
209 error:
210     if (interp) {
211         Tcl_SetObjResult(interp, Tcl_ObjPrintf(
212                 "Bad label anchor specification %s", Tcl_GetString(objPtr)));
213         Tcl_SetErrorCode(interp, "TTK", "LABEL", "ANCHOR", NULL);
214     }
215     return TCL_ERROR;
216 }
217
218 /* LabelAnchorSide --
219  *      Returns the side corresponding to a LabelAnchor value.
220  */
221 static Ttk_Side LabelAnchorSide(Ttk_PositionSpec flags)
222 {
223     if (flags & TTK_PACK_LEFT)          return TTK_SIDE_LEFT;
224     else if (flags & TTK_PACK_RIGHT)    return TTK_SIDE_RIGHT;
225     else if (flags & TTK_PACK_TOP)      return TTK_SIDE_TOP;
226     else if (flags & TTK_PACK_BOTTOM)   return TTK_SIDE_BOTTOM;
227     /*NOTREACHED*/
228     return TTK_SIDE_TOP;
229 }
230
231 /*
232  * Labelframe widget record:
233  */
234 typedef struct {
235     Tcl_Obj     *labelAnchorObj;
236     Tcl_Obj     *textObj;
237     Tcl_Obj     *underlineObj;
238     Tk_Window   labelWidget;
239
240     Ttk_Manager *mgr;
241     Ttk_Layout  labelLayout;    /* Sublayout for label */
242     Ttk_Box     labelParcel;    /* Set in layoutProc */
243 } LabelframePart;
244
245 typedef struct {
246     WidgetCore          core;
247     FramePart           frame;
248     LabelframePart      label;
249 } Labelframe;
250
251 #define LABELWIDGET_CHANGED 0x100
252
253 static Tk_OptionSpec LabelframeOptionSpecs[] = {
254     {TK_OPTION_STRING, "-labelanchor", "labelAnchor", "LabelAnchor",
255         "nw", Tk_Offset(Labelframe, label.labelAnchorObj),-1,
256         0,0,GEOMETRY_CHANGED},
257     {TK_OPTION_STRING, "-text", "text", "Text", "",
258         Tk_Offset(Labelframe,label.textObj), -1,
259         0,0,GEOMETRY_CHANGED },
260     {TK_OPTION_INT, "-underline", "underline", "Underline",
261         "-1", Tk_Offset(Labelframe,label.underlineObj), -1,
262         0,0,0 },
263     {TK_OPTION_WINDOW, "-labelwidget", "labelWidget", "LabelWidget", NULL,
264         -1, Tk_Offset(Labelframe,label.labelWidget),
265         TK_OPTION_NULL_OK,0,LABELWIDGET_CHANGED|GEOMETRY_CHANGED },
266
267     WIDGET_INHERIT_OPTIONS(FrameOptionSpecs)
268 };
269
270 /*
271  * Labelframe style parameters:
272  */
273 typedef struct {
274     int                 borderWidth;    /* border width */
275     Ttk_Padding         padding;        /* internal padding */
276     Ttk_PositionSpec    labelAnchor;    /* corner/side to place label */
277     Ttk_Padding         labelMargins;   /* extra space around label */
278     int                 labelOutside;   /* true=>place label outside border */
279 } LabelframeStyle;
280
281 static void LabelframeStyleOptions(Labelframe *lf, LabelframeStyle *style)
282 {
283     Ttk_Layout layout = lf->core.layout;
284     Tcl_Obj *objPtr;
285
286     style->borderWidth = DEFAULT_BORDERWIDTH;
287     style->padding = Ttk_UniformPadding(0);
288     style->labelAnchor = TTK_PACK_TOP | TTK_STICK_W;
289     style->labelOutside = 0;
290
291     if ((objPtr = Ttk_QueryOption(layout, "-borderwidth", 0)) != NULL) {
292         Tk_GetPixelsFromObj(NULL, lf->core.tkwin, objPtr, &style->borderWidth);
293     }
294     if ((objPtr = Ttk_QueryOption(layout, "-padding", 0)) != NULL) {
295         Ttk_GetPaddingFromObj(NULL, lf->core.tkwin, objPtr, &style->padding);
296     }
297     if ((objPtr = Ttk_QueryOption(layout,"-labelanchor", 0)) != NULL) {
298         TtkGetLabelAnchorFromObj(NULL, objPtr, &style->labelAnchor);
299     }
300     if ((objPtr = Ttk_QueryOption(layout,"-labelmargins", 0)) != NULL) {
301         Ttk_GetBorderFromObj(NULL, objPtr, &style->labelMargins);
302     } else {
303         if (style->labelAnchor & (TTK_PACK_TOP|TTK_PACK_BOTTOM)) {
304             style->labelMargins =
305                 Ttk_MakePadding(DEFAULT_LABELINSET,0,DEFAULT_LABELINSET,0);
306         } else {
307             style->labelMargins =
308                 Ttk_MakePadding(0,DEFAULT_LABELINSET,0,DEFAULT_LABELINSET);
309         }
310     }
311     if ((objPtr = Ttk_QueryOption(layout,"-labeloutside", 0)) != NULL) {
312         Tcl_GetBooleanFromObj(NULL, objPtr, &style->labelOutside);
313     }
314
315     return;
316 }
317
318 /* LabelframeLabelSize --
319  *      Extract the requested width and height of the labelframe's label:
320  *      taken from the label widget if specified, otherwise the text label.
321  */
322 static void
323 LabelframeLabelSize(Labelframe *lframePtr, int *widthPtr, int *heightPtr)
324 {
325     Tk_Window labelWidget = lframePtr->label.labelWidget;
326     Ttk_Layout labelLayout = lframePtr->label.labelLayout;
327
328     if (labelWidget) {
329         *widthPtr = Tk_ReqWidth(labelWidget);
330         *heightPtr = Tk_ReqHeight(labelWidget);
331     } else if (labelLayout) {
332         Ttk_LayoutSize(labelLayout, 0, widthPtr, heightPtr);
333     } else {
334         *widthPtr = *heightPtr = 0;
335     }
336 }
337
338 /*
339  * LabelframeSize --
340  *      Like the frame, this doesn't request a size of its own
341  *      but it does have internal padding and a minimum size.
342  */
343 static int LabelframeSize(
344     void *recordPtr,
345     TCL_UNUSED(int *),
346     TCL_UNUSED(int *))
347 {
348     Labelframe *lframePtr = (Labelframe *)recordPtr;
349     WidgetCore *corePtr = &lframePtr->core;
350     Ttk_Padding margins;
351     LabelframeStyle style;
352     int labelWidth, labelHeight;
353
354     LabelframeStyleOptions(lframePtr, &style);
355
356     /* Compute base margins (See also: FrameMargins)
357      */
358     margins = Ttk_AddPadding(
359                 style.padding, Ttk_UniformPadding((short)style.borderWidth));
360
361     /* Adjust margins based on label size and position:
362      */
363     LabelframeLabelSize(lframePtr, &labelWidth, &labelHeight);
364     labelWidth += Ttk_PaddingWidth(style.labelMargins);
365     labelHeight += Ttk_PaddingHeight(style.labelMargins);
366
367     switch (LabelAnchorSide(style.labelAnchor)) {
368         case TTK_SIDE_LEFT:     margins.left   += labelWidth;   break;
369         case TTK_SIDE_RIGHT:    margins.right  += labelWidth;   break;
370         case TTK_SIDE_TOP:      margins.top    += labelHeight;  break;
371         case TTK_SIDE_BOTTOM:   margins.bottom += labelHeight;  break;
372     }
373
374     Ttk_SetMargins(corePtr->tkwin,margins);
375
376     /* Request minimum size based on border width and label size:
377      */
378     Tk_SetMinimumRequestSize(corePtr->tkwin,
379             labelWidth + 2*style.borderWidth,
380             labelHeight + 2*style.borderWidth);
381
382     return 0;
383 }
384
385 /*
386  * LabelframeGetLayout --
387  *      Getlayout widget hook.
388  */
389
390 static Ttk_Layout LabelframeGetLayout(
391     Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)
392 {
393     Labelframe *lf = (Labelframe *)recordPtr;
394     Ttk_Layout frameLayout = TtkWidgetGetLayout(interp, theme, recordPtr);
395     Ttk_Layout labelLayout;
396
397     if (!frameLayout) {
398         return NULL;
399     }
400
401     labelLayout = Ttk_CreateSublayout(
402         interp, theme, frameLayout, ".Label", lf->core.optionTable);
403
404     if (labelLayout) {
405         if (lf->label.labelLayout) {
406             Ttk_FreeLayout(lf->label.labelLayout);
407         }
408         Ttk_RebindSublayout(labelLayout, recordPtr);
409         lf->label.labelLayout = labelLayout;
410     }
411
412     return frameLayout;
413 }
414
415 /*
416  * LabelframeDoLayout --
417  *      Labelframe layout hook.
418  *
419  * Side effects: Computes labelParcel.
420  */
421
422 static void LabelframeDoLayout(void *recordPtr)
423 {
424     Labelframe *lframePtr = (Labelframe *)recordPtr;
425     WidgetCore *corePtr = &lframePtr->core;
426     int lw, lh;                 /* Label width and height */
427     LabelframeStyle style;
428     Ttk_Box borderParcel = Ttk_WinBox(lframePtr->core.tkwin);
429     Ttk_Box labelParcel;
430
431     /*
432      * Compute label parcel:
433      */
434     LabelframeStyleOptions(lframePtr, &style);
435     LabelframeLabelSize(lframePtr, &lw, &lh);
436     lw += Ttk_PaddingWidth(style.labelMargins);
437     lh += Ttk_PaddingHeight(style.labelMargins);
438
439     labelParcel = Ttk_PadBox(
440         Ttk_PositionBox(&borderParcel, lw, lh, style.labelAnchor),
441         style.labelMargins);
442
443     if (!style.labelOutside) {
444         /* Move border edge so it's over label:
445         */
446         switch (LabelAnchorSide(style.labelAnchor)) {
447             case TTK_SIDE_LEFT:         borderParcel.x -= lw / 2;
448             /* FALLTHRU */
449             case TTK_SIDE_RIGHT:        borderParcel.width += lw/2;     break;
450             case TTK_SIDE_TOP:          borderParcel.y -= lh / 2;
451             /* FALLTHRU */
452             case TTK_SIDE_BOTTOM:       borderParcel.height += lh / 2;  break;
453         }
454     }
455
456     /*
457      * Place border and label:
458      */
459     Ttk_PlaceLayout(corePtr->layout, corePtr->state, borderParcel);
460     if (lframePtr->label.labelLayout) {
461         Ttk_PlaceLayout(
462             lframePtr->label.labelLayout, corePtr->state, labelParcel);
463     }
464     /* labelWidget placed in LabelframePlaceContent GM hook */
465     lframePtr->label.labelParcel = labelParcel;
466 }
467
468 static void LabelframeDisplay(void *recordPtr, Drawable d)
469 {
470     Labelframe *lframePtr = (Labelframe *)recordPtr;
471     Ttk_DrawLayout(lframePtr->core.layout, lframePtr->core.state, d);
472     if (lframePtr->label.labelLayout) {
473         Ttk_DrawLayout(lframePtr->label.labelLayout, lframePtr->core.state, d);
474     }
475 }
476
477 /* +++ Labelframe geometry manager hooks.
478  */
479
480 /* LabelframePlaceContent --
481  *      Sets the position and size of the labelwidget.
482  */
483 static void LabelframePlaceContent(void *recordPtr)
484 {
485     Labelframe *lframe = (Labelframe *)recordPtr;
486
487     if (Ttk_NumberContent(lframe->label.mgr) == 1) {
488         Ttk_Box b;
489         LabelframeDoLayout(recordPtr);
490         b = lframe->label.labelParcel;
491         /* ASSERT: content #0 is lframe->label.labelWidget */
492         Ttk_PlaceContent(lframe->label.mgr, 0, b.x,b.y,b.width,b.height);
493     }
494 }
495
496 static int LabelRequest(
497     TCL_UNUSED(void *),
498     TCL_UNUSED(int),
499     TCL_UNUSED(int),
500     TCL_UNUSED(int))
501 {
502     return 1;
503 }
504
505 /* LabelRemoved --
506  *      Unset the -labelwidget option.
507  *
508  * <<NOTE-LABELREMOVED>>:
509  *      This routine is also called when the widget voluntarily forgets
510  *      the window in LabelframeConfigure.
511  */
512 static void LabelRemoved(
513     void *managerData,
514     TCL_UNUSED(int))
515 {
516     Labelframe *lframe = (Labelframe *)managerData;
517
518     lframe->label.labelWidget = 0;
519 }
520
521 static Ttk_ManagerSpec LabelframeManagerSpec = {
522     { "labelframe", Ttk_GeometryRequestProc, Ttk_LostContentProc },
523     LabelframeSize,
524     LabelframePlaceContent,
525     LabelRequest,
526     LabelRemoved
527 };
528
529 /* LabelframeInitialize --
530  *      Initialization hook.
531  */
532 static void LabelframeInitialize(
533     TCL_UNUSED(Tcl_Interp *),
534     void *recordPtr)
535 {
536     Labelframe *lframe = (Labelframe *)recordPtr;
537
538     lframe->label.mgr = Ttk_CreateManager(
539         &LabelframeManagerSpec, lframe, lframe->core.tkwin);
540     lframe->label.labelWidget = 0;
541     lframe->label.labelLayout = 0;
542     lframe->label.labelParcel = Ttk_MakeBox(-1,-1,-1,-1);
543 }
544
545 /* LabelframeCleanup --
546  *      Cleanup hook.
547  */
548 static void LabelframeCleanup(void *recordPtr)
549 {
550     Labelframe *lframe = (Labelframe *)recordPtr;
551     Ttk_DeleteManager(lframe->label.mgr);
552     if (lframe->label.labelLayout) {
553         Ttk_FreeLayout(lframe->label.labelLayout);
554     }
555 }
556
557 /* RaiseLabelWidget --
558  *      Raise the -labelwidget to ensure that the labelframe doesn't
559  *      obscure it (if it's not a direct child), or bring it to
560  *      the top of the stacking order (if it is).
561  */
562 static void RaiseLabelWidget(Labelframe *lframe)
563 {
564     Tk_Window parent = Tk_Parent(lframe->label.labelWidget);
565     Tk_Window sibling = NULL;
566     Tk_Window w = lframe->core.tkwin;
567
568     while (w && w != parent) {
569         sibling = w;
570         w = Tk_Parent(w);
571     }
572
573     Tk_RestackWindow(lframe->label.labelWidget, Above, sibling);
574 }
575
576 /* LabelframeConfigure --
577  *      Configuration hook.
578  */
579 static int LabelframeConfigure(Tcl_Interp *interp,void *recordPtr,int mask)
580 {
581     Labelframe *lframePtr = (Labelframe *)recordPtr;
582     Tk_Window labelWidget = lframePtr->label.labelWidget;
583     Ttk_PositionSpec unused;
584
585     /* Validate options:
586      */
587     if (mask & LABELWIDGET_CHANGED && labelWidget != NULL) {
588         if (!Ttk_Maintainable(interp, labelWidget, lframePtr->core.tkwin)) {
589             return TCL_ERROR;
590         }
591     }
592
593     if (TtkGetLabelAnchorFromObj(
594         interp, lframePtr->label.labelAnchorObj, &unused) != TCL_OK)
595     {
596         return TCL_ERROR;
597     }
598
599     /* Base class configuration:
600      */
601     if (FrameConfigure(interp, recordPtr, mask) != TCL_OK) {
602         return TCL_ERROR;
603     }
604
605     /* Update -labelwidget changes, if any:
606      */
607     if (mask & LABELWIDGET_CHANGED) {
608         if (Ttk_NumberContent(lframePtr->label.mgr) == 1) {
609             Ttk_ForgetContent(lframePtr->label.mgr, 0);
610             /* Restore labelWidget field (see <<NOTE-LABELREMOVED>>)
611              */
612             lframePtr->label.labelWidget = labelWidget;
613         }
614
615         if (labelWidget) {
616                 Ttk_InsertContent(lframePtr->label.mgr, 0, labelWidget, NULL);
617             RaiseLabelWidget(lframePtr);
618         }
619     }
620
621     if (mask & GEOMETRY_CHANGED) {
622         Ttk_ManagerSizeChanged(lframePtr->label.mgr);
623         Ttk_ManagerLayoutChanged(lframePtr->label.mgr);
624     }
625
626     return TCL_OK;
627 }
628
629 static WidgetSpec LabelframeWidgetSpec = {
630     "TLabelframe",              /* className */
631     sizeof(Labelframe),         /* recordSize */
632     LabelframeOptionSpecs,      /* optionSpecs */
633     FrameCommands,              /* subcommands */
634     LabelframeInitialize,       /* initializeProc */
635     LabelframeCleanup,          /* cleanupProc */
636     LabelframeConfigure,        /* configureProc */
637     TtkNullPostConfigure,       /* postConfigureProc */
638     LabelframeGetLayout,        /* getLayoutProc */
639     LabelframeSize,             /* sizeProc */
640     LabelframeDoLayout,         /* layoutProc */
641     LabelframeDisplay           /* displayProc */
642 };
643
644 TTK_BEGIN_LAYOUT(LabelframeLayout)
645     TTK_NODE("Labelframe.border", TTK_FILL_BOTH)
646 TTK_END_LAYOUT
647
648 TTK_BEGIN_LAYOUT(LabelSublayout)
649     TTK_GROUP("Label.fill", TTK_FILL_BOTH,
650         TTK_NODE("Label.text", TTK_FILL_BOTH))
651 TTK_END_LAYOUT
652
653 /* ======================================================================
654  * +++ Initialization.
655  */
656
657 MODULE_SCOPE
658 void TtkFrame_Init(Tcl_Interp *interp)
659 {
660     Ttk_Theme theme =  Ttk_GetDefaultTheme(interp);
661
662     Ttk_RegisterLayout(theme, "TFrame", FrameLayout);
663     Ttk_RegisterLayout(theme, "TLabelframe", LabelframeLayout);
664     Ttk_RegisterLayout(theme, "Label", LabelSublayout);
665
666     RegisterWidget(interp, "ttk::frame", &FrameWidgetSpec);
667     RegisterWidget(interp, "ttk::labelframe", &LabelframeWidgetSpec);
668 }
669