Sunday, 28 June 2009

Migrating applets to Awn 0.4

Since we're trying really hard to get Awn 0.4 into a usable state with all the glory and most of the applets we had in the previous releases, I'll try to describe the important changes that happened in the API, so it's easier to convert existing applets to work in 0.4. Please note that if you were using onox's awnlib, the conversion should be painless, because it wraps libawn API and therefore applets did not need to be modified (but I might be wrong, onox will know better).

If you're interested in an article about how to write an actual applet from the beggining, I do plan to write that too, so check back later.
I also plan to write an article about the completely new functions/methods/classes, so you'll have to wait for that a bit as well.

Note that for the sake of simplicity I'll be using pythonish syntax, even though I mostly write C code, so here and there the class names etc. might more resemble C.

So here is a quick list of the most important changes:
  1. AwnApplet was completely revamped - now its base class is GtkPlug (as opposed to GtkEventBox) and it handles connecting to main Awn process, sending signals to whoever is interested, etc.
  2. therefore AwnPlug died.
  3. many (if not all) of AwnAppletSimple's methods were renamed.
  4. AwnAppletDialog is now AwnDialog.
  5. AwnTitle got also renamed to AwnTooltip.
  6. the job of AwnIcons now handles AwnThemedIcon (which is part of AppletSimple).
And now to show you some actual code, I'll help myself by looking at the modifications that were needed to get media-control applet to work in 0.4 (thank you `bzr diff` for making this easy):

I'll start with the AwnApplet(Simple) constructor. In 0.2 (note that I use 0.2 for Awn versions 0.2.x and 0.3.x, since the API was pretty much the same) you'd have:
class MyApplet(awn.AppletSimple):
def __init__(self, uid, orient, height):
awn.AppletSimple.__init__(self, uid, orient, height)
# do stuff

# creating an instance looked like this
if __name__ == '__main__':
awn.init (sys.argv[1:])
applet = MyApplet(awn.uid, awn.orient, awn.height)
# ...
This will now be:
class MyApplet(awn.AppletSimple):
def __init__(self, uid, panel_id):
# of course you can pass also the "applet-name", that's up to you
awn.AppletSimple(self, "applet-name", uid, panel_id)
# do stuff
# to get the former "height" ie. size of the applet, you can now do:
size = self.get_size()

# creating an instance is now:
if __name__ == '__main__':
awn.init (sys.argv[1:])
applet = MyApplet(awn.uid, awn.panel_id)
# ...
Now let's talk about the methods of AppletSimple, these methods no longer exist:
# imagine we have "self" an instance of awn.AppletSimple
self.set_title(text)
self.set_title_visibility(bool)
self.set_icon(pixbuf)
self.set_icon_context(cairo_context)
self.set_awn_icon(applet_name, icon_name)
self.get_awn_icons()

# and now the commonly used methods of AwnIcons:
self.get_awn_icons().get_icon_simple_at_height(height)
self.get_awn_icons().get_icon_simple() # returned icon with size equal to 48
But you can use these instead:
self.set_tooltip_text(text)
# if you want to show tooltip on mouse-over and hide it on mouse-out you DON'T
# need to call these, there are properties of AwnTooltip which handle it.
# this means you probably no longer need to connect to enter/leave-notify-events
# and show/hide the tooltip manually
# (for more info see "smart-behavior" property on libawn API pages)
self.get_tooltip().show() or self.get_tooltip().hide()
self.set_icon_pixbuf(pixbuf)
self.set_icon_context(cairo_context)
self.set_icon_name(icon_name) # applet_name is taken from what you passed to the constructor
self.get_icon() # returns awn.ThemedIcon

# you can get former AwnIcons functionality with:
self.get_icon().get_icon_at_size(size)

As for "awn.AppletDialog", the only thing you need to do is to substitute it for "awn.Dialog".

And that's it, these are all the changes that had to be done for media-control applet and it should hopefully help you convert your applet.

P.S.
Our API is still not officially "frozen", so there could be some more changes, but we will try to minimize them, for me the only unknown is malept's config client (awn.Config) which probably will need to be renamed, since it will be now part of libdesktop-agnostic, but other than that its API should be more or less compatible.

Also current version of libawn API can be currently found at http://www.stud.fit.vutbr.cz/~xhruby16/libawn/.

Edit: There was one more change to the AwnApplet constructor, now you need to pass canonical-name for the applet as first parameter. The code above was updated to reflect this change.

Saturday, 27 June 2009

Hello world!

Hi there, and thanks for stopping by at my blog.

So, I'll start by introducing myself - I'm a computer science student, who participates in a couple of open source projects. Currently I'm spending most of my open source development time working on Awn (avant-window-navigator), which is a shiny dock/panel for *nix platforms.

As one of Awn's core developers, I noticed that we don't have many tutorials on how to write Awn applets and such, and people usually have to turn to existing code. This might not always be the best source of tips, so I'll try to fill in the gap... There are also many interesting ideas flowing in the Awn-land, so I'll try to share some of them from time to time. Other than that... well who knows what will come to mind and what I'll have desperate need to share with the world. :)

And that's about it for the start, expect a real Awn-related tutorial soon.