Random thoughts, daily life, being a student, quantum computing.


Monkeybars with IntelliJ Swing Designer

I had originally intended to do this once I had cucumber testing integrated, but I think that would just make the blog too long.

This post lets you get monkeybars (which uses  JRuby) working on IntelliJ using their form designer.

The first step, as usual, is getting everything installed. I'll assume you have IntelliJ version 11 installed and have installed the ruby plug-in for IntelliJ. If not, see the jetbrains site.

If you haven't installed JRuby - use the excellent rvm package to do this if on Linux or Mac. If you are on windows, there is an installer for you at the JRuby site.

Disclaimer: I am using Mac OSX 10.7, JRuby and rvm, so examples and experience is based on that.

The required background is:

  • Java 1.6 is installed
  • JRuby is installed (preferably via rvm)
  • You have set JRuby to be your default ruby (again, if using rvm)
  • IntelliJ is installed
  • The command line does not make you quiver in fear
  • You have decided to torture yourself and do swing development rather than Rails

Step1 - Install Monkeybars and rawr gems
Start a command window, go to it and do the following commands which add a new gem source and then install. The standard rubygems.org source is out of date for monkeybars.
  • jruby -S gem source -a http://gems.neurogami.com
  • jruby -S gem install monkeybars rawr
Installing monkeybars also installs the gems "bones" and "swingset".

Step2 - Set up the project
Change directory to wherever you want your project, (I am using ij in this example) then do the setup commands below.
  • jruby -S monkeybars ij
  • cd ij
  • jruby -S rawr -c com.yourdomain.ij.Main install
  • jruby -S rake generate ALL=src/ij
These commands will take a bit of time as they download a couple of gems and the latest version of the jruby-complete.jar. At this point, you will have a monkeybars project created in your directory.
Now, start up IntelliJ and create a new project. In the dialog, chose "Create Project From Existing Sources". In the next panel, navigate to your directory. IntelliJ will properly detect your java and ruby sources (ruby in ij, java in ij/src), at least it did for me. The next panel will note the three jars: jruby-complete.jar, miglayout-, and monkeybars-1.1.1.jar. Next panel, it sets up a Java module based on your src directory. Then, the final panel detects the JRuby framework.

Expand the project pane in IntelliJ and you should see something like this:

In IntelliJ, remove the org.rubyforge.rawr package and the main file under it.

Create a "run configuration" in IntelliJ to run your Main.java file. The easiest way to do this is right click on the Main file and select "Create Main.main()...". In the config dialog, change the working directory to add the src directory at the end. It should look like this:

To complete the project setup, edit two ruby files: manifest.rb and main.rb

In manifest.rb add the two lines:
add_to_load_path '../lib/ruby'
require "ij/ij_controller"
in main.rb, near the bottom of the file, there is a begin/rescue/end block. Right after begin, add the line:
Run the program via IntelliJ and this should appear:

Now - you have Monkeybars working with JRuby within IntelliJ. Whew!

In the old days with NetBeans, you would just design a form with the included designer and rock and roll. It is almost that simple with IntelliJ, there are just a couple of minor items to take care of.

Step 3 - Design a little form in IntelliJ
Add a new package for your forms (not required, I'm just anal about separating such things :). Within that package, right click and in the pop-up menu, select "Gui Form". Name it "Iform".

In the properties list on the left side, select the top level panel and give it the name "topPanel". (You can name any of the components, we need the top panel named to make things work in one of the alternate scenarios below. :). For purposes of the example, I just added a Jlabel and a Jbutton. Name them message and my_button respectively.

By default, IntelliJ associates a class with the form and will add private members for the elements on your form - panels are an exception, unless you name them as noted above.

If you preview the form, it should now look like this:

and the code of the associated form should look like this:

Step 4 - Create the top level frame.
IntelliJ's gui designer is for panels, forms and dialogs but not the top frame and its menu. It seems the simplest way to do this is just take the form class and extend it from a JFrame. The resulting code in Iform should look like this.

package com.yourdomain.ij.forms;

import javax.swing.*;
import java.awt.*;

public class Iform extends JFrame{

    public Iform(){
        super("Ij Frame");
        setMinimumSize(new Dimension(300,200));


    private JPanel topPanel;
    private JButton my_button;
    private JLabel message;}

Alternate to Step 4 - use JRuby and Swingset:
You can use JRuby with a swing wrapper to drive the form if you prefer. swingset is included with monkey bars, but I expect others such as Rubeus would work as well. Using JRuby, we would add a new JRuby class (I just re-used the ij_ui code that was generated. Then the JRuby code for step 4 looks like:

require 'swingset'
include  Neurogami::SwingSet::Core

class IjUi < Frame
  include  Neurogami::SwingSet::MiG
  attr_accessor :form
  attr_accessor :my_button
  FRAME_WIDTH  = 300
  def initialize *args
    self.minimum_width  = FRAME_WIDTH
    self.minimum_height = FRAME_HEIGHT
    default_close_operation = EXIT_ON_CLOSE
  def set_up_form
    @form =   com.yourdomain.ij.forms.Iform.new
    add  @form.get_top_panel
  def my_button

This code requires you to add accessors for any of the form fields that require interaction - my_button so you can define handlers, form so you can gain access to message. for mapping between the view and the model. Note this would change some of the wiring in step 5.

Step 5 - wire everything up the monkey bars way
The last step! (assuming you just changed Iform to extend JFrame).

First, update the model code to include a message for the label:

class IjModel
  attr_accessor :message
  def initialize
    @message = "Swing is ok..."

Next, in the file ij_view.rb found under src/ij, change the value IjUi to com.yourdomain.ij.forms.Iform. Then add a mapping from the view label to the model. The code will now look like this

class IjView < ApplicationView
  set_java_class com.yourdomain.ij.forms.Iform
  map :view => "message.text", :model => :message

Finally, add a handler for your button in the ij_controller:

class IjController < ApplicationController
  set_model 'IjModel'
  set_view 'IjView'
  set_close_action :exit
  def my_button_action_performed
    model.message = "<html>But Swing with Monkeybars<br>is awesome!"

And then BOOM - run it and you will see your form appear. Click the button and the label text will change.

That is the VERY beginning of getting started.

I hope this helps - comments welcomed!


  • I got most of the way using the book "Using JRuby" by Nutter, Sieger, Enobo, Bini and Dees.
  • Examples in the monkeybars source code shamelessly copied and hardly modified (Thanks James Britt)


Approaching HUnit

My January goals for LQPL include using TDD practices to create the code for the LQPL server. I am doing that, and at this point, I am starting to see some of the "warts" with the way I am tackling the TDD. For example, to be able to parse a set of five input text commands, I've created 56 cases (assertions).  Each case is a single line, but that is a lot of reading. For the "error out" cases, I created a function that improved the readability quite a bit.

    expectLeftString :: Either String a -> Bool
    expectLeftString (Left _)  = True
    expectLeftString _ = False
    makeBoolParseError :: String -> Assertion
    makeBoolParseError s = assertBool ("'"++s++"' returns error") (expectLeftString (getCommand s))
This gets used in the test creation like this:  

    "parseL3 " ~: makeBoolParseError "load"

For the positive cases, however, it becomes quite a bit messier. For example:

    "parseL2aSpace " ~: "'load     /x/xxx addint.qpo' returns QCLoad" ~:
               Right (QCLoad "/a/bc with space.qpo") @=? (getCommand "load /a/bc with space.qpo") 

Multiple lines of this become rather difficult to parse.

One solution would be to create a helper function for creating the positive assertions as well. I'll give that a shot and see how it looks!


Thesis, Here I come!

2012 is going to be a banner year for my research! I will be able to dedicate myself to it full-time starting in April, which is like a dream come true. To get ready for that, I've set myself some goals for the first three months of the year, while I am still working.

LQPL Goals:

  • January - Document new separated View and Controller interfaces for the new "server" type emulator.
  • January - Write tests in HUnit (or SmallCheck or QuickCheck) as part of the development of this server and client interface
  • January - Actually write the code!
  • January - Have Grover's Algorithm working as before.
  • February - Write a new HCAR entry
Inverse Categories Research Goals:

  • February - Review and update the proofs on lifting inverse product to a product and the equivalence proof
  • March - Beef up Inverse Co-Product paper
  • March - Get Inverse Products paper ready for submission to TAC
Other (things to support research):
  • Make physical fitness a habit.
  • Catch up on reading
  • Present something (Likely on reversible computing and linear logic)