LiveScribe penlet timers

This is a quick post on timers in a LiveScribe pen penlet (pen application).  I had asked in the forums about how to track the pen position as it moved across the page.  The following is my take on the response I got.

Sample Code

In this case, I am going to start with code and then describe it.

package com.wordpress.alankent.livescribe.play;

import com.livescribe.penlet.Penlet;
import com.livescribe.penlet.PenletStateChangeException;
import com.livescribe.penlet.Region;
import com.livescribe.storage.StrokeStorage;
import com.livescribe.ui.ScrollLabel;
import com.livescribe.util.Timer;
import com.livescribe.util.TimerTask;
import com.livescribe.afp.PageInstance;
import com.livescribe.display.Display;
import com.livescribe.event.PenTipListener;
import com.livescribe.geom.Point;

public class TrackPenPosition extends Penlet
        implements PenTipListener {

    private Display display;
    private ScrollLabel label;
    private PollTask pollTask;
    private Timer pollTimer;

    public TrackPenPosition() {
    }

    public void initApp() throws PenletStateChangeException {
        display = this.context.getDisplay();
        label = new ScrollLabel();
        label.enableFlickScrub(false);
    }

    public void activateApp(int reason, Object[] args) {
        context.addPenTipListener(this);
        if (reason == Penlet.ACTIVATED_BY_MENU) {
            this.label.draw("Here is my scrolling label", true);
            this.label.enableFlickScrub(false);
            this.display.setCurrent(this.label);
        }
    }

    public void deactivateApp(int reason) {
    }

    public void destroyApp() throws PenletStateChangeException {
    }

    public void penDown(long time, Region region,
                        PageInstance page) {
        System.out.println(">>> PEN DOWN <<<");
        StrokeStorage ss = new StrokeStorage(page);
        pollTask = new PollTask(ss);
        pollTimer = new Timer();
        pollTimer.schedule(pollTask, 10, 15);
    }

    public void penUp(long time, Region region,
                      PageInstance page) {
        System.out.println(">>> PEN UP <<<");
        pollTimer.cancel();
    }

    public static class PollTask extends TimerTask {

        StrokeStorage ss;

        public PollTask(StrokeStorage ss) {
            this.ss = ss;
        }

        public void run() {
            Point p = ss.getLastCoord();

            // Do work with the new coordinate
            System.out.println("Coord = " +  p.toString());
        }
    }

    public void doubleTap(long time, int x, int y) {
    }

    public void singleTap(long time, int x, int y) {
    }
}

Description

What the above code does is create a new Timer instance when the pen goes down.  It also creates a new class that is called when the timer expires.  You can used a non-static inner class giving it full access to the parent penlet class, although you might prefer to use a separate class and pass all the required information across in the constructor.

Timers can issue multiple events, which I have used in this case.  The Timer.schedule() method takes the callback class to use, the initial timeout, and the time between subsequent timeouts as arguments.

To get the current pen position, in the timer it asks the stroke storage for the last coordinate.  See StrokeStorage.getLastCoord().

The end result is you get told about when each pen move occurs.

Beware however that you may need to use synchroized methods to protect penlet class variables.  The Timer class uses a separate thread.  Its not uncommon in real code to require a synchronized keyword on all the Penlet methods as soon as Timer instances are introduced in order to make sure that any code triggered by the Timer is thread safe with respect to the main Penlet class.  Its too big a job to describe synchronization and thread safety here – its important to understand however if you are going to use Timers safely.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: