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