Create a CheckListboxItem
Sometimes you need a list where the items are checkable. The ItemListbox introduced in CEGUI 0.5 accepts all sorts of items, as long as they inherit ItemEntry. I'm going to teach you how to create a CheckListboxItem to put in your list.
Contents
Getting started!
I'm assuming you are just using a standard imageset, with a standard scheme (currently TaharezLook and WindowsLook are supported).
We are first going to get started by writing the looknfeel entry. This is the most important part of this tutorial, as its basically 70% of what we need to do to achieve our goal. First of all, this entry has a few states:
- Enabled: How the item looks when the item is enabled.
- Disabled: How the item looks when the item is disabled.
- SelectedEnabled: How the item looks when the item is selected and is enabled.
- SelectedDisabled: How the item looks when the item is selected and is disabled.
Writing the requirements
Open the appriopiate looknfeel file (WindowsLook.looknfeel or TaharezLook.looknfeel), and place this at the bottom (inside the Falagard tags though!)
Our start
<WidgetLook name="WindowsLook/CheckListboxItem"> </WidgetLook>
We first need to define a WidgetLook, this is where all the action happens in. It takes one attribute, name. This is simply the name of the widget you are defining. Now we are going to add the states. These states are necessary for the item to respond to certain events. For example, when the item is disabled, the state Disabled is used.
<WidgetLook name="WindowsLook/CheckListboxItem"> <StateImagery name="Enabled"> <Layer> <Section section="label"> <ColourProperty name="TextColour" /> </Section> </Layer> </StateImagery> <StateImagery name="Disabled"> <Layer> <Section section="label"> <ColourProperty name="TextColour" /> </Section> </Layer> </StateImagery> </WidgetLook>
We define a state via StateImagery. It requires the attribute name which specifies what state its in. Don't worry about Layer for now. Section is always used. This part takes care of actually changing the look. It requires a attribute section, this is actually WHAT to change, in this case the label. TextColour is a simple colour (black), we will define it below. Now as you can see the Enabled state just sets the text colour to black, thats all it does. Same goes for Disabled (remember this is an item, items are not commonly disabled).
Now we are going to take a look at the other two states.
<WidgetLook name="WindowsLook/CheckListboxItem"> <StateImagery name="Enabled"> <Layer> <Section section="label"> <ColourProperty name="TextColour" /> </Section> </Layer> </StateImagery> <StateImagery name="Disabled"> <Layer> <Section section="label"> <ColourProperty name="TextColour" /> </Section> </Layer> </StateImagery> <StateImagery name="SelectedEnabled"> <Layer> <Section section="selection" /> <Section section="label"> <ColourProperty name="SelectedTextColour" /> </Section> </Layer> </StateImagery> <StateImagery name="SelectedDisabled"> <Layer> <Section section="selection" /> <Section section="label"> <ColourProperty name="SelectedTextColour" /> </Section> </Layer> </StateImagery> </WidgetLook>
These states pretty much speak for themselves altough there are more sections listed. Section not only defines what to change, also defines what needs to be shown. In the Enabled state we dont want it to look like its selected, so there is no selection section. Note that the order of which you put the Sections are also the Z order. In this case we are putting the selection image first, and then text. If we would do it the other way around, we wouldn't see the text.
Now we are going to add the definitions of some colors and property's.
<WidgetLook name="WindowsLook/CheckListboxItem"> <PropertyDefinition name="TextColour" initialValue="FF000000" redrawOnWrite="true" /> <PropertyDefinition name="SelectedTextColour" initialValue="FFFFFFFF" redrawOnWrite="true" /> <PropertyDefinition name="SelectionBrush" initialValue="set:WindowsLook image:Background" redrawOnWrite="true" /> <PropertyDefinition name="SelectionColour" initialValue="FF3030FF" redrawOnWrite="true" /> <Property name="Selectable" value="True" /> <StateImagery name="Enabled"> <Layer> <Section section="label"> <ColourProperty name="TextColour" /> </Section> </Layer> </StateImagery> <StateImagery name="Disabled"> <Layer> <Section section="label"> <ColourProperty name="TextColour" /> </Section> </Layer> </StateImagery> <StateImagery name="SelectedEnabled"> <Layer> <Section section="selection" /> <Section section="label"> <ColourProperty name="SelectedTextColour" /> </Section> </Layer> </StateImagery> <StateImagery name="SelectedDisabled"> <Layer> <Section section="selection" /> <Section section="label"> <ColourProperty name="SelectedTextColour" /> </Section> </Layer> </StateImagery> </WidgetLook>
Our first PropertyDefinition just defines a text for a colour used in the StateImagery sections. Same goes for the other PropertyDefinitions except the SelectionBrush. Instead of defining a color, it defines a image. In this case it uses the WindowsLook Background image defined in the imageset. Then we got a Property, which simply implies some sort of setting. In this case, we make it a item by adding the Property 'Selectable' and setting it to true as we want it to act like an item.
Writing the functional parts
We now need to add the parts where the background, text and the selection gets drawn. This seems hard, but isn't actually. We are going to start off with a NamedArea. This is required for a listbox item as the listbox needs to know how big the item is to fit it into the list.
<WidgetLook name="WindowsLook/CheckListboxItem"> <PropertyDefinition name="TextColour" initialValue="FF000000" redrawOnWrite="true" /> <PropertyDefinition name="SelectedTextColour" initialValue="FFFFFFFF" redrawOnWrite="true" /> <PropertyDefinition name="SelectionBrush" initialValue="set:WindowsLook image:Background" redrawOnWrite="true" /> <PropertyDefinition name="SelectionColour" initialValue="FF3030FF" redrawOnWrite="true" /> <Property name="Selectable" value="True" /> <NamedArea name="ContentSize"> <Area> <Dim type="LeftEdge" > <AbsoluteDim value="0" /> </Dim> <Dim type="TopEdge" > <AbsoluteDim value="0" /> </Dim> <Dim type="Width" > <FontDim type="HorzExtent" padding="6" /> </Dim> <Dim type="Height" > <FontDim type="LineSpacing" /> </Dim> </Area> </NamedArea> <StateImagery name="Enabled"> <Layer> <Section section="label"> <ColourProperty name="TextColour" /> </Section> </Layer> </StateImagery> <StateImagery name="Disabled"> <Layer> <Section section="label"> <ColourProperty name="TextColour" /> </Section> </Layer> </StateImagery> <StateImagery name="SelectedEnabled"> <Layer> <Section section="selection" /> <Section section="label"> <ColourProperty name="SelectedTextColour" /> </Section> </Layer> </StateImagery> <StateImagery name="SelectedDisabled"> <Layer> <Section section="selection" /> <Section section="label"> <ColourProperty name="SelectedTextColour" /> </Section> </Layer> </StateImagery> </WidgetLook>
I am assuming you know what the basics like the Area, Dim and such. Though FontDim is used to change the size of the item depending on a label. The part we just added now defines the size of the item. Instead of adding the whole code here again, I'm only showing the additions from now on.
Ok! Now we are going to add the actual Checkbox. This is crucial for our goal, as it allows the item to be checked upon click. We dont have to write the states and all that for the Checkbox, we just use Child! Just place this under our NamedArea and above the first StateImagery.
<Child type ="WindowsLook/Checkbox" nameSuffix="__auto__checkbox"> <Area> <Dim type="LeftEdge"> <UnifiedDim scale="0" type="LeftEdge" /> <AbsoluteDim value="3" /> </Dim> <Dim type="TopEdge"> <UnifiedDim scale="0" type="TopEdge" /> </Dim> <Dim type="Width"> <UnifiedDim scale="1" type="Width" /> </Dim> <Dim type="Height"> <UnifiedDim scale="1" type="Height"/> </Dim> </Area> </Child>
This adds a WindowsLook/Checkbox to our item. The suffix is necessary to make the name unique. the rest is pretty straight forward - it adds the checkbox on the left side of the item, starting from 3 pixels to make it look smooth.
Now we need a label, this part is simple and I will not spend as much time on clarifying it, it basically explains itself.
<ImagerySection name="label"> <TextComponent> <Area> <Dim type="TopEdge"> <AbsoluteDim value="0" /> </Dim> <Dim type="LeftEdge"> <AbsoluteDim value="18" /> </Dim> <Dim type="RightEdge"> <UnifiedDim scale="1" offset="-3" type="RightEdge" /> </Dim> <Dim type="BottomEdge"> <UnifiedDim scale="1" type="BottomEdge" /> </Dim> </Area> </TextComponent> </ImagerySection>
The TextComponent simply states this this can contain text. The Dim's are just positioning. Note the LeftEdge, the label starts at 18 pixels from the left. This is because the first ~15 pixels are occupied by the checkbox.
Now something important! The selection image.
<ImagerySection name="selection"> <ImageryComponent> <Area> <Dim type="TopEdge"> <AbsoluteDim value="0" /> </Dim> <Dim type="LeftEdge"> <AbsoluteDim value="0" /> </Dim> <Dim type="RightEdge"> <UnifiedDim scale="1" type="RightEdge" /> </Dim> <Dim type="BottomEdge"> <UnifiedDim scale="1" type="BottomEdge" /> </Dim> </Area> <ImageProperty name="SelectionBrush" /> <ColourProperty name="SelectionColour" /> <VertFormat type="Stretched" /> <HorzFormat type="Stretched" /> </ImageryComponent> </ImagerySection>
Note that we give it the name selection, as used in the StateImagery. The Area part is just positioning and fitting again. The Dim's used there simply make sure the whole item is filled. ImageProperty defines the image to use. We have defined SelectionBrush at the top of our WidgetLook. It simply fills the Area with that image now. ColourProperty colors the image, we have also defined SelectionColour at the top of the WidgetLook. VertFormat and HorzFormat are stretched, if its not stretched, it will only draw one pixel of the image, making it near invisible. Stretching it just makes sure the whole area is covered.
That was it! We wrote our looknfeel entry!!
<WidgetLook name="WindowsLook/CheckListboxItem"> <PropertyDefinition name="TextColour" initialValue="FF000000" redrawOnWrite="true" /> <PropertyDefinition name="SelectedTextColour" initialValue="FFFFFFFF" redrawOnWrite="true" /> <PropertyDefinition name="SelectionBrush" initialValue="set:WindowsLook image:Background" redrawOnWrite="true" /> <PropertyDefinition name="SelectionColour" initialValue="FF3030FF" redrawOnWrite="true" /> <Property name="Selectable" value="True" /> <NamedArea name="ContentSize"> <Area> <Dim type="LeftEdge" > <AbsoluteDim value="0" /> </Dim> <Dim type="TopEdge" > <AbsoluteDim value="0" /> </Dim> <Dim type="Width" > <FontDim type="HorzExtent" padding="6" /> </Dim> <Dim type="Height" > <FontDim type="LineSpacing" /> </Dim> </Area> </NamedArea> <Child type ="WindowsLook/Checkbox" nameSuffix="__auto__checkbox"> <Area> <Dim type="LeftEdge"> <UnifiedDim scale="0" type="LeftEdge" /> <AbsoluteDim value="3" /> </Dim> <Dim type="TopEdge"> <UnifiedDim scale="0" type="TopEdge" /> </Dim> <Dim type="Width"> <UnifiedDim scale="1" type="Width" /> </Dim> <Dim type="Height"> <UnifiedDim scale="1" type="Height"/> </Dim> </Area> </Child> <ImagerySection name="label"> <TextComponent> <Area> <Dim type="TopEdge"> <AbsoluteDim value="0" /> </Dim> <Dim type="LeftEdge"> <AbsoluteDim value="18" /> </Dim> <Dim type="RightEdge"> <UnifiedDim scale="1" offset="-3" type="RightEdge" /> </Dim> <Dim type="BottomEdge"> <UnifiedDim scale="1" type="BottomEdge" /> </Dim> </Area> </TextComponent> </ImagerySection> <ImagerySection name="selection"> <ImageryComponent> <Area> <Dim type="TopEdge"> <AbsoluteDim value="0" /> </Dim> <Dim type="LeftEdge"> <AbsoluteDim value="0" /> </Dim> <Dim type="RightEdge"> <UnifiedDim scale="1" type="RightEdge" /> </Dim> <Dim type="BottomEdge"> <UnifiedDim scale="1" type="BottomEdge" /> </Dim> </Area> <ImageProperty name="SelectionBrush" /> <ColourProperty name="SelectionColour" /> <VertFormat type="Stretched" /> <HorzFormat type="Stretched" /> </ImageryComponent> </ImagerySection> <StateImagery name="Enabled"> <Layer> <Section section="label"> <ColourProperty name="TextColour" /> </Section> </Layer> </StateImagery> <StateImagery name="Disabled"> <Layer> <Section section="label"> <ColourProperty name="TextColour" /> </Section> </Layer> </StateImagery> <StateImagery name="SelectedEnabled"> <Layer> <Section section="selection" /> <Section section="label"> <ColourProperty name="SelectedTextColour" /> </Section> </Layer> </StateImagery> <StateImagery name="SelectedDisabled"> <Layer> <Section section="selection" /> <Section section="label"> <ColourProperty name="SelectedTextColour" /> </Section> </Layer> </StateImagery> </WidgetLook>
Pfew am I glad thats done.
Coding our item
We have come to the part where we actually try out our new item. We need to do a few things to call this one finished. First, we need to create the CheckListboxItem class. Then we are going to add the window factory to the system. Last but not least is adding the Falagard mapping. We'll start with the CheckListboxItem class. // TODO: More to come, gotta go for now :)
--Levia 21:10, 5 April 2007 (GMT+1)