Skinning tutorial part 5

From TrillWiki

Jump to: navigation, search

[edit] Part 5 - Adding Control

Reference Files:


So a resizing window outline is not good enough for you huh?

You want buttons as well?

Some people are so greedy.

To explain how to add buttons, we need to go over controls again. As I mentioned back in Part 1, all buttons, switchers, scrollbars, text, progress bars etc are all defined in Controls. They are then placed in the different windows via IControls. Re-read this part to familiarise yourselves with the concept once more, then continue.

First off I am going to teach you how to create a control, to give that control a specific "type" (eg button), and then how to place it, using my min, max and hide buttons as examples.

Now as Controls can be called from any window (depending on type), and an infinate number of times, it would not be practical to store them in the individual components. If you open up your trillian.xml file, you will see a section that starts <prefs> and ends with </prefs> (as always). Inside prefs, you will see the following:

&topics;
&displaysEdits;
&misc-controls;
&listsIcons;
&buttons;
&switchers;
&scrollbars;
&menus;
<control name="colors" type="colors">
<colors file="System/colours.ini"/>
</control>
<control name="emoticons" type="emoticons">
&emoticons;
&avatars;
</control>

The top block are standard dtd references that you saw previously for xfer.ext, files.ext etc. These files are where you will store your control details (more in just a sec).

The other two bits are examples of slightly unique controls that we will come onto later, suffice it to say they are the controls for colours.ini and the emoticons (no, you do not get a prize for having already guessed that ;))

Ok, so the first controls we are going to define our for our min max and close buttons. I like to split my controls up into files depending on the "type" of the control - in this case "button". So open up your xml/controls/buttons.ext and you should see the following:

<version Trillian="0.70"/>
<skindesc
name="SKIN NAME"
author="YOUR NAME"
email="YOUR EMAIL ADDRESS"
/>
<!-- Buttons -->

All standard stuff - again notice the section at the top for entering you skin details. This is often the quickest way to detect if someoen has ripped your work, as people are too lazy/dont know about it to change it.

After this we can stick our very first button control. The first control I am going to add is the close button. As I am too lazy to type out the code, I grabbed the following code from the button control page of the reference.

<control name="[name of control]" type="button">
<background name="[state]">
<source name="[bitmap name]" left="0" right="0" top="0" bottom="0"/>
<rect>
<left num="0" width="0"/>
<right num="0" width="1"/>
<top num="0" height="0"/>
<bottom num="0" height="1"/>
</rect>
</background>
<action name="[action type]" value="[value]"/>
</control>

Now, this is not quite all we need, as we need 3 copies of the "background" code, but ignoring that for a second, let's break it down:

<control name="[name of control]" type="button">

This line is where the control is declared - much in the same way a component is (and as we'll see later, IControls and more as well). The control can be called anything you want, but it is helpful to give it a representative name, so as to help you out when you go back to look at it - remember, as with comments, to help yourself remember what thigns do as it will save you time in the long run.

I usually call my controls any number of names, but recently I have found that prefixing them with "control-" helps me distinguish between bmps and controls. For my maximise control here, I am going to call it "control-xfer-close". I included the "xfer" bit, because although I can also use this control in the buddylist, message windows etc, I haven't designed them yet, and they might be different. If you have already designed your windows and they all share the minmaxclosehide buttons, feel free to call it "control-close". It's up to you - an example of the freedom on SkinXML.

<background name="[state]">

This is the next line, which should look somewhat familier to you. In this instance, though, the "name" property has been replaced with "state". A "state" is how the button should appear, depending on how the user interects with it. The reference has kindly documented what "state" a button control can have, and they take logical names, so you should easily figure out what they do :).

  • flat
  • over
  • push
  • disabled

The "disabled" state is present on some buttons, but not the min/max/close/hide ones. Examples of buttons which do use this state would be the text editing buttnos in the message windows - which use the disabled state when the medium doesn't support it.

The next bit is the standard "source" and "rec" stuff we have used for background of windows.

The final line;

<action name="[action type]" value="[value]"/>

Is redundant, as mentioned on the reference page. It is there for legacy purposes - scrap it.

We do, however need to have the code for all three background "states". To do this we simply copy everything between the <background> tags and paste it another two times after the first one. Fill in the state properties and it should look as below:

<control name="control-xfer-close" type="button">
<background name="flat">
<source name="[bitmap name]" left="0" right="0" top="0" bottom="0"/>
<rect>
<left num="0" width="0"/>
<right num="0" width="1"/>
<top num="0" height="0"/>
<bottom num="0" height="1"/>
</rect>
</background>
<background name="over">
<source name="[bitmap name]" left="0" right="0" top="0" bottom="0"/>
<rect>
<left num="0" width="0"/>
<right num="0" width="1"/>
<top num="0" height="0"/>
<bottom num="0" height="1"/>
</rect>
</background>
<background name="push">
<source name="[bitmap name]" left="0" right="0" top="0" bottom="0"/>
<rect>
<left num="0" width="0"/>
<right num="0" width="1"/>
<top num="0" height="0"/>
<bottom num="0" height="1"/>
</rect>
</background>
</control>

You may have noticed that

<rect>
<left num="0" width="0"/>
<right num="0" width="1"/>
<top num="0" height="0"/>
<bottom num="0" height="1"/>
</rect>

Is repeated 3 times! This is just an irritating waste of space. All the code means is that the rectangular region takes up all of the space - as we saw with the colour definition to fill up that blue in Part 3 (If you want, go back and replace that with &rect; ). As it occurs so often, all skinners create a file with this in and call it "rect" or "zero". I call mine "rect" and have a dtd entry set up in the skin structure. So every time you see that, just replace it with &rect; like so:

<control name="control-xfer-close" type="button">
<background name="flat">
<source name="[bitmap name]" left="0" right="0" top="0" bottom="0"/>
&rect;
</background>
<background name="over">
<source name="[bitmap name]" left="0" right="0" top="0" bottom="0"/>
&rect;
</background>
<background name="push">
<source name="[bitmap name]" left="0" right="0" top="0" bottom="0"/>
&rect;
</background>
</control>

It's looking like less and less code already huh?

Ok, now my graphics are coming from the graphics/controls/xfer-controls.gif file, shown below;

Button images
Button images

We need to add this the the files.ext, so that it knows where to get the pics from:

<bitmap name="bmpXferControls" file="Graphics/controls/xfer-controls.gif"/>

It is the (H)(M)(C) bits we are interested in for this part, as they're my minmaxclosehide buttons for the xfer window. The top row is the "flat" state, the 2nd "over" and 3rd "push".

All we need to do is grab the coords and punch them straight into the "source" tags - simple as that.

My close buttons flat state goes from coord 138,12 to 156,31 so my "source" tag will look like this:

<background name="flat">
<source name="bmpXferControls" left="138" right="156" top="12" bottom="31"/>
&rect;
</background>

Simple as. My over and push states have coords (138,39) to (156,58 ) and (138,66) to (156,85) respectively. All put together, my close button control now looks like this:

<control name="control-xfer-close" type="button">
<background name="flat">
<source name="bmpXferControls" left="138" right="156" top="12" bottom="31"/>
&rect;
</background>
<background name="over">
<source name="bmpXferControls" left="138" right="156" top="39" bottom="58"/>
&rect;
</background>
<background name="push">
<source name="bmpXferControls" left="138" right="156" top="66" bottom="85"/>
&rect;
</background>
</control>

Now, I'm sure you've noticed, due to the way I lined my graphics up in the file, the left and right nums are the same in all three states. Remember this when designing your graphics, as it will save you alot of time looking up and writing in coords - once you have noe <source> tag done, copy and paste it to the other two states, and then all you need to change are the top and bottom nums. All this equates to less and less work than you might have at first believed.

Now we have the control coded, we need to add it to the window itself. We do this with an IControl. An IControl looks very similar to background code, only without the <source> tag:

<icontrol source="[control name]" name="[name]" visible="1">
<rect>
<left num="0" width="0" />
<top num="0" height="0" />
<right num="0" width="0" />
<bottom num="0" height="0" />
</rect>
</icontrol>

The only thing which should look unfamilier here is the visible="1" attribute of the IControl tag. This does exactly what you would expect, and is useful for hiding IControls when testing things.

The source="" bit is where you enter the name of your control you just defined. In my case, this will be "control-xfer-close". The 'name' property is not user-definable - this is what tells Trillian what the IControl actually does. To find what to put here, we check the Transfer Window IControl page from the reference. As it happens, it's called "close", so that's what we put there.

Finally, we tell Trillian where on the window to place it. Remember, we are placing this ON THE WINDOW, so it needs to go inside the <component> tags. You must be getting used to this by now. Mine will go in the top right corner, so the left and right "width"s will be 1. The heights will be 0. My IControl looks like this:

<icontrol source="control-xfer-close" name="close" visible="1">
<rect>
<left num="26" width="1" />
<top num="12" height="0" />
<right num="8" width="1" />
<bottom num="31" height="0" />
</rect>
</icontrol>

Enter in your code, save the file and fire it up in the skin tester. With luck, your button should show up where you placed it. Hoever over it and push it, to test that you coded your states correctly.

Close button
Close button

Congratulations, you have now completed your first button - yet another hurdle overcome. With any luck, you now know how to add buttons - and it's a very small jump adding all sorts of other cool stuff, I promise. I am going to briefly go through the minimize and hide buttons, just to be sure the procedure is clear. Before we start adding more buttons - add a comment above the control/IControl which tells you what it does.

So then - how to quickly add in the minimize and hide buttons. First off, in your buttons.ext file, copy the close button control, and past it twice. Rename one to "control-xfer-minimize" and one to "control-xfer-hide". Now trillian recognises them as different controls, but they all still point to the same graphics. However, we can re-use the top and bottom nums, because of the way we lined them up in the file - just in the same way we previously re-used the left and right nums. So, in actuality, all we have to change are the left and right nums.

My hide button goes from 96 to 114, and my minimize button from 117 to 135. Inputting these numbers, completes my min close and hide controls - simple, huh.

Now the controls are done, we need to add in the IControls. Copy/paste, the IControls, and change their "name" values - check them in the reference if you are unsure. Also, don't forget to change the "source" property to the new control names (I forget this all the time). When this is complete, all that remains is to change the left and right values of the hide and minimize buttons. My hide button goes from 68 to 50 (remember, these numbers appear the wrong way round, because they are relative to the right hand side), and my minimize from 47 to 29.

Save, and fire up in skinviewer. You will notice, that while the hide and close buttons do nothing, the minimize button actually minimises the window - a good way to check you have put in the correct "name" property of the IControl.

Now it's your turn to add a button completely by yourself. Add in the "options" button. You know how to do it, and this is where you can test your knowledge - create the control, make the IControl and test in the skinviewer. It should look something like this:

Window with all buttons added
Window with all buttons added

If it doesn't, download THIS zip file of my two files, and check yours against it. If you still can't find the problem, jump over to the forums and someone will help you out.

Ok, so we have our buttons coded. Next up, we need to add some text to our window, so we can display info such as who's sending the file/speed etc. Text is displayed via topic controls. These are still controls much the same as buttons (just with different properties). and so you start one like this:

<control name="[name]" type="topic">
</control>

Now, most of our text will appear the same, so we only need to define 1 control for most of the text (all the text that changes as the transfer progresses), and one for each of the labels (same font, just bold text).

I will call my standard one "control-xfer-text-standard". I want the text to be black, so I include the forecolor tag inside the control. I know what tags I can use by looking at the topic controls page. The RGB for black is 0,0,0, so my forecolor tag looks like this:

<forecolor red="0" green="0" blue="0" />

We also need to tell trillian what font to use. I'm using the default font, so I include a <font> tag, with the property; source="fontfile". I want to make the text size 12pt, so I also include another attribute: size="12".

We could set a background colour, but this is not really necessary, as it will make the background transparent if we leave it off.

Finally, I want to make the text left-justified. This is the default justification, and not really necessary, but I like to include it for peace of mind, so I include the following line:

<settings name="alignment" value="left" />

Altogether, my control now looks like this:

<control name="control-xfer-text-standard" type="topic">
<font source="fontfile" size="12" />
<forecolor red="0" green="0" blue="0" />
<settings name="alignment" value="left" />
</control>

This code goes inside the XML/controls/topics.ext file.

Before I go about adding the Icontrols, I'm going to quickly add in the othe controls for my lables, and it's mainly a cut-&-paste job. There are, however, a couple of things we need to add to our new controls.

The first is to make the text bold. This is very simple - all we need to add is another attribute to the top <font> tag; bold="1".

The next thing we need to do is tell trillian what text we want the control to display, as these are our labels. We could have added these labels as part of the graphics, but this way, the user can resize the text to suit their needs. To add this text, we use another <settings> tag, with the name of "default-text":

<settings name="default-text" value="TEXT GOES HERE" />

If you remember from our original picture:

Final window
Final window

We need 5 labels: "You", "Buddy", "Filename", "Rate" and "Time Left". And these will be the "value" attributes.

Finally, I want these labels right-hand justified, so i set the alignment "right".

So, the first Control is going to be like this (changes/additions in bold):

<control name="control-xfer-text-label-You" type="topic">
<font source="fontfile" size="12" bold="1"/>
<forecolor red="0" green="0" blue="0" />
<settings name="alignment" value="right" />
<settings name="default-text" value="You:" />
</control>


More To Come?