diff --git a/libraries/FreetronicsLCD/BoolField.cpp b/libraries/FreetronicsLCD/BoolField.cpp index 4cf1dc40..defa9149 100644 --- a/libraries/FreetronicsLCD/BoolField.cpp +++ b/libraries/FreetronicsLCD/BoolField.cpp @@ -59,7 +59,9 @@ * Use TextField for read-only fields that report boolean values but * which are not modifiable by the user. * - * \sa Field, TextField + * ListField can be used to select between more than two items. + * + * \sa Field, ListField, TextField */ /** diff --git a/libraries/FreetronicsLCD/Field.cpp b/libraries/FreetronicsLCD/Field.cpp index cdcc449a..c28878c5 100644 --- a/libraries/FreetronicsLCD/Field.cpp +++ b/libraries/FreetronicsLCD/Field.cpp @@ -26,7 +26,7 @@ * \class Field Field.h * \brief Manages a single data input/output field within a Form. * - * \sa Form, BoolField, IntField, TextField, TimeField + * \sa Form, BoolField, IntField, ListField, TextField, TimeField */ /** diff --git a/libraries/FreetronicsLCD/ListField.cpp b/libraries/FreetronicsLCD/ListField.cpp new file mode 100644 index 00000000..04400ba3 --- /dev/null +++ b/libraries/FreetronicsLCD/ListField.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2012 Southern Storm Software, Pty Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "ListField.h" +#include + +/** + * \class ListField ListField.h + * \brief Field that manages selection from a static list of items. + * + * ListField is intended for selecting an element from a list of items. + * Each items is represented by a string within program memory, with the + * list terminated by null. For example: + * + * \code + * const char item_Eggs[] PROGMEM = "Eggs"; + * const char item_Cheese[] PROGMEM = "Cheese"; + * const char item_Pumpkin[] PROGMEM = "Pumpkin"; + * ListItem const ingredients[] PROGMEM = { + * item_Eggs, + * item_Cheese, + * item_Pumpkin, + * 0 + * }; + * + * Form mainForm(lcd); + * ListField ingredient(mainForm, "Select ingredient", ingredients); + * \endcode + * + * If there are only two items in the list, then BoolField can be used instead. + * + * \sa Field, BoolField + */ + +/** + * \brief Constructs a new list field with a specific \a label. + * + * The field is initially not associated with a Form. The field can be + * added to a form later using Form::addField(). + * + * Initially, items() is null and value() is -1. + * + * \sa Form::addField() + */ +ListField::ListField(const String &label) + : Field(label) + , _items(0) + , _itemCount(0) + , _value(-1) + , _printLen(0) +{ +} + +/** + * \brief Constructs a new list field with a specific \a label, + * list of \a items, and \a value, and attaches it to a \a form. + */ +ListField::ListField(Form &form, const String &label, ListItems items, int value) + : Field(form, label) + , _items(0) + , _itemCount(0) + , _value(value) + , _printLen(0) +{ + setItems(items); +} + +int ListField::dispatch(int event) +{ + if (event == LCD_BUTTON_DOWN) { + if (_value >= (_itemCount - 1)) + setValue(0); + else + setValue(_value + 1); + return FORM_CHANGED; + } else if (event == LCD_BUTTON_UP) { + if (_value <= 0) + setValue(_itemCount - 1); + else + setValue(_value - 1); + return FORM_CHANGED; + } + return -1; +} + +void ListField::enterField(bool reverse) +{ + Field::enterField(reverse); + _printLen = 0; + printValue(); +} + +/** + * \fn ListItems ListField::items() const + * \brief Returns the array of items in this list. + * + * \sa setItems() + */ + +/** + * \brief Sets the array of \a items for this list. + * + * The \a items must be stored within program memory and terminated by null; + * for example: + * + * \code + * const char item_Eggs[] PROGMEM = "Eggs"; + * const char item_Cheese[] PROGMEM = "Cheese"; + * const char item_Pumpkin[] PROGMEM = "Pumpkin"; + * ListItem const ingredients[] PROGMEM = { + * item_Eggs, + * item_Cheese, + * item_Pumpkin, + * 0 + * }; + * + * list.setItems(ingredients); + * \endcode + * + * \sa items() + */ +void ListField::setItems(ListItems items) +{ + _items = items; + _itemCount = 0; + if (items) { + for (;;) { + ListItem item = (ListItem)pgm_read_word(items); + if (!item) + break; + ++items; + ++_itemCount; + } + } + if (_value >= _itemCount) + _value = _itemCount - 1; + if (isCurrent()) + printValue(); +} + +/** + * \fn int ListField::value() const + * \brief Returns the value of this list; i.e. the index within items() of the + * selected item. + * + * Returns -1 if the items() array is empty or null. + * + * \sa setValue(), items() + */ + +/** + * \brief Sets the \a value of this list; i.e. the index within items() of the + * selected item. + * + * The \a value will be clamped to the range of items(). + * + * \sa value(), items() + */ +void ListField::setValue(int value) +{ + if (_value != value) { + _value = value; + if (_value < 0) + _value = 0; + if (_value >= _itemCount) + _value = _itemCount - 1; + if (isCurrent()) + printValue(); + } +} + +void ListField::printValue() +{ + lcd()->setCursor(0, 1); + int len = 0; + if (_value >= 0) { + ListItem str = (ListItem)pgm_read_word(&(_items[_value])); + char ch; + while ((ch = pgm_read_byte(str)) != 0) { + lcd()->write(ch); + ++len; + ++str; + } + } + while (_printLen-- > len) + lcd()->write(' '); + _printLen = len; +} diff --git a/libraries/FreetronicsLCD/ListField.h b/libraries/FreetronicsLCD/ListField.h new file mode 100644 index 00000000..a959be95 --- /dev/null +++ b/libraries/FreetronicsLCD/ListField.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 Southern Storm Software, Pty Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef ListField_h +#define ListField_h + +#include "Field.h" +#include + +typedef const prog_char *ListItem; +typedef const PROGMEM ListItem *ListItems; + +class ListField : public Field { +public: + explicit ListField(const String &label); + ListField(Form &form, const String &label, ListItems items, int value = 0); + + int dispatch(int event); + + void enterField(bool reverse); + + ListItems items() const { return _items; } + void setItems(ListItems items); + + int value() const { return _value; } + void setValue(int value); + +private: + ListItems _items; + int _itemCount; + int _value; + int _printLen; + + void printValue(); +}; + +#endif