1 // Window for placing a Canvas onto it (for dialogs, menus, etc.)
3 // Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #include "canvas_mgr.hxx"
21 #include <Main/globals.hxx>
22 #include <simgear/canvas/Canvas.hxx>
23 #include <simgear/scene/util/OsgMath.hxx>
25 #include <osgGA/GUIEventHandler>
27 #include <boost/algorithm/string/predicate.hpp>
28 #include <boost/foreach.hpp>
32 //----------------------------------------------------------------------------
33 Window::Window(SGPropertyNode* node):
34 PropertyBasedElement(node),
36 _image(simgear::canvas::CanvasPtr(), node),
38 _capture_events(true),
39 _resize_top(node, "resize-top"),
40 _resize_right(node, "resize-right"),
41 _resize_bottom(node, "resize-bottom"),
42 _resize_left(node, "resize-left"),
43 _resize_status(node, "resize-status")
45 _image.removeListener();
47 node->setFloatValue("source/right", 1);
48 node->setFloatValue("source/bottom", 1);
49 node->setBoolValue("source/normalized", true);
52 //----------------------------------------------------------------------------
55 if( _canvas_decoration )
56 _canvas_decoration->destroy();
59 //----------------------------------------------------------------------------
60 void Window::update(double delta_time_sec)
62 _image.update(delta_time_sec);
64 if( _attributes_dirty & SHADOW )
66 float radius = get<float>("shadow-radius"),
67 inset = get<float>("shadow-inset"),
68 slice_width = radius + inset;
70 if( slice_width <= 1 || _canvas_content.expired() )
74 getGroup()->removeChild(_image_shadow->getMatrixTransform());
75 _image_shadow.reset();
82 _image_shadow.reset(new simgear::canvas::Image(
84 _node->getChild("image-shadow", 0, true)
86 _image_shadow->set<std::string>("file", "gui/images/shadow.png");
87 _image_shadow->set<float>("slice", 7);
88 _image_shadow->set<std::string>("fill", "#000000");
89 getGroup()->insertChild(0, _image_shadow->getMatrixTransform());
92 simgear::canvas::CanvasPtr canvas = _canvas_decoration
94 : _canvas_content.lock();
96 _image_shadow->set<float>("slice-width", slice_width);
97 _image_shadow->set<int>("x", -radius);
98 _image_shadow->set<int>("y", -radius);
99 _image_shadow->set<int>("size[0]", canvas->getViewWidth() + 2 * radius);
100 _image_shadow->set<int>("size[1]", canvas->getViewHeight()+ 2 * radius);
103 _attributes_dirty &= ~SHADOW;
107 _image_shadow->update(delta_time_sec);
110 //----------------------------------------------------------------------------
111 void Window::valueChanged(SGPropertyNode * node)
113 bool handled = false;
114 if( node->getParent() == _node )
117 const std::string& name = node->getNameString();
118 if( name == "raise-top" )
120 else if( name == "resize" )
121 _resizable = node->getBoolValue();
122 else if( name == "capture-events" )
123 _capture_events = node->getBoolValue();
124 else if( name == "decoration-border" )
125 parseDecorationBorder(node->getStringValue());
126 else if( boost::starts_with(name, "shadow-") )
127 _attributes_dirty |= SHADOW;
133 _image.valueChanged(node);
136 //----------------------------------------------------------------------------
137 void Window::childAdded(SGPropertyNode* parent, SGPropertyNode* child)
139 _image.childAdded(parent, child);
142 //----------------------------------------------------------------------------
143 void Window::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
145 _image.childRemoved(parent, child);
148 //----------------------------------------------------------------------------
149 osg::Group* Window::getGroup()
151 return _image.getMatrixTransform();
154 //----------------------------------------------------------------------------
155 const SGRect<float>& Window::getRegion() const
157 return _image.getRegion();
160 //----------------------------------------------------------------------------
161 const SGVec2<float> Window::getPosition() const
163 const osg::Matrix& m = _image.getMatrixTransform()->getMatrix();
164 return SGVec2<float>( m(3, 0), m(3, 1) );
167 //----------------------------------------------------------------------------
168 const SGRect<float> Window::getScreenRegion() const
170 return getPosition() + getRegion();
173 //----------------------------------------------------------------------------
174 void Window::setCanvas(simgear::canvas::CanvasPtr canvas)
176 _canvas_content = canvas;
177 _image.setSrcCanvas(canvas);
180 //----------------------------------------------------------------------------
181 simgear::canvas::CanvasWeakPtr Window::getCanvas() const
183 return _image.getSrcCanvas();
186 //----------------------------------------------------------------------------
187 simgear::canvas::CanvasPtr Window::getCanvasDecoration()
189 return _canvas_decoration;
192 //----------------------------------------------------------------------------
193 bool Window::isVisible() const
195 return _image.isVisible();
198 //----------------------------------------------------------------------------
199 bool Window::isResizable() const
204 //----------------------------------------------------------------------------
205 bool Window::isCapturingEvents() const
207 return _capture_events;
210 //----------------------------------------------------------------------------
211 bool Window::handleMouseEvent(const simgear::canvas::MouseEventPtr& event)
213 return _image.handleEvent(event);
216 //----------------------------------------------------------------------------
217 void Window::handleResize(uint8_t mode, const osg::Vec2f& delta)
224 else if( mode & INIT )
226 _resize_top = getRegion().t();
227 _resize_right = getRegion().r();
228 _resize_bottom = getRegion().b();
229 _resize_left = getRegion().l();
234 _resize_bottom += delta.y();
235 else if( mode & TOP )
236 _resize_top += delta.y();
238 if( mode & canvas::Window::RIGHT )
239 _resize_right += delta.x();
240 else if( mode & canvas::Window::LEFT )
241 _resize_left += delta.x();
244 //----------------------------------------------------------------------------
245 void Window::doRaise(SGPropertyNode* node_raise)
247 if( node_raise && !node_raise->getBoolValue() )
250 BOOST_FOREACH(osg::Group* parent, getGroup()->getParents())
253 parent->removeChild(getGroup());
255 // ...and add again as topmost window
256 parent->addChild(getGroup());
260 node_raise->setBoolValue(false);
263 //----------------------------------------------------------------------------
264 void Window::parseDecorationBorder( const std::string& str )
266 _decoration_border = simgear::CSSBorder::parse(str);
267 if( _decoration_border.isNone() )
269 simgear::canvas::CanvasPtr canvas_content = _canvas_content.lock();
270 _image.setSrcCanvas(canvas_content);
271 _image.set<int>("size[0]", canvas_content->getViewWidth());
272 _image.set<int>("size[1]", canvas_content->getViewHeight());
274 _image_content.reset();
275 _canvas_decoration->destroy();
276 _canvas_decoration.reset();
280 simgear::canvas::CanvasPtr content = _canvas_content.lock();
281 if( !_canvas_decoration )
284 dynamic_cast<CanvasMgr*>(globals->get_subsystem("Canvas"));
288 SG_LOG(SG_GENERAL, SG_WARN, "canvas::Window: no canvas manager!");
292 _canvas_decoration = mgr->createCanvas("window-decoration");
293 _canvas_decoration->getProps()->setStringValue("background", "rgba(0,0,0,0)");
294 _image.setSrcCanvas(_canvas_decoration);
296 // Decoration should be drawn first...
297 _canvas_decoration->createGroup("decoration");
299 // ...to allow drawing the actual content on top of the decoration
301 boost::dynamic_pointer_cast<simgear::canvas::Image>(
302 _canvas_decoration->getRootGroup()->createChild("image", "content")
304 _image_content->setSrcCanvas(content);
307 simgear::CSSBorder::Offsets const border =
308 _decoration_border.getAbsOffsets(content->getViewport());
310 int outer_width = border.l + content->getViewWidth() + border.r,
311 outer_height = border.t + content->getViewHeight() + border.b;
313 _canvas_decoration->setSizeX( outer_width );
314 _canvas_decoration->setSizeY( outer_height );
315 _canvas_decoration->setViewWidth( outer_width );
316 _canvas_decoration->setViewHeight( outer_height );
318 _image.set<int>("size[0]", outer_width);
319 _image.set<int>("size[1]", outer_height);
321 assert(_image_content);
322 _image_content->set<int>("x", border.l);
323 _image_content->set<int>("y", border.t);
326 } // namespace canvas