This guest post is contributed by Martin
Sadler, who has over 10 years experience
in the web development industry working with a range of successful high
profile businesses, public sector organisations, and individuals. He is
best known in the Ruby community as the creator of Working With
Rails and is a keen advocate of the Ruby
on Rails Framework.

Introduction

In this article I’m going to show you how easy it is to create a nifty
little cross-platform system tray/menu bar application using
JRuby.

The application enables a user to take a screenshot of their desktop and
then do something interesting with it!

What’s covered in this article

What is JRuby?

JRuby is a version of Ruby that runs on top of the
JVM. It runs just
the same as regular MRI Ruby
except it’s about twice as fast and you get access to existing Java
libraries.

Getting started with JRuby

It’s never been easier to try JRuby out.
RVM is your friend here. Assuming you
have RVM already installed it’s simply
a case of doing the following inside your terminal session:

rvm install jruby

and then (where x.y.z is the version of JRuby)

rvm use jruby-x.y.z

From this point all your normal ruby commands will be using JRuby in the
current terminal. Sweet.

Part 1: Taking a screenshot

Robot
does for the Desktop what Selenium and other
automation tools do for the browser. The main difference is that you
have far more access to a users machine. You can move the mouse around,
control keystrokes, manipulate other programs, and most usefully take a
screenshot.

What is
Robot?
It’s a Java class and we going to make good use of it in our first
script.

The resulting screenshot gets saved to the same directory you are in as
‘test.png’. Result.

Tip: One question you might be asking by this point is how do you
know what classes are available when you include Java? Java API
docs have the
answer.\
Now, although helpful, it’s still pure Java so you’ll need to do a bit
of translating to the equivalent JRuby calls. The tree view makes it
easier to see how all the classes fit together.

So we’ve got a script to take a screenshot, it does the job, but we can
make it better.

By moving the code into a class method it’s much tidier and easier to
use for the next part of the application.

Gotcha: File naming is really important here. The Ruby class defined
in the file must be the CamelCase version of the filename for the
require to work otherwise you’ll get errors like :\
LoadError: use ‘java_import’ to load normal Java classes\
Note, this is only the case in JRuby not regular MRI Ruby

Part 2: Creating the system tray application

Now we have a class for taking a screenshot lets create the system tray
application:

A similar pattern of refactoring was carried out here as per the
Screenshot class.

Probably the most interesting point is the way you can use Ruby to
capture a block of code. In the case of the Screenshot application there
are certain actions we only want to be executed when the user clicks a
menu item. You can see these as code surrounded by curly braces.
Alternatively they could have been written as follows:

app.item('Take Screenshot') do
Screenshot.capture
end

Which does more or less the same job. Usually the do/end format is
preferred for multi-line code blocks.

What is handy for us is that we can capture these code blocks using the
█ parameter in the method definition. This makes the block available as
a local variable inside the method and it can be simply pushed onto an
array (@menu_items) for later recall.

Curious as to how a block is executed once stored? Here is a simple
example:

def hello(█)
block.call # execute the contents of the hello block using call
end
hello do
p "hello there"
end

Tip: Always try to keep your code tidy as you go along. Look for
patterns and bake them into classes if need be. Think about how the end
product will look like and work out how to get there. See also: Readme
Driven
Development.

Part 4: One further improvement

So now we have a tray application that takes a screenshot and saves to
disk. How about we get it to open in an image browser too. No problem.

So currently you’ll need JRuby in order to run this application. One
of the main benefits of JRuby is it compiles down to Java
bytecode and will run
on any Java enabled platform. Mac, Windows, and Unix support in one
go!

Variations on the theme

Why stop at screenshots? Here are few more ideas:

Drag and drop copy and upload of files to a web service

A notification service e.g. new support messages, tweets

System analytics tool

Copy and Paste share bin

Reference

Attribution

In Summary

I hope you found this article valuable and that it gives you an insight
into the world of possibilities with JRuby and desktop applications.
Feel free to ask questions and give feedback in the comments section of
this post. Thanks!