Button.java
/**
* Copyright (c) 2013 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;
import com.nokia.mid.ui.CanvasGraphicsItem;
import com.nokia.mid.ui.CanvasItem;
import java.io.IOException;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
/*
* Button control is based on CanvasGraphicsItem. This class show the basic
* usage of Canvas graphics control to encapsulate simple control.
*
* Button control handles pointer events to change between normal and pressed
* state, it executes the "click" event handler given through the constructor
* when Button is pressed and released. Button can be disabled.
*
* Button appearance is defined in class ButtonState (class definition at the
* end of this this file) objects which allow usage of different background
* bitmaps and font colors.
*/
public class Button extends CanvasGraphicsItem {
// Text to be shown on Button
private String text = null;
// Button states
private ButtonState normalState;
private ButtonState pressedState;
private ButtonState dimmedState;
private ButtonState currentState;
private boolean enabled = true;
private boolean pressed = false;
Runnable clickHandler;
Button(Canvas parent, String text, Runnable clickHandler) throws Exception {
// CanvasGraphicsItem needs a non-zero size for its construction.
super(1, 1);
this.setParent(parent);
this.text = text;
this.clickHandler = clickHandler;
try {
// Create different button states with distinct look and colors
this.normalState = new ButtonState(
this, "/images/NormalButton.png", 0xFFFFFF);
this.pressedState = new ButtonState(
this, "/images/PressedButton.png", 0xFFB600);
this.dimmedState = new ButtonState(
this, "/images/DimmedButton.png", 0xa0a0a0);
} catch (Exception ex) {
throw ex;
}
// Set size based on normal state size
this.setSize(this.normalState.getWidth(), this.normalState.getHeight());
this.updateState();
this.setVisible(true);
this.repaint();
}
/**
* Enables or disables Button. Disabled Button doesn't process pointer
* events.
*/
public void setEnabled(boolean enabled) {
if (this.enabled == enabled) {
return;
}
this.enabled = enabled;
this.updateState();
this.repaint();
}
/**
* Sets whether Button is pressed.
*/
public void setPressed(boolean pressed) {
this.pressed = pressed;
this.updateState();
this.repaint();
}
/**
* This method sets size of the Button by setting size of the
* CanvasGraphicsItem. Width is checked for minimum and maximum value.
*/
public void setSize(int w, int h) {
int buttonWidth = w;
if (buttonWidth < 70) {
buttonWidth = 70;
} else if (buttonWidth > this.normalState.getWidth()) {
buttonWidth = this.normalState.getWidth();
}
super.setSize(buttonWidth, h);
}
/**
* This is very basic pointer event handling. It does not expect drag
* events, only consecutive pressed and released events.
*
* CanvasGraphicsItem does not receive any pointer events, they are
* delivered to parent Canvas, so this method needs to be called from
* Canvas.pointerPressed() and Canvas.pointerReleased() overrides.
*/
public void handlePointerEvent(int x, int y) {
if (this.isVisible() && this.enabled) {
if (x >= this.getPositionX()
&& x < (this.getPositionX() + this.getWidth())
&& y >= this.getPositionY()
&& y < (this.getPositionY() + this.getHeight())) {
// Pointer event is in Button area
if (this.pressed) {
// Call event handler
this.clickHandler.run();
this.setPressed(false);
} else {
this.setPressed(true);
}
} else if (this.pressed) {
this.setPressed(false);
}
}
}
/**
* Paint the Button by painting its current state.
*/
public void paint(Graphics graphics) {
this.currentState.paint(graphics, this.text);
}
/**
* It is necessary to set parent of the CanvasGraphicsItem to null before
* the MIDlet terminates.
*/
public void dispose() {
this.setParent(null);
}
/**
* Checks the state flags pressed and enabled, and updates the current
* appearance of the Button.
*/
private void updateState() {
if (this.enabled) {
if (this.pressed) {
this.currentState = this.pressedState;
} else {
this.currentState = this.normalState;
}
} else {
this.currentState = this.dimmedState;
}
}
/**
* Class encapsulating Button state. Each state has its background image and
* text color.
*/
class ButtonState {
protected int labelColor;
protected Image background;
protected CanvasItem owner;
public ButtonState(CanvasItem owner, String image, int color)
throws Exception {
this.owner = owner;
this.labelColor = color;
try {
this.background = Image.createImage(image);
} catch (IOException e) {
throw new Exception("Unable to load graphics resources.");
}
}
public int getWidth() {
return this.background.getWidth();
}
public int getHeight() {
return this.background.getHeight();
}
/**
* Paint the state. Should be called from Button's paint method.
*/
public void paint(Graphics gfx, String text) {
gfx.drawImage(
background,
owner.getWidth() / 2, owner.getHeight() / 2,
Graphics.VCENTER | Graphics.HCENTER);
gfx.setColor(0x000000);
gfx.drawRect(0, 0, owner.getWidth() - 1, owner.getHeight() - 1);
gfx.setColor(this.labelColor);
gfx.drawString(
text,
owner.getWidth() / 2, (owner.getHeight() / 3) * 2,
Graphics.BASELINE | Graphics.HCENTER);
}
}
}