Eris 1.3.19
|
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 // Element is a virtual class because we expect to 00027 // get an inheritance hierarchy like: 00028 // 00029 // Element 00030 // | | 00031 // FrameElement MyElement 00032 // | | 00033 // MyFrameElement 00034 // 00035 // where MyElement and MyFrameElement are classes 00036 // in client-side bindings. There should only be 00037 // one Element instance in MyFrameElement, so 00038 // we want children of Element to inherit 00039 // virtually. 00040 00042 class Element 00043 { 00044 public: 00045 virtual ~Element() {} 00046 00047 // implementations of this function should emit PropertiesChanged for 00048 // valid properties 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 // create a dialog element 00112 virtual Element* create(IDMap&) const; 00113 // create a new factory 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; // _id plus all parent ids, for use in connecting slots 00138 BaseGen* _gen; 00139 bool _persistent; // factories not created by the server 00140 unsigned long _refcount; 00141 Atlas::Message::Element::MapType _attrs; 00142 }; 00143 00144 // factory for children of Atlas::Objects::Entity::Frame 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 // for the base slot classes 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 // a trick to get reasonable syntax for the interface, 00229 // e.g. Bind<Foo>(bindings).slot("foo"); 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 // put an Element on the screen as a dialog 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 }} // namespace Eris::UI 00258 00259 #endif