// This file is part of VSTGUI. It is subject to the license terms // in the LICENSE file found in the top-level directory of this // distribution and at http://github.com/steinbergmedia/vstgui/LICENSE #include "clayeredviewcontainer.h" #include "cframe.h" #include "cdrawcontext.h" #include "coffscreencontext.h" #include "platform/iplatformframe.h" namespace VSTGUI { //----------------------------------------------------------------------------- CLayeredViewContainer::CLayeredViewContainer (const CRect& r) : CViewContainer (r) { } //----------------------------------------------------------------------------- void CLayeredViewContainer::setZIndex (uint32_t _zIndex) { if (_zIndex != zIndex) { zIndex = _zIndex; if (layer) layer->setZIndex (zIndex); } } //----------------------------------------------------------------------------- void CLayeredViewContainer::updateLayerSize () { if (!layer) return; CRect newSize = getViewSize (); getTransform ().transform (newSize); auto frame = getFrame (); auto* parent = static_cast (getParentView ()); while (parent && parent != frame) { CRect parentSize = parent->getViewSize (); parent->getTransform ().transform (newSize); newSize.offset (parentSize.left, parentSize.top); newSize.bound (parentSize); parent = static_cast (parent->getParentView ()); } frame->getTransform ().transform (newSize); if (parentLayerView) { CPoint p (parentLayerView->getVisibleViewSize ().getTopLeft ()); parentLayerView->translateToGlobal (p); newSize.offsetInverse (p); } if (layer) layer->setSize (newSize); } //----------------------------------------------------------------------------- bool CLayeredViewContainer::removed (CView* parent) { if (!isAttached ()) return false; registerListeners (false); if (layer) { layer = nullptr; parentLayerView = nullptr; getFrame ()->unregisterScaleFactorChangedListener (this); } return CViewContainer::removed (parent); } //----------------------------------------------------------------------------- bool CLayeredViewContainer::attached (CView* parent) { if (isAttached ()) return false; setParentView (parent); setParentFrame (parent->getFrame ()); if (auto frame = getFrame ()) { while (parent && dynamic_cast(parent) == nullptr) { parentLayerView = dynamic_cast(parent); if (parentLayerView) { break; } parent = parent->getParentView (); } layer = frame->getPlatformFrame ()->createPlatformViewLayer (this, parentLayerView ? parentLayerView->layer : nullptr); if (layer) { layer->setZIndex (zIndex); layer->setAlpha (getAlphaValue ()); updateLayerSize (); frame->registerScaleFactorChangedListener (this); } } parent = getParentView (); registerListeners (true); setParentView (nullptr); setParentFrame (nullptr); return CViewContainer::attached (parent); } //----------------------------------------------------------------------------- void CLayeredViewContainer::registerListeners (bool state) { auto* parent = static_cast (getParentView ()); while (parent) { if (state) parent->registerViewContainerListener (this); else parent->unregisterViewContainerListener (this); parent = static_cast (parent->getParentView ()); } } //----------------------------------------------------------------------------- void CLayeredViewContainer::viewContainerTransformChanged (CViewContainer* container) { updateLayerSize (); } //----------------------------------------------------------------------------- void CLayeredViewContainer::invalid () { CRect r = getViewSize (); r.originize (); invalidRect (r); } //----------------------------------------------------------------------------- void CLayeredViewContainer::invalidRect (const CRect& rect) { if (layer) { CRect r (rect); getDrawTransform ().transform (r); layer->invalidRect (r); } else { CViewContainer::invalidRect (rect); } } //----------------------------------------------------------------------------- void CLayeredViewContainer::parentSizeChanged () { CViewContainer::parentSizeChanged (); if (layer) { updateLayerSize (); invalid (); } } //----------------------------------------------------------------------------- void CLayeredViewContainer::setViewSize (const CRect& rect, bool invalid) { CViewContainer::setViewSize (rect, invalid); updateLayerSize (); } //----------------------------------------------------------------------------- void CLayeredViewContainer::setAlphaValue (float alpha) { if (layer) { setAlphaValueNoInvalidate (alpha); layer->setAlpha (alpha); } else CViewContainer::setAlphaValue (alpha); } //----------------------------------------------------------------------------- void CLayeredViewContainer::drawRect (CDrawContext* pContext, const CRect& updateRect) { auto drawsIntoBitmap = false; if (auto offscreenContext = dynamic_cast (pContext)) drawsIntoBitmap = offscreenContext->getBitmap () != nullptr; if (!layer || drawsIntoBitmap) CViewContainer::drawRect (pContext, updateRect); } //----------------------------------------------------------------------------- void CLayeredViewContainer::drawViewLayerRects (const PlatformGraphicsDeviceContextPtr& context, double scaleFactor, const std::vector& rects) { CGraphicsTransform drawTransform = getDrawTransform (); CRect visibleSize = getVisibleViewSize (); CRect viewSize = getViewSize (); CPoint p (viewSize.left < 0 ? viewSize.left - visibleSize.left : visibleSize.left, viewSize.top < 0 ? viewSize.top - visibleSize.top : visibleSize.top); auto surfaceSize = getViewSize (); surfaceSize.originize (); CDrawContext drawContext (context, surfaceSize, scaleFactor); CDrawContext::Transform transform ( drawContext, drawTransform * CGraphicsTransform ().translate (-p.x, -p.y)); for (auto dirtyRect : rects) { drawTransform.inverse ().transform (dirtyRect); dirtyRect.offset (p.x, p.y); drawContext.saveGlobalState (); drawContext.setClipRect (dirtyRect); CViewContainer::drawRect (&drawContext, dirtyRect); drawContext.restoreGlobalState (); } } //----------------------------------------------------------------------------- CGraphicsTransform CLayeredViewContainer::getDrawTransform () const { using ParentViews = std::list; CGraphicsTransform transform; ParentViews parents; auto frame = getFrame (); auto* parent = static_cast (getParentView ()); while (parent && parent != frame) { parents.push_front (parent); parent = static_cast (parent->getParentView ()); } for (const auto& p : parents) transform = p->getTransform () * transform; auto self = static_cast (this); if (self) transform = self->getTransform () * transform; if (frame) transform = frame->getTransform () * transform; return transform; } //----------------------------------------------------------------------------- void CLayeredViewContainer::onScaleFactorChanged (CFrame* frame, double newScaleFactor) { if (layer) layer->onScaleFactorChanged (newScaleFactor); } }