Creating a new widget

From CEGUI Wiki - Crazy Eddie's GUI System (Open Source)
Jump to: navigation, search

Creating a new type of widget for CEGUI is relatively easy once you know all the details. CEGUI gives you a lot of freedom in creating a new widget, you can basically create anything you want and it is relatively easy once you know all the basics. This page will help you understand the changes you need to undertake to make a new widget (and possibly get it accepted into the CEGUI codebase, which would help the entire community).

A widget can be broken down into two defining parts:

  • The logic part
  • The rendering part

The Logic Part

The logic part is encapsuled in classes that derive from the CEGUI::Window class. In version 0.8.X, these "widget logic" classes are located in cegui/src/widgets and the headers in cegui/include/CEGUI/widgets. Examples are ProgressBar, ToggleButton, PushButton, HorizontalLayoutContainer, etc. In these classes the inputs, interactions, events and might be used to define the current "state" (clicked, pushed, etc) of the widget for rendering. A list of these classes can be found here:

The logic part might often be enough to achieve what you want, as you can use existing widgets as child windows and only need to create the necessary extra stuff to deal with these and their events. In this case, you might not need a rendering class, and can define your widget just with a logic class and some XML (more about that at the end)

The Rendering Part

The rendering part consists of the C++ class and the XML defining the "look". The C++ classes for rendering are in the CoreWindowRendererSet: The Falagard classes. (Theoretically you could create your own Window Renderer Set but since, as far as we know, no one did that so far, we assume you are not using this either) A list of these classes, which most of all handle which LNF state is to be displayed currently, can be found here: The XML part of rendering consists of the .scheme and .looknfeel files. The looknfeel defines the look of a widget and also what child windows it contains. The scheme defines windows that can be created and what look, Falagard class, and logic class they use. More info on the look n' feel and schemes here:

Putting it together

Finally, let's go back to the earlier proposition of creating a new widget that combines existing widgets and unifies them into a new widget with specific behaviour. Your look n' feel would define the child widgets. For comparison, simply look at any ".../Spinner", ".../TabControl" or WidgetLook in your .looknfeel files. You will see it merely combines existing widgets as <Child> widgets inside the new look.

Then, regarding the scheme, you would do something like this:

<FalagardMapping windowType="YourWindowCategory/YourWindow" targetType="YourLogicClass" renderer="Core/Default" lookNFeel="Vanilla/Label" />
  • "YourWindowCategory/YourWindow" <-- this will be used as the string for creating windows of this new widget type, using the WindowManager
  • The "renderer" references a "Core/..." class and in this case "Core/Default". The Core classes are the Falagard classes (CoreWindowRendererSet). The "Core/Default" renders nothing on its own, but will of course render the children appropriately - which is what we want in this case.
  • The "targetType" references your logic class by name, but they must be registered using a function. This can be done from outside CEGUI like this:

CEGUI internally does in the following function, but this is only relevant if you want to directly modify the CEGUI library, e.g. if you want to make a contribution to it:

void System::addStandardWindowFactories()

The name is found in the "WidgetTypeName" member variable in the classes. If DefaultWindow is chosen then the widget won't have any specific logic behind it.

  • Finally, the "lookNFeel" attribute references your widget's appearance as defined in the .looknfeel file.