Thank you to anyone who has already donated - your generous donations helped make three months of treatment possible.

My brother Nate continues to fight stage IV Hodgkin's lymphoma. He's just 31, with a wife and baby girl. They have no active income (since he's been unable to return to work), no insurance, and cannot afford the treatment he needs. Nate and his family need your help. Please consider a donation, every dollar helps. Thanks.


package org.emerick.rtm.ui.lists;

import java.util.Vector;

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.KeypadListener;
import net.rim.device.api.ui.ContextMenu;
import net.rim.device.api.ui.DrawStyle;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Keypad;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.ListField;
import net.rim.device.api.ui.component.ListFieldCallback;
import net.rim.device.api.ui.component.NullField;

import org.emerick.rtm.RTM;
import org.emerick.rtm.beans.Task;
import org.emerick.rtm.ui.field.FontColorField;
import org.emerick.rtm.ui.screens.DetailTaskScreen;


public class TaskListField extends ListField implements ListFieldCallback
{

	private Vector tasks;
	private Vector rows;
	private Bitmap p1;
	private Bitmap p2;
	private Bitmap p3;

	public TaskListField(Vector tasks)
	{
		super(0, ListField.MULTI_SELECT);
		setRowHeight(40);
		setEmptyString("Hooray, no tasks here!", DrawStyle.HCENTER);
		setCallback(this);
		setSearchable(false);

		p1 = Bitmap.getBitmapResource("p1.png");
		p2 = Bitmap.getBitmapResource("p2.png");
		p3 = Bitmap.getBitmapResource("p3.png");

		this.tasks = tasks;
		rows = new Vector();

		for (int x = 0; x < tasks.size(); ++x)
		{
			TableRowManager row = new TableRowManager();

			// SET THE PRIORITY BITMAP FIELD
			Task task = (Task)tasks.elementAt(x);

			switch (task.getPriority())
			{
			case 1:
				// if high priority, display p1 bitmap
				row.add(new BitmapField(p1));
				break;
			case 2:
				// if priority is 2, set p2 bitmap
				row.add(new BitmapField(p2));
				break;
			case 3:
				// if priority is 3, set p3 bitmap
				row.add(new BitmapField(p3));
				break;
			default:
				// no priority set
				row.add(new NullField());
				break;
			}

			// SET THE TASK NAME LABELFIELD
			// if overdue, bold/underline
			LabelField taskname = new LabelField(task.getName(), DrawStyle.ELLIPSIS);
			// if due today, bold
			if (task.overdue())
			{
				taskname.setFont(Font.getDefault().derive(Font.BOLD | Font.UNDERLINED));
			}
			else if (task.dueToday())
			{
				taskname.setFont(Font.getDefault().derive(Font.BOLD));
			}

			row.add(taskname);

			// SET THE LIST NAME
			row.add(new FontColorField(RTM.getListName(task.getListID()), DrawStyle.ELLIPSIS, 0x00878787));

			// SET THE DUE DATE/TIME
			row.add(new FontColorField(task.getFormattedDue(), DrawStyle.ELLIPSIS | LabelField.USE_ALL_WIDTH
					| DrawStyle.RIGHT, 0x00878787));

			rows.addElement(row);
		}

		setSize(rows.size());
	}

	private class TableRowManager extends Manager
	{
		public TableRowManager()
		{
			super(0);
		}

		// Causes the fields within this row manager to be layed out then
		// painted.
		public void drawRow(Graphics g, int x, int y, int width, int height)
		{
			// Arrange the cell fields within this row manager.
			layout(width, height);

			// Place this row manager within its enclosing list.
			setPosition(x, y);

			// Apply a translating/clipping transformation to the graphics
			// context so that this row paints in the right area.
			g.pushRegion(getExtent());

			// Paint this manager's controlled fields.
			subpaint(g);

			g.setColor(0x00CACACA);
			g.drawLine(0, 0, getPreferredWidth(), 0);
			g.drawLine(10, 0, 10, getPreferredHeight());

			// Restore the graphics context.
			g.popContext();
		}

		// Arrages this manager's controlled fields from left to right within
		// the enclosing table's columns.
		protected void sublayout(int width, int height)
		{
			// set the size and position of each field.
			int fontHeight = Font.getDefault().getHeight();
			int preferredWidth = getPreferredWidth();

			// start with the Bitmap Field of the priority icon
			Field field = getField(0);
			layoutChild(field, 10, 40);
			setPositionChild(field, 0, 0);

			// set the task name label field
			field = getField(1);
			layoutChild(field, preferredWidth - 16, fontHeight + 1);
			setPositionChild(field, 16, 3);

			// set the list name label field
			field = getField(2);
			layoutChild(field, 150, fontHeight + 1);
			setPositionChild(field, 16, fontHeight + 6);

			// set the due time name label field
			field = getField(3);
			layoutChild(field, 150, fontHeight + 1);
			setPositionChild(field, preferredWidth - 152, fontHeight + 6);

			setExtent(preferredWidth, getPreferredHeight());
		}

		// The preferred width of a row is defined by the list renderer.
		public int getPreferredWidth()
		{
			return Graphics.getScreenWidth();
		}

		// The preferred height of a row is the "row height" as defined in the
		// enclosing list.
		public int getPreferredHeight()
		{
			return getRowHeight();
		}
	}

	// ListFieldCallback Implementation
	public void drawListRow(ListField listField, Graphics g, int index, int y, int width)
	{
		TaskListField list = (TaskListField) listField;
		TableRowManager rowManager = (TableRowManager) list.rows.elementAt(index);
		rowManager.drawRow(g, 0, y, width, list.getRowHeight());
	}

	public Object get(ListField list, int index)
	{
		return tasks.elementAt(index);
	}

	public int indexOfList(ListField list, String prefix, int start)
	{
		for(int x = start; x < tasks.size(); ++x)
		{
			Task task = (Task)tasks.elementAt(x);
			if(task.getName().startsWith(prefix))
			{
				return x;
			}
		}
		return -1;
	}

	public int getPreferredWidth(ListField list)
	{
		return Graphics.getScreenWidth();
	}

	public ContextMenu getContextMenu()
	{
		ContextMenu menu = super.getContextMenu();

		menu.addItem(new CompleteTaskMenuItem());
		menu.addItem(new EditTaskMenuItem());
		menu.addItem(new DeleteTaskMenuItem());
		menu.addItem(new PostponeTaskMenuItem());

		return menu;
	}

	protected boolean navigationClick(int status, int time)
	{
		if ((status & KeypadListener.STATUS_TRACKWHEEL) == KeypadListener.STATUS_TRACKWHEEL)
			return false;

		selectItem();

		return true;
	}

	protected boolean keyDown(int keycode, int time)
	{
		if (Keypad.key(keycode) == Keypad.KEY_ENTER)
		{
			selectItem();
		}
		else if (Keypad.key(keycode) == Keypad.KEY_DELETE)
		{
			deleteSelected();
		}
		else if (Keypad.map(keycode) == 'c')
		{
			completeSelected();
		}
		else if (Keypad.map(keycode) == 'p')
		{
			postponeSelected();
		}
		else if(Keypad.map(keycode) == 't')
		{
			setSelectedIndex(0);
			setFocus();
		}
		else if(Keypad.map(keycode) == 'b')
		{
			setSelectedIndex(tasks.size() - 1);
			setFocus();
		}
		else
		{
			return false;
		}
		return true;
	}

	public void delete(int index)
	{		
		super.delete(index);
		tasks.removeElementAt(index);
	}

	public void selectItem()
	{
		int index = getSelectedIndex();

		UiApplication.getUiApplication().pushScreen(new DetailTaskScreen((Task)tasks.elementAt(index)));
	}

	public void completeSelected()
	{
		int[] items = getSelection();
		for (int x = items.length; x > 0; x--)
		{
			RTM.completeTask((Task)tasks.elementAt(items[x - 1]));
			delete(items[x - 1]);
		}
	}

	public void deleteSelected()
	{
		int[] items = getSelection();
		for (int x = items.length; x > 0; x--)
		{
			RTM.deleteTask((Task)tasks.elementAt(items[x - 1]));
			delete(items[x - 1]);
		}
	}

	public void postponeSelected()
	{
		int[] items = getSelection();
		for (int x = items.length; x > 0; x--)
		{
			RTM.postponeTask((Task)tasks.elementAt(items[x - 1]));
			((Task)tasks.elementAt(items[x - 1])).postpone();
		}
	}

	private final class CompleteTaskMenuItem extends MenuItem
	{
		public CompleteTaskMenuItem()
		{
			super("Complete", 100000, 1);
		}

		public void run()
		{
			completeSelected();
		}
	}

	private final class EditTaskMenuItem extends MenuItem
	{
		public EditTaskMenuItem()
		{
			super("Edit", 100001, 2);
		}

		public void run()
		{
			selectItem();
		}
	}

	private final class DeleteTaskMenuItem extends MenuItem
	{
		public DeleteTaskMenuItem()
		{
			super("Delete", 100002, 3);
		}

		public void run()
		{
			deleteSelected();
		}
	}

	private final class PostponeTaskMenuItem extends MenuItem
	{
		public PostponeTaskMenuItem()
		{
			super("Postpone", 100004, 4);
		}

		public void run()
		{
			postponeSelected();
		}
	}

}