Friday, May 8, 2009

Multiple Image Scrolling

I thought through a couple different ways to allow users to see multiple images for a given node, and I decided that the simplest user interaction was just to have the image change to the next one when clicked on. It wasn't actually as simple to implement as it is to use. 

I created a Rectangle class extending the UIObject class, which the EventManager class sends events to. The rectangle also has a reference to the overall PApplet (Processing Applet), so as to control drawing this invisible rectangle on the screen. On a mouse click event, the EventManager sends the event to whatever UIObjects it knows of, and waits for one of them to handle it before resorting to other options. The Rectangle class handles MOUSE_RELEASED events that fall inside the area of the image. 

First roadblock - either the rectangles were responding to clicks indiscriminately, no matter where they were, or they weren't responding at all. Then when debugging through I realized the EventManager had references to a lot more UIObjects than seemed reasonable... until I realized that for every node on every new frame I was creating a new rectangle instead of updating that node's existing one. That lead to thousands of rectangles in a very short time and caused much of the strange click-response I'd been getting. 

Finding the click area itself was a bit of a task, because there aren't clear variables defining it. The function drawing the image is called using local coordinates, but my rectangle needed to be called using world coordinates. This is where my CIS 460 knowledge came in handy, because otherwise I wouldn't have even known the difference let alone how to handle it. I was able to find variables called realX and realY in world coordinates, which I thought would be the solution to my problem, except for some reason only the bottom left side of the image was responding to clicks. A lot of debugging and detective work lead me to find out that that the realX and realY coordinates are actually that location of the center of the node dot, not the top left corner of the image as I had previously thought. So even though my rectangle was drawn in the right place (tested in color, so I'd know where it was), the code deciding which clicks to recognize was handling the wrong area. 

Once I figured that out, the next step was to try and fix it. The image is drawn just to the right of that node dot, but how far? Some quick math got me a rough estimate, except that value changes depending on the zoom level. What solved it for me was the variable dotWidth, which changed along with the zoom. Turns out the image's top left side is approximately one "dot-width" away from the realX and realY coordinates. Since the dot hits at the center of the image, vertically, I subtracted half the height from the y coordinate and finally ended up with the correct "click area." 

The last step was to handle actually making a click do something other than print out "click!" which is what I'd been using to test it until then. After some quick searching around, I found that the ImageSearcher2 object has a next() function. So I called that. Nothing happened. Then I added a line for loadImageURL() and finally I had changing images on clicks! Except when it got to the end of the available images it stopped. So I added a check to restart from the first when it got to the end, and that is the long but exciting story about how I got my last feature working properly. 

I want to add some sort of way to check whether it's displaying the "Image not available" image, since that's annoying. But other than that, I do believe I'm done! 

Things I learned on this section: 
- PhyloWidget's handling of events and how to interact with it
- The image and node rendering processes, the many variables involved, and how much more hacked together it is than the rest of the code I'd been reading 'till now. 
- I'm a lot faster at debugging now, since a lot of this is trial and error, or rather "trial and figure out where the error is."
- Processing's shape-drawing language. I hadn't really gotten to interact much with it yet, and it was a nice introduction to how to draw shapes, specify coordinates and colors, etc. Of course you can't see my shapes, but they're there doing their job. 

With that, and since I just used all three forms of words sounding like "there" in one phrase, I consider this blog post done. 

No comments: