|
Restrictions: How and Why?
The subject of restrictions should already be familiar to you if
you've read How Does it Work?. If you
haven't, please do so before reading the rest of this section as it
contains important information needed to understand the content of
this page.
Reasons For Restrictions
During the development of more complex skins, some special
requirements may become apparent to you. For example, you want to
change the text somewhere in a Messenger window and you don't want
the modification to look bad in localized versions of Messenger.
Without restrictions, the only way to do this properly would be to
create two different versions of your skin and distribute them
separately. If you then want to add a third and fourth language,
maintaining all the different versions of the same skin can quickly
become troublesome.
Languages are used here as an example to illustrate the need for
a more general feature: being able to specify resources that depend
on external factors. This ability can be found in the Messenger
Plus! skinning system through the use of restrictions. Restrictions
represent the first key element you'll need to learn to do more in
your skins and stop feeling constrained in a static
environment.
Resource groups exist because of restrictions. In all the
examples you've seen so far in this documentation, the use of
resource groups was limited to its most primary use: one resource
group with one version restriction to create one specific target
for the skin. Adding more resource groups to your skin becomes a
necessity when you start considering issues such as language and
you don't want to copy/paste big chunk of data because of a single
line of text. If we keep on using the example of localization, here
is how the problem cited above could be solved:
Resource Group 1
Restriction: version
Replace resources: pictures, definitions, style
Resource Group 2
Restriction: version, language (English)
Replace resources: strings (English)
Resource Group 3
Restriction: version, language (French)
Replace resources: strings (French)
In the first group, most resources are defined with a single
version restriction to target the appropriate Messenger version.
Everything that does not include text written in a specific
language is included in this group. A specific group is then
created for each of the languages supported, defining only the
resources that are language-specific. When the skin is loaded,
Messenger Plus! analyses every group one by one and load their
content if the set of restriction is valid in the current
environment. Here are some examples of loading sequences that could
happen with the above conditions:
- In a non matching version of Messenger, no group is
loaded.
- In a matching English version of Messenger, Group 1 and Group 2
are loaded.
- In a matching French version of Messenger, Group 1 and Group 3
are loaded.
- In matching Spanish version of Messenger, Group1 only is
loaded.
Be careful about the last example: you must never forget to add
a default for specific restrictions. In the example above, if you
wanted to restrict the whole skin to either English or French users
of Messenger, then a matching language restriction would have to be
added in Group 1.
Resource Group 1
Restriction: version, language (English, French)
Replace resources: pictures, definitions, style
If you want your skin to be available to anybody, load English
by default and still support French, just remove the language
restriction from Group 2.
Resource Group 2
Restriction: version, language (English)
Replace resources: strings (English)
Resource groups don't have numbers in skininfo files but
Messenger Plus! loads the groups in the order they're specified. So
if Group 2 was to include the default English strings with no
language restriction, everything would work fine: English strings
are always loaded by the skinning system when parsing Group 2 and
if the restrictions of Group 3 are matching (French version of
Messenger), then the strings are loaded again in French. Resources
that are redefined in several groups are simply reloaded while the
groups are analyzed sequentially. This means that the last
definition of a resource is the one that's used in Messenger. If
you were to switch Group 2 and Group 3, then the strings would
always be displayed in English as the second group would be loaded
conditionally in a French version of Messenger and the third group
would always be loaded without language restriction, replacing any
localized version of the text.
Messenger Versions
One important role of restrictions is the specification of
Messenger versions. This is the only mandatory restriction that's
required by Messenger Plus! to load a resource group. Restricting
versions is required because you can't know what the next version
of Messenger will be like and you certainly don't want to crash the
all the users who've trusted your work in the last couple of months
because they've just upgraded their Messenger. Versions
restrictions allow you create a single skin that will work on every
known version of Messenger. Version compatibility is the first
cause of trouble for users who are interested in installing a skin
and restrictions solve that problem transparently, without any
hassle for the developer.
Let's re-use the logic of the previous language example. The
problem is different but the implementation is the same and this
time, we'll write it in proper XML. Consider this: you want to
create a skin that replaces two pictures and a window definition
file in Messenger. The skin needs to work with both Messenger 8.1
and Messenger 8.5. After analysis, you notice that the window
definition file is different for each versions but the pictures'
ids are the same. Here is the resulting skininfo data:
<MessengerSkin>
<!-- Pictures for Messenger 8.1 and 8.5 -->
<ResGroup>
<Restrictions>
<MsgVersions>
<Version Major="8" Minor="1"/>
<Version Major="8" Minor="5"/>
</MsgVersions>
</Restrictions>
<Resources><Replace>
<Graphics><Pictures>
<Picture Id="162">
<File>away.png</File>
</Picture>
<Picture Id="163">
<File>busy.png</File>
</Picture>
</Pictures></Graphics>
</Replace></Resources>
</ResGroup>
<!-- Definition File for Messenger 8.1 -->
<ResGroup>
<Restrictions>
<MsgVersions>
<Version Major="8" Minor="1"/>
</MsgVersions>
</Restrictions>
<Resources><Replace>
<Windows><Definitions>
<Definition Id="920">
<File>convodef_81.txt</File>
</Definition>
</Definitions></Windows>
</Replace></Resources>
</ResGroup>
<!-- Definition File for Messenger 8.5 -->
<ResGroup>
<Restrictions>
<MsgVersions>
<Version Major="8" Minor="5"/>
</MsgVersions>
</Restrictions>
<Resources><Replace>
<Windows><Definitions>
<Definition Id="920">
<File>convodef_85.txt</File>
</Definition>
</Definitions></Windows>
</Replace></Resources>
</ResGroup>
</MessengerSkin>
XML tends to make simple things look bigger than what they
really are so the interesting parts have been formatted in bold. In
this code, you can see 3 different resource groups, each one with a
different set of restrictions and resources. Here is the result of
this skin:
Combining Restrictions
Because many kinds of restrictions exist in Messenger Plus! (as
seen in the schema of
SkinInfo), it is important to understand how they combine with
each other. The rule is simple: restrictions of a same kind combine
with a logical OR and groups of different kinds combine with an
AND. In the example shown above, the first group specifies two
restrictions of the same kind: Messenger version 8.1 and Messenger
version 8.5. This is interpreted as "Use this group if the version
of Messenger is either 8.1 OR 8.5".
Let's say you add a language restriction in the mix to target
only American English versions of Messenger, like this:
<Restrictions>
<MsgVersions>
<Version Major="8" Minor="1"/>
<Version Major="8" Minor="5"/>
</MsgVersions>
<MsgLanguages>
<Language IsoCode="en-us"/>
</MsgLanguages>
</Restrictions>
It would be interpreted as "Use this group if the version of
Messenger is either 8.1 OR 8.5, AND the language of Messenger is
English-US". So you'd need either Messenger 8.1 English-US
or Messenger 8.5 English-US.
If a second language restriction is added for French, as show
here:
<Restrictions>
<MsgVersions>
<Version Major="8" Minor="1"/>
<Version Major="8" Minor="5"/>
</MsgVersions>
<MsgLanguages>
<Language IsoCode="en-us"/>
<Language IsoCode="fr-fr"/>
</MsgLanguages>
</Restrictions>
The resulting interpretation would be "Use this group if the
version of Messenger is either 8.1 OR 8.5, AND the language of
Messenger is either English-US or French-FR". The skin would be
applied to Messenger 8.1 English-US, Messenger 8.5
English-US, Messenger 8.1 French-FR and Messenger
8.5 French-FR.
Note that in the particular case of languages, it is possible to
exclude a language instead of including it using the FilterMode attribute. For example, if you know your
skin works with every localized version of Messenger 8.5 but does
not work with the Traditional Chinese one, you can write the
corresponding restriction as:
<Restrictions>
<MsgVersions>
<Version Major="8" Minor="5"/>
</MsgVersions>
<MsgLanguages FilterMode="exclude">
<Language IsoCode="zh-tw"/>
</MsgLanguages>
</Restrictions>
Unlimited Possibilities
Messenger Plus! gives you access to several basic restrictions
for your skin and more restriction kinds may be added in the
future. However, what would happen if you wanted to add your own
rules into your files? this would mean allowing users to change
your skin at runtime with some kind of modifiable options.
Fortunately, the system already supports this feature and calls it
Skin Options. All you need to know about that
subject can be found in the following
section.
See Also
Specialized Subjects,
How Does it Work?.
|