1 // Interface for 2D Canvas elements
3 // Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Library General Public
7 // License as published by the Free Software Foundation; either
8 // version 2 of the License, or (at your option) any later version.
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Library General Public License for more details.
15 // You should have received a copy of the GNU Library General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #ifndef CANVAS_ELEMENT_HXX_
20 #define CANVAS_ELEMENT_HXX_
22 #include <simgear/canvas/canvas_fwd.hxx>
23 #include <simgear/canvas/CanvasEvent.hxx>
24 #include <simgear/props/PropertyBasedElement.hxx>
25 #include <simgear/misc/stdint.hxx> // for uint32_t
26 #include <simgear/nasal/cppbind/Ghost.hxx>
28 #include <osg/BoundingBox>
29 #include <osg/MatrixTransform>
31 #include <boost/bind.hpp>
32 #include <boost/function.hpp>
45 public PropertyBasedElement
50 * Store pointer to window as user data
53 public osg::Referenced
57 OSGUserData(ElementPtr element);
60 typedef boost::function<bool(Element&, const SGPropertyNode*)>
62 typedef boost::function<void(Element&, const SGPropertyNode*)>
63 StyleSetterFuncUnchecked;
68 SGSharedPtr<StyleSetter> next;
72 StyleSetter setter; ///!< Function(s) for setting this style
73 std::string type; ///!< Interpolation type
74 bool inheritable; ///!< Whether children can inherit this style from
81 virtual ~Element() = 0;
83 virtual void setSelf(const PropertyBasedElementPtr& self);
84 virtual void onDestroy();
86 ElementWeakPtr getWeakPtr() const;
89 * Called every frame to update internal state
91 * @param dt Frame time in seconds
93 virtual void update(double dt);
95 naRef addEventListener(const nasal::CallContext& ctx);
96 virtual void clearEventListener();
98 virtual bool accept(EventVisitor& visitor);
99 virtual bool ascend(EventVisitor& visitor);
100 virtual bool traverse(EventVisitor& visitor);
102 virtual bool handleEvent(canvas::EventPtr event);
104 virtual bool hitBound( const osg::Vec2f& pos,
105 const osg::Vec2f& local_pos ) const;
108 * Get whether the element is visible or hidden (Can be changed with
109 * setting property "visible" accordingly).
111 bool isVisible() const;
113 osg::MatrixTransform* getMatrixTransform();
114 osg::MatrixTransform const* getMatrixTransform() const;
116 virtual void childAdded( SGPropertyNode * parent,
117 SGPropertyNode * child );
118 virtual void childRemoved( SGPropertyNode * parent,
119 SGPropertyNode * child );
120 virtual void valueChanged(SGPropertyNode * child);
122 virtual bool setStyle( const SGPropertyNode* child,
123 const StyleInfo* style_info = 0 );
128 * @note Only "rect(<top>, <right>, <bottom>, <left>)" is supported
129 * @see http://www.w3.org/TR/CSS21/visufx.html#propdef-clip
131 void setClip(const std::string& clip);
134 * Write the given bounding box to the property tree
136 void setBoundingBox(const osg::BoundingBox& bb);
139 * Get bounding box with children/drawables transformed by passed matrix
141 virtual osg::BoundingBox getTransformedBounds(const osg::Matrix& m) const;
144 * Create an canvas Element
146 * @tparam Derived Type of element (needs to derive from Element)
148 template<typename Derived>
150 typename boost::enable_if<
151 boost::is_base_of<Element, Derived>,
153 >::type create( const CanvasWeakPtr& canvas,
154 const SGPropertyNode_ptr& node,
158 ElementPtr el( new Derived(canvas, node, style, parent) );
168 LAST_ATTRIBUTE = BLEND_FUNC << 1
180 CanvasWeakPtr _canvas;
183 uint32_t _attributes_dirty;
185 bool _transform_dirty;
186 osg::observer_ptr<osg::MatrixTransform> _transform;
187 std::vector<TransformType> _transform_types;
190 std::vector<SGPropertyNode_ptr> _bounding_box;
192 typedef std::vector<EventListenerPtr> Listener;
193 typedef std::map<Event::Type, Listener> ListenerMap;
195 ListenerMap _listener;
197 typedef std::map<std::string, StyleInfo> StyleSetters;
198 static StyleSetters _style_setters;
200 Element( const CanvasWeakPtr& canvas,
201 const SGPropertyNode_ptr& node,
202 const Style& parent_style,
206 * Returns false on first call and true on any successive call. Use to
207 * perform initialization tasks which are only required once per element
210 * @tparam Derived (Derived) class type
212 template<class Derived>
215 static bool is_init = false;
224 * Register a function for setting a style specified by the given property
226 * @param name Property name
227 * @param type Interpolation type
228 * @param setter Setter function
230 * @tparam T1 Type of value used to retrieve value from property
232 * @tparam T2 Type of value the setter function expects
233 * @tparam Derived Type of class the setter can be applied to
235 * @note T1 needs to be convertible to T2
243 addStyle( const std::string& name,
244 const std::string& type,
245 const boost::function<void (Derived&, T2)>& setter,
246 bool inheritable = true )
248 StyleInfo& style_info = _style_setters[ name ];
251 if( !style_info.type.empty() && type != style_info.type )
256 "changing animation type for '" << name << "': "
257 << style_info.type << " -> " << type
260 style_info.type = type;
262 // TODO check if changed?
263 style_info.inheritable = inheritable;
265 StyleSetter* style = &style_info.setter;
269 style = style->next = new StyleSetter;
271 style->func = boost::bind
273 &type_match<Derived>::call,
276 bindStyleSetter<T1>(name, setter)
286 addStyle( const std::string& name,
287 const std::string& type,
288 const boost::function<void (Derived&, T)>& setter,
289 bool inheritable = true )
291 return addStyle<T, T>(name, type, setter, inheritable);
299 addStyle( const std::string& name,
300 const std::string& type,
301 void (Derived::*setter)(T),
302 bool inheritable = true )
304 return addStyle<T, T>
308 boost::function<void (Derived&, T)>(setter),
319 addStyle( const std::string& name,
320 const std::string& type,
321 void (Derived::*setter)(T2),
322 bool inheritable = true )
328 boost::function<void (Derived&, T2)>(setter),
337 addStyle( const std::string& name,
338 const std::string& type,
339 void (Derived::*setter)(const std::string&),
340 bool inheritable = true )
342 return addStyle<const char*, const std::string&>
346 boost::function<void (Derived&, const std::string&)>(setter),
358 addStyle( const std::string& name,
359 const std::string& type,
360 void (Other::*setter)(T),
361 OtherRef Derived::*instance_ref,
362 bool inheritable = true )
364 return addStyle<T, T>
368 bindOther(setter, instance_ref),
381 addStyle( const std::string& name,
382 const std::string& type,
383 void (Other::*setter)(T2),
384 OtherRef Derived::*instance_ref,
385 bool inheritable = true )
391 bindOther(setter, instance_ref),
404 addStyle( const std::string& name,
405 const std::string& type,
406 const boost::function<void (Other&, T2)>& setter,
407 OtherRef Derived::*instance_ref,
408 bool inheritable = true )
414 bindOther(setter, instance_ref),
425 addStyle( const std::string& name,
426 const std::string& type,
427 void (Other::*setter)(const std::string&),
428 OtherRef Derived::*instance_ref,
429 bool inheritable = true )
431 return addStyle<const char*, const std::string&>
435 boost::function<void (Other&, const std::string&)>(setter),
441 template<typename T, class Derived, class Other, class OtherRef>
442 boost::function<void (Derived&, T)>
443 bindOther( void (Other::*setter)(T), OtherRef Derived::*instance_ref )
445 return boost::bind(setter, boost::bind(instance_ref, _1), _2);
448 template<typename T, class Derived, class Other, class OtherRef>
449 boost::function<void (Derived&, T)>
450 bindOther( const boost::function<void (Other&, T)>& setter,
451 OtherRef Derived::*instance_ref )
458 &reference_from_pointer<Other, OtherRef>,
459 boost::bind(instance_ref, _1)
465 template<typename T1, typename T2, class Derived>
466 StyleSetterFuncUnchecked
467 bindStyleSetter( const std::string& name,
468 const boost::function<void (Derived&, T2)>& setter )
473 // We will only call setters with Derived instances, so we can safely
475 boost::bind(&derived_cast<Derived>, _1),
476 boost::bind(&getValue<T1>, _2)
480 bool isStyleEmpty(const SGPropertyNode* child) const;
481 bool canApplyStyle(const SGPropertyNode* child) const;
482 bool setStyleImpl( const SGPropertyNode* child,
483 const StyleInfo* style_info = 0 );
485 const StyleInfo* getStyleInfo(const std::string& name) const;
486 const StyleSetter* getStyleSetter(const std::string& name) const;
487 const SGPropertyNode* getParentStyle(const SGPropertyNode* child) const;
489 virtual void childAdded(SGPropertyNode * child) {}
490 virtual void childRemoved(SGPropertyNode * child){}
491 virtual void childChanged(SGPropertyNode * child){}
493 void setDrawable(osg::Drawable* drawable);
496 * Get stateset of drawable if available or use transform otherwise
498 osg::StateSet* getOrCreateStateSet();
504 osg::ref_ptr<osg::Drawable> _drawable;
506 Element(const Element&);// = delete
508 template<class Derived>
509 static Derived& derived_cast(Element& el)
511 return static_cast<Derived&>(el);
514 template<class T, class SharedPtr>
515 static T& reference_from_pointer(const SharedPtr& p)
517 return *get_pointer(p);
521 * Helper to call a function only of the element type can be converted to
524 * @return Whether the function has been called
526 template<class Derived>
529 static bool call( Element& el,
530 const SGPropertyNode* prop,
531 const StyleSetterFuncUnchecked& func )
533 Derived* d = dynamic_cast<Derived*>(&el);
542 } // namespace canvas
543 } // namespace simgear
545 #endif /* CANVAS_ELEMENT_HXX_ */