File: csskin.h

package info (click to toggle)
crystalspace 0.94-20020412-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 62,276 kB
  • ctags: 52,843
  • sloc: cpp: 274,783; ansic: 6,608; perl: 6,276; objc: 3,952; asm: 2,942; python: 2,354; php: 542; pascal: 530; sh: 430; makefile: 370; awk: 193
file content (348 lines) | stat: -rw-r--r-- 12,483 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
/*
    Crystal Space Windowing System: Skin interface
    Copyright (C) 2000 by Andrew Zabolotny, <bit@eltech.ru>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef __CSSKIN_H__
#define __CSSKIN_H__

#include "csutil/csvector.h"

class csSkin;
class csSkinSlice;
class csApp;
class csComponent;
class csButton;
class csWindow;
class csDialog;
class csListBox;
class csListBoxItem;
class csBackground;

/**
 * This class defines the interface for a container of skins.
 * Most of the functionality you will want is already here; the
 * only method that you will sometimes want to override is the
 * constructor and the Initialize() method. In constructor you
 * should assign the appropiate value to the "Prefix" member
 * variable which is used to find the sections that refer
 * to the respective theme. Initialize() used to query all
 * kinds of resources from the application object when a
 * skin is initialized.
 *<p>
 * Generally there should be only one object of this class,
 * which is stored into the csApp object. However, you can use
 * a skin for some component and all his children if you wish,
 * but you will have to store the respective skin container
 * somewhere inside that component (and override his GetSkin()
 * method so that child components can use the skin when initialized).
 *<p>
 * The repository contains a number of objects that are responsible
 * for the exterior of the respective components (and which are called
 * `skins'). These objects are identified by a text string. After you change
 * the skin repository, you should call the Apply() method of the repository
 * so that the given objects and all components which are inserted into that
 * component (note that this does NOT have to do anything with class
 * hierarchy!) will receive the cscmdSkinChanged broadcast.
 */
class csSkin : public csVector
{
  /// The application
  csApp *app;

public:
  /// This is the prefix for section names in CSWS' configuration file
  const char *Prefix;

  /// Create the skin repository object
  csSkin () : csVector (16, 16), Prefix (NULL) {}

  /// Destroy all skins in this repository
  virtual ~csSkin ();

  /// Free a skin from this repository
  virtual bool FreeItem (csSome Item);

  /// Compare a item from this array with some key
  virtual int CompareKey (csSome Item, csConstSome Key, int) const;

  /// Compare two items from this array
  virtual int Compare (csSome Item1, csSome Item2, int) const;

  /// Get a skin from this array
  csSkinSlice *Get (int iIndex)
  { return (csSkinSlice *)csVector::Get (iIndex); }

  /// Apply this skin to some component and all components inserted into it
  void Apply (csComponent *iComp);

  /// Initialize all skin slices with given application object
  virtual void Initialize (csApp *iApp);

  /// Free any resources allocated by the skin slices
  virtual void Deinitialize ();

  /// Utility function: get a skin-specific string from csws config file
  const char *GetConfigStr (const char *iSection, const char *iKey, const char *iDefault);
  /// Same but get a boolean value
  bool GetConfigYesNo (const char *iSection, const char *iKey, bool iDefault);

  /// Utility function: read background from given section with given key prefix
  void Load (csBackground &oBack, const char *iSection, const char *iPrefix);

private:
  bool ReadGradient (const char *iText, csRGBcolor *color, int iNum);
};

/**
 * A `skin slice' is responsible for managing the external view of a
 * certain component. Every `skin slice' is designed to take care of
 * some specific component type; you should be careful to provide all
 * `slices' for all used types of components, otherwise the windowing
 * system will print a error message and abort the program. Every
 * csComponent has a pointer to a csSkinSlice object inside, which
 * points to the respective object responsible for his exterior.
 *<p>
 * This is an abstract class, meant to be uses as a common parent
 * for all derived classes. Since some derived objects will implement
 * additional functionality over the basic csSkinSlice functionality,
 * it is recommended to #define a SKIN macro at the top of every
 * file with the implementation of the respective component like this:
 *<p>
 * #define SKIN ((csDefaultButtonSkin *)skinslice)
 *<p>
 * Then you can use the SKIN macro as if it was a member variable.
 * Note that the safety of the typecast is guaranteed by the uniquity
 * of the string returned by the csSkinSlice::GetName() method.
 *<p>
 * Also note that most skin slices don't have a constructor. This is
 * because skin slices are usually created before the application, thus
 * you don't have any place to gather initialization information from.
 * If you need to query some data from the application (e.g. some textures
 * and so on) you will have to overload the Initialize() virtual method.
 */
class csSkinSlice
{
public:
  /// Destroy this skin slice
  virtual ~csSkinSlice ()
  { Deinitialize (); }

  /**
   * Initialize the skin slice, if desired, by querying any information
   * you want from given application object. At the time this routine is
   * called, the application is fully initialized, configuration file is
   * opened, textures are loaded and so on. This method is called once
   * from csApp::Initialize() method and also every time you call
   * csApp::SetSkin().
   */
  virtual void Initialize (csApp * /*iApp*/, csSkin * /*Parent*/) {}

  /**
   * This method is called from application's destructor.
   * The skin should free any resources allocated in Initialize()
   * here, because later (at destructor time) some plugins (e.g. the
   * texture manager) may be unloaded already. It is legal to call
   * Deinitialize() multiple times; if the resources were already
   * freed, the method should do nothing.
   */
  virtual void Deinitialize () {}

  /// Get the identifier of the component this skin slice is for
  virtual const char *GetName () = 0;

  /// Initialize the object we are responsible for: called once we set the skin
  virtual void Apply (csComponent &This);

  /**
   * Reset a component to its "default" state.
   * This removes the custom palette if any, resets
   * component size etc. This is usually called by skin slices
   * inside Apply() method before applying any changes
   * to the component. If the component has the `skinslice'
   * non-NULL, the Initialize() method calls this method of
   * the old skin slice so that it will restore the component
   * to the initial state.
   */
  virtual void Reset (csComponent &This);

  /// Draw the component we are responsible for
  virtual void Draw (csComponent &This) = 0;
};

/**
 * This class defines the interface for a button skin slice.
 * Every skin slice that is meant for buttons should inherit
 * from this interface.
 */
class csButtonSkin : public csSkinSlice
{
public:
  /// Get the identifier of the component this skin slice is for
  virtual const char *GetName ()
  { return "Button"; }

  /// Suggest the optimal size of the button, given an already filled object
  virtual void SuggestSize (csButton &This, int &w, int &h) = 0;
};

/**
 * This class defines the interface for a window skin slice.
 * Every skin slice that is meant for windows should inherit
 * from this interface.
 */
class csWindowSkin : public csSkinSlice
{
public:
  /// Get the identifier of the component this skin slice is for
  virtual const char *GetName ()
  { return "Window"; }

  /// Create a button for window's titlebar
  virtual csButton *CreateButton (csWindow &This, int ButtonID) = 0;

  /// Place all gadgets (titlebar, buttons, menu and toolbar)
  virtual void PlaceGadgets (csWindow &This) = 0;

  /// Called to reflect some specific window state change on gagdets
  virtual void SetState (csWindow &This, int Which, bool State) = 0;

  /// Set window border width and height depending on frame style
  virtual void SetBorderSize (csWindow &This) = 0;
};

/**
 * This class defines the interface for a dialog skin slice.
 * Every skin slice that is meant for dialogs should inherit
 * from this interface.
 */
class csDialogSkin : public csSkinSlice
{
public:
  /// Get the identifier of the component this skin slice is for
  virtual const char *GetName ()
  { return "Dialog"; }

  /// Set dialog border width and height depending on frame style
  virtual void SetBorderSize (csDialog &This) = 0;
};

/**
 * This class defines the interface for a window titlebar skin slice.
 * Every skin slice that is meant for title bars should inherit
 * from this interface.
 */
class csTitlebarSkin : public csSkinSlice
{
public:
  /// Get the identifier of the component this skin slice is for
  virtual const char *GetName ()
  { return "Titlebar"; }
};

/**
 * This class defines the interface for a listbox skin slice.
 * Every skin slice that is meant for listboxes should inherit
 * from this interface.
 */
class csListBoxSkin : public csSkinSlice
{
public:
  /// Get the identifier of the component this skin slice is for
  virtual const char *GetName ()
  { return "Listbox"; }

  /// Suggest the optimal size of the button, given an already filled object
  virtual void SuggestSize (csListBox &This, int &w, int &h) = 0;
};

/**
 * This class defines the interface for a listbox item skin slice.
 * Every skin slice that is meant for listboxe items should inherit
 * from this interface.
 */
class csListBoxItemSkin : public csSkinSlice
{
public:
  /// Get the identifier of the component this skin slice is for
  virtual const char *GetName ()
  { return "ListboxItem"; }
};


/**
 * This class defines the interface for a scrollbar skin slice.
 * Every skin slice that is meant for scrollbars should inherit
 * from this interface.
 */
class csScrollBarSkin : public csSkinSlice
{
public:
  /// Get the identifier of the component this skin slice is for
  virtual const char *GetName ()
  { return "ScrollBar"; }
};

/**
 * Use the following macros to declare a skin.
 * You should declare all the skins that your program will use
 * preferably inside the main module of your program. The following
 * macros are used to select custom skin slices if you know in advance
 * which components (e.g. buttons, windows, listboxes etc) your application
 * will use. This has the advantage of avoiding insclusion of dead code
 * into your program (e.g. if you don't use the tree view, you don't need
 * the tree view skin either - and a single skin slice can be as big as
 * 30K of code or even more!). For simple programs you can use the simple
 * CSWS_SKIN_DECLARE_XXX macros (defined inside the respective skin header file)
 * which includes ALL the components of the skin; but if you want a finer
 * grade of control you should use the macros below.
 */

/**
 * Start the declaration of a skin.
 * <p>`name' is the name of the skin (e.g. "Default")
 * <p>`base' is the base class of the skin (e.g. "csSkin")
 * <p>`prefix' is the prefix for section names in CSWS' configuration file
 */
#define CSWS_SKIN_DECLARE(name,base)	\
  class name : public base	\
  {				\
  public:			\
    name ()			\
    {
/**
 * Declare a single skin slice to be included into the skin
 * that is in process of definition. "comp" is the component
 * name, e.g. "Button", "Window" and so on.
 */
#define CSWS_SKIN_SLICE(comp)	\
      InsertSorted (new cs##comp##Skin);

/**
 * Finish the definition of a skin.
 * After CSWS_SKIN_DECLARE_END you should put either a variable name
 * (e.g. "CSWS_SKIN_DECLARE_END myskin;") or simply a ';' - in the later
 * case you will define just a <b>type</b> called [name], where
 * `name' is the first parameter passed to CSWS_SKIN_DECLARE(), and you will
 * have to declare somewhere a variable of this type in order to use
 * the skin.
 */
#define CSWS_SKIN_DECLARE_END	\
    }				\
  }

#endif // __CSSKIN_H__