TipBox.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.amaze.ui;

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

import com.nokia.example.amaze.Main;
import com.nokia.example.amaze.model.MyTimer;

/**
 * A small dialog-like box for displaying tips for the user.  
 */
public class TipBox implements MyTimer.Listener {
	// Constants
	private static final int WIDTH = 220;
	private static final int TEXT_WIDTH = 180;
	private static final int TEXT_HEIGHT = 100;
	private static final int TEXT_X_MARGIN = 20;
	private static final int TEXT_Y_TOP_MARGIN = 40;
	private static final int X_POSITION = (240 - WIDTH) / 2;
	private static final int Y_POSITION = 190;
	private static final int TIMEOUT = 8000; // Milliseconds
	
	// Members
	static private TipBox _instance = null;
	private final Image _backgroundImage = Main.makeImage("/graphics/tip-box-bg.png");
	private TextWrapper _textWrapper = null;
	private String _text = null;
	private boolean _visible = false;
	private int _textY = 0;
	
	/**
	 * Constructor.
	 */
	private TipBox() {
		_textWrapper = TextWrapper.instance(Font.getDefaultFont(), TEXT_WIDTH);
	}
	
	/**
	 * Shows the tip box.
	 * @param text The tip text to show.
	 */
	static public void show(final String text) {
		if (_instance == null) {
			_instance = new TipBox();
		}
		
		if (text != null && text.length() > 0) {
			_instance._text = text;
			_instance._visible = true;
			_instance._textWrapper.setText(_instance._text);
			_instance._textY =
					(TEXT_HEIGHT - _instance._textWrapper.lineCount()
							* _instance._textWrapper.lineHeight()) / 2;
			
			// Set the timer to hide the tip box after timeout
			MyTimer.instance().addListener(_instance, false, TIMEOUT);
		}
	}
	
	/**
	 * Hides the tip box.
	 */
	static public void hide() {
		// Automatic tip showing ->
		if (tipsToShow > 0) {
			_instance._visible = false;
			_instance._text = null;
			return;
		}
		// <- Automatic tip showing
		
		if (_instance != null) {
			MyTimer.instance().removeListener(_instance);
			_instance._visible = false;
			_instance._text = null;
			free();
		}
	}
	
	/** 
	 * @return True if the tip is visible, false otherwise.
	 */
	static public boolean visible() {
		if (_instance != null) {
			return _instance._visible;
		}
		
		return false;
	}
	
	/**
	 * Releases the handle of the singleton instance so the garbage collector
	 * can collect it.
	 */
	static public void free() {
		if (_instance != null) {
			System.out.println("TipBox::free(): Releasing the instance.");
			_instance = null;
		}
	}
	
	// LOGIC FOR AUTOMATICALLY SHOWING THE TIPS STARTS HERE
	// But some of it is added to timeout() and hide()
	static final private int TIP_INTERVAL = TIMEOUT; // Milliseconds
	static final private String[] TIPS =
		{
		/* 3rd */ "Tip: To recalibrate the accelerometer sensor pause and resume the game.",
		/* 2nd */ "Tip: Douple tap the screen to toggle between the set and the default zoom.",
		/* 1st */ "Tip: Pinch the screen to zoom in and out."
		};
	static private int tipsToShow = TIPS.length;
	
	/**
	 * Starts the timed tip showing procedure.
	 */
	static public void showTips() {
		if (_instance == null) {
			_instance = new TipBox();
		}
		
		MyTimer.instance().addListener(_instance, true, TIP_INTERVAL);
	}
	// LOGIC FOR AUTOMATICALLY SHOWING THE TIPS STOPS HERE
	
	/**
	 * Static public interface for painting the tip box.
	 * @param graphics
	 */
	static public void paint(Graphics graphics) {
		if (_instance != null) {
			_instance.doPaint(graphics);
		}
	}
	
	/**
	 * From MyTimer.Listener.
	 * Hides the tip box.
	 */
	public void onTimeout() {
		System.out.println("TipBox::onTimeout()");
		
		// Automatic tip showing ->
		if (tipsToShow > 0) {
			if (_text == null) {
				show(TIPS[tipsToShow - 1]);
				tipsToShow--;
			}
			else {
				_visible = false;
				_text = null;
			}
			
			return;
		}
		// <- Automatic tip showing
		
		hide();
	}
	
	/**
	 * Paints the tip box.
	 * @param graphics
	 */
	private void doPaint(Graphics graphics) {
		if (!_visible || _text == null || _text.length() == 0) {
			return;
		}
		
		// Draw background
		final int topLeft = Graphics.TOP | Graphics.LEFT;
		graphics.drawImage(_backgroundImage, X_POSITION, Y_POSITION, topLeft);
		
		// Draw the tip text
		graphics.setColor(MazeCanvas.TEXT_COLOR);
		_textWrapper.setWidth(TEXT_WIDTH);
		int y = Y_POSITION + TEXT_Y_TOP_MARGIN + _textY;
		
		try {
			_textWrapper.setText(_text);
			String line = null;

			while (_textWrapper.hasMoreLines()) {
				line = _textWrapper.nextLine();
				graphics.drawString(line,
						X_POSITION + TEXT_X_MARGIN
							+ (TEXT_WIDTH - _textWrapper.lineWidth(line)) / 2,
						y, topLeft);
				y += _textWrapper.lineHeight();
			}
		}
		catch (IllegalArgumentException e) {}			
	}
}