package lejos.util; import lejos.nxt.Button; import lejos.nxt.LCD; /** *Displays a list of items. The select() method allows the user to scroll the list using the right and left keys to scroll forward and backward * through the list. The location of the list , and an optional title can be specified. * @author Roger Glassey Feb 20, 2007 */ public class TextMenu { /** * index of the list item at the top of the list; set by constructor, used by select() **/ private int _topIndex = 0; /** * index of the currently selected item; updated by select() used by display(); */ private int _selectedIndex = 0; /** * number of rows displayed; set by constructor, used by display() */ private int _size = 8; /** *location of the top row of the list; set by constructor, used by display() */ private int _topRow = 0; /** *array of items to be displayed ;set by constructor, used by select(); */ private String [] _items; /** *identifies the currently selected item */ private String _selChar = ">"; /** * a blank line */ public static String blank = " "; /** *optional menu title displayed immediately above the list of items */ private String _title; /** * boolean to cause select to quit */ private boolean _quit = false; /** * effective length of items array - number of items before null */ private int _length; /** * startb time for select() */ private int _startTime; /** * This constructor sets location of the top row of the item list to row 0 of the display. */ public TextMenu( String[] items) { this.setItems(items); } /** * This constructor allows specification location of the item list . */ public TextMenu( String[] items, int topRow) { _topRow = topRow; this.setItems(items); } /** * This constuctor allows the specfication of a title (of up to 16 characters) and the location of the item list <br> * The title is displayed in the row above the item list. * @param items - string array containing the menu items. No items beyond the first null will be displayed. */ public TextMenu(String[] items, int topRow, String title) { _topRow = topRow; setTitle(title); this.setItems(items); } /** * set menu title. * @param title the new title */ public void setTitle(String title) { _title = title; if(_topRow == 0)_topRow = 1; if(_length <= 8)_size = _length; if(_size > 8 - _topRow) _size = 8 - _topRow; } /** * set the array of items to be displayed * @param items */ public void setItems(String[] items) { _items = items; if(items == null) return; int i = 0; while(i < items.length && items[i] != null)i++; _length = i; _size = _length; if(_size > 8 - _topRow) _size = 8 - _topRow; _quit = false; _topIndex = 0; } /** * Allows the user to scroll through the items, using the right and left buttons (forward and back) The Enter key closes the menu <br> * and returns the index of the selected item. <br> * The menu display wraps items that scroll off the top will reappear on the bottom and vice versa. * * The selectedIndex is set to the first menu item. * * @return the index of the selected item **/ public int select() { return select(0,0); } /** * Version of select without timeout */ public int select(int selectedIndex) { return select(selectedIndex, 0); } /** * Allows the user to scroll through the items, using the right and left buttons (forward and back) The Enter key closes the menu <br> * and returns the index of the selected item. <br> * The menu display wraps items that scroll off the top will reappear on the bottom and vice versa. * * This version of select allows the selected index to be set when the menu is first displayed. * * @param selectedIndex the index to start the menu on * @return the index of the selected item **/ public int select(int selectedIndex, int timeout) { _selectedIndex = selectedIndex; // if (_length<_size) _size = _length; int button = 0; _quit = false; resetTimeout(); // LCD.clear(); display(); while(!_quit) { while(Button.readButtons()>0 && !_quit)Thread.yield();// wait for release while(Button.readButtons()==0 && !_quit) { if (timeout > 0 && ((int) System.currentTimeMillis())- _startTime >= timeout) return -3; // timeout Thread.yield(); } if (_quit) return -2; // quit by another thread Delay.msDelay(20); button=Button.readButtons(); if(button == 1) return _selectedIndex; if(button == 8) return -1; //Escape if(button == 4)//scroll forward { _selectedIndex ++; // check for index out of bounds if(_selectedIndex >= _length) _selectedIndex -= _length; int diff = _selectedIndex - _topIndex; if(diff < 0)diff += _length; if(diff >= _size) _topIndex = 1+ _selectedIndex - _size; } if(button == 2)//scroll backward { _selectedIndex --; // check for index out of bounds if(_selectedIndex < 0) _selectedIndex += _length; int diff = _selectedIndex - _topIndex; if(diff > _length) diff -= _length; if(diff < 0 || diff >= _size)_topIndex = _selectedIndex; } display(); } return -2; } /** * method to call from another thread to quit the menu */ public void quit() { _quit = true; } /** * helper method used by select() */ private void display() { if(_title != null)LCD.drawString(_title,0,_topRow-1); for (int i = 0;i<_size;i++) { LCD.drawString(blank,0,i + _topRow); int indx = index(i); if(_items[indx] !=null) { LCD.drawString(_items[indx],1,i + _topRow); if(indx == _selectedIndex) LCD.drawString(_selChar,0,i + _topRow); } else LCD.drawString(blank,0,i + _topRow); } // clear to bottom of screen for (int i = _size + _topRow; i<8; i++) LCD.drawString(blank,0,i); LCD.refresh(); } /** * helper method used by display() to calculate the index in the items array corresponding to a row of the * menu display */ private int index(int row) { return (_topIndex + row + _length)%_length; } /** * returns list of items in this menu; * @return the array of item names */ public String[] getItems() { return _items; } /** * Reset the timeout period. */ public void resetTimeout() { _startTime = (int) System.currentTimeMillis(); } }