Subversion Repositories RTK

Compare Revisions

Ignore whitespace Rev 412 → Rev 413

/trunk/!RTK/rtk/desktop/selection_field.h
New file
0,0 → 1,183
// This file is part of the RISC OS Toolkit (RTK).
// Copyright © 2007 Graham Shaw.
// Distribution and use are subject to the GNU Lesser General Public License,
// a copy of which may be found in the file !RTK.Copyright.
 
#ifndef _RTK_DESKTOP_SELECTION_FIELD
#define _RTK_DESKTOP_SELECTION_FIELD
 
#include "rtk/util/lexical_cast.h"
#include "rtk/desktop/writable_field.h"
#include "rtk/events/arrow_click.h"
 
namespace rtk {
namespace desktop {
 
/** A class to represent a field for selecting a member of a sequence.
* The sequence is specified in the usual manner by a pair of iterators.
* These may be provided by a standard container or by some other means.
* For example, the class rtk::util::linear_sequence<> can be used to
* generate an arbitarily long sequence of integers while using only a
* few bytes of memory.
*
* A selection field will respond to arrow_click events (as might be
* generated by an associated pair of adjuster arrows). It may or may
* not be directly writable by the user.
*/
template<class const_iterator>
class selection_field:
public rtk::desktop::writable_field,
public rtk::events::arrow_click::handler
{
public:
/** The type of a member of the sequence value. */
typedef typename const_iterator::value_type value_type;
private:
/** The first member of the sequence. */
const_iterator _first;
 
/** The last member of the sequence, plus one. */
const_iterator _last;
public:
/** Construct selection field.
* By default the field is writable.
* @param first the first member of the sequence
* @param last the last member of the sequence, plus one
*/
selection_field(const_iterator first,const_iterator last);
 
virtual void handle_event(events::arrow_click& ev);
 
/** Get value.
* This function does not snap the value to a member of the sequence.
* @return the content of the field as a value_type.
*/
value_type value() const;
 
/** Set value.
* This function sets the content of the field to a given value.
* The value need not be a member of the sequence (although in
* most cases it probably ought to be).
* @param value the required value
* @return a reference to this
*/
selection_field& value(value_type value);
 
/** Snap to an allowed value.
* This function ensures that the displayed field value is a member
* of the sequence of allowed values.
* @return a reference to this
*/
selection_field& snap();
 
/** Step value upwards or downwards by specified distance.
* The distance number of steps refers to the sequence, not to
* value_type (which may or may not be numeric).
* @param steps the required number of steps
* @return a reference to this
*/
selection_field& step(int steps);
 
/** Get writable flag.
* @return true if the field content is directly editable by the user,
* otherwise false
*/
bool writable() const
{ return button()==14; }
 
/** Set writable flag.
* @param writable true if the field is required to be directly
* writable by the user, otherwise false
* @return a reference to this
*/
selection_field& writable(bool writable);
};
 
template<class const_iterator>
selection_field<const_iterator>::selection_field(const_iterator first,
const_iterator last):
_first(first),
_last(last)
{
writable(true);
text(rtk::util::lexical_cast<std::string>(*_first));
}
 
template<class const_iterator>
void selection_field<const_iterator>::handle_event(events::arrow_click& ev)
{
step(ev.steps());
}
 
template<class const_iterator>
typename selection_field<const_iterator>::value_type
selection_field<const_iterator>::value() const
{
return rtk::util::lexical_cast<value_type>(text());
}
 
template<class const_iterator>
selection_field<const_iterator>&
selection_field<const_iterator>::value(value_type value)
{
text(rtk::util::lexical_cast<std::string>(value));
return *this;
}
 
template<class const_iterator>
selection_field<const_iterator>&
selection_field<const_iterator>::snap()
{
const_iterator i=std::lower_bound(_first,_last,value());
if ((i!=_first)&&(*i!=value)) --i;
if (i==_last) --i;
return *this;
}
 
template<class const_iterator>
selection_field<const_iterator>&
selection_field<const_iterator>::step(int steps)
{
value_type _value=value();
const_iterator i=std::lower_bound(_first,_last,_value);
if ((steps>=0)&&(i!=_first)&&(*i!=_value)) --i;
 
while ((steps<0)&&(i!=_first))
{
--i;
++steps;
}
while ((steps>0)&&(i!=_last))
{
++i;
--steps;
}
if (i==_last) --i;
 
value(*i);
return *this;
}
 
template<class const_iterator>
selection_field<const_iterator>&
selection_field<const_iterator>::writable(bool writable)
{
if (writable)
{
validation("Ktar;Pptr_write");
button(14);
bcolour(0);
}
else
{
validation("R2");
button(0);
bcolour(1);
}
return *this;
}
 
} /* namespace desktop */
} /* namespace rtk */
 
#endif