package todo;
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.Label;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import com.buglabs.bug.module.gps.pub.IPositionProvider;
import com.buglabs.bug.module.gps.pub.LatLon;
import com.buglabs.bug.module.lcd.pub.IModuleDisplay;
import util.PositionHelper;
/**
*
* @author finsprings
*
*/
public class MyApplication {
private static final String NEAREST = "NEAREST";
private static final long PERIOD = 3000;
private LatLon currentLocation;
private Frame frame;
private Label currentTodoName;
private Label currentTodoDistance;
private final Timer timer = new Timer();
private IModuleDisplay display;
private IPositionProvider position;
private final java.util.List todos = new ArrayList();
private TodoList currentTodoList;
private TodoList lastTodoList;
private final DecimalFormat distanceFormat = new DecimalFormat("##0.00;-##0.00");
private java.awt.List items;
private boolean chooseNearest = true;
public MyApplication() {
loadTodos();
}
private void loadTodos() {
// TODO: get todo lists from file
{
// Canned Home todo list
final LatLon location = new LatLon();
location.latitude = 40.744194444444446;
location.longitude = -73.99397222222223;
final TodoList todo = new TodoList( "home", location );
todo.addItem( "clean up garage" );
todo.addItem( "clear leaves" );
todo.addItem( "wash the dishes" );
todos.add( todo );
}
{
// Canned Work todo list
final LatLon location = new LatLon();
location.latitude = 40.744638888888886;
location.longitude = -73.99536111111111;
final TodoList todo = new TodoList( "work", location );
todo.addItem( "read email" );
todo.addItem( "surf the web" );
todo.addItem( "research cake" );
todos.add( todo );
}
{
// Canned food todo list
final LatLon location = new LatLon();
location.latitude = 40.743611111111115;
location.longitude = -73.99591666666667;
final TodoList todo = new TodoList( "supermarket", location );
todo.addItem( "eggs" );
todo.addItem( "milk" );
todo.addItem( "bread" );
todo.addItem( "cake" );
todo.addItem( "more cake" );
todos.add( todo );
// make this the default list for now
currentTodoList = todo;
}
}
private void saveTodos() {
// TODO: save todo lists to file (put them in a serializable object? or be clean and use XML?)
}
/**
* Start ourselves up.
*
* @param display handle to the display service so we can make our UI
* @param position handle to the position service (GPS)
*/
public void start(IModuleDisplay display, IPositionProvider position) {
this.display = display;
this.position = position;
System.out.println( "todo: app starting" );
createUI();
update();
frame.show();
// Set up our timer to fire every PERIOD ms and call our update method.
timer.schedule( new TimerTask() {
public void run() {
MyApplication.this.update();
}
}, 0, PERIOD );
System.out.println( "todo: app started" );
}
/**
* Shut ourselves down.
*/
public void stop() {
System.out.println( "todo: app stopping" );
// make sure we don't try and update again
timer.cancel();
saveTodos();
// get rid of our UI
frame.dispose();
System.out.println( "todo: app stopped" );
}
/**
* Build our ugly UI.
*/
private void createUI() {
frame = display.getFrame();
frame.removeAll();
// build menu
final Menu menu = new Menu( "Choose a Todo List" );
// special item that means the todo list for the nearest location
final MenuItem nearest = new MenuItem( NEAREST );
nearest.addActionListener(new ActionListener() {
public void actionPerformed( ActionEvent e ) {
MyApplication.this.chooseNearest = true;
}
});
menu.add( nearest );
menu.addSeparator();
final Iterator iter = todos.iterator();
while ( iter.hasNext() ) {
final TodoList todoList = (TodoList) iter.next();
final MenuItem menuItem = new MenuItem( todoList.getName() );
menuItem.addActionListener(new ActionListener() {
public void actionPerformed( ActionEvent e ) {
MyApplication.this.setTodoList( ( (MenuItem) e.getSource() ).getLabel() );
}
});
menu.add( menuItem );
}
final MenuBar menuBar = new MenuBar();
menuBar.add( menu );
frame.setMenuBar( menuBar );
frame.setLayout( new BorderLayout() );
final Panel info = new Panel();
info.setLayout( new BorderLayout() );
currentTodoName = new Label();
info.add( currentTodoName, BorderLayout.CENTER );
currentTodoDistance = new Label();
info.add( currentTodoDistance, BorderLayout.EAST );
frame.add( info, BorderLayout.NORTH );
items = new java.awt.List();
frame.add( items, BorderLayout.CENTER );
}
// can be called from timer or by user choosing menu item, so sync it
private synchronized void updateUI() {
if ( lastTodoList != currentTodoList ) {
System.out.println( "Updating UI for new list " +
currentTodoList.getName() + " with " +
currentTodoList.getItems().size() + " items." );
// we've just switched lists, so update the list contents too
items.removeAll();
final Iterator iter = currentTodoList.getItems().iterator();
while ( iter.hasNext() ) {
final String item = (String) iter.next();
items.add( item );
}
lastTodoList = currentTodoList;
}
// always update the name (in case the user switched to/from nearest
// but ended up on the same todo list, in which case we want to add/remove
// the " (Nearest)"
currentTodoName.setText( currentTodoList.getName() +
( chooseNearest ? " (Nearest)" : "" ));
// always update the distance
final String distance;
if (currentLocation != null) {
distance = distanceFormat.format(
PositionHelper.kilometersToMiles(
PositionHelper.calculateDistance(
currentTodoList.getLocation(),
currentLocation )));
} else {
distance = "?";
}
currentTodoDistance.setText( distance + " miles");
System.out.println("Distance now " + distance);
}
/**
* Our callback when our update timer fires. We
* need to get our current position and update our UI.
*/
private void update() {
System.out.println( "todo: updating" );
// save where we are now
currentLocation = position.getLatitudeLongitude();
if (currentLocation != null) {
System.out.println( "current lat:" + currentLocation.latitude );
System.out.println( "current lon:" + currentLocation.longitude );
if ( chooseNearest ) {
updateCurrentTodoList();
}
updateUI();
}
}
private void updateCurrentTodoList() {
if (currentLocation != null) {
lastTodoList = currentTodoList;
// save how far we are from the current todo list
double currentDistance = PositionHelper.calculateDistance(
currentTodoList.getLocation(),
currentLocation);
// update closest todo
final Iterator iter = todos.iterator();
while ( iter.hasNext() ) {
final TodoList todoList = (TodoList) iter.next();
final double distance = PositionHelper.calculateDistance(
todoList.getLocation(),
currentLocation);
System.out.println("Distance to " + todoList.getName() + ": " + distance);
if ( distance < currentDistance ) {
System.out.println( "Switching to " + todoList.getName() );
currentDistance = distance;
currentTodoList = todoList;
}
}
}
}
private TodoList findTodoList( final String name ) {
final Iterator iter = todos.iterator();
while ( iter.hasNext() ) {
final TodoList todoList = (TodoList) iter.next();
if ( todoList.getName().equals( name ) ) {
return todoList;
}
}
return null;
}
private void setTodoList( final String name ) {
final TodoList todoList = findTodoList( name );
if ( todoList != null ) {
System.out.println( "Manually switching to " + name );
chooseNearest = false;
currentTodoList = todoList;
updateUI();
}
}
}