Talks ∋ Tying your shoes

I gave this talk at Ruby Manor Classic. I gave it alongside Martin Sadler as a two parter about building GUIs with Ruby. Martin spoke about using monkeybars via Jruby, and we had a shared intro. This transcript only covers my part of the talk, not the shared intro, and not Martinʼs bit.

The transcript comes from my presenter notes and these were a first draft, so itʼs very unlikely to be a word-for-word copy of what I said on the day. It should be very close though.

A video of this talk is available from Ruby Manor:

a screenshot of the video for the talk from the ruby manor website

This video is of the full talk including the shared intro, Martinʼs monkeybars talk, and my shoes talk. The shoes part of the talk starts at about 22minutes.

A closeup picture of hands tying the laces on a pair of trainers. text: A whirlwind guide to tying your shoes

This is going to be a quick tour of shoes.

text: What is shoes?

So what is Shoes?

It’s a GUI framework written by _why the lucky stiff.

The hackety-hack logo. text: A little history

Some of you may remember Hackety-hack, a project _why came up with to teach programming to young school kids.

The hackety-hack logo with the gecko logo superimposed over the hand. text: A little history

His first attempt at Hackety-hack used an embedded Gecko engine and a lot of the UI was pretty much HTML. However, it seems that this didn’t cut it for some reason, perhaps it was too complex to make changes to or perhaps embedding Gecko was too prone to oddness. I’m not really sure.

The hackety-hack logo with the Shoes logo superimposed over the hand. text: A little history

So _why put Hackety-hack on hiatus to work on Shoes as a replacement for the Gecko engine in Hackety-hack.

A photograph of The Ultimate HTML Reference book by Ian Lloyd. text: This is familiar

As you might imagine from something designed to replace an embedded HTML rendering engine, Shoes is heavily influenced by HTML. To me it’s always felt like a weird combo of HTML, JS and CSS. Except, rather than learning three syntaxes and splitting everything over three files (if you’re doing it semantically, unobtrusively and presentationally); you’re learning one syntax (ruby) and defining everything in one place. I think if you’re at all familiar with building apps for the web, you’ll feel completely at home very quickly with Shoes.

It’s also inspired by Nodebox and Processing - so everything is a canvas. Just imagine that a body tag is also a canvas tag and you’ll be set!

A photograph of many ruby gemstones. text: gem install shoes

You might think that installing shoes is as simple as:

gem install shoes
A photograph of many ruby gemstones. text: gem install shoes. No!

But unfortunately not. Unlike other ruby GUI frameworks, Shoes is not a gem. This isn’t a quirky way of packaging it, it’s by design because it’s actually a separate ruby runtime that you download and install. You then ask Shoes to run the programs you create, instead of your standard ruby install. It’s based on 1.8.6 though so it should be fine. It also has gems support (using gems 1.2), so you can still use the ruby eco-system that you know and love, but not specifically the one that you’ve pre-installed.

A photograph of a brown shoe among some leaves. text: How do I get shoes? http://shoooes.net

So, if it’s not a gem, how do you get it? First off go to shoooes.net for all your Shoes needs.

A photograph of a brown shoe among some leaves with arrows pointing to the 3 eyelets. text: How do I get shoes? http://shoooes.net, beware the “o”s. 3 “o”s in shoooes. 3 eyelets in a shoe

A nice hint to remember the url is this:

There are 3 “o”s in shoooes just like there are 3 eyelets in a standard man’s shoe.

SIMPLE!1

A photograph of cardboard cutouts of a shoes window running on OS X, Windows, and GTK+. text: Shoes is for Everyone, Mac OS X (Universal), Windows (XP & Vista), GTK+ (Linux and BSD)

Anyway, once at shoooes.net you can find the version of Shoes for your platform.

It’s cross platform, currently available for OS X (PPC & Intel, although PPC tends to lag behind on some features - it took ages to get Video support into PPC), Windows and Linux / BSD using GTK+.

Download it, install it and you are all set to go!

text: How to ties your shoes. Loop it, Swoop it, & Pull

So. Now we all have Shoes, we want to know how to tie them. (or … you know … build applications).

Martin and I decided that we’d both build a simple Twitter client as the demonstration app for our talks. The app I built is called Talon.

A snippet of code showing the simplest shoes app possible. code: https://gist.github.com/h-lame/caaf6d8a2c91b3cce8fea05cc6b25d7a#file-slide-13-the-simplest-shoes-app-code-rb
Gist for code in slide

This is the simplest Shoes app you can write. Shoes.app is your gateway. Everything is a block…

A screenshot of the window running the code from the previous slide; it's an empty window

Running this (drag the file onto the Shoes icon in the dock or use the “Open…” menu) brings up an empty Shoes window.

A snippet of code showing how to customise the title and background of a shoes app. code: https://gist.github.com/h-lame/caaf6d8a2c91b3cce8fea05cc6b25d7a#file-slide-15-customising-a-shoes-app-rb
Gist for code in slide

So let’s spruce it up a bit, we’ll give it a title and give it a nice crisp white background.

We specify the title via a styles hash on the Shoes.app call. We could specify other things here, such as the window size, but we’ll leave that for now. The default is ok for us.

The background colour is specified as a method. The block passed to Shoes.app is evaluated in the context of the Shoes application. So this background method comes from Shoes.app.

A screenshot of the window running the code from the previous slide; the background colour and titlebar have been updated

Anyway, this gives us the following, as you might expect. Let’s do something more exciting.

A snippet of code showing more customisations to creat the main Talon app layout. code: https://gist.github.com/h-lame/caaf6d8a2c91b3cce8fea05cc6b25d7a#file-slide-17-building-the-main-talon-window-rb
Gist for code in slide

Ohhh… what’s all this?

So we’re adding a second background to add an image, and we’re specifically positioning it with those bottom and right style entries in the hash. The positioning stuff should be very familiar to anyone with a passing knowledge of CSS. For those with more than a passing knowledge you should recognise the multiple backgrounds stuff from CSS3 (which would get rid of things like the sliding doors technique).

Next we’re encountering this curious object called a flow. We’ll come back to it later, but for now it’s enough to know that it’s a container that we can put other things in. Note that we pass a block and everything in that block is evaluated in the context of that flow. So by calling background here, we’re setting the background of the flow, not our main Shoes.app. (The curve param passed the background call gives us rounded corners - sweet!)

The final thing is the title method. This lets us specify some text. Text in Shoes is all based on derivatives of the para element and helpfully (much like HTML) provides several default styles to get you started (for example: title, subtitle, caption). They act much like h1 - h6 and simply scale the text up and down in terms of font-size.

A screenshot of the window running the code from the previous slide; There is a title text and a graphical background element

Anyway running that code this gives us this.

I mean, that’s pretty awesome. It’s almost ready to ship! Ok, Perhaps we need … a login screen?

A screenshot of the Talon app window with a log in screen asking for username and password

We want something like this. Now we’re going to have to talk about buttons, controls and layouts. Once you know that, well, there’s not much else to learn. So let’s go!

A snippet of code that describes how to build the outline of the log in screen presented on the previous slide. code: https://gist.github.com/h-lame/caaf6d8a2c91b3cce8fea05cc6b25d7a#file-slide-20-the-talon-login-window-base-code-rb
Gist for code in slide

To build this login box we need to start with the container for all the elements; the title, the two edit boxes, their labels, and the button.

The box is a stack, the second of the two Shoes layout containers. We’re applying a margin to it so it doesn’t fill up the whole window width and is spaced away from the main app title. Just like CSS we can specify this stuff in array form, or individually with margin-top etc…

We’ve now seen both a flow (used earlier to contain the main app title) and a stack (used here to contain the whole login UI). So it’s as good a time as any to talk about the features shoes provides for laying out your UI elements.

These are the only two layout containers that Shoes provides, anyone familiar with other GUI frameworks will be used to things like Grid Layouts or Compass Layouts or whatever… nothing so complex with Shoes.

A photograph of a stack of ruby books. text: Stacks

First up are stacks. Imagine all the technical books on your desk. If you want to tidy the desk you’ll probably stack the books up on top of each other to save space. Each book goes on top of the previous one creating a new layer in the stack with each book.

That’s how it is in Shoes with stacks. Each element you add to the stack creates a new vertical layer. Except…

A photograph of a stack of ruby books flipped vertically so it is upside down. text: Stacks

…gravity is upside down. Elements fill down the page, not up.

A photograph of a box of matches, partially open showing the layers of matches inside. text: Flows

Next are flows. Imagine an empty box of matches. As you put matches into the box they fill up the bottom layer of the box. Once that layer is full we start filling up the next layer, until that’s filled up and we create a new layer, and so-on.

flows in Shoes are very similar. UI elements in a flow fills up the width of the flow from left to right and then drop down horizontally and fill up that layer, and so on.

So that’s layout in Shoes: stacks and flows. Which are, yes, almost exactly like inline vs block elements in HTML & CSS. Also, just like CSS you can ignore these containers and position things absolutely with top, bottom, left and right style attributes.

A screenshot of the Talon app window with a log in screen asking for username and password

Remember, we are trying to build this. Now that you know what kinds of layout options are available, and that I’ve already shown you that I’ve got a stack box to contain the whole login UI, you should have a pretty good idea of how to combine stacks and flows to create the rest of the layout.

It’s four things in a stack:

  1. the ‘who goes there?’ title
  2. the ‘user name’ label and entry
  3. the ‘password’ label and entry
  4. the login button

And it should be pretty obvious that each label and entry are contained within a flow.

A snippet of code showing how to build the fields and buttons on the talon log in screen. code: https://gist.github.com/h-lame/caaf6d8a2c91b3cce8fea05cc6b25d7a#file-slide-25-the-talon-login-window-ui-layout-code-rb
Gist for code in slide

We’ve already seen the title and stack, so here’s the rest of it. Is this what you thought it would be? Give yourself a clap on the back if you did. The only weird things are the extra stacks around the paras to act as the labels. Text elements are truly inline and don’t have specifiable widths; it's not just because they’re in a flow here.

Other interesting things to note about this code:

  1. the edit_line - this is how you get a text box
  2. the negative widths on the text box, what this means is be 100% of the box wide minus 170px. Because this is in a flow, it allows us to combine stacks and other “wide-able” elements to create single “layer” of elements in the flow.
  3. the button - the block passed to the button is what will happen when the button is clicked. This is how you add event handlers to things in Shoes. Anyone who has written GUI event handling code in java will surely appreciate this brevity.
  4. For the first time I’m doing something with the results of these methods that create objects. For both the user and password edit boxes I’m assigning them to instance variables (remember, everything in Shoes is evaluated in the context of Shoes.app, so these are instance variables available to the whole app). Every method in Shoes returns the object you’re creating, even things like background.
A photograph of a high-heeled shoe with gems embedded in the heel. text: Shoes & Gems

Now that we have a login screen we’re going to need to be able to log into Twitter. I’ve used the twitter gem by John Nunemaker. But, I mentioned that shoes is it’s own version of ruby, and that it has it’s own version of rubygems, so if you want to use other gems in your app how do you do it?

A snippet of code showing how you would normally require a gem in ruby. code: https://gist.github.com/h-lame/caaf6d8a2c91b3cce8fea05cc6b25d7a#file-slide-27-gem-twitter-rb
Gist for code in slide

Well, unfortunately, it’s a bit more complex than you’d expect. You can’t just require the gem you want, like in this example. Still, it’s not significantly more complex, and it does something quite neat.

A snippet of code showing how you would require a gem in a shoes app. code: https://gist.github.com/h-lame/caaf6d8a2c91b3cce8fea05cc6b25d7a#file-slide-28-shoes-setup-gem-twitter-rb
Gist for code in slide

You put the gem statement in a Shoes.setup block. This will tell Shoes that you want to use that gem. Shoes will also go and download / setup / install that gem if you don’t have it. Which is pretty cool.

It can be a bit temperamental right now, but it’s only going to get better as Shoes moves on.

A snippet of code showing how to log in to twitter in the Talon app. code: https://gist.github.com/h-lame/caaf6d8a2c91b3cce8fea05cc6b25d7a#file-slide-29-the-talon-login-method-rb

So here’s the login method. Pretty boring really. The only thing to note is the @login.hide. In the real version of Talon, I’ve recorded the stack used to contain all the login UI in an instance variable, so when you login successfully I can hide it. All UI Elements in Shoes have these sort of methods to hide, show, toggle, etc… them.

A snippet of code showing how Talon reacts when the login details are incorrect. code: https://gist.github.com/h-lame/caaf6d8a2c91b3cce8fea05cc6b25d7a#file-slide-30-32-incorrect_login-rb
Gist for code in slide

With the login screen, I wanted to do something fun with it instead of just showing an alert box with “incorrect” in it. I thought it would be nice to do the same as the OS X login screen and shake the box if you got it wrong. So here’s the code to do that.

The same snippet of code as the previous slide, this time highlighting the animation block that shakes the screen. code: https://gist.github.com/h-lame/caaf6d8a2c91b3cce8fea05cc6b25d7a#file-slide-30-32-incorrect_login-rb
Gist for code in slide

Shoes has a nifty animate method that takes a block that will be run for every frame of your animation (it defaults to 10fps, but can take an arg to say how many fps you want). What I’m doing here is using another handy element method displace to move the whole login UI by employing some MATHS. displace is different to move because it doesn’t cause the whole UI to reflow, it’s almost like it was intended for this sort of little effect.

If we did nothing else this animation would run forever.

The same snippet of code as slide 30, this time highlighting the timer block that stops the shaking effect after 2 seconds. code: https://gist.github.com/h-lame/caaf6d8a2c91b3cce8fea05cc6b25d7a#file-slide-30-32-incorrect_login-rb
Gist for code in slide

That’s what this timer block is for. timer blocks take an arg to say how many seconds in the future you want the block to fire, and then when that time has passed, the block fires. Here we use this block to stop the animation. Remember, everything in Shoes returns what you just built, even animate and timer. timers can then be started or stopped. There’s also the every timer, for events you want to fire every so often instead of once after a short time has passed.

text: Tying more complicated shoes

So… I could go on and show you how I’ve built the rest of Talon. It does connect to Twitter and get a list of your friends tweets and even allow you to post a tweet back to Twitter. But I won’t, I don’t have much time, and I want to briefly mention some other stuff that Shoes does that I didn’t really have the time to build into Talon. Also, the rest of the Talon code doesn’t really show off anything new, apart from perhaps some other style attributes, or UI elements.

A photograph of a childs drawing of some flowers. text: Drawing

I mentioned at the start that Shoes is influenced by Nodebox and Processing. Everything is a canvas and it has some really powerful animation (which I touched on) and drawing (which I didn’t) features. In recent builds _why has been building in more and more features for doing really neat graphical stuff (like filters and alpha transparency). Thankfully also without sacrificing the simplicity of the API. Remember, the goal of this is to power Hackety-hack, a tool for teaching kids to program. Adding this to the fact that you can do pixel perfect layout of elements means you could do some stunning looking animated UIs. For example, if you wanted a random name generator you could draw a hat that spits out stars and then picks a random name2. Or… something good.

A photograph of a mechanical control panel with many dials, buttons, toggles, and switches. text: Custom controls

Shoes has the ability to create custom controls, so if you need a dial or big flippy switch as a UI element, you can combine the drawing stuff I just mentioned and the existing controls and layouts in a class that extends from Shoes::Widget. You can then use these custom widgets inside your Shoes app and not have to worry about repeating code, or having code in the wrong place cluttering up your main logic.

A photograph of a large collection of shoes on a large shoe-tree. text: Organising your shoes

Speaking, as I was just briefly about tidying up the code and so on, I should point out that all the code I’ve shown you has been from one file: talon.rb. That’s not to say that you can’t organise your code better. Shoes has some interesting features that could help this. I have to say, I’ve not fully explored this aspect of Shoes, so I’m just letting you know that it’s out there.

A snippet of code showing a shoes app that has urls to point to new functions. text: Organising your shoes. code: https://gist.github.com/h-lame/caaf6d8a2c91b3cce8fea05cc6b25d7a#file-slide-37-organising-your-shoes-with-urls-rb
Gist for code in slide

You can extend Shoes itself and this lets you define url endpoints which are methods in your Shoes class that you can call with the visit method. visit takes a url, relative or absolute. You can have regexp’s in the URL and any groups in the pattern become arguments to the method being visited. The main advantage here is then being able to put your Shoes code into multiple files.

It’s not clear to me the full power of advantage of this, except for the fact that the urls you visit can be absolute, and thus you can put shoes apps online to perhaps combine the power of a desktop app with the simplicity of updating via a central web app.

A photograph of some post office PostPak parcels. text: Packaging your App

Shoes has an excellent in built packaging feature. From the “Package” menu of any Shoes app you can bundle up your Shoes code, along with Shoes and dependencies, as a Windows, OS X, Linux or Shoes application. Shoes has a cross-platform bundle called SHY which you can use instead.

It’s a really simple and nice way of bundling your code, much easier than any other mechanism I’ve used in the past, and it’s awesome that it’s built in.

A list of resources for further information about shoes. text: Find out more (see trnascript for other links)

So, that’s it.

Hopefully I’ve whetted your appetite for Shoes, if you want to know more there are excellent resources out there about shoes. First is the shoes manual, which is built into every shoes app. Press cmd m to make it appear. Then go and get a copy of “nobody knows shoes”. Then explore the rest.

I really recommend it3.

A list of urls for the photographs used in the previous slides. text: Without whom (see transcript for other links)