X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FCanvas%2Fwindow.cxx;h=012915faf80bbee9d5917093b3ee212b53d3b18f;hb=2beb0f29afba98c49606a4b929a49bda4f6db91a;hp=d0d72f509077262f9346908178e587b8b6ed2dc0;hpb=1b49f5cc78a1d431a38cb36ec3f35e0a96d60a1d;p=flightgear.git diff --git a/src/Canvas/window.cxx b/src/Canvas/window.cxx index d0d72f509..012915faf 100644 --- a/src/Canvas/window.cxx +++ b/src/Canvas/window.cxx @@ -16,21 +16,31 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +#include "canvas_mgr.hxx" #include "window.hxx" +#include
#include +#include #include +#include #include namespace canvas { + namespace sc = simgear::canvas; + + //---------------------------------------------------------------------------- + const std::string Window::TYPE_NAME = "window"; + //---------------------------------------------------------------------------- - Window::Window(SGPropertyNode* node): - PropertyBasedElement(node), - _image( simgear::canvas::CanvasPtr(), - node, - simgear::canvas::Style() ), + Window::Window( const simgear::canvas::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"), @@ -39,14 +49,6 @@ namespace canvas _resize_left(node, "resize-left"), _resize_status(node, "resize-status") { - _image.removeListener(); - - // TODO probably better remove default position and size - node->setFloatValue("x", 50); - node->setFloatValue("y", 100); - node->setFloatValue("size[0]", 400); - node->setFloatValue("size[1]", 300); - node->setFloatValue("source/right", 1); node->setFloatValue("source/bottom", 1); node->setBoolValue("source/normalized", true); @@ -55,13 +57,20 @@ namespace canvas //---------------------------------------------------------------------------- Window::~Window() { - + if( _canvas_decoration ) + _canvas_decoration->destroy(); } //---------------------------------------------------------------------------- void Window::update(double delta_time_sec) { - _image.update(delta_time_sec); + if( _attributes_dirty & DECORATION ) + { + updateDecoration(); + _attributes_dirty &= ~DECORATION; + } + + Image::update(delta_time_sec); } //---------------------------------------------------------------------------- @@ -71,48 +80,67 @@ namespace canvas if( node->getParent() == _node ) { handled = true; - if( node->getNameString() == "raise-top" ) - doRaise(node); - else if( node->getNameString() == "resize" ) + const std::string& name = node->getNameString(); + if( name == "resize" ) _resizable = node->getBoolValue(); - else if( node->getNameString() == "capture-events" ) + 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); + Image::valueChanged(node); } //---------------------------------------------------------------------------- osg::Group* Window::getGroup() { - return _image.getMatrixTransform(); + return getMatrixTransform(); } //---------------------------------------------------------------------------- - const SGRect& Window::getRegion() const + const SGVec2 Window::getPosition() const { - return _image.getRegion(); + const osg::Matrix& m = getMatrixTransform()->getMatrix(); + return SGVec2( m(3, 0), m(3, 1) ); } //---------------------------------------------------------------------------- - void Window::setCanvas(simgear::canvas::CanvasPtr canvas) + const SGRect Window::getScreenRegion() const { - _image.setSrcCanvas(canvas); + return getPosition() + getRegion(); } //---------------------------------------------------------------------------- - simgear::canvas::CanvasWeakPtr Window::getCanvas() const + void Window::setCanvasContent(sc::CanvasPtr canvas) { - return _image.getSrcCanvas(); + _canvas_content = canvas; + + if( _image_content ) + // Placement within decoration canvas + _image_content->setSrcCanvas(canvas); + else + setSrcCanvas(canvas); } //---------------------------------------------------------------------------- - bool Window::isVisible() const + sc::CanvasWeakPtr Window::getCanvasContent() const { - return _image.isVisible(); + return _canvas_content; + } + + //---------------------------------------------------------------------------- + sc::CanvasPtr Window::getCanvasDecoration() + { + return _canvas_decoration; } //---------------------------------------------------------------------------- @@ -128,13 +156,16 @@ namespace canvas } //---------------------------------------------------------------------------- - bool Window::handleMouseEvent(const simgear::canvas::MouseEventPtr& event) + void Window::raise() { - return _image.handleMouseEvent(event); + // 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& delta) + void Window::handleResize( uint8_t mode, + const osg::Vec2f& offset ) { if( mode == NONE ) { @@ -151,33 +182,130 @@ namespace canvas } if( mode & BOTTOM ) - _resize_bottom += delta.y(); + _resize_bottom = getRegion().b() + offset.y(); else if( mode & TOP ) - _resize_top += delta.y(); + _resize_top = getRegion().t() + offset.y(); if( mode & canvas::Window::RIGHT ) - _resize_right += delta.x(); + _resize_right = getRegion().r() + offset.x(); else if( mode & canvas::Window::LEFT ) - _resize_left += delta.x(); + _resize_left = getRegion().l() + offset.x(); } //---------------------------------------------------------------------------- - void Window::doRaise(SGPropertyNode* node_raise) + void Window::parseDecorationBorder(const std::string& str) { - if( node_raise && !node_raise->getBoolValue() ) + _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; + + sc::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; + } - BOOST_FOREACH(osg::Group* parent, getGroup()->getParents()) + if( !_canvas_decoration ) { - // Remove window... - parent->removeChild(getGroup()); + CanvasMgr* mgr = + dynamic_cast(globals->get_subsystem("Canvas")); + + if( !mgr ) + { + SG_LOG(SG_GENERAL, SG_WARN, "canvas::Window: no canvas manager!"); + return; + } - // ...and add again as topmost window - parent->addChild(getGroup()); + _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); } - if( node_raise ) - node_raise->setBoolValue(false); + sc::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? + + simgear::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("file", "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