From: Thomas Geymayer Date: Fri, 9 May 2014 14:01:25 +0000 (+0200) Subject: Canvas: move window from flightgear. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=23279b4d0aa04576b5b362f32a534eb494998b91;p=simgear.git Canvas: move window from flightgear. --- diff --git a/simgear/canvas/CMakeLists.txt b/simgear/canvas/CMakeLists.txt index 086c83cb..cbeffbaa 100644 --- a/simgear/canvas/CMakeLists.txt +++ b/simgear/canvas/CMakeLists.txt @@ -11,6 +11,7 @@ set(HEADERS CanvasObjectPlacement.hxx CanvasPlacement.hxx CanvasSystemAdapter.hxx + CanvasWindow.hxx MouseEvent.hxx ODGauge.hxx VGInitOperation.hxx @@ -24,6 +25,7 @@ set(SOURCES CanvasMgr.cxx CanvasObjectPlacement.cxx CanvasPlacement.cxx + CanvasWindow.cxx ODGauge.cxx VGInitOperation.cxx ) diff --git a/simgear/canvas/CanvasMgr.hxx b/simgear/canvas/CanvasMgr.hxx index 084364e3..51ffa576 100644 --- a/simgear/canvas/CanvasMgr.hxx +++ b/simgear/canvas/CanvasMgr.hxx @@ -33,7 +33,7 @@ namespace canvas public: /** - * @param node Root node of branch used to control canvasses + * @param node Root node of branch used to control canvasses */ CanvasMgr(SGPropertyNode_ptr node); diff --git a/simgear/canvas/CanvasSystemAdapter.hxx b/simgear/canvas/CanvasSystemAdapter.hxx index a5c18487..2492bb91 100644 --- a/simgear/canvas/CanvasSystemAdapter.hxx +++ b/simgear/canvas/CanvasSystemAdapter.hxx @@ -21,6 +21,8 @@ #include "canvas_fwd.hxx" +class SGSubsystem; + namespace simgear { namespace HTTP { class Client; } @@ -36,6 +38,7 @@ namespace canvas virtual void addCamera(osg::Camera* camera) const = 0; virtual void removeCamera(osg::Camera* camera) const = 0; virtual osg::Image* getImage(const std::string& path) const = 0; + virtual SGSubsystem* getSubsystem(const std::string& name) const = 0; virtual HTTP::Client* getHTTPClient() const = 0; }; diff --git a/simgear/canvas/CanvasWindow.cxx b/simgear/canvas/CanvasWindow.cxx new file mode 100644 index 00000000..55f4d9b7 --- /dev/null +++ b/simgear/canvas/CanvasWindow.cxx @@ -0,0 +1,315 @@ +// Window for placing a Canvas onto it (for dialogs, menus, etc.) +// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#include "CanvasMgr.hxx" +#include "CanvasSystemAdapter.hxx" +#include "CanvasWindow.hxx" + +#include +#include + +#include + +#include +#include + +namespace simgear +{ +namespace canvas +{ + + //---------------------------------------------------------------------------- + const std::string Window::TYPE_NAME = "window"; + + //---------------------------------------------------------------------------- + Window::Window( const CanvasWeakPtr& canvas, + const SGPropertyNode_ptr& node, + const Style& parent_style, + Element* parent ): + Image(canvas, node, parent_style, parent), + _attributes_dirty(0), + _resizable(false), + _capture_events(true), + _resize_top(node, "resize-top"), + _resize_right(node, "resize-right"), + _resize_bottom(node, "resize-bottom"), + _resize_left(node, "resize-left"), + _resize_status(node, "resize-status") + { + node->setFloatValue("source/right", 1); + node->setFloatValue("source/bottom", 1); + node->setBoolValue("source/normalized", true); + } + + //---------------------------------------------------------------------------- + Window::~Window() + { + if( _canvas_decoration ) + _canvas_decoration->destroy(); + } + + //---------------------------------------------------------------------------- + void Window::update(double delta_time_sec) + { + if( _attributes_dirty & DECORATION ) + { + updateDecoration(); + _attributes_dirty &= ~DECORATION; + } + + Image::update(delta_time_sec); + } + + //---------------------------------------------------------------------------- + void Window::valueChanged(SGPropertyNode * node) + { + bool handled = false; + if( node->getParent() == _node ) + { + handled = true; + const std::string& name = node->getNameString(); + if( name == "resize" ) + _resizable = node->getBoolValue(); + else if( name == "update" ) + update(0); + else if( name == "capture-events" ) + _capture_events = node->getBoolValue(); + else if( name == "decoration-border" ) + parseDecorationBorder(node->getStringValue()); + else if( boost::starts_with(name, "shadow-") + || name == "content-size" ) + _attributes_dirty |= DECORATION; + else + handled = false; + } + + if( !handled ) + Image::valueChanged(node); + } + + //---------------------------------------------------------------------------- + osg::Group* Window::getGroup() + { + return getMatrixTransform(); + } + + //---------------------------------------------------------------------------- + const SGVec2 Window::getPosition() const + { + const osg::Matrix& m = getMatrixTransform()->getMatrix(); + return SGVec2( m(3, 0), m(3, 1) ); + } + + //---------------------------------------------------------------------------- + const SGRect Window::getScreenRegion() const + { + return getPosition() + getRegion(); + } + + //---------------------------------------------------------------------------- + void Window::setCanvasContent(CanvasPtr canvas) + { + _canvas_content = canvas; + + if( _image_content ) + // Placement within decoration canvas + _image_content->setSrcCanvas(canvas); + else + setSrcCanvas(canvas); + } + + //---------------------------------------------------------------------------- + CanvasWeakPtr Window::getCanvasContent() const + { + return _canvas_content; + } + + //---------------------------------------------------------------------------- + CanvasPtr Window::getCanvasDecoration() const + { + return _canvas_decoration; + } + + //---------------------------------------------------------------------------- + bool Window::isResizable() const + { + return _resizable; + } + + //---------------------------------------------------------------------------- + bool Window::isCapturingEvents() const + { + return _capture_events; + } + + //---------------------------------------------------------------------------- + void Window::raise() + { + // on writing the z-index the window always is moved to the top of all other + // windows with the same z-index. + set("z-index", get("z-index", 0)); + } + + //---------------------------------------------------------------------------- + void Window::handleResize( uint8_t mode, + const osg::Vec2f& offset ) + { + if( mode == NONE ) + { + _resize_status = 0; + return; + } + else if( mode & INIT ) + { + _resize_top = getRegion().t(); + _resize_right = getRegion().r(); + _resize_bottom = getRegion().b(); + _resize_left = getRegion().l(); + _resize_status = 1; + } + + if( mode & BOTTOM ) + _resize_bottom = getRegion().b() + offset.y(); + else if( mode & TOP ) + _resize_top = getRegion().t() + offset.y(); + + if( mode & canvas::Window::RIGHT ) + _resize_right = getRegion().r() + offset.x(); + else if( mode & canvas::Window::LEFT ) + _resize_left = getRegion().l() + offset.x(); + } + + //---------------------------------------------------------------------------- + void Window::parseDecorationBorder(const std::string& str) + { + _decoration_border = simgear::CSSBorder::parse(str); + _attributes_dirty |= DECORATION; + } + + //---------------------------------------------------------------------------- + void Window::updateDecoration() + { + int shadow_radius = get("shadow-radius") + 0.5; + if( shadow_radius < 2 ) + shadow_radius = 0; + + CanvasPtr content = _canvas_content.lock(); + SGRect content_view + ( + 0, + 0, + get("content-size[0]", content ? content->getViewWidth() : 400), + get("content-size[1]", content ? content->getViewHeight() : 300) + ); + + if( _decoration_border.isNone() && !shadow_radius ) + { + setSrcCanvas(content); + set("size[0]", content_view.width()); + set("size[1]", content_view.height()); + + _image_content.reset(); + _image_shadow.reset(); + if( _canvas_decoration ) + _canvas_decoration->destroy(); + _canvas_decoration.reset(); + return; + } + + if( !_canvas_decoration ) + { + CanvasMgr* mgr = dynamic_cast( + Canvas::getSystemAdapter()->getSubsystem("Canvas") + ); + + if( !mgr ) + { + SG_LOG(SG_GENERAL, SG_WARN, "canvas::Window: no canvas manager!"); + return; + } + + _canvas_decoration = mgr->createCanvas("window-decoration"); + _canvas_decoration->getProps() + ->setStringValue("background", "rgba(0,0,0,0)"); + setSrcCanvas(_canvas_decoration); + + _image_content = _canvas_decoration->getRootGroup() + ->createChild("content"); + _image_content->setSrcCanvas(content); + + // Draw content on top of decoration + _image_content->set("z-index", 1); + } + + GroupPtr group_decoration = + _canvas_decoration->getOrCreateGroup("decoration"); + group_decoration->set("tf/t[0]", shadow_radius); + group_decoration->set("tf/t[1]", shadow_radius); + // TODO do we need clipping or shall we trust the decorator not to draw over + // the shadow? + + CSSBorder::Offsets const border = + _decoration_border.getAbsOffsets(content_view); + + int shad2 = 2 * shadow_radius, + outer_width = border.l + content_view.width() + border.r + shad2, + outer_height = border.t + content_view.height() + border.b + shad2; + + _canvas_decoration->setSizeX( outer_width ); + _canvas_decoration->setSizeY( outer_height ); + _canvas_decoration->setViewWidth( outer_width ); + _canvas_decoration->setViewHeight( outer_height ); + + set("size[0]", outer_width - shad2); + set("size[1]", outer_height - shad2); + set("outset", shadow_radius); + + assert(_image_content); + _image_content->set("x", shadow_radius + border.l); + _image_content->set("y", shadow_radius + border.t); + _image_content->set("size[0]", content_view.width()); + _image_content->set("size[1]", content_view.height()); + + if( !shadow_radius ) + { + if( _image_shadow ) + { + _image_shadow->destroy(); + _image_shadow.reset(); + } + return; + } + + int shadow_inset = std::max(get("shadow-inset") + 0.5, 0), + slice_width = shadow_radius + shadow_inset; + + _image_shadow = _canvas_decoration->getRootGroup() + ->getOrCreateChild("shadow"); + _image_shadow->set("src", "gui/images/shadow.png"); + _image_shadow->set("slice", 7); + _image_shadow->set("fill", "#000000"); + _image_shadow->set("slice-width", slice_width); + _image_shadow->set("size[0]", outer_width); + _image_shadow->set("size[1]", outer_height); + + // Draw shadow below decoration + _image_shadow->set("z-index", -1); + } + +} // namespace canvas +} // namespace simgear diff --git a/simgear/canvas/CanvasWindow.hxx b/simgear/canvas/CanvasWindow.hxx new file mode 100644 index 00000000..74bdf33f --- /dev/null +++ b/simgear/canvas/CanvasWindow.hxx @@ -0,0 +1,126 @@ +// Window for placing a Canvas onto it (for dialogs, menus, etc.) +// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#ifndef CANVAS_WINDOW_HXX_ +#define CANVAS_WINDOW_HXX_ + +#include +#include +#include +#include +#include + +#include +#include + +namespace simgear +{ +namespace canvas +{ + + class Window: + public Image + { + public: + static const std::string TYPE_NAME; + + enum Resize + { + NONE = 0, + LEFT = 1, + RIGHT = LEFT << 1, + TOP = RIGHT << 1, + BOTTOM = TOP << 1, + INIT = BOTTOM << 1 + }; + + /** + * @param node Property node containing settings for this window: + * capture-events Disable/Enable event capturing + * content-size[0-1] Size of content area (excluding + * decoration border) + * decoration-border Size of decoration border + * resize Enable resize cursor and properties + * shadow-inset Inset of shadow image + * shadow-radius Radius/outset of shadow image + */ + Window( const CanvasWeakPtr& canvas, + const SGPropertyNode_ptr& node, + const Style& parent_style = Style(), + Element* parent = 0 ); + virtual ~Window(); + + virtual void update(double delta_time_sec); + virtual void valueChanged(SGPropertyNode* node); + + osg::Group* getGroup(); + const SGVec2 getPosition() const; + const SGRect getScreenRegion() const; + + void setCanvasContent(CanvasPtr canvas); + simgear::canvas::CanvasWeakPtr getCanvasContent() const; + + CanvasPtr getCanvasDecoration() const; + + bool isResizable() const; + bool isCapturingEvents() const; + + /** + * Moves window on top of all other windows with the same z-index. + * + * @note If no z-index is set it defaults to 0. + */ + void raise(); + + void handleResize( uint8_t mode, + const osg::Vec2f& offset = osg::Vec2f() ); + + protected: + + enum Attributes + { + DECORATION = 1 + }; + + uint32_t _attributes_dirty; + + CanvasPtr _canvas_decoration; + CanvasWeakPtr _canvas_content; + + ImagePtr _image_content, + _image_shadow; + + bool _resizable, + _capture_events; + + PropertyObject _resize_top, + _resize_right, + _resize_bottom, + _resize_left, + _resize_status; + + CSSBorder _decoration_border; + + void parseDecorationBorder(const std::string& str); + void updateDecoration(); + }; + +} // namespace canvas +} // namespace simgear + +#endif /* CANVAS_WINDOW_HXX_ */ diff --git a/simgear/canvas/canvas_fwd.hxx b/simgear/canvas/canvas_fwd.hxx index d91696eb..6b34e028 100644 --- a/simgear/canvas/canvas_fwd.hxx +++ b/simgear/canvas/canvas_fwd.hxx @@ -49,6 +49,7 @@ namespace canvas SG_FWD_DECL(Map) SG_FWD_DECL(Path) SG_FWD_DECL(Text) + SG_FWD_DECL(Window) #undef SG_FWD_DECL