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

2012-02-20

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 1.6.5.1 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-3.7.3.1.jar, 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:
IjController.instance.open
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));
        setDefaultCloseOperation(EXIT_ON_CLOSE);


        setContentPane(topPanel);
    }


    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
  mig_layout
  FRAME_WIDTH  = 300
  FRAME_HEIGHT = 200
  def initialize *args
    super
    self.minimum_width  = FRAME_WIDTH
    self.minimum_height = FRAME_HEIGHT
    set_up_form
    default_close_operation = EXIT_ON_CLOSE
  end
  def set_up_form
    @form =   com.yourdomain.ij.forms.Iform.new
    add  @form.get_top_panel
  end
  def my_button
    @form.get_mbutton
  end
end

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..."
  end
end


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
end


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!"
    update_view
  end
end


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!

Acknowledgements:

  • 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)



No comments: