00001 #ifndef ERIS_UI_FACTORY_H
00002 #define ERIS_UI_FACTORY_H
00003
00004 #include <Atlas/Message/Element.h>
00005
00006 #include <sigc++/object.h>
00007 #include <sigc++/signal.h>
00008
00009 #include <list>
00010
00011 namespace Atlas {
00012 namespace Objects {
00013 namespace Operation {
00014 class Create;
00015 }
00016 namespace Entity {
00017 class UIEntity;
00018 class Frame;
00019 class Slot;
00020 }
00021 }
00022 }
00023
00024 namespace Eris { namespace UI {
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00042 class Element
00043 {
00044 public:
00045 virtual ~Element() {}
00046
00047
00048
00049 virtual void setProperties(const Atlas::Message::Element::MapType&) = 0;
00050
00051 void setProperty(const std::string& name, const Atlas::Message::Element& arg)
00052 {
00053 Atlas::Message::Element::MapType map;
00054 map[name] = arg;
00055 setProperties(map);
00056 }
00057
00058 SigC::Signal1<void,const Atlas::Message::Element::MapType&> PropertiesChanged;
00059 };
00060
00061 class SlotElement : public Element, virtual public SigC::Object
00062 {
00063 public:
00064 virtual void action(const Atlas::Message::Element::MapType&) = 0;
00065 };
00066
00067 class FrameElement : virtual public Element
00068 {
00069 public:
00070 ~FrameElement()
00071 {
00072 for(SlotList::iterator I = _list.begin(); I!= _list.end(); ++I)
00073 delete *I;
00074 }
00075
00076 virtual void pack(Element*) = 0;
00077 void packSlot(SlotElement* slot) {_list.push_back(slot);}
00078
00079 private:
00080 typedef std::list<SlotElement*> SlotList;
00081 SlotList _list;
00082 };
00083
00084 class Bindings;
00085
00086 class Factory
00087 {
00088 public:
00089 class BaseGen
00090 {
00091 public:
00092 virtual ~BaseGen() {}
00093 virtual Element* create(const Atlas::Message::Element::MapType&) = 0;
00094 };
00095
00096 template<class E>
00097 class Gen : public BaseGen
00098 {
00099 public:
00100 virtual Element* create(const Atlas::Message::Element::MapType& attrs)
00101 {return E(attrs);}
00102 };
00103
00104 Factory(const std::string& id, BaseGen* gen)
00105 : _id(id), _gen(gen), _persistent(true), _refcount(1)
00106 {_id_list.push_back(id);}
00107 virtual ~Factory() {if(_persistent && _gen) delete _gen;}
00108
00109 typedef std::map<std::string,Element*> IDMap;
00110
00111
00112 virtual Element* create(IDMap&) const;
00113
00114 virtual Factory* parse(const Atlas::Message::Element::MapType&, const Bindings&) const;
00115
00116 void ref() {++_refcount;}
00117 void unref() {if(--_refcount == 0) delete this;}
00118 bool unique() const {return _refcount == 1;}
00119 bool persistent() const {return _persistent;}
00120 const std::string& id() const {return _id;}
00121
00122 protected:
00123 typedef std::list<std::string> IDList;
00124
00125 Factory(const Atlas::Objects::Entity::UIEntity&, const std::string&,
00126 const IDList&, const Atlas::Message::Element::MapType&, BaseGen*);
00127
00128 const Atlas::Message::Element::MapType& attrs() const {return _attrs;}
00129 const IDList& idlist() const {return _id_list;}
00130 BaseGen* gen() const {return _gen;}
00131
00132 private:
00133 Factory(const Factory&);
00134 Factory& operator=(const Factory&);
00135
00136 std::string _id;
00137 IDList _id_list;
00138 BaseGen* _gen;
00139 bool _persistent;
00140 unsigned long _refcount;
00141 Atlas::Message::Element::MapType _attrs;
00142 };
00143
00144
00145 class FrameFactory : public Factory
00146 {
00147 public:
00148 class BaseGen
00149 {
00150 public:
00151 virtual ~BaseGen() {}
00152 virtual FrameElement* create(const std::string& valign,
00153 const std::string& halign, const std::string& rel_pos,
00154 const Atlas::Message::Element::MapType&) = 0;
00155 };
00156 template<class FE>
00157 class Gen : public BaseGen
00158 {
00159 public:
00160 virtual FrameElement* create(const std::string& valign,
00161 const std::string& halign, const std::string& rel_pos,
00162 const Atlas::Message::Element::MapType& attrs)
00163 {return new FE(valign, halign, rel_pos, attrs);}
00164 };
00165
00166
00167 FrameFactory(BaseGen* gen) : Factory("frame", 0), _valign("center"),
00168 _halign("center"), _rel_pos("right"), _gen(gen) {}
00169 virtual ~FrameFactory();
00170
00171 virtual Element* create(IDMap&) const;
00172 virtual Factory* parse(const Atlas::Message::Element::MapType&, const Bindings&) const;
00173
00174 private:
00175 FrameFactory(const Atlas::Objects::Entity::Frame&, const IDList&,
00176 const Bindings&, const Atlas::Message::Element::MapType&, BaseGen*);
00177
00178 std::string _valign, _halign, _rel_pos;
00179 typedef std::list<Factory*> ChildList;
00180 ChildList _children;
00181 BaseGen* _gen;
00182 };
00183
00184 class SlotFactory : public Factory
00185 {
00186 public:
00187
00188 SlotFactory(const std::string& id, BaseGen* gen) : Factory(id, gen) {}
00189
00190 virtual Element* create(IDMap&) const;
00191 virtual Factory* parse(const Atlas::Message::Element::MapType&, const Bindings&) const;
00192
00193 const Atlas::Message::Element::ListType& target() const {return _target;}
00194
00195 private:
00196 SlotFactory(const Atlas::Objects::Entity::Slot&, const IDList&,
00197 const Atlas::Message::Element::MapType&, BaseGen*);
00198
00199 Atlas::Message::Element::ListType _target;
00200 };
00201
00203 class Bindings
00204 {
00205 public:
00206 Bindings();
00207 virtual ~Bindings();
00208
00209 void parse(const Atlas::Message::Element&);
00210
00212 void clear();
00213
00214 Factory* findFactory(const Atlas::Message::Element& id) const
00215 {
00216 return id.isString() ? findFactory(id.asString()) : 0;
00217 }
00218
00219 Factory* findFactory(const std::string& id) const
00220 {
00221 FactoryMap::const_iterator I = _factory_map.find(id);
00222 return (I != _factory_map.end()) ? I->second : 0;
00223 }
00224
00225 bool bind(Factory* f) {return _factory_map.insert(
00226 FactoryMap::value_type(f->id(), f)).second;}
00227
00228
00229
00230 template<class C>
00231 friend struct Bind
00232 {
00233 public:
00234 Bind(Bindings& b) : _b(b) {}
00235
00236 bool slot(const std::string& id)
00237 {return _b.bind(new SlotFactory(id, new SlotFactory::Gen<C>()));}
00238 bool element(const std::string& id)
00239 {return _b.bind(new Factory(id, new Factory::Gen<C>()));}
00240 bool frame()
00241 {return _b.bind(new FrameFactory(new FrameFactory::Gen<C>()));}
00242 private:
00243 Bindings& _b;
00244 };
00245
00246
00247 virtual void display(Element*, const std::string& id) = 0;
00248
00249 virtual void createConsoleElement(const Atlas::Objects::Entity::UIEntity&) = 0;
00250
00251 private:
00252
00253 typedef std::map<std::string,Factory*> FactoryMap;
00254 FactoryMap _factory_map;
00255 };
00256
00257 }}
00258
00259 #endif