Files
2026-08-16 18:24:52 +07:00

261 lines
7.1 KiB
C++

// 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<CViewContainer*> (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<CViewContainer*> (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<CFrame*>(parent) == nullptr)
{
parentLayerView = dynamic_cast<CLayeredViewContainer*>(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<CViewContainer*> (getParentView ());
while (parent)
{
if (state)
parent->registerViewContainerListener (this);
else
parent->unregisterViewContainerListener (this);
parent = static_cast<CViewContainer*> (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<COffscreenContext*> (pContext))
drawsIntoBitmap = offscreenContext->getBitmap () != nullptr;
if (!layer || drawsIntoBitmap)
CViewContainer::drawRect (pContext, updateRect);
}
//-----------------------------------------------------------------------------
void CLayeredViewContainer::drawViewLayerRects (const PlatformGraphicsDeviceContextPtr& context,
double scaleFactor, const std::vector<CRect>& 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<CViewContainer*>;
CGraphicsTransform transform;
ParentViews parents;
auto frame = getFrame ();
auto* parent = static_cast<CViewContainer*> (getParentView ());
while (parent && parent != frame)
{
parents.push_front (parent);
parent = static_cast<CViewContainer*> (parent->getParentView ());
}
for (const auto& p : parents)
transform = p->getTransform () * transform;
auto self = static_cast<const CViewContainer*> (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);
}
}