Xcos MVC: implement rpar / ipar / uid
[scilab.git] / scilab / modules / scicos / src / cpp / view_scilab / BaseAdapter.hxx
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2014-2014 - Scilab Enterprises - Clement DAVID
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 #ifndef BASEADAPTER_HXX_
14 #define BASEADAPTER_HXX_
15
16 #include <algorithm>
17 #include <string>
18 #include <sstream>
19
20 #include "user.hxx"
21 #include "internal.hxx"
22 #include "string.hxx"
23
24 #include "Controller.hxx"
25 #include "Adapters.hxx"
26 #include "model/BaseObject.hxx"
27
28 namespace org_scilab_modules_scicos
29 {
30 namespace view_scilab
31 {
32
33 /**
34  * A property used as a getter/setter for a specific name
35  */
36 template<typename Adaptor>
37 struct property
38 {
39 public:
40     typedef types::InternalType* (*getter_t)(const Adaptor& adaptor, const Controller& controller);
41     typedef bool (*setter_t)(Adaptor& adaptor, types::InternalType* v, Controller& controller);
42
43     typedef std::vector< property<Adaptor> > props_t;
44     typedef typename props_t::iterator props_t_it;
45
46
47     property(const std::wstring& prop, getter_t g, setter_t s) : original_index(fields.size()), name(prop), get(g), set(s) {};
48     ~property() {};
49
50     size_t original_index;
51     std::wstring name;
52     getter_t get;
53     setter_t set;
54
55     bool operator< (const std::wstring& v) const
56     {
57         return name < v;
58     }
59
60     static bool original_index_cmp(property<Adaptor> p1, property<Adaptor> p2)
61     {
62         return p1.original_index < p2.original_index;
63     }
64
65     /*
66      * Static properties accessors
67      */
68     static props_t fields;
69
70     /**
71      * @return true if the properties has already been setup, false otherwise.
72      */
73     static bool properties_has_not_been_set()
74     {
75         return fields.empty();
76     }
77
78     /**
79      * Add a property to an Adaptor
80      */
81     static void add_property(const std::wstring& name, getter_t g, setter_t s)
82     {
83         property<Adaptor>::props_t_it pos = std::lower_bound(fields.begin(), fields.end(), name);
84         fields.insert(pos, property(name, g, s));
85     }
86 };
87
88
89 /**
90  * Base definition of the adapter pattern, implement the get / set dispatch.
91  *
92  * Note that sub-classes are responsible to fill the fields accordingly to theirs interfaces.
93  */
94 template<typename Adaptor, typename Adaptee>
95 class BaseAdapter : public types::User<Adaptor>
96 {
97
98 public:
99     BaseAdapter(Adaptee* o) : adaptee(o) {};
100     BaseAdapter(const BaseAdapter& o) : adaptee(o.adaptee) {};
101     virtual ~BaseAdapter() {};
102
103     /*
104      * property accessors
105      */
106
107     bool hasProperty(const std::wstring& _sKey) const
108     {
109         typename property<Adaptor>::props_t_it found = std::lower_bound(property<Adaptor>::fields.begin(), property<Adaptor>::fields.end(), _sKey);
110         return found != property<Adaptor>::fields.end() && !(_sKey < found->name);
111     }
112
113     types::InternalType* getProperty(const std::wstring& _sKey, Controller controller = Controller()) const
114     {
115         typename property<Adaptor>::props_t_it found = std::lower_bound(property<Adaptor>::fields.begin(), property<Adaptor>::fields.end(), _sKey);
116         if (found != property<Adaptor>::fields.end() && !(_sKey < found->name))
117         {
118             return found->get(static_cast<Adaptor*>(this), controller);
119         }
120         return 0;
121     }
122
123     bool setProperty(const std::wstring& _sKey, types::InternalType* v, Controller controller = Controller())
124     {
125         typename property<Adaptor>::props_t_it found = std::lower_bound(property<Adaptor>::fields.begin(), property<Adaptor>::fields.end(), _sKey);
126         if (found != property<Adaptor>::fields.end() && !(_sKey < found->name))
127         {
128             return found->set(*static_cast<Adaptor*>(this), v, controller);
129         }
130         return false;
131     }
132
133     /**
134      * @return the Adaptee instance
135      */
136     Adaptee* getAdaptee() const
137     {
138         return adaptee;
139     };
140
141     /**
142      * set the adaptee
143      */
144     void setAdaptee(Adaptee* adaptee)
145     {
146         this->adaptee = adaptee;
147     }
148
149     /*
150      * All following methods should be implemented by each template instance
151      */
152
153     virtual std::wstring getTypeStr() = 0;
154     virtual std::wstring getShortTypeStr() = 0;
155
156     /*
157      * Implement a specific types::User
158      */
159 private:
160     types::InternalType* clone()
161     {
162         return new Adaptor(*static_cast<Adaptor*>(this));
163     }
164
165     bool isAssignable()
166     {
167         return true;
168     }
169
170     bool extract(const std::wstring & name, types::InternalType *& out)
171     {
172         typename property<Adaptor>::props_t_it found = std::lower_bound(property<Adaptor>::fields.begin(), property<Adaptor>::fields.end(), name);
173         if (found != property<Adaptor>::fields.end() && !(name < found->name))
174         {
175             Controller controller = Controller();
176             types::InternalType* value = found->get(*static_cast<Adaptor*>(this), controller);
177             if (value == 0)
178             {
179                 return false;
180             }
181
182             out = value;
183             return true;
184         }
185         return false;
186     }
187
188     void whoAmI(void)
189     {
190         std::cout << "scicos object";
191     }
192
193     bool toString(std::wostringstream& ostr)
194     {
195         typename property<Adaptor>::props_t properties = property<Adaptor>::fields;
196         std::sort(properties.begin(), properties.end(), property<Adaptor>::original_index_cmp);
197
198         ostr << L"scicos_" <<  getTypeStr() << L" type :" << std::endl;
199         for (typename property<Adaptor>::props_t_it it = properties.begin(); it != properties.end(); ++it)
200         {
201             ostr << L"  " << it->name << std::endl;
202         }
203         return true;
204     }
205
206
207 private:
208     Adaptee* adaptee;
209 };
210
211
212 } /* view_scilab */
213 } /* namespace org_scilab_modules_scicos */
214
215 #endif /* BASEADAPTER_HXX_ */