1
0
mirror of https://github.com/taigrr/arduinolibs synced 2025-01-18 04:33:12 -08:00

Add ListField for selecting from a string list

This commit is contained in:
Rhys Weatherley 2012-05-23 14:26:17 +10:00
parent ad3f892430
commit 23c98820f7
4 changed files with 267 additions and 2 deletions

View File

@ -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
*/
/**

View File

@ -26,7 +26,7 @@
* \class Field Field.h <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
*/
/**

View File

@ -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 <string.h>
/**
* \class ListField ListField.h <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;
}

View File

@ -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 <avr/pgmspace.h>
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