Migration

I'm working on moving my 'util' stuff to a wiki. If you feel like helping, please do! The wiki is: http://naib.webhop.org/~markfickett/utilwiki/doku.php.

A (sort of) Quick Introduction to making your own .AdiumMessageStyle

Written by Mark Fickett (Perez on the Adium forums); quote and take code, but give credit.
Written with Adium 0.60 in mind in June 2004; may or may not go out of date.

Advisory

This document is finished, barring any major bugs (technical or explanatory). If you see something that's odd, unclear, or just plain wrong, please ping me. As of 2004-Jul-08, I am 'freezing' this HTML file; although I may make additions or modifications to the message style this tutorial creates, I will no longer update this tutorial. (This means that what you download from the X(tras) site may not match the tutorial; the file hosted on this server, which includes mockups and the like, will also be frozen and will therefore match the tutorial.)

Contents

Introduction

This is intended as a basic introduction, to get you started; it should require no knowledge of (but plenty of willingness to learn) HTML or CSS, and is not expected to get you to the point of making something fancier than (or even as fancy as) Smooth Operator (one of the styles included with Adium). I call it "(sort of) Quick" because it's certainly not too in-depth, but it did end up being fairly long. I highly recommend The Barebones Guide to HTML as an HTML reference (though not necessarily an introduction) and Westiv's Complete CSS Guide, which is where I learned my CSS. (These resources and others are listed at the bottom of the page.) For anyone who knows HTML, CSS should be quick and easy — which isn't to say it's not incredibly powerful, elegant, and otherwise useful.

This guide expects you to have a couple things: Mac OS X Panther (10.3) (required for WebKit message styles), A home directory in the usual place, a text editor (or something similar), a web browser that can deal with HTML/CSS (though it's not critical), Terminal (in the Utilities folder in Applications — again, not critical, but I like it; you may need admin privileges to get to it, depending on your setup), and a copy of Adium, hopefully installed at /Applications (your Applications folder). If that's not exactly your setup, it should still be edifying, and you can almost surely make it work, but it's easier if your uniqueness is just like everyone else's.

Also, note that although I tell you how to go through and build everything from scratch (or where to get something if you can't easily make it), I've mirrored all the files I reference online — so if I talk about Outgoing/buddy_icon.png, and you just don't feel like going and copying it out of Smooth Operator's files, you can also find it at ...tutorial/Outgoing/buddy_icon.png. If you want, you can even get the X(tra) (which includes only the message style, and may evolve so it doesn't exactly match this tutorial) or get a zipped version with mockups and the like. (Download it and, after unzipping, double-click it and Adium will install it; control-click and select 'show package contents' to see all the innards.)

But enough of this: Let's make a message style.

About HTML and CSS

The philosophy of CSS is to separate content and appearance: HTML is the content, CSS is the appearance. If you view source for this document (cmd-opt-v for Safari), you will see that the HTML is pretty unexciting — and lacking much display definition; the paragraphs don't have linebreaks before and after, the code doesn't have monospace specified anywhere, the titles aren't in bold tags. What you will see is lots of classes specified, and that's where CSS comes in. (It's actually towards the top of the page, in the <head> tags, so you may have to scroll down to see the HTML.) The CSS tells the browser what style it should use for displaying the various elements presented in the HTML.

I won't go into more detail; if you want to do more than be able to cobble together a message style (and you should, it's fun!), you would really do better to learn HTML (I recommend looking at peoples' source, seeing what they're doing, and learning from that — with a good reference handy) and CSS (which, as mentioned, is pretty straightforward).

How the WebKit Views are Put Together

The WebKit views are, in essence, web pages. Really. The Adium Devs have hooked everything up so that as content flows into Adium, it gets stuck onto the end of the web page in a nice way, but as far as anyone writing a message style cares, it's a web site with a very specific focus.

More specifically, a message style is a directory structured like this (as noted in the Adium Message Styles: Centralized Thread, another good resource):

<stylename>.AdiumMessageStyle [directory] Contents [directory] Info.plist Resources [directory] main.css Footer.html Header.html Status.html template.html Incoming [directory] Content.html NextContent.html Context.html NextContext.html buddy_icon.png Outgoing [directory] Content.html NextContent.html Context.html NextContext.html buddy_icon.png Variants [directory, optional] slightlydifferent.css

(A .AdiumMessageStyle lives either in ~/Library/Application\ Support/Adium\ 2.0/Message\ Styles/ (where ~/ means your home directory, and all the backslashes before the spaces are so you could copy that into terminal and say cd /that/very\ long/path/with\ spaces\ in\ it/"cd doesn't allow spaces in its name), if it's one you've downloaded, or, if default in Adium.app; specifically, hidden away in /Applications/Adium.app/Contents/Resources/Message\ Styles. When you download a new .AdiumMessageStyle, you can simply double-click it, and Adium will open, copy it to the correct place, and tell you [if] it worked.)

Adium takes the various HTML documents and appends them as appropriate to the end of the current message (whose HTML document starts out as template.html — a file the message style author can safely ignore), using either main.css or one of the stylesheets found in the variants subfolders (which probably imports main) as a guide for how the HTML should look.

Specifically, when you receive a message, Adium sticks Incoming/Content.html into template.html at the end of the current text; a second message from the same person, and it will add on a copy of Incoming/NextContent.html — in each case, replacing various parts of the HTML (name, message, etc) with the appropriate data for the specific message being sent.

The various other HTML files are fairly straight forward as to when Adium sticks them in the message window: Header.html and Footer.html appear at the head and foot of the message, respectively (though I didn't have much luck with them when, several versions of Adium back, I experimented with them). Status.html is what defines the structure of a status message, such as an idle, away, or connect/disconnect. The Incoming and Outgoing directories are for messages coming in (theirs) and going out (yours); often they will be very similar, with probably only the classes of some of the elements different so the CSS can distinguish between them. Content.html and NextContent.html are for normal message content as outlined above; Context.html and NextContext.html are the same thing, but for Adium's Message History feature (that displays the last few lines from the most recent conversation when you open a new window).

Making a Style: Getting Ready

So now that you've an understanding of the structure and process, it's time to play with some code. There are two basic options for making a style: finding one that's sort of what you want and modifying it (with the author's permission probably; definitely if you're going to redistribute it) or starting from scratch. I'm going to do the latter here, because (I hope) it will lend a greater understanding to the reader and I can tailor it to the needs of the tutorial. Besides, it's fun.

You can make a style with anything, be it a text editor (I like vi, you can use TextEdit, or even AppleWorks if you save it as plain text — make sure not to use rich text format, .rtf, if you're using TextEdit) or something that knows you're writing HTML and CSS — I would caution you against anything that writes or modifies your code for you, since we won't be writing full HTML documents (and it's just a better learning experience to write it yourself).

To start out, we need somewhere to put this thing. I'm going to stick mine on the desktop, because it's handy — if you're up for playing with Terminal, that means cd ~/Desktop. Then we need to create the directory structure — make the different directories outlined above. (I won't go through the whole thing in Terminal, but the first step is mkdir tutorialstyle.AdiumMessageStyle. If you're doing this in the finder, be warned that adding the .AdiumMessageStyle extension will render the directory difficult to deal with (if you double-click, Adium will try to install it; you have to right-click (control-click) and chose 'show package contents'), so you might want to hold off on that part until you're done.)

And now, all of a sudden, I realize I'm just like my sophomore Chem. teacher: I lied. I'm not really doing this from scratch, because I need two files (and will steal two more just because) that I don't know how to write, offhand: I'm going to filch Info.plist and template.html, and also snag a buddy_icon.png for the Incoming and Outgoing directories. The only one of those we really need to worry about (though you can do something fun with the buddy icon files if you want — they appear if your contacts don't have icons) is , and we'll get back to it later. For now, just get them and put them where they go (see above). (Now you really should fire up Terminal and type cd /Applications/Adium.app/Contents/Resources/Message\ Styles/ (take a quick breath, look around — make sure the unwrappable line of code doesn't get too long) cd Smooth\ Operator.AdiumMessageStyle/Contents/, then open ., then poke around for the files you want and copy them somewhere useful. And actually, I lied again: if you're copying files from one of the built-in styles, you have to get template.html from /Applications/Adium.app/Contents/PlugIns/Webkit\ Message\ View.AdiumPlugin/Contents/Resources.) (If you don't want to do this truly from scratch-and-cannibalism, you can get the files here: incoming icon, outgoing icon, Template.html; control-click or right-click and chose "Save Linked File As..." to save them to disk.)

Making a Style: Writing the HTML

The HTML for a webkit view doesn't need anything very specific; it just needs to have reasonably logical class attributes. I'm going to write the HTML for Incoming/Content.html like this, to start:

<div class="incoming"> <span class="content"> <span class="buddyicon"><img src="%userIconPath%" alt="icon" /></span> <span class="buddyiconmask"></span> <span class="time">%time% </span> <span class="sender">%sender% </span>< <span class="message">%message%</span> <div id="insert"></div> </span> </div>

There are three requirements I'm satisfying with this: content, reasonable structure, and whitespace. The first is easy; I'm just getting in all the pieces that I want to end up with — timestamp, sender's name, icon, and message. (The <div id="insert"></div> is for Adium, so it knows where to put a secondary message, if 'combine consecutive messages' is on. The <span class="buddyiconmask"></span> is because later on I want to put a semitransparent mask on top of the icon, to fade it slightly; the icon is at the beginning because it's a predictable width, and that will be handy later. And no, I didn't think of that beforehand.)

The second requirement — reasonable structure — is for the CSS. When I want to refer to the timestamp on a first incoming content message, I don't want to have to do anything fancier than I need to; I also don't want to have to specify each separate case where timestamps occur if I decide they should all look the same. The structure also applies to how I've laid it out on the page; I want it to be easy to see, at a glance, that the <span> that contains the time is inside that which specifies content, which is in turn inside the one that specifies incoming.

The last is whitespace, which is why I've used a combination of <span>s and a <div>. Both <span>s and <div>s are generic HTML elements that contain something and let you talk about whatever's inside — text or images in our case. They differ in the default type the browser treats them as, and, relatedly, how text copied out of them looks in a text editor (or pasted into another IM, for example). A division is a block display; when copied (or when you don't tell it to do something else), it starts on a new line and starts a new line after itself. A <span> displays inline by default all my in-text code examples are contained in <span> elements, and both appear and copy just like normal text, along with whatever's on the sides. I used a <div> for the message at large so that each person's message would be on a new line, with a space after the time and sender so time, sender, and message won't run together when copy-pasted.

Note that I haven't made use of all the possible keywords (appearing between %percentsigns%); a full list is available in the Adium Message Styles: Centralized Thread thread on the Official Adium Forums. Most notably, I've used %sender% instead of %senderScreenName%, which lets the user chose which format to use in the Adium Preferences, and %time% instead of %time{}% (with a time formatter string in the curly braces, { and }) except where I only want the minute and second (%time{%M:%S}%), not the full time. I also haven't made use of the keywords for Header.html and Footer.html.

For the moment, we'll leave the HTML like that; if we decide we want something else we can put it in later if needed for how we want it to look. This particular code goes in Incoming/Content.html. Similar code goes in Incoming/Context.html, except class="content" is changed to class="context". Files similar to each of those two go in Outgoing, except with class="incoming" changed to . Then we need new code for NextContent.html and NextContext.html, which get used if someone sends more than one message in a row (or they did, and it's being displayed as context). I'm going to use this for NextContent.html, with similar code (class="nextcontent" changed to class="nextcontext") for NextContext.html. Note that there doesn't need to be a different version for incoming and outgoing because of the placement of <div id="insert"></div>, which is where the next files end up. (The double-tab indent is so it matches the indentation of the insertion point.)

<br /> <span class="nextcontent"> <span class="time">%time% </span> <span class="message">&raquo; %message%</span> </span> <div id="insert"></div>

Lastly, we need HTML for a status message, which will go in Status.html. It looks only a little different from the others:

<div class="status"> <span class="%status%"> <span class="time">%time% </span> <span class="message">%message%</span> </span> </div>

Note that the %status% is replaced with a status keyword, one of the following:

One other file we may want to create for testing purposes is mockup.html, with a fake conversation in it, pasted in from the various files. It would look like this, with the appropriate substitutions — have fun, make up some messages, names, and times, and replace the %userIconPath% keyword with either Incominb/buddy_icon.png or Outgoing/buddy_icon.png as the case warrants. (For this example, put the mockup file in Resources.) Because it gets very long very quickly, I've put my mockup in a separate file (the linked file is specific to this point and has no CSS file, but you can take out the comment code, <!-- and -->, and it'll work right or you can download one with the CSS referenced, just don't look at it online for how this appears with no CSS), but it starts out looking like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd "> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>Message Style Mockup (tutorial)</title> <link rel="stylesheet" type="text/css" href="main.css"> </head> <body> <!-- insert scintillating, demonstrative conversation here --> </body> </html>

Everything's there, but it's certainly not an exciting (or even easily readable) view yet. It does, however, look pretty good if you copy-paste into a plain text document.

Time for the CSS!

Making a Style: Writing the CSS

Since CSS is all about how the information (defined in the HTML) is displayed, the first job is to decide what the view should look like. Poking around in all the great view on the X(tras) site, I made a list of some of the features I saw that I liked, along with my own ideas/criteria (probably better explained by my mockup):

Given that list, I came up with this mockup (if you want, you can download the Freehand 10 file):

mockup of message view

Now, time to write the CSS. The first thing to do is set up the basic parameters — background, font, size, and text color; links because we may as well have fun while we're doing CSS. Create a (text) file in Resources called main.css, and start it as follows (or similarly). I recommend you open up your mockup file and reload it as you edit main.css so you can see what's changing — and do things differently if you feel like it.

body { background: #fff url(background.png) fixed no-repeat 50px 30px; font-family: Arial, sans-serif; /* font-size: 10pt; */ color: #000; padding: 0px; margin: 0px; }

In the above, body is a selector (the link goes to Westiv's CSS guide). It tells the browser which part of the HTML — what element — the upcoming CSS is referring to. After the selector, the statements in the curly-braces are what apply to that selector.

For the most part, the statements in CSS are pretty obvious (especially with a good reference handy). The #fff and #000 are abbreviated hexadecimal; hexadecimal color codes are usually written out as #RRGGBB in HTML, but CSS allows you to write it shorthand; #22aaff can become #2af. I could as easily have used the keyword black, or said rgb(0,0,0); I'm just used to hexadecimal from writing HTML. Either of the two numeric forms specifies the amount of red, green, and blue (additive color) you want; hex. ranges from 0 to f (by way of 9 and then a), rgb() from 0 to 255. (Note, if you're interested, that "ff" is in base sixteen, and is in fact (15*(16^1) + 15*(16^0)) = 255.)

The background image is specified by its relative url in url(background.png), and then its repeat after that (the other options being repeat-y, repeat-x, and repeat, defaulting to the last). The background's position is specified as 10 pixels down from the top and 30 pixels out from the edge; there are lots of other ways to specify similar things. (I just used the flap.png file tucked away in Adium.app and made it grayscale and lighter; you can download it here.) The font is specified first as the specific font I want (it would be in quotes were it more than one word, like "Times New Roman") and then the font family. I've commented out the font-size line with /* and */ because it was causing problems. The last line makes sure I know what to expect for the edge of my workspace, so when I set margins for the message boxes I have my reference point right; a browser window usually comes with some margin and/or padding that keeps text from being right up against the edge of the window.

Next, just because, I'll do links (without a lot of explanation — see Westiv for full coverage).

a:link { color: #558; text-decoration: underline; } a:visited { color: #447; text-decoration: none; } a:hover { color: #669; text-decoration: underline; } a:active { color: #77a; text-decoration: underline; }

The first line of this next little snippet I don't really understand, as to why it's necessary, but it makes another aspect of CSS act the way I want and expect; Westiv states that absolute positioning "lets a developer say where the top left hand corner of an element should be located with respect to its parent element." Unfortunately, this is not so by default; only if the parent element in question has had its display set — I'm using relative because it doesn't have any effect at all (for some reason fixed, the default, does). Anyway, the following lets me position the internal elements of the messages (be they peoples' or status notifications') absolutely — put them wherever I please, exactly.

The second line is so that if you get a long link, the URL will make a scrollbar happen, instead of just waltzing out off the right side of the window.

The selectors in this case refer to the class="incoming" (or outgoing, or status) in the HTML.

.incoming, .outgoing, .status { position: relative; } .message { overflow: auto; }

Next, let's set up the basic flow and appearance of the document: the boxes in which the various messages reside. These are things with a class of incoming, outgoing, and status. The two smaller pieces which will look similar have classes of sender and time. We aren't worried that some of the times won't be in little boxes (as we're about to specify), because we can always contradict ourselves by saying something later and/or more specific. The CSS looks like this:

.incoming, .outgoing { margin: 12px 10px 8px; } .status { margin: 8px 25px 8px 30px; } .incoming, .outgoing, .status, .sender, .time { border: 1px solid #ccc; background: rgba(255,255,255,.25); }

The incoming and outgoing messages will be laid out on the page the same way: a margin of 12 pixels on the top, 10 pixels on each side, and 8 pixels underneath. (More room on the top for the sender and time boxes, which protrude). The status containers' margins are specified going clockwise from top around to left, with the same margin of 8 pixels top and bottom, and larger margins left and right. (Here's some evidence of my having worked out the message view beforehand, and come back to explain the CSS later: those side margins are so that the status messages' senders and times will line up with those of the regular incoming and outgoing messages. And no, I didn't write it all perfectly in one pass; I rewrote the CSS once, totally, and revised both CSS and HTML a couple times.)

Finally, we want all these parts we've been talking about (selecting) to be semi-transparent (the background is specified as red, green, blue, and alpha channels; the range for the RGB part is 0 to 255, so it's white, and 25% opaque; this method isn't widely implemented (in other cases I would use semi-transparent PNG images), but since we can count on the WebKit view being rendered by ... the WebKit, we don't have to worry about compatability in this case) boxes with light grey (#ccc) borders. Borders can also be dashed, dotted, different widths, etc.

While we're on the subject, let's put the sender and time <span>s where they go. We want to position them absolutely with respect to their parent element (the incoming or outgoing message box). The tops should be a few pixels above the top of the message box (-6px down) for both of them, the text should be lighter than the actual message text, and there should be a little padding (3 pixels) on the sides, though we don't need any for the top and bottom. (Padding, and margins, can be specified in a couple ways; one value (padding: 1px) will put that amount all the way around. Two values (padding: 0px 3px) put the first amount on the top and bottom, the second on the sides. Three (padding: 0px 3px 2px), and you get the first on top, the second on the sides, and the last underneath. Four values (padding: 0px 5px 2px 3px), and they trickle around clockwise, getting applied (in order) to top, right, bottom, and left. And remember — padding is inside, margins are outside. If in doubt, stick a border on whatever you're playing with, and see what it's doing.)

The specific alignment of the sender and time are different only in left- and right- alignment. The sender <span>'s left edge should be (oh, offhand) 18 pixels out from the left edge of the message container; the time should have its right edge 14 pixels from the right edge of that same parent container.

.sender, .time { position: absolute; top: -6px; color: #666; padding: 0px 3px; } .sender { left: 18px; } .time { right: 14px; }

As long as we're talking about times, it has become clear that something bad has happened to the times in the status containers (.status .time selects things with class="time" inside class="status"). We want them to be, not up-and-in, but aligned with the outside of the 1-pixel border on the status container, so they blend in.

.status .time { top: -1px; right: -1px; }

Next up, let's deal with those unsightly icons (and make them a little more sightly).

.buddyicon, .buddyiconmask { position: absolute; top: 4px; left: 4px; width: 32px; height: 32px; background: rgba(255,255,255,.75); z-index: -1; } .buddyicon img { width: 32px; height: 32px; }

We want all the pieces involved — the icon image itself (another 'child' selector on the last line there), its container, and the 'mask' — to be 32x32 pixels. The icon and the mask are both to be in the same place (with the mask on top, since it appears later in the HTML), 4 pixels down and to the right from the top left corner of the message container; both should also be 'lower' than the other contents of the message container (z-index: -1). And although we don't particularly need a 75% opaque white background on the image itself — just the mask — it saves us the trouble of writing out another selector to give that background to both.

.message { display: block; } .status .message { margin: 0px 5px; } .away_message .message { margin: 0px 5px 3px; }

This chunk of code deals with the actual messages inside status containers generally and then (because they're different) away message containers. (Recall that we get this distinction from the %status% keyword.) We want a little padding to the sides of status messages, though we don't need any to the top or bottom, and the display: block is so that if the message is more than one line long, lines after the first also get padded away from the sides. (We want this to be the case for all messages, so it's a separate selection.) For away messages, we want a little extra padding on the bottom, just because it looks better.

Now it's time to deal with the content (and context) messages, which have until now been flapping in the wind. They've already been told to act like blocks, so we don't have to do that again; we just need to set up the margins so they sit where we want 'em.

.content .message, .context .message { margin: 15px 4px 10px; } .nextcontent .message, .nextcontext .message { margin: -25px 3px 10px 5px; }

Why such strange margins? Because I can't make min-height do anything. (It's broken in Safari 1.2.2, but the next release will fix it.) Therefore, the first message must be tall enough to stretch the message container so that the icon appears entirely inside it, with a comfortable bottom margin — and then consecutive messages have to make up for that ridiculous bottom margin (but retain it themselves, so that later consecutive messages, which will have the same big negative margin, get in the right place). (I tried another workaround, which was adding in a minimum-height 'stretcher' element, but for some reason or another it didn't work.)

Now, recall how we were going to have cool, big, in-the-background, greyed-out times for consecutive messages? It's time for that.

.nextcontent .time, .nextcontext .time, .away_message .time { border: none; background: none; color: #ccc; font-weight: bold; font-size: 14pt; z-index: -1; } .nextcontent .time, .nextcontext .time { position: relative; float: right; top: -24px; right: 20px; height: 11px; } .away_message .time { top: 15%; right: 8px; }

First, let's define the general appearance (and make away messages' times look like that too, since they usually come right after a 'so-and-so went away' notification and we don't really need the timestamp). We have to undo the border we put around all times and take off the background we put behind the same things (noticeable to varying degrees depending on background) a while back, make these times especially lighter, bolder, and bigger, and stick 'em in the background (like we did for icons).

The positioning for nexts' times is different from that of away messages', so we do them separately. We want them to be on the right (float: right makes an element 'float' to the right end of the code in its parent element, so in this case the class="time" will be the last, and therefore rightmost, element in the class="next*" (content or context) container). Then we want to push them around a little bit relative to where they would be otherwise; up 24 pixels (see what those nasty margins on the next messages are doing to us?) and out 20 pixels. The height specification is so that the times don't run into each other; even though the text doesn't actually touch, the containers are too big otherwise, and the times push each other around. (If you want to play around with snipping out parts of the times, fiddle with overflow: hidden and height.)

Away messages' times are different, because it's more fun if they can be further down for multi-line away messages. They are, therefore, left as position: absolute, and the top is specified as a percentage, not a pixel-value. They're also a little closer to the right edge.

Now that everything's (more or less) where we want it, let's tweak how it looks a little: time to take advantage of the %status% keyword.

.status .message { color: #666; } .online .message { color: #686; } .offline .message { color: #866; } .away .message, .return_away .message { color: #886; } .away_message .message { color: #665; } .idle .message, .return_idle .message { color: #888; } .date_separator .message { color: #444; }

This should be pretty self-explanatory at this point — just remember, the hexadecimal values are red, green, then blue.

Lastly, let's make the context message look different from regular content — a little faded out.

.context .message { color: #888; } .context .buddyiconmask { background: rgba(255,255,255,.90); }

First, the messages themselves are lightened. (Note that this gets overridden if the person you're chatting with happens to use some unusual color.) Then we make the mask a little more opaque — 90% works for me.

That's it for now — but feel free (and encouraged) to tweak it to your liking. Maybe you prefer colored senders' names, and want .incoming .sender and .outgoing .sender to be different colors. Maybe you don't want to see icons at all (display: none for the appropriate classes). Or maybe you just want to make the whole thing a little less subtle. Depending on how sweeping your changes, you might just want to make a variant.

Info.plist (I)

Before we can get Adium to talk to our message style, we have to give it a proper introduction. I'm just going to quote a whole huge piece from Adium Message Styles: Centralized Thread, because it's all good stuff:

AllowTextColors can be set to <false/> to disable sent and received colors in messages. This should only be done if normal sending colors (say, black) just plain aren't going to be visible on your default background. This can be done on a per-variant basis.

More keys will be added in the future to allow greater control over preferences and such.. the only required key is CFBundleName, though the others in Smooth Operator's info.plist are recommended.

If you wish to create Variants, simply create a Variants subfolder in the Resources folder. Variants will be displayed in Adium's menu using their filename (minus .CSS of course). Your variant will want to import "../main.css", of course.

Per-variant setting keys may be created by appending ":VARIANTNAME" to the key. For example, to set a default background color for your variant "Black Version.css", which would display as "Black Version" in the menu, you set the key "DefaultBackgroundColor:Black Version" (without quotes, of course) to the color (perhaps 000000) as a string. When looking for the settings for a variant, the variant-specific version is tried first. If none is found, the general style setting is tried. If no general setting is found, the default value is used.

So for starters, we need to give our style a name; make the default font family and size, and the default background, match what we chose earlier; and if we feel like it tell it to show user icons and let people fiddle with the background color.

So fire up vi, TextEdit, or (if you feel like doing the expected and have the developer tools installed) just double-click on Info.plist to open it in the .plist editor, and let's change some keys. I'll narrate for a text editor, because that's what I'm doing.

When we actually open up Info.plist, we see that there are in fact a lot more keys that we were told about — which is fine, since we can figure out what they are pretty easily. Here's what I'm doing: Leave the language as English. Change CFBunelGetInfoString to Tutorial Adium Message Style (inside the <string> tags... look familiar?), change the CFBundleIdentifier to com.adiumx.tutorial.style, leave the dictionary version alone, change CFBunelName (ah hah, one we recognize!) to Tutorial, skip the next two, change the DefaultFontFamily to Arial and (as it happens) leave DefaultFontSize, ShowUserIcons, DisableCustomBackground, DefaultBackgroundCOlor as they are. Just to be sure, here's what mine looks like now:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>English</string> <key>CFBundleGetInfoString</key> <string>Tutorial Adium Message Style</string> <key>CFBundleIdentifier</key> <string>com.adiumx.tutorial.style</string> <key>CFBundleInfoDictionaryVersion</key> <string>1.0</string> <key>CFBundleName</key> <string>Tutorial</string> <key>CFBundlePackageType</key> <string>AdIM</string> <key>MessageViewVersion</key> <integer>1</integer> <key>DefaultFontFamily</key> <string>Arial</string> <key>DefaultFontSize</key> <integer>10</integer> <key>ShowsUserIcons</key> <true/> <key>DisableCustomBackground</key> <false/> <key>DefaultBackgroundColor</key> <string>FFFFFF</string> </dict> </plist>

Yours may well have a more interesting title, a different font, things like that — just so long as the fields are filled in usefully. (I'm purposefully ignoring all the variant stuff until we've gone and made a varian to play with. Also, I fixed an indentation problem in my .plist file; ShowUserIcons was indented with four spaces instead of a tab, which probably looked the same to whoever did it. Lastly, I wrapped the Doctype declaration onto two lines, just so it's easier for people browsing to see everything.)

Making a Variant

The variant I'm going to go through making is just a dark version — complete with an Evil Duck background. As I've been saying, feel very free to do your own thing, and just refer here for how it's done.

In order to make a variant, we need the directory Resources/Variants, if it's not already there, and in it the CSS file for the variant — for this example, we'll call it BlackBackground.css.

(You may also want to make a new copy of the mockup file in which (if it's in Resources) references Variants/BlackBackground.css; that is, the mockup file should be the same as the other(s) but modified so that the stylesheet line reads <link rel="stylesheet" type="text/css" href="Variants/BlackBackground.css" />. Again, here's my mockup, and the associated Freehand 10 mockup file.)

Then we need to edit the CSS file, the first line of which is this:

@import url(../main.css);

The @import imports the file main.css in the directory one level up, in Resources, which means we don't have to rewrite (or even copy) all the positioning code — just the things that are different between the original version and the variant.

After that, the CSS launches right into changing stuff around. In general, we want a black background with (I decided) a nice silhouette of the Evil Duck, scourge of the night that he is. (Since I made the image as a mostly-transparent PNG, it should show up well on any near-black background, though it's almost invisible against white. If you're interested, I you can also download the Photoshop Document.)

body { color: #fff; background: #000 url(evilduckmask.png) left bottom fixed no-repeat; }

This time, I specified the placement of the background image using the keywords left bottom, since I think that's where the silhouette looks best, instead of the top/left offset values in pixels I used before.

The most glaring fault with the new background is that all the boxes are the wrong color: they stand out as light, look layered atop each other, and have none-too-subtle borders.

.incoming, .outgoing, .status, .time, .sender { border: 1px solid #222; background: rgba(0,0,0,.50); }

So, selecting the box-like elements, let's make their borders darker and make the backgrounds 50% opaque black.

After that, it's the big and bold next times which show up as very wrong.

.nextcontent .time, .nextcontext .time, .away_message .time { color: #333; border: none; }

To fix them, we lighten the text color and (since we just put the border back from the original @imported state) strip off the borders.

Finally, let's make the faded icons blend in with our new black background, using semi-transparent black instead of the white — the 50% opaque for normal messages, and 75% opaque for the context messages.

.buddyiconmask { background: rgba(0,0,0,.50); } .context .buddyiconmask { background: rgba(0,0,0,.75); }

Although the variant isn't totally beautiful, it's workable, and all the major changes have been made. I'll leave the tweaking up to Dear Reader, so you can have something all your very own (and I don't have to do it). (If you come up with a variant you really like, send a note my way and I'll probably be happy to include it.)

Info.plist (II)

Now that we have a variant (I told you we'd get back to that reference to variants we ignored), we can fill in a little more of Info.plist. Referencing what I quoted earlier, there are a couple things we might (and do) want to do, the first of which is make a variant-specific setting. Open up Info.plist again, however you did it before, and just after DefaultBackgroundColor (or anywhere else, but I feel like putting it there), add in:

<key>DefaultBackgroundColor:BlackBackground</key> <string>000000</string>

That should do it, since we already named the CSS file BlackBackground.css. We could also set a couple other keys: DisplayNameForNoVariant, so the default style has a useful name in the sub-menu (WhiteBackground sounds likely), and because "normal sending colors (say, black) just plain aren't going to be visible on your default background" we should also set AllowTextColors to false.

<key>DisplayNameForNoVariant</key> <string>WhiteBackground</string> <key>AllowTextColors:BlackBackground</key> <false;/>

All done! Now, go make your own variant, or style, and have fun! And feel free to send questions, comments, suggestions, etc to me at this address (either domain after the naib. works), or you can private-message me in the Adium forums.

Submitting/Installing X(tra)s

Depending on how much you've departed from my example, or if you've followed this and then gone and done your own, you may have a message style that you want to post on the Adium X(tras) site. The submission process is simple: Go to the X(tras) site, click and click on the "Contribute" tab, then on Sign up now! After you've registered, confirmed by e-mail, and logged in (back at the "Contribute" tab, or using the Log In link at the bottom of every page), the "Contribute" tab will let you submit the X(tra). For a message style, you can submit:

If you don't have the non-required bits ready, you can go ahead and submit your X(tra), and then come back and update the listing (in the "My X(tras)" tab) when you've got them ready.

Installing X(tras) is very easy: double-click, and Adium copies the package to the right place. You can throw away the copy that's left from the download if you don't want it for dissection.

Resources

These are links which you may find useful in getting more information for making message styles (or writing HTML/CSS in general). Most of them appeared in the text of the tutorial.

Contact

This document, hosted by Adium X on the SourceForge server to save the author's bandwidth, is a mirror of http://naib.webhop.org/~markfickett/adium/tutorial/AdiumMessageStyle.html, however the "finished" status of this tutorial should mean there will be no updates in the original that the mirror lacks.