OSDN Git Service

Please enter the commit message for your changes. Lines starting
[eos/base.git] / util / src / TclTk / tk8.6.12 / generic / ttk / ttkSquare.c
1 /* square.c - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sourceforge.net>
2  *
3  * Minimal sample ttk widget.
4  */
5
6 #include "tkInt.h"
7 #include "ttkTheme.h"
8 #include "ttkWidget.h"
9
10 #if defined(TTK_SQUARE_WIDGET) || 1
11
12 #ifndef DEFAULT_BORDERWIDTH
13 #define DEFAULT_BORDERWIDTH "2"
14 #endif
15
16 /*
17  * First, we setup the widget record. The Ttk package provides a structure
18  * that contains standard widget data so it is only necessary to define
19  * a structure that holds the data required for our widget. We do this by
20  * defining a widget part and then specifying the widget record as the
21  * concatenation of the two structures.
22  */
23
24 typedef struct
25 {
26     Tcl_Obj *widthObj;
27     Tcl_Obj *heightObj;
28     Tcl_Obj *reliefObj;
29     Tcl_Obj *borderWidthObj;
30     Tcl_Obj *foregroundObj;
31     Tcl_Obj *paddingObj;
32     Tcl_Obj *anchorObj;
33 } SquarePart;
34
35 typedef struct
36 {
37     WidgetCore core;
38     SquarePart square;
39 } Square;
40
41 /*
42  * Widget options.
43  *
44  * This structure is the same as the option specification structure used
45  * for Tk widgets. For each option we provide the type, name and options
46  * database name and class name and the position in the structure and
47  * default values. At the bottom we bring in the standard widget option
48  * defined for all widgets.
49  */
50
51 static Tk_OptionSpec SquareOptionSpecs[] =
52 {
53     {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
54      DEFAULT_BORDERWIDTH, Tk_Offset(Square,square.borderWidthObj), -1,
55      0,0,GEOMETRY_CHANGED },
56     {TK_OPTION_BORDER, "-foreground", "foreground", "Foreground",
57      DEFAULT_BACKGROUND, Tk_Offset(Square,square.foregroundObj),
58      -1, 0, 0, 0},
59
60     {TK_OPTION_PIXELS, "-width", "width", "Width",
61      "50", Tk_Offset(Square,square.widthObj), -1, 0, 0,
62      GEOMETRY_CHANGED},
63     {TK_OPTION_PIXELS, "-height", "height", "Height",
64      "50", Tk_Offset(Square,square.heightObj), -1, 0, 0,
65      GEOMETRY_CHANGED},
66
67     {TK_OPTION_STRING, "-padding", "padding", "Pad", NULL,
68      Tk_Offset(Square,square.paddingObj), -1,
69      TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED },
70
71     {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
72      NULL, Tk_Offset(Square,square.reliefObj), -1, TK_OPTION_NULL_OK, 0, 0},
73
74     {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
75      NULL, Tk_Offset(Square,square.anchorObj), -1, TK_OPTION_NULL_OK, 0, 0},
76
77     WIDGET_TAKEFOCUS_TRUE,
78     WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
79 };
80
81 /*
82  * Almost all of the widget functionality is handled by the default Ttk
83  * widget code and the contained element. The one thing that we must handle
84  * is the -anchor option which positions the square element within the parcel
85  * of space available for the widget.
86  * To do this we must find out the layout preferences for the square
87  * element and adjust its position within our region.
88  *
89  * Note that if we do not have a "square" elememt then just the default
90  * layout will be done. So if someone places a label element into the
91  * widget layout it will still be handled but the -anchor option will be
92  * passed onto the label element instead of handled here.
93  */
94
95 static void
96 SquareDoLayout(void *clientData)
97 {
98     WidgetCore *corePtr = (WidgetCore *)clientData;
99     Ttk_Box winBox;
100     Ttk_Element squareNode;
101
102     squareNode = Ttk_FindElement(corePtr->layout, "square");
103     winBox = Ttk_WinBox(corePtr->tkwin);
104     Ttk_PlaceLayout(corePtr->layout, corePtr->state, winBox);
105
106     /*
107      * Adjust the position of the square element within the widget according
108      * to the -anchor option.
109      */
110
111     if (squareNode) {
112         Square *squarePtr = (Square *)clientData;
113         Tk_Anchor anchor = TK_ANCHOR_CENTER;
114         Ttk_Box b;
115
116         b = Ttk_ElementParcel(squareNode);
117         if (squarePtr->square.anchorObj != NULL)
118             Tk_GetAnchorFromObj(NULL, squarePtr->square.anchorObj, &anchor);
119         b = Ttk_AnchorBox(winBox, b.width, b.height, anchor);
120
121         Ttk_PlaceElement(corePtr->layout, squareNode, b);
122     }
123 }
124
125 /*
126  * Widget commands. A widget is impelemented as an ensemble and the
127  * subcommands are listed here. Ttk provides default implementations
128  * that are sufficient for our needs.
129  */
130
131 static const Ttk_Ensemble SquareCommands[] = {
132     { "configure",      TtkWidgetConfigureCommand,0 },
133     { "cget",           TtkWidgetCgetCommand,0 },
134     { "identify",       TtkWidgetIdentifyCommand,0 },
135     { "instate",        TtkWidgetInstateCommand,0 },
136     { "state",          TtkWidgetStateCommand,0 },
137     { 0,0,0 }
138 };
139
140 /*
141  * The Widget specification structure holds all the implementation
142  * information about this widget and this is what must be registered
143  * with Tk in the package initialization code (see bottom).
144  */
145
146 static WidgetSpec SquareWidgetSpec =
147 {
148     "TSquare",                  /* className */
149     sizeof(Square),             /* recordSize */
150     SquareOptionSpecs,          /* optionSpecs */
151     SquareCommands,             /* subcommands */
152     TtkNullInitialize,          /* initializeProc */
153     TtkNullCleanup,             /* cleanupProc */
154     TtkCoreConfigure,           /* configureProc */
155     TtkNullPostConfigure,               /* postConfigureProc */
156     TtkWidgetGetLayout,         /* getLayoutProc */
157     TtkWidgetSize,              /* sizeProc */
158     SquareDoLayout,             /* layoutProc */
159     TtkWidgetDisplay            /* displayProc */
160 };
161
162 /* ----------------------------------------------------------------------
163  * Square element
164  *
165  * In this section we demonstrate what is required to create a new themed
166  * element.
167  */
168
169 typedef struct
170 {
171     Tcl_Obj *borderObj;
172     Tcl_Obj *foregroundObj;
173     Tcl_Obj *borderWidthObj;
174     Tcl_Obj *reliefObj;
175     Tcl_Obj *widthObj;
176     Tcl_Obj *heightObj;
177 } SquareElement;
178
179 static Ttk_ElementOptionSpec SquareElementOptions[] =
180 {
181     { "-background", TK_OPTION_BORDER, Tk_Offset(SquareElement,borderObj),
182         DEFAULT_BACKGROUND },
183     { "-foreground", TK_OPTION_BORDER, Tk_Offset(SquareElement,foregroundObj),
184         DEFAULT_BACKGROUND },
185     { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SquareElement,borderWidthObj),
186         DEFAULT_BORDERWIDTH },
187     { "-relief", TK_OPTION_RELIEF, Tk_Offset(SquareElement,reliefObj),
188         "raised" },
189     { "-width",  TK_OPTION_PIXELS, Tk_Offset(SquareElement,widthObj), "20"},
190     { "-height", TK_OPTION_PIXELS, Tk_Offset(SquareElement,heightObj), "20"},
191     { NULL, TK_OPTION_BOOLEAN, 0, NULL }
192 };
193
194 /*
195  * The element geometry function is called when the layout code wishes to
196  * find out how big this element wants to be. We must return our preferred
197  * size and padding information
198  */
199
200 static void SquareElementSize(
201     void *dummy, void *elementRecord, Tk_Window tkwin,
202     int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
203 {
204     SquareElement *square = (SquareElement *)elementRecord;
205     int borderWidth = 0;
206     (void)dummy;
207
208     Tcl_GetIntFromObj(NULL, square->borderWidthObj, &borderWidth);
209     *paddingPtr = Ttk_UniformPadding((short)borderWidth);
210     Tk_GetPixelsFromObj(NULL, tkwin, square->widthObj, widthPtr);
211     Tk_GetPixelsFromObj(NULL, tkwin, square->heightObj, heightPtr);
212 }
213
214 /*
215  * Draw the element in the box provided.
216  */
217
218 static void SquareElementDraw(
219     void *dummy, void *elementRecord, Tk_Window tkwin,
220     Drawable d, Ttk_Box b, unsigned int state)
221 {
222     SquareElement *square = (SquareElement *)elementRecord;
223     Tk_3DBorder foreground = NULL;
224     int borderWidth = 1, relief = TK_RELIEF_FLAT;
225     (void)dummy;
226     (void)state;
227
228     foreground = Tk_Get3DBorderFromObj(tkwin, square->foregroundObj);
229     Tcl_GetIntFromObj(NULL, square->borderWidthObj, &borderWidth);
230     Tk_GetReliefFromObj(NULL, square->reliefObj, &relief);
231
232     Tk_Fill3DRectangle(tkwin, d, foreground,
233         b.x, b.y, b.width, b.height, borderWidth, relief);
234 }
235
236 static Ttk_ElementSpec SquareElementSpec =
237 {
238     TK_STYLE_VERSION_2,
239     sizeof(SquareElement),
240     SquareElementOptions,
241     SquareElementSize,
242     SquareElementDraw
243 };
244
245 /* ----------------------------------------------------------------------
246  *
247  * Layout section.
248  *
249  * Every widget class needs a layout style that specifies which elements
250  * are part of the widget and how they should be placed. The element layout
251  * engine is similar to the Tk pack geometry manager. Read the documentation
252  * for the details. In this example we just need to have the square element
253  * that has been defined for this widget placed on a background. We will
254  * also need some padding to keep it away from the edges.
255  */
256
257 TTK_BEGIN_LAYOUT(SquareLayout)
258      TTK_NODE("Square.background", TTK_FILL_BOTH)
259      TTK_GROUP("Square.padding", TTK_FILL_BOTH,
260          TTK_NODE("Square.square", 0))
261 TTK_END_LAYOUT
262
263 /* ----------------------------------------------------------------------
264  *
265  * Widget initialization.
266  *
267  * This file defines a new element and a new widget. We need to register
268  * the element with the themes that will need it. In this case we will
269  * register with the default theme that is the root of the theme inheritance
270  * tree. This means all themes will find this element.
271  * We then need to register the widget class style. This is the layout
272  * specification. If a different theme requires an alternative layout, we
273  * could register that here. For instance, in some themes the scrollbars have
274  * one uparrow, in other themes there are two uparrow elements.
275  * Finally we register the widget itself. This step creates a tcl command so
276  * that we can actually create an instance of this class. The widget is
277  * linked to a particular style by the widget class name. This is important
278  * to realise as the programmer may change the classname when creating a
279  * new instance. If this is done, a new layout will need to be created (which
280  * can be done at script level). Some widgets may require particular elements
281  * to be present but we try to avoid this where possible. In this widget's C
282  * code, no reference is made to any particular elements. The programmer is
283  * free to specify a new style using completely different elements.
284  */
285
286 /* public */ MODULE_SCOPE int
287 TtkSquareWidget_Init(Tcl_Interp *interp)
288 {
289     Ttk_Theme theme = Ttk_GetDefaultTheme(interp);
290
291     /* register the new elements for this theme engine */
292     Ttk_RegisterElement(interp, theme, "square", &SquareElementSpec, NULL);
293
294     /* register the layout for this theme */
295     Ttk_RegisterLayout(theme, "TSquare", SquareLayout);
296
297     /* register the widget */
298     RegisterWidget(interp, "ttk::square", &SquareWidgetSpec);
299
300     return TCL_OK;
301 }
302
303 #endif /* TTK_SQUARE_WIDGET */
304