// Copyright 2001-2005, Danger, Inc.  All Rights Reserved.
// This file is subject to the Danger, Inc. Sample Code License,
// which is provided in the file SAMPLE_CODE_LICENSE.
// Copies are also available from http://developer.danger.com/

package com.example.GUIDemo;

/**
 * In order to allow active selection while using the UI, this sub-class of 
 * FolderView will override the event methods and execute putting the demonstration
 * dialogs up.
 */
import danger.app.Event;
import danger.app.EventType;
import danger.ui.Bitmap;
import danger.ui.Color;
import danger.ui.FolderView;
import danger.ui.Font;
import danger.ui.MenuItem;
import danger.ui.Pen;
import danger.ui.Rect;
import danger.util.Folder;
import danger.util.StringUtils;

public class DemoFolderView extends FolderView implements Resources, Commands {


	// Non default constructor must pass along parameters to super class.
	public DemoFolderView(Rect arg0) {
		super(arg0);
	}

	/**
	 * When this DemoFolderView is called upon to draw a single item in an open
	 * folder, this override will be called. This will take the object that was
	 * saved with the line, and draw the text string associated with the
	 * MenuItem object.
	 */
	private static final int kPixelIndent = 10;
	private static final int kIconIndent = 20;

	protected void drawItemLine(Pen pen, Object menu, Rect r, boolean selected) {
		MenuItem mi = (MenuItem) menu;
		Font sysFont = Font.findSystemFont();
		int x, y;
		int rHeight = r.bottom - r.top;

		// Draw the MenuItem title in the Rect passed in, but take into account
		// the ascent and descent of the font being used. The font is to be
		// drawn halfway between the top and bottom of the Rect. This calculates
		// that fudge factor so that it is font and cell size independent.
		pen.setFont(sysFont);

		// If it's not implemented yet, grey it out.
		if (mi.getEvent() == null) {
			pen.setColor(Color.GRAY9);
		}

		x = r.left + kPixelIndent; // shift items in to emphasize folder feel.
		y = sysFont.getAscent() + sysFont.getDescent(); // height of font only
		y = (rHeight - y) / 2; // fudge space for top or bottom
		y = y + sysFont.getAscent(); // add fudge to font height
		y = r.top + y; // to get final font baseline to draw.
		pen.drawText(x, y, mi.getTitle());

		// If the entry has an Icon, draw it on the right edge. This is
		// primarily for calling out the 2.3 only views.
		Bitmap bits = mi.getIcon();
		if (bits != null) {
			pen.drawBitmap(r.right - kIconIndent, r.top, bits);
		}
	}

	/**
	 * For eventKeyUp, look for the ActivateChar (usually \r), and if so, handle
	 * the selection. For Folder items, pass it back to the superclass for
	 * opening/closing. For folder items, send the event associated with the
	 * item to activate it.
	 */
	public boolean eventKeyUp(char arg0, Event arg1) {
		if (StringUtils.isActivateChar(arg0)) {
			activateSelection();
		}
		return super.eventKeyUp(arg0, arg1);
	}

	/**
	 * When the user clicks in the FolderView on an item, that's the signal to
	 * put up a dialog with the chosen UI widget in it. The item currently
	 * selected is a MenuItem in this case, so this will take that MenuItem and
	 * extract the event to be sent, and send it to the target. The target
	 * ScreenWindow will accept the event and handle performing the operation.
	 * Doing it this way allows for this code to not need to know any details of
	 * what is being selected or sent, it's all done indirectly through events.
	 */
	public boolean eventWidgetUp(int arg0, Event evt) {
		if (evt.what == EventType.DEVICE_WHEEL_BUTTON) {
			activateSelection();
		}

		// Folders are open/closed by the superclass
		return super.eventWidgetUp(arg0, evt);
	}

	/**
	 * When the Next button is selected in any dialog, this will be called.
	 * 
	 * Move the selection to the next item in the list. When the next selection
	 * is chosen, the corresponding event will be sent, bringing up the next
	 * dialog. If it's a folder as the next item, just open the folder.
	 * 
	 * If it's at the very last item, just return and do nothing.
	 */
	public void nextSelection() {
		Folder f = getFolder(mCurrentFolder);

		// At the last item, last folder, just do nothing.
		if (((mCurrentFolder + 1) >= folderCount())
				&& ((mCurrentItem + 1) >= f.size())) {
			return;
		}

		// If the current selection is a closed folder, just open it.
		if (!f.isOpen()) {
			f.setOpen(true);
			invalidate();
			return;
		}

		// If it's not the last item in a folder, select the next item.
		if ((mCurrentItem + 1) < f.size()) {
			setSelection(mCurrentFolder, mCurrentItem + 1);
			activateSelection();
			return;
		}

		// It is the last item in a folder, select the next folder. -1 for
		// the item, makes it the folder, not the first item IN the folder.
		// Force the folder open upon selection this way.
		setSelection(mCurrentFolder + 1, -1);
		getFolder(mCurrentFolder).setOpen(true);
		invalidate();
	}

	public void previousSelection() {
		Folder previousF = getFolder(mCurrentFolder - 1); // preceding folder.

		// At the very top of the list, just do nothing.
		if (((mCurrentFolder - 1) < 0) && ((mCurrentItem) < 0)) {
			return;
		}

		// If the item isn't the folder itself (-1), then back up one and select
		// it.
		if ((mCurrentItem) >= 0) {
			setSelection(mCurrentFolder, mCurrentItem - 1);
			activateSelection();
			return;
		}

		// If the preceding folder is closed, just open it.
		if (!previousF.isOpen()) {
			previousF.setOpen(true);
			invalidate();
			return;
		}

		// Lastly, it must be a folder that is presently selected, back into the
		// last item in the preceding folder and fire it off.
		setSelection(mCurrentFolder - 1, previousF.size());
		activateSelection();
	}

	/**
	 * Utility routine to activate whatever the current selection is showing.
	 * Sends the event to the ScreenWindow to have the widget demoed.
	 * 
	 * If it's not a MenuItem, don't do anything. And if it's greyed, the event
	 * sent will be null.
	 */
	public void activateSelection() {
		Object choice = getSelection();

		// Only reference for items, not Folders.
		if (choice instanceof MenuItem) {
			((MenuItem) choice).sendEvent();
		}
	}
}
