OptionsDialog.java

/*
 * Copyright © 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.sudokumaster;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

public class OptionsDialog extends ImageView {

    private static final String[] ITEMS = {"Restart", "New Game", "Exit"};
    private static final int TEXT_COLOR = 0x00000000;
    private static final int HIGHLIGHT_COLOR = 0x00ffff99;
    private static final int ANIMATION_STEPS = 5;
    private int[] itemYs = null;
    private final Listener listener;
    private int highlighted = -1;
    private int highlightAnimationCounter = 0;

    public OptionsDialog(Image backgroundImage, Listener listener) {
        super(backgroundImage);
        this.listener = listener;
    }

    public void update() {
        if (highlighted < 0) {
            highlightAnimationCounter = 0;
        }
        if (highlightAnimationCounter > 0) {
            int h = highlightHeight();
            highlightAnimationCounter = Math.max(highlightAnimationCounter - 1, 0);
            int newH = highlightHeight();
            if (h != newH) {
                invalidate();
            }
        }
    }

    public void setTop(int top) {
        super.setTop(top);
        itemYs = null;
    }

    public void setBottom(int bottom) {
        super.setBottom(bottom);
        itemYs = null;
    }

    public void setHeight(int height) {
        super.setHeight(height);
        itemYs = null;
    }

    private int highlightHeight() {
        return (height / 6 - height * highlightAnimationCounter / ANIMATION_STEPS / 12) / 2 * 2;
    }

    protected void paint(Graphics g) {
        super.paint(g);
        if (itemYs == null) {
            itemYs = new int[ITEMS.length];
            int padding = height / 10;
            int itemHeight = (height - padding) / ITEMS.length;
            int itemCenter = top + (padding + itemHeight) / 2;
            for (int i = 0; i < ITEMS.length; i++) {
                itemYs[i] = itemCenter + i * itemHeight;
            }
        }
        if (highlighted >= 0) {
            int w = width - (width > 128 ? 8 : 6);
            int h = highlightHeight();
            int x = left + (width - w) / 2;
            int y = itemYs[highlighted] - h / 2;
            g.setColor(HIGHLIGHT_COLOR);
            g.fillRect(x, y, w, h);
        }
        int x, y;
        x = left + width / 2;
        g.setColor(TEXT_COLOR);
        for (int i = 0; i < ITEMS.length; i++) {
            y = itemYs[i] - g.getFont().getHeight() / 2;
            g.drawString(ITEMS[i], x, y, Graphics.HCENTER | Graphics.TOP);
        }
    }

    public void setVisible(boolean visible) {
        super.setVisible(visible);
        highlighted = -1;
        highlightAnimationCounter = 0;
    }

    public boolean handlePointerEvent(int type, int x, int y) {
        boolean ret = false;
        if (!isVisible()) {
            return ret;
        }
        final int oldHighlighted = highlighted;
        if (hits(x, y)) {
            highlighted = getItemIndex(x, y);
            if (type == View.POINTER_RELEASED && highlighted >= 0) {
                listener.onItemClick(highlighted);
            }
            ret = true;
        }
        else {
            highlighted = -1;
        }
        if (oldHighlighted != highlighted) {
            highlightAnimationCounter = ANIMATION_STEPS;
            invalidate();
        }
        return ret;
    }

    public void keyEvent(int type, int key) {
        if (type == KEY_RELEASED) {
            return;
        }
        switch (key) {
            case KEY_UP:
                highlightItem(highlighted < 0 ? 0 : (highlighted - 1 + ITEMS.length) % ITEMS.length);
                break;
            case KEY_DOWN:
                highlightItem(highlighted < 0 ? 0 : (highlighted + 1) % ITEMS.length);
                break;
            case KEY_SELECT:
                if (highlighted < 0) {
                    highlightItem(0);
                }
                else if (type == KEY_PRESSED) {
                    listener.onItemClick(highlighted);
                }
                break;
            default:
                break;
        }
    }

    private int getItemIndex(int x, int y) {
        if (x < left + width / 6 || x > left + width * 5 / 6) {
            return -1;
        }
        else {
            return Math.min((y - top) / (height / 3), ITEMS.length - 1);
        }
    }

    public void highlightItem(int i) {
        highlighted = i;
        highlightAnimationCounter = ANIMATION_STEPS;
        invalidate();
    }

    public static interface Listener {
        void onItemClick(int itemIndex);
    }
}