Skip to content
Martin Prout edited this page Jul 6, 2015 · 29 revisions

To be revised after reading this

Some people think java reflection is cool (they are mistaken, it is not is a pain), where possible avoid using it at all costs, unfortunately some of the processing guys seem to think it is cool, so they have contaminated the processing api with it. Fortunately there are often ways to avoid it (and sometimes come up with something that is more appropriate for use in a ruby environment). One such example is the thread convenience method of processing, that relies on reflection to allow you to pass a function to a thread.

// in java processing
thread("someFunction");
void someFunction(){
  do stuff..
}

In ruby-processing we have overridden the thread convenience method to be much more ruby like (in keeping with ruby Thread, whilst actually using a java thread under hood) to take a block.

# in ruby-processing
thread do
  some stuff..
end

Actually we don't really need this convenience function in ruby-processing we've just overridden it to prevent any confusion, it is just as easy to use the existing Thread syntax...

# natively available with jruby
Thread.new do
  some stuff..
end

Another example where we can do better in ruby-processing, is in a replacement for the selectInput convenience method. This method also relies on reflection, and is now deprecated in ruby-processing ( and probably wouldn't work anyway ). See the file_chooser library, which uses JFileChooser under the hood, but we have created a more capable chooser (easy setup of file filters), and a much more ruby-like experience, with block encapsulation. You could of course roll your own file chooser implementation, if you create something better please let us know.

A further example where reflection gets pressed into action ( in vanilla processing ) is the recommended way that you registerMethods with the processing Applet from a processing library, this is done using reflection as follows

// in java processing
public BasicLibrary(PApplet parent) {
    this.parent = parent;
    parent.registerMethod("dispose", this);
  }

  public void dispose() {
    // Anything in here will be called automatically when 
    // the parent sketch shuts down. For instance, this might
    // shut down a thread used by this library.
  }

You have to go through hoops to replicate this in ruby but it can be done:-

# in ruby-processing using reflection
require 'jruby/core_ext'

class TestRegister
  attr_reader :parent
  def initialize parent
    @parent = parent
    register = parent.java_method :registerMethod, [Java::JavaLang::String, java.lang.Object]
    register.call(:draw, self)
    register.call(:pre, self)
  end

  def pre
    puts 'before draw'
    parent.background(100)
  end

  def draw
    puts 'at begin draw...'
    parent.fill(200, 100)
    parent.ellipse(100, 100, 60, 60)
  end
  
  become_java!
end

The magic in the penultimate line ensures that the TestRegister class becomes java, so that when you pass self, it is a java.lang.Object. And believe it or not this actually works see following sketch:-

# test class ruby-processing
load "./register.rb"

def setup
  size 200, 200
  TestRegister.new self
  no_loop
end

def draw
  fill(0, 0, 200)
  ellipse(120, 120, 60, 60)
end

test.png

Anyone who can get registerMethod("mouseEvent") or registerMethod("keyEvent") to actually work in ruby-processing might find this useful, please be kind enough to let us know how you got it to work!!!

Alternative Strategy

I have created ArcBall (mouse drag to rotate and mousewheel zoom) functionality for ruby processing see here for details. I did this by writing a jruby java extension, this may well be the way forward to use the reflection capabilities built into processing pre(), post(), draw(), etc.