1 #ifndef ATTRIBUTE_H
2 #define ATTRIBUTE_H
3 
4 #include <string>
5 #include <vector>
6 
7 #include "entity.h"
8 
9 class Object;
10 class Signal;
11 class Completion;
12 
13 /* Attributes.
14  * Attributes are members of Objects that expose internal state variables to the
15  * object tree accessible through the 'attr' command.
16  * The class Attribute is abstract and is used to form a common base.
17  *
18  * Attribute_<T> are regular (static) attributes.
19  * They provide static methods for conversion from/to string (parse() and str()).
20  * A validator can be specified that performs checks before accepting external
21  * input. Error messages produced by the validator are propagated back to the user.
22  * The validator is not called when the attribute is set internally.
23  * Static attributes are read-only by default and need to set writable either
24  * explicitely or by setting a validator.
25  * Static attributes provide a signal "changed" that emits whenever the attribute
26  * is altered (internally or externally).
27  * Likewise, they are by-default hookable. For some attributes a hook does not make
28  * sense, so it can be disabled on an individual basis.
29  *
30  * DynAttribute_<T> are shallow attributes and not physically present.
31  * A common reason for having a dynamic attribute is for backwards-compatibility
32  * or to provide some kind of magic in an attribute.
33  * However, for allowing triggers by the user, an Action should be used instead.
34  * Actions are designated properly and can accept multiple arguments.
35  * The can be read-only using a getter callback, or rw with an additional
36  * setter callback. Validation is done within the setter.
37  * Dynamic attributes do not provide a changed signal. They could do it easily in
38  * theory, however it would most-probably be a bad idea to attach to such a signal
39  * instead of to the underlying mechanics.
40  * Note that for similar reasons, dynamic attributes are not hookable.
41  */
42 
43 class Attribute : public Entity, public HasDocumentation {
44 
45 public:
Attribute(const std::string & name,bool writable)46     Attribute(const std::string &name,
47               bool writable)
48         : Entity(name), writable_(writable) {}
49     ~Attribute() override = default;
50 
51     // set the owner after object creation (when pointer is available)
setOwner(Object * owner)52     void setOwner(Object *owner) { owner_ = owner; }
53     // make this attribute writable (default is typically read-only)
54     void setWritable(bool writable = true) { writable_ = writable; }
55     // change if attribute can be expected to trigger hooks (rarely used)
setHookable(bool hookable)56     void setHookable(bool hookable) { hookable_ = hookable; }
57 
writable()58     bool writable() const { return writable_; }
hookable()59     bool hookable() const { return hookable_; }
60     virtual Signal& changed() = 0;
61 
str()62     virtual std::string str() { return {}; }
63     virtual std::string change(const std::string &payload) = 0;
64     //! suggestions for a new value of the attribute
65     virtual void complete(Completion& complete) = 0;
66 
67     // find the current value of the attribute in the given range and then
68     // assign the succeeding value to the attribute (wth wrap around)
69     std::string cycleValue(std::vector<std::string>::const_iterator begin,
70                            std::vector<std::string>::const_iterator end);
71 
72     //! if the attribute has a default value, reset it, otherwise return false
resetValue()73     virtual bool resetValue() { return false; }
74 
75     void detachFromOwner();
76 
77 protected:
78     Object *owner_ = nullptr;
79 
80     bool writable_ = false, hookable_ = true;
81 };
82 
83 
84 #endif // ATTRIBUTE_H
85