Mega Code Archive

 
Categories / Java / J2ME
 

Todo MIDlet

/*-------------------------------------------------- * TodoMIDlet.java * * The main class for todo list MIDlet * * Example from the book:     Core J2ME Technology * Copyright John W. Muchow   http://www.CoreJ2ME.com * You may use/modify for any non-commercial purpose *-------------------------------------------------*/ import java.io.*; import java.util.*; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import javax.microedition.rms.*; public class TodoMIDlet extends MIDlet implements ItemStateListener, CommandListener {   private Display display;      // Our display   private Form fmMain;         // Main Form   private FormAdd fmAdd;       // Form to add todo item   private Command cmAdd,       // Command to add todo                   cmPrefs,     // Command to set preferences                   cmExit;      // Command to exit   private Vector vecTodo;       // The "master" list of todo items   private ChoiceGroup cgTodo;  // Todo items (read from vecTodo)   protected DisplayManager displayMgr;  // Class to help manage screens   //-------------------------------------------------   // Record Stores. One for todo, one for preferences   //-------------------------------------------------   private RecordStore rsTodo;   private RecordStore rsPref;   private static final String REC_STORE_TODO = "TodoList";   private static final String REC_STORE_PREF = "TodoPrefs";   private boolean flagSortByPriority = false, // Sort by priority?                   flagShowPriority = true;    // Show priorities ?   //-------------------------------------------------   // Re-use these input streams throughout the MIDlet   //-------------------------------------------------   // Read from a specified byte array   private ByteArrayInputStream istrmBytes = null;   // Read Java data types from the above byte array   private DataInputStream istrmDataType = null;   // If you change length of a todo entry, bump this   byte[] recData = new byte[25];   //-------------------------------------------------   // Re-use these output streams throughout the MIDlet   //-------------------------------------------------   // Write data into an internal byte array   ByteArrayOutputStream ostrmBytes = null;   // Write Java data types into the above byte array   DataOutputStream ostrmDataType = null;   //-------------------------------------------------   // Record Enumerator and compare class   //-------------------------------------------------   private RecordEnumeration e = null;   private ComparatorInt comp = null;   /*--------------------------------------------------   * MIDlet constructor.   *-------------------------------------------------*/   public TodoMIDlet()   {     display = Display.getDisplay(this);     // Create 'main' and 'add todo item' forms     // Form for setting prefs is in commandAction()     fmMain = new Form("Todo List");     fmAdd = new FormAdd("Add Todo", this);     // Todo list and vector     cgTodo = new ChoiceGroup("", Choice.MULTIPLE);     vecTodo = new Vector();     // Commands     cmAdd = new Command("Add Todo", Command.SCREEN, 2);     cmPrefs = new Command("Preferences", Command.SCREEN, 3);     cmExit = new Command("Exit", Command.EXIT, 1);     // Add all to form and listen for events     fmMain.addCommand(cmAdd);     fmMain.addCommand(cmPrefs);     fmMain.addCommand(cmExit);     fmMain.append(cgTodo);     fmMain.setCommandListener(this);     fmMain.setItemStateListener(this);     // Create a display manager object     displayMgr = new DisplayManager(display, fmMain);     // Open/create the record stores     rsTodo = openRecStore(REC_STORE_TODO);     rsPref = openRecStore(REC_STORE_PREF);     // Initialize the streams     initInputStreams();     initOutputStreams();     // Read preferences from rms     refreshPreferences();     // Initialize the enumeration for todo rms     initEnumeration();    // Read rms into vector     writeRMS2Vector();     // Build the todo list (choice group)     rebuildTodoList();   }   /*--------------------------------------------------   * Show the main Form   *-------------------------------------------------*/   public void startApp ()   {     display.setCurrent(fmMain);   }   /*--------------------------------------------------   * Shutting down. Cleanup all we created   *-------------------------------------------------*/   public void destroyApp (boolean unconditional)   {     // Cleanup for enumerator     if (comp != null)       comp.compareIntClose();     if (e != null)       e.destroy();     // Cleanup streams     try     {       if (istrmDataType != null)         istrmDataType.close();       if (istrmBytes != null)         istrmBytes.close();       if (ostrmDataType != null)         ostrmDataType.close();       if (ostrmBytes != null)         ostrmBytes.close();     }     catch (Exception e)     {       db(e.toString());     }     // Cleanup rms     closeRecStore(rsTodo);     closeRecStore(rsPref);   }   /*--------------------------------------------------   * No pause code necessary   *-------------------------------------------------*/   public void pauseApp ()   { }   /*--------------------------------------------------   * Open input streams   *-------------------------------------------------*/   private void initInputStreams()   {     istrmBytes = new ByteArrayInputStream(recData);     istrmDataType = new DataInputStream(istrmBytes);   }   /*--------------------------------------------------   * Open output streams   *-------------------------------------------------*/   private void initOutputStreams()   {     ostrmBytes = new ByteArrayOutputStream();     ostrmDataType = new DataOutputStream(ostrmBytes);   }   /*--------------------------------------------------   * Initialize enumeration for todo rms   *-------------------------------------------------*/   private void initEnumeration()   {     // Are we to bother with sorting?     if (flagSortByPriority)       comp = new ComparatorInt();     else       // We must set this to null to clear out       // any previous setting       comp = null;     try     {       e = rsTodo.enumerateRecords(null, comp, false);     }     catch (Exception e)     {       db(e.toString());     }   }   /*--------------------------------------------------   * Open a record store   *-------------------------------------------------*/   private RecordStore openRecStore(String name)   {     try     {       // Open the Record Store, creating it if necessary       return RecordStore.openRecordStore(name, true);     }     catch (Exception e)     {       db(e.toString());       return null;     }   }   /*--------------------------------------------------   * Close a record store   *-------------------------------------------------*/   private void closeRecStore(RecordStore rs)   {     try     {       rs.closeRecordStore();     }     catch (Exception e)     {       db(e.toString());     }   }   /*--------------------------------------------------   * Delete a record store   *-------------------------------------------------*/   private void deleteRecStore(String name)   {     try     {       RecordStore.deleteRecordStore(name);     }     catch (Exception e)     {       db(e.toString());     }   }   /*--------------------------------------------------   * Write new todo item   *   - Write a new record into the rms   *   - Write a new item into the vector   *   - Recreate the vector from the rms (which will   *     use the proper sort (using rms enumeration)   *   - Rebuild todo list from vector   *-------------------------------------------------*/   protected void addTodoItem(int priority, String text)   {     try     {       // Toss any data in the internal array so writes       // starts at beginning (of the internal array)       ostrmBytes.reset();       // Write priority and todo text       ostrmDataType.writeInt(priority);       ostrmDataType.writeUTF(text);       // Clear any buffered data       ostrmDataType.flush();       // Get stream data into byte array and write record       byte[] record = ostrmBytes.toByteArray();       int recordId = rsTodo.addRecord(record, 0, record.length);       // Create a new Todo item and insert it into our Vector       TodoItem item = new TodoItem(priority, text, recordId);       vecTodo.addElement(item);            }     catch (Exception e)     {       db(e.toString());     }     // Read rms into vector     writeRMS2Vector();     // Rebuild todo list     rebuildTodoList();   }   /*--------------------------------------------------   * Save preferences to record store   *-------------------------------------------------*/   protected void savePreferences(boolean sort, boolean showSort)   {     // No changes we made     if (sort == flagSortByPriority && showSort == flagShowPriority)       return;     // Save the current sort status     boolean previouslySorted = flagSortByPriority;     boolean previouslyShowPriority = flagShowPriority;     try     {       // Update prefs in private variables       flagSortByPriority = sort;       flagShowPriority = showSort;       // Toss any data in the internal array so writes       // starts at beginning (of the internal array)       ostrmBytes.reset();       // Write the sort order and keep completed flags       ostrmDataType.writeBoolean(flagSortByPriority);       ostrmDataType.writeBoolean(flagShowPriority);       // Clear any buffered data       ostrmDataType.flush();       // Get stream data into byte array and write record       byte[] record = ostrmBytes.toByteArray();       // Always write preferences at first record       // We cannot request to set the first record unless       // the record store has contents.       // If empty => add a record       // If not   => overwrite the first record       if (rsPref.getNumRecords() == 0)         rsPref.addRecord(record, 0, record.length);       else         rsPref.setRecord(1, record, 0, record.length);     }     catch (Exception e)     {       db(e.toString());     }     // If the sort order was changed, rebuild enumeration     if (previouslySorted != flagSortByPriority)       initEnumeration();     // If we are going from non-sorted to sorted     // or changing whether or not to show priority      // then we must update what's currently displayed     if ((!previouslySorted && flagSortByPriority) ||         (previouslyShowPriority != flagShowPriority))     {       // Read rms into vector       writeRMS2Vector();              // Rebuild todo list       rebuildTodoList();     }   }   /*--------------------------------------------------   * Read preferences from record store   *-------------------------------------------------*/   private void refreshPreferences()   {     try     {       // Record store is empty       if (rsPref.getNumRecords() == 0)       {         // Write into the store the default preferences         savePreferences(flagSortByPriority, flagShowPriority);         return;       }       // Reset input back to the beginning       istrmBytes.reset();       // Read configuration data stored in the first record       rsPref.getRecord(1, recData, 0);       flagSortByPriority = istrmDataType.readBoolean();       flagShowPriority = istrmDataType.readBoolean();       System.out.println("Sort: " + flagSortByPriority);       System.out.println("Show: " + flagShowPriority);     }     catch (Exception e)     {       db(e.toString());     }   }   /*--------------------------------------------------   * Create the vector from record store contents   *-------------------------------------------------*/   private void writeRMS2Vector()   {     // Cleanout the vector     vecTodo.removeAllElements();     try     {       // Rebuild enumeration for any changes       e.rebuild();       while (e.hasNextElement())       {         // Reset input back to the beginning         istrmBytes.reset();         // Get data into the byte array         int id = e.nextRecordId();         rsTodo.getRecord(id, recData, 0);         // Create a new Todo item and insert it into our Vector         TodoItem item = new TodoItem(istrmDataType.readInt(), istrmDataType.readUTF(), id);         vecTodo.addElement(item);       }     }     catch (Exception e)     {       db(e.toString());     }   }   /*--------------------------------------------------   * Store the current vector contents to the rms   *-------------------------------------------------*/   private void writeVector2RMS()   {     try     {       byte[] record;       for (int i = 0; i < vecTodo.size(); i++)       {         TodoItem item = (TodoItem) vecTodo.elementAt(i);         int priority = item.getPriority();         String text = item.getText();         // Toss any data in the internal array so writes         // starts at beginning (of the internal array)         ostrmBytes.reset();         // Write priority and todo text         ostrmDataType.writeInt(priority);         ostrmDataType.writeUTF(text);         // Clear any buffered data         ostrmDataType.flush();         // Get stream data into byte array and write record         record = ostrmBytes.toByteArray();         rsTodo.addRecord(record, 0, record.length);       }     }     catch (Exception e)     {       db(e.toString());     }   }   /*--------------------------------------------------   * Rebuild todo list (ChoiceGroup) from the Vector   *-------------------------------------------------*/   protected void rebuildTodoList()   {     // Clear out the ChoiceGroup.     for (int i = cgTodo.size(); i > 0; i--)       cgTodo.delete(i - 1);     TodoItem item;     int priority;     String text;     StringBuffer strb;     for (int i = 0; i < vecTodo.size(); i++)     {       // Get a todo item from vector       item = (TodoItem) vecTodo.elementAt(i);       // Read values from todoitem class       priority = item.getPriority();       text = item.getText();       // Are we are to show priority as part of the text?       strb = new StringBuffer((flagShowPriority ? (Integer.toString(priority) + "-"): ""));       strb.append(text);       // Append to todo choicegroup       cgTodo.append(strb.toString(), null);     }   }   /*--------------------------------------------------   * This method is called when a todo item has been   * selected in the choicegroup. We treat this as   * a request to delete the item   *-------------------------------------------------*/   public void itemStateChanged(Item item)   {     ChoiceGroup cg;     // Cast the item to a ChoiceGroup type     cg = (ChoiceGroup) item;     // Create an array that mirrors the ChoiceGroup     // and populate with those items selected     boolean selected[] = new boolean[cg.size()];     cg.getSelectedFlags(selected);     // Unfortunately, there is no (easy) way to determine     // which item in the choiceGroup was "clicked" to     // initiate this event. The best we can do is look at     // each entry and determine its current selection state     // For each element, see if it is selected     // If so, delete it. Once we have found a selected     // item, we can exit - there will never be more than     // one item selected at any time     for (int i = 0; i < cg.size(); i++)     {       if (selected[i])       {         // Get the record id from the todoItem          // and delete record from rms         TodoItem todoitem = (TodoItem) vecTodo.elementAt(i);         try         {           rsTodo.deleteRecord(todoitem.getRecordId());         }         catch (Exception e)         {           db(e.toString());         }                  break;       }     }        // Read rms into vector     writeRMS2Vector();            // Rebuild todo list     rebuildTodoList();   }   /*--------------------------------------------------   * Process events for the main form   *-------------------------------------------------*/   public void commandAction(Command c, Displayable d)   {     if (c == cmExit)     {       destroyApp(false);       notifyDestroyed();     }     else     {       if (c == cmAdd)       {         // Reset the textfield and choicegroup         // on the 'add todo' form         fmAdd.tfTodo.setString("");         fmAdd.cgPriority.setSelectedIndex(0, true);         // Push current displayable and activate 'add todo' form         displayMgr.pushDisplayable(fmAdd);       }       else if (c == cmPrefs)       {         boolean flags[] = {flagSortByPriority, flagShowPriority};         // Push current displayable and show preferences form          // passing in current preference settings                 displayMgr.pushDisplayable(new FormPrefs("Preferences", this, flags));       }     }   }   /*--------------------------------------------------   * Simple message to console for debug/errors   *-------------------------------------------------*/   private void db(String str)   {     System.err.println("Msg: " + str);   } } /*-------------------------------------------------- * Use a stack to push and pop displayable objects * * public void pushDisplayable(Displayable) * public void popDisplayable() * public void home()   * * Example from the book:     Core J2ME Technology * Copyright John W. Muchow   http://www.CoreJ2ME.com * You may use/modify for any non-commercial purpose *-------------------------------------------------*/ class DisplayManager extends Stack {   private Display display;      // Reference to Display object   private Displayable mainDisplayable; // Main displayable for MIDlet   private Alert alStackError;  // Alert for error conditions   /*--------------------------------------------------   * Display manager constructor   *-------------------------------------------------*/   public DisplayManager(Display display, Displayable mainDisplayable)   {     // Only one display object per midlet, this is it     this.display = display;     this.mainDisplayable = mainDisplayable;          // Create an alert displayed when an error occurs     alStackError = new Alert("Displayable Stack Error");     alStackError.setTimeout(Alert.FOREVER);  // Modal   }   /*--------------------------------------------------   * Push the current displayable onto stack and set   * the passed in displayable as active   *-------------------------------------------------*/   public void pushDisplayable(Displayable newDisplayable)   {     push(display.getCurrent());     display.setCurrent(newDisplayable);   }   /*--------------------------------------------------   * Return to the main displayable object of MIDlet   *-------------------------------------------------*/   public void home()   {     while (elementCount > 1)       pop();     display.setCurrent(mainDisplayable);   }      /*--------------------------------------------------   * Pop displayable from stack and set as active   *-------------------------------------------------*/   public void popDisplayable()   {     // If the stack is not empty, pop next displayable     if (empty() == false)       display.setCurrent((Displayable) pop());     else       // On error show an alert       // Once acknowldeged, set 'mainDisplayable' as active       display.setCurrent(alStackError, mainDisplayable);   } } /*-------------------------------------------------- * FormAdd.java * * Form for adding new todoitems * Supporting class for TodoMIDlet * * Example from the book:     Core J2ME Technology * Copyright John W. Muchow   http://www.CoreJ2ME.com * You may use/modify for any non-commercial purpose *-------------------------------------------------*/ class FormAdd extends Form implements CommandListener {   private Command cmBack,                   cmSave;   protected TextField tfTodo;   protected ChoiceGroup cgPriority;   private TodoMIDlet midlet;   public FormAdd(String title, TodoMIDlet midlet)   {     // Call the Form constructor     super(title);     // Save reference to MIDlet so we can access     // the display manager class and rms     this.midlet = midlet;     // Commands     cmSave = new Command("Save", Command.SCREEN, 1);     cmBack = new Command("Back", Command.BACK, 2);     // Create textfield for entering todo items     tfTodo = new TextField("Todo", null, 15, TextField.ANY);     // Create choicegroup and append options (no images)     cgPriority = new ChoiceGroup("Priority", Choice.EXCLUSIVE);     cgPriority.append("Today", null);     cgPriority.append("Tomorrow", null);     cgPriority.append("This Week", null);     cgPriority.append("This Month", null);     cgPriority.append("Someday", null);     // Add stuff to form and listen for events     addCommand(cmSave);     addCommand(cmBack);     append(tfTodo);     append(cgPriority);     setCommandListener(this);   }   public void commandAction(Command c, Displayable s)   {     if (c == cmSave)     {       // Add a new todo item       // Notice we bump priority by 1. This is because the        // choicegroup entries start at zero. We would like        // the records in the rms to store priorities starting       // at 1. Thus, if a user requests to display priorities        // on the todo list, the highest priority is 1 (not zero)       midlet.addTodoItem(cgPriority.getSelectedIndex() + 1,                      tfTodo.getString());     }     // Any other event and we go back to the main form...     // Pop the last displayable off the stack     midlet.displayMgr.popDisplayable();   } } /*-------------------------------------------------- * ComparatorInt.java * * Sorts rms records based on todo item priority * Provides compare() method for RecordEnumerator * Supporting class for TodoMIDlet * * Example from the book:     Core J2ME Technology * Copyright John W. Muchow   http://www.CoreJ2ME.com * You may use/modify for any non-commercial purpose *-------------------------------------------------*/ class ComparatorInt implements RecordComparator {   private byte[] record = new byte[10];   // Read from a specified byte array   private ByteArrayInputStream strmBytes = null;   // Read Java data types from the above byte array   private DataInputStream strmDataType = null;   public void compareIntClose()   {     try     {       if (strmBytes != null)         strmBytes.close();       if (strmDataType != null)         strmDataType.close();     }     catch (Exception e)     {}   }   public int compare(byte[] rec1, byte[] rec2)   {     int x1, x2;     try     {       // If either record is larger than our buffer, reallocate       int maxsize = Math.max(rec1.length, rec2.length);       if (maxsize > record.length)         record = new byte[maxsize];       // Read record #1       // We want the priority which is first "field"       strmBytes = new ByteArrayInputStream(rec1);       strmDataType = new DataInputStream(strmBytes);       x1 = strmDataType.readInt();       // Read record #2       strmBytes = new ByteArrayInputStream(rec2);       strmDataType = new DataInputStream(strmBytes);       x2 = strmDataType.readInt();       // Compare record #1 and #2       if (x1 == x2)         return RecordComparator.EQUIVALENT;       else if (x1 < x2)         return RecordComparator.PRECEDES;       else         return RecordComparator.FOLLOWS;     }     catch (Exception e)     {       return RecordComparator.EQUIVALENT;     }   } }   /*-------------------------------------------------- * TodoItem.java * * Holds data/methods for a single todo item * Supporting class for todoMIDlet * * Example from the book:     Core J2ME Technology * Copyright John W. Muchow   http://www.CoreJ2ME.com * You may use/modify for any non-commercial purpose *-------------------------------------------------*/ class TodoItem {   private int priority;   private String text;   private int recordId;   public TodoItem(int priority, String text, int recordId)   {     this.priority = priority;     this.text = text;     this.recordId = recordId;   }   public int getPriority()   {     return priority;   }   public void setPriority(int priority)   {     this.priority = priority;   }   public String getText()   {     return text;   }   public void setText(String text)   {     this.text = text;   }      public int getRecordId()   {     return recordId;   } }   /*-------------------------------------------------- * FormPrefs.java * * Form for specifying user preferences * Supporting class for TodoMIDlet * * Example from the book:     Core J2ME Technology * Copyright John W. Muchow   http://www.CoreJ2ME.com * You may use/modify for any non-commercial purpose *-------------------------------------------------*/ class FormPrefs extends Form implements CommandListener {   private Command cmBack,                   cmSave;   private TodoMIDlet midlet;   private ChoiceGroup cgPrefs;   public FormPrefs(String title, TodoMIDlet midlet, boolean flags[])   {     // Call the Form constructor     super(title);     // Save reference to MIDlet so we can access     // the display manager class and rms     this.midlet = midlet;     // Commands     cmSave = new Command("Save", Command.SCREEN, 1);     cmBack = new Command("Back", Command.BACK, 2);     // Choicegroup for sort order and showing priority     cgPrefs = new ChoiceGroup("Preferences", Choice.MULTIPLE);     cgPrefs.append("Sort by Priority", null);     cgPrefs.append("Show Priority", null);     // Set the current status of each entry     cgPrefs.setSelectedFlags(flags);     // Add to form and listen for events     append(cgPrefs);     addCommand(cmBack);     addCommand(cmSave);     setCommandListener(this);   }   public void commandAction(Command c, Displayable s)   {     if (c == cmSave)     {       // Save the preferences       midlet.savePreferences(cgPrefs.isSelected(0),                              cgPrefs.isSelected(1));     }     // Any other event and we go back to the main form...     // Pop the last displayable off the stack     midlet.displayMgr.popDisplayable();   } }