|
Boost :
|
Hi,
I've built a small library based on boost::signals to provide a
mechanism to update related-values across an application. Any comment
welcome.
Note that the documentation is very minimal for now and I continue
working on it, but I think there is enough to have feedbacks and to
discuss the place of such library in boost. Feedbacks may also
influence how I will continue working on it.
Regards,
Nicolas Fleury
Event-Driven Values
EDV (Event-Driven Values)
Introduction
Separate the view from the model, and in the MVC architecture, is a
common practice in application design. However, most currently
available GUI toolkits often violates this design by including data in
their widgets. For example, a label usually contains the text it
displays, even if this text is in fact the direct transformation of data
in the model. This forces the programmer to continuously update
the data in widgets in function of the data in the model.
The purpose EDV library is to provide a flexible mechanism to update
related values used in different parts of an application.
The value Class
The value class is the base class for all values classes. Values
encapsulate a read-only value and call a signal each time this value
changed. The basic interface of value is:
template <typename Type>
class value
{
public:
typedef Type type;
typedef boost::signal<void (type previous_value)>
change_signal;
typedef boost::signal<void ()> deletion_signal;
inline type get() const;
inline boost::signals::connection listen_change(
const typename change_signal::slot_type slot) const;
inline boost::signals::connection listen_deletion(
const typename deletion_signal::slot_type slot)
const;
...
protected:
void set(type);
...
};
The simpler class derived from the value class is the concrete_value
class. This class basically make the set member function public.
Value Views
Value views are used to create values that have the same value of
another value object. An operation can also be specified to make
the view the result of that operation.
int double_value(int v) { return v * 2; }
concrete_value<int> i(4);
value_view<int> j(i);
value_view<int> k(j, boost::function<int
(int)>(&double_value));
i = 6; // j now equal to 6, k to 12
Operation Values
Most binary and unary operators have their correspondant value
class. These value classes are used to build values that are the
result of a basic operation on one or two other values.
concrete_value<int> i(4), j(6);
sum_value<int> sum(i, j); // sum now equal to 10
diff_value<int> diff(i, j); // diff now equal to -2
i = 6; // sum now equal to 12, diff to 0
The constructors of these value classes also accept pointers for
adoption or simple constant values (it is the same for all composite
values presented in this document):
sum_value<int> result(i, new diff_value<int>(j, 7));
String Values
The string_convert_value class is the simpler class to produce a value
containing the string equivalent of another value.
concrete_value<int> i(3);
string_convert_value<int, std::string> str(i); // str
content is "3"
i = 0; // str content becomes "0"
The ostringstream_value class is a more powerful utility to create
string values from multiple values.
ostringstream_value<std::string> str2;
concrete_value<int> i(4), j(6);
str2 << "The sum of " << i << " and " << j
<< " is " << new sum_value<int>(i, j);
i = 6; // str2 content is changed accordingly
Sync Values
The sync_value class provides a mechanism to build values that have a
bi-directional update relation.
sync_value<double> i(4);
sync_value<double> j(6);
sync_value<double> k(8);
make_equal_relation(i, j); // i and j equal to 4
make_diff_relation(j, k, 10.0); // k now equal to 14
i = 2; // j now equal to 2 and k to 12
j = 3; // i now equal to 3 and k to 13
k = 4; // i and j now equal to -6
Custom relations can also be made by calling the connect function.
Triggers
Triggers are similar to signals with two major differences:
- They can only be connected to one thing (another trigger or a
slot)
- They know if they are connected ultimately, after going through
zero or more other triggers, to a slot.
Triggers are particularly useful for actions triggered by a UI.
For example, a button widget using a trigger could be disabled as long
as there's no action associated with it.
(Note: triggers in early development)
- application/zip attachment: EDV.zip
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk