NumberSelector.java

/*
 * Copyright © 2011 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;
            }
        } else {
            setKeyPressed(5);
        }
    }

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