ScrollableView.java

/**
 * Copyright (c) 2012 Nokia Corporation. All rights reserved.
 * Nokia and Nokia Connecting People are registered trademarks of Nokia 
Corporation.
 * Oracle and Java are trademarks or registered trademarks of Oracle and/or its
 * affiliates. Other product and company names mentioned herein may be trademarks
 * or trade names of their respective owners.
 * See LICENSE.TXT for license information.
 */

package com.nokia.example.frameanimdemo;

import com.nokia.mid.ui.frameanimator.FrameAnimator;
import com.nokia.mid.ui.frameanimator.FrameAnimatorListener;
import com.nokia.mid.ui.gestures.GestureEvent;
import com.nokia.mid.ui.gestures.GestureInteractiveZone;
import com.nokia.mid.ui.gestures.GestureListener;
import com.nokia.mid.ui.gestures.GestureRegistrationManager;
import java.util.Timer;
import java.util.TimerTask;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;

public class ScrollableView
        extends GameCanvas
        implements GestureListener, FrameAnimatorListener {

    private Timer mTimer;
    private Graphics g;
    private int x = 0;
    private int y = 0;
    private FrameAnimator animator;
    private Image buffer;
    private Graphics bg;
    public static final int LISTITEM_AMOUNT = 30;
    private int lowerLimit = (-LISTITEM_AMOUNT * ListItem.HEIGHT);

    public ScrollableView() {
        super(false);
        setFullScreenMode(true);
        lowerLimit += getHeight();
        animator = new FrameAnimator();
        short fps = 0;
        short pps = 0;
        // when fps and or pps is zero, will use platform default values
        animator.register(x, y, fps, pps, this);
        // register for gesture events
        GestureInteractiveZone giz = new GestureInteractiveZone(
                GestureInteractiveZone.GESTURE_DRAG |
                GestureInteractiveZone.GESTURE_DROP |
                GestureInteractiveZone.GESTURE_FLICK |
                GestureInteractiveZone.GESTURE_LONG_PRESS |
                GestureInteractiveZone.GESTURE_LONG_PRESS_REPEATED |
                GestureInteractiveZone.GESTURE_TAP);
        GestureRegistrationManager.register(this, giz);
        GestureRegistrationManager.setListener(this, this);
        drawList();
    }

    /**
     * Draws just a dummy list that doesn't do anything. Good for this scrolling
     * demonstration.
     */
    private void drawList() {
        buffer = Image.createImage(getWidth(),
                                   LISTITEM_AMOUNT * ListItem.HEIGHT);
        bg = buffer.getGraphics();
        for (int i = 0; i < LISTITEM_AMOUNT; i++) {
            ListItem l = new ListItem("item " + (i + 1));
            l.setPosition(0, i * ListItem.HEIGHT);
            l.render(bg);
        }
    }

    public void showNotify() {
        mTimer = new Timer();
        g = getGraphics();
        TimerTask ui = new TimerTask() {

            public void run() {
                render(g);
                flushGraphics();
            }
        };
        mTimer.schedule(ui, 0, 20);
    }

    public void hideNotify() {
        mTimer.cancel();
    }

    public void render(Graphics g) {
        g.setColor(0xFFFFFF);
        g.fillRect(0, 0, getWidth(), getHeight());
        if (this.y > 0) {
            this.y = 0;
        }
        else if (this.y < lowerLimit) {
            this.y = lowerLimit;
        }

        g.drawImage(buffer, x, y, g.TOP | g.LEFT);
    }

    public void animate(
            FrameAnimator animator,
            int x,
            int y,
            short delta,
            short deltaX,
            short deltaY,
            boolean lastFrame) {
        this.y = y;
        render(g);
        flushGraphics();
    }

    public void gestureAction(
            Object container,
            GestureInteractiveZone giz,
            GestureEvent event) {
        switch (event.getType()) {
            case GestureInteractiveZone.GESTURE_DRAG:
                animator.drag(this.x + event.getDragDistanceX(),
                              this.y + event.getDragDistanceY());
                break;
            case GestureInteractiveZone.GESTURE_FLICK:
                animator.kineticScroll(event.getFlickSpeed(),
                                       FrameAnimator.FRAME_ANIMATOR_FREE_ANGLE,
                                       FrameAnimator.FRAME_ANIMATOR_FRICTION_MEDIUM,
                                       event.getFlickDirection());
                break;
            default:
                break;
        }
    }
}