NumberSelector.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;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.lcdui.game.TiledLayer;

public class NumberSelector extends View {

    private static final int TEXT_COLOR = 0x00FFFFFF;
    private final Image buttonImage;
    private final Image largeButtonImage;
    private final Listener listener;
    private TiledLayer numberButtons;
    private Sprite cButton;
    private final int numberButtonWidth, numberButtonHeight;
    private final int cButtonWidth, cButtonHeight;
    private int keyPressed;
    private volatile boolean refreshButtons = true;

    public NumberSelector(int width, int height, Image buttonImage,
            Image largeButtonImage, Listener listener) {
        super(0, 0, width, height);
        this.buttonImage = buttonImage;
        this.largeButtonImage = largeButtonImage;
        this.listener = listener;
        numberButtonWidth = buttonImage.getWidth() / 2;
        numberButtonHeight = buttonImage.getHeight();
        cButtonWidth = largeButtonImage.getWidth() / 2;
        cButtonHeight = largeButtonImage.getHeight();
    }

    public void setLeft(int left) {
        super.setLeft(left);
        refreshButtonPositions();
    }

    public void setRight(int right) {
        super.setRight(right);
        refreshButtonPositions();
    }

    public void setWidth(int width) {
        super.setWidth(width);
        refreshButtonPositions();
    }

    public void setTop(int top) {
        super.setTop(top);
        refreshButtonPositions();
    }

    public void setBottom(int bottom) {
        super.setBottom(bottom);
        refreshButtonPositions();
    }

    public void setHeight(int height) {
        super.setHeight(height);
        refreshButtonPositions();
    }

    private void refreshButtonPositions() {
        if (numberButtons != null) {
            numberButtons.setPosition(left, top);
        }
        if (cButton != null) {
            cButton.setPosition(left, top + numberButtonHeight * 3);
        }
    }

    protected void paint(Graphics g) {
        if (numberButtons == null || cButton == null) {
            numberButtons = new TiledLayer(3, 3, buttonImage, numberButtonWidth,
                                           numberButtonHeight);
            cButton = new Sprite(largeButtonImage, cButtonWidth, cButtonHeight);
            refreshButtonPositions();
        }
        if (refreshButtons) {
            refreshButtons();
        }
        numberButtons.paint(g);
        cButton.paint(g);
        paintNumbers(g);
    }

    private void paintNumbers(Graphics g) {
        g.setColor(TEXT_COLOR);
        final int xOffset = left + numberButtonWidth / 2;
        final int yOffset = top + numberButtonHeight / 2 - g.getFont().getHeight() / 2;
        int x, y, n;
        for (int row = 0; row < 3; row++) {
            y = yOffset + row * numberButtonHeight;
            for (int col = 0; col < 3; col++) {
                x = xOffset + col * numberButtonWidth;
                n = row * 3 + col + 1;
                g.drawString(String.valueOf(n), x, y,
                             Graphics.HCENTER | Graphics.TOP);
            }
        }
        x = cButton.getX() + cButton.getWidth() / 2;
        y = cButton.getY() + cButton.getHeight() / 2 - g.getFont().getHeight() / 2;
        g.drawString("C", x, y, Graphics.HCENTER | Graphics.TOP);
    }

    private void refreshButtons() {
        refreshButtons = false;
        numberButtons.fillCells(0, 0, 3, 3, 1);
        cButton.setFrame(0);
        if (keyPressed > 9) {
            cButton.setFrame(1);
        }
        else if (keyPressed > 0) {
            int col = (keyPressed - 1) % 3;
            int row = (keyPressed - 1) / 3;
            numberButtons.setCell(col, row, 2);
        }
    }

    public void handlePointerEvent(int type, int x, int y) {
        if (!isVisible()) {
            return;
        }
        if (type == View.POINTER_RELEASED) {
            if (hits(x, y)) {
                listener.numberSelected(getKey(x, y));
            }
        }
        else {
            setKeyPressed(hits(x, y) ? getKey(x, y) : 0);
        }
    }

    private int getKey(int x, int y) {
        if (y < top + numberButtonHeight * 3) {
            int col = Math.min((x - left) / numberButtonWidth, 2);
            int row = Math.min((y - top) / numberButtonHeight, 2);
            return col + 3 * row + 1;
        }
        else {
            return 10;
        }
    }

    public void setVisible(boolean visible) {
        super.setVisible(visible);
        setKeyPressed(0);
    }

    public void setKeyPressed(int n) {
        if (keyPressed != n) {
            keyPressed = n;
            refreshButtons = true;
            invalidate();
        }
    }

    public void keyEvent(int type, int key) {
        if (type == KEY_RELEASED) {
            return;
        }
        if (keyPressed > 0) {
            switch (key) {
                case KEY_UP:
                    setKeyPressed((keyPressed - 3 - 1 + 12) % 12 + 1);
                    break;
                case KEY_DOWN:
                    setKeyPressed((keyPressed + 3 - 1) % 12 + 1);
                    break;
                case KEY_LEFT:
                    setKeyPressed(
                            (keyPressed - 1) / 3 * 3 + (keyPressed - 1 + 2) % 3 + 1);
                    break;
                case KEY_RIGHT:
                    setKeyPressed(
                            (keyPressed - 1) / 3 * 3 + (keyPressed + 1 + 2) % 3 + 1);
                    break;
                case KEY_SELECT:
                    if (type == KEY_PRESSED) {
                        listener.numberSelected(keyPressed);
                    }
                    break;
                default:
                    break;
            }
        }
        else {
            setKeyPressed(5);
        }
    }

    public static interface Listener {
        void numberSelected(int n);
    }
}