Eris  1.3.19
UIFactory.h
1 #ifndef ERIS_UI_FACTORY_H
2 #define ERIS_UI_FACTORY_H
3 
4 #include <Atlas/Message/Element.h>
5 
6 #include <sigc++/object.h>
7 #include <sigc++/signal.h>
8 
9 #include <list>
10 
11 namespace Atlas {
12  namespace Objects {
13  namespace Operation {
14  class Create;
15  }
16  namespace Entity {
17  class UIEntity;
18  class Frame;
19  class Slot;
20  }
21  }
22 }
23 
24 namespace Eris { namespace UI {
25 
26 // Element is a virtual class because we expect to
27 // get an inheritance hierarchy like:
28 //
29 // Element
30 // | |
31 // FrameElement MyElement
32 // | |
33 // MyFrameElement
34 //
35 // where MyElement and MyFrameElement are classes
36 // in client-side bindings. There should only be
37 // one Element instance in MyFrameElement, so
38 // we want children of Element to inherit
39 // virtually.
40 
42 class Element
43 {
44  public:
45  virtual ~Element() {}
46 
47  // implementations of this function should emit PropertiesChanged for
48  // valid properties
49  virtual void setProperties(const Atlas::Message::Element::MapType&) = 0;
50 
51  void setProperty(const std::string& name, const Atlas::Message::Element& arg)
52  {
53  Atlas::Message::Element::MapType map;
54  map[name] = arg;
55  setProperties(map);
56  }
57 
58  SigC::Signal1<void,const Atlas::Message::Element::MapType&> PropertiesChanged;
59 };
60 
61 class SlotElement : public Element, virtual public SigC::Object
62 {
63  public:
64  virtual void action(const Atlas::Message::Element::MapType&) = 0;
65 };
66 
67 class FrameElement : virtual public Element
68 {
69  public:
70  ~FrameElement()
71  {
72  for(SlotList::iterator I = _list.begin(); I!= _list.end(); ++I)
73  delete *I;
74  }
75 
76  virtual void pack(Element*) = 0;
77  void packSlot(SlotElement* slot) {_list.push_back(slot);}
78 
79  private:
80  typedef std::list<SlotElement*> SlotList;
81  SlotList _list;
82 };
83 
84 class Bindings;
85 
86 class Factory
87 {
88  public:
89  class BaseGen
90  {
91  public:
92  virtual ~BaseGen() {}
93  virtual Element* create(const Atlas::Message::Element::MapType&) = 0;
94  };
95 
96  template<class E>
97  class Gen : public BaseGen
98  {
99  public:
100  virtual Element* create(const Atlas::Message::Element::MapType& attrs)
101  {return E(attrs);}
102  };
103 
104  Factory(const std::string& id, BaseGen* gen)
105  : _id(id), _gen(gen), _persistent(true), _refcount(1)
106  {_id_list.push_back(id);}
107  virtual ~Factory() {if(_persistent && _gen) delete _gen;}
108 
109  typedef std::map<std::string,Element*> IDMap;
110 
111  // create a dialog element
112  virtual Element* create(IDMap&) const;
113  // create a new factory
114  virtual Factory* parse(const Atlas::Message::Element::MapType&, const Bindings&) const;
115 
116  void ref() {++_refcount;}
117  void unref() {if(--_refcount == 0) delete this;}
118  bool unique() const {return _refcount == 1;}
119  bool persistent() const {return _persistent;}
120  const std::string& id() const {return _id;}
121 
122  protected:
123  typedef std::list<std::string> IDList;
124 
125  Factory(const Atlas::Objects::Entity::UIEntity&, const std::string&,
126  const IDList&, const Atlas::Message::Element::MapType&, BaseGen*);
127 
128  const Atlas::Message::Element::MapType& attrs() const {return _attrs;}
129  const IDList& idlist() const {return _id_list;}
130  BaseGen* gen() const {return _gen;}
131 
132  private:
133  Factory(const Factory&);
134  Factory& operator=(const Factory&);
135 
136  std::string _id;
137  IDList _id_list; // _id plus all parent ids, for use in connecting slots
138  BaseGen* _gen;
139  bool _persistent; // factories not created by the server
140  unsigned long _refcount;
141  Atlas::Message::Element::MapType _attrs;
142 };
143 
144 // factory for children of Atlas::Objects::Entity::Frame
145 class FrameFactory : public Factory
146 {
147  public:
148  class BaseGen
149  {
150  public:
151  virtual ~BaseGen() {}
152  virtual FrameElement* create(const std::string& valign,
153  const std::string& halign, const std::string& rel_pos,
154  const Atlas::Message::Element::MapType&) = 0;
155  };
156  template<class FE>
157  class Gen : public BaseGen
158  {
159  public:
160  virtual FrameElement* create(const std::string& valign,
161  const std::string& halign, const std::string& rel_pos,
162  const Atlas::Message::Element::MapType& attrs)
163  {return new FE(valign, halign, rel_pos, attrs);}
164  };
165 
166 
167  FrameFactory(BaseGen* gen) : Factory("frame", 0), _valign("center"),
168  _halign("center"), _rel_pos("right"), _gen(gen) {}
169  virtual ~FrameFactory();
170 
171  virtual Element* create(IDMap&) const;
172  virtual Factory* parse(const Atlas::Message::Element::MapType&, const Bindings&) const;
173 
174  private:
175  FrameFactory(const Atlas::Objects::Entity::Frame&, const IDList&,
176  const Bindings&, const Atlas::Message::Element::MapType&, BaseGen*);
177 
178  std::string _valign, _halign, _rel_pos;
179  typedef std::list<Factory*> ChildList;
180  ChildList _children;
181  BaseGen* _gen;
182 };
183 
184 class SlotFactory : public Factory
185 {
186  public:
187  // for the base slot classes
188  SlotFactory(const std::string& id, BaseGen* gen) : Factory(id, gen) {}
189 
190  virtual Element* create(IDMap&) const;
191  virtual Factory* parse(const Atlas::Message::Element::MapType&, const Bindings&) const;
192 
193  const Atlas::Message::Element::ListType& target() const {return _target;}
194 
195  private:
196  SlotFactory(const Atlas::Objects::Entity::Slot&, const IDList&,
197  const Atlas::Message::Element::MapType&, BaseGen*);
198 
199  Atlas::Message::Element::ListType _target;
200 };
201 
203 class Bindings
204 {
205  public:
206  Bindings();
207  virtual ~Bindings();
208 
209  void parse(const Atlas::Message::Element&);
210 
212  void clear();
213 
214  Factory* findFactory(const Atlas::Message::Element& id) const
215  {
216  return id.isString() ? findFactory(id.asString()) : 0;
217  }
218 
219  Factory* findFactory(const std::string& id) const
220  {
221  FactoryMap::const_iterator I = _factory_map.find(id);
222  return (I != _factory_map.end()) ? I->second : 0;
223  }
224 
225  bool bind(Factory* f) {return _factory_map.insert(
226  FactoryMap::value_type(f->id(), f)).second;}
227 
228  // a trick to get reasonable syntax for the interface,
229  // e.g. Bind<Foo>(bindings).slot("foo");
230  template<class C>
231  friend struct Bind
232  {
233  public:
234  Bind(Bindings& b) : _b(b) {}
235 
236  bool slot(const std::string& id)
237  {return _b.bind(new SlotFactory(id, new SlotFactory::Gen<C>()));}
238  bool element(const std::string& id)
239  {return _b.bind(new Factory(id, new Factory::Gen<C>()));}
240  bool frame()
241  {return _b.bind(new FrameFactory(new FrameFactory::Gen<C>()));}
242  private:
243  Bindings& _b;
244  };
245 
246  // put an Element on the screen as a dialog
247  virtual void display(Element*, const std::string& id) = 0;
248 
249  virtual void createConsoleElement(const Atlas::Objects::Entity::UIEntity&) = 0;
250 
251  private:
252 
253  typedef std::map<std::string,Factory*> FactoryMap;
254  FactoryMap _factory_map;
255 };
256 
257 }} // namespace Eris::UI
258 
259 #endif
Definition: UIFactory.h:67
Definition: UIFactory.h:184
Factory is used to allow custom entity creation by client libraries.
Definition: Factory.h:14
void clear()
purge all server-generated classes
Definition: UIFactory.h:145
the dialog generator/handler
Definition: UIFactory.h:203
Definition: UIFactory.h:148
Definition: UIFactory.h:89
Definition: UIFactory.h:61
Definition: UIFactory.h:97
an instantiated dialog element
Definition: UIFactory.h:42
Definition: UIFactory.h:86
Definition: UIFactory.h:157