/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
const drawinglayer::primitive2d::Primitive2DContainer& ScNoteOverlay::getOrCreatePrimitive2DSequence()
{ if (!maSequence.empty()) // sequence already created, return it return maSequence;
// get some local data ptrs
ScViewData& rViewData(mrScGridWindow.getViewData());
ScDocument& rDoc(rViewData.GetDocument());
ScDrawLayer* pScDrawLayer(rDoc.GetDrawLayer());
// use existing SdrPage - old version did allocate a SdrModel/SdrPage // for every visualization
SdrPage* pSdrPage(pScDrawLayer->GetPage(0)); if (nullptr == pSdrPage) return maSequence;
// when using existing SdrPage do not forget to save change state of // the DrawingLayer. Unfortunately CreateTempCaption below *does* add // the SdrObject to the SdrPage - not necessary for the model stuff, // but a comment there claims that else the text cannot be set (?) constbool bModelChanged(pScDrawLayer->IsChanged()); const tools::Rectangle aVisibleRectangle(calculateVisibleRectangle());
if (mxObject.is())
{ // get the primitives from it
mxObject->GetViewContact().getViewIndependentPrimitive2DContainer(maSequence);
// cleanup: remove again immediately
pSdrPage->NbcRemoveObject(mxObject->GetOrdNum());
// show the visualization with slight transparency staticbool bUseTransparency(true); if (bUseTransparency && !maSequence.empty())
{
maSequence = drawinglayer::primitive2d::Primitive2DContainer{
rtl::Reference<drawinglayer::primitive2d::UnifiedTransparencePrimitive2D>( new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(std::move(maSequence), 0.1))};
}
}
// restore changed state of DrawingLayer
pScDrawLayer->SetChanged(bModelChanged); return maSequence;
}
tools::Rectangle ScNoteOverlay::calculateVisibleRectangle()
{ // to not change anything for now in positioning/object // creation sticked together from previous versions. This // can (should) be converted to transformation stuff // later. In principle it calculates the size of the // merged WindowSpace (all SplitWindows) and transforms // that range to logical coordinates in one of the // ScGridWindow's const ScViewData& rViewData(mrScGridWindow.getViewData()); constbool bHSplit(SC_SPLIT_NONE != rViewData.GetHSplitMode()); constbool bVSplit(SC_SPLIT_NONE != rViewData.GetVSplitMode()); const ScTabView* pScTabView(rViewData.GetView()); const vcl::Window* pLeft(pScTabView->GetWindowByPos(bVSplit ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT)); const vcl::Window* pRight(bHSplit ? pScTabView->GetWindowByPos( bVSplit ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT ) : nullptr); const vcl::Window* pBottom(bVSplit ? pScTabView->GetWindowByPos( SC_SPLIT_BOTTOMLEFT ) : nullptr); const vcl::Window* pDiagonal((bHSplit && bVSplit) ? pScTabView->GetWindowByPos(SC_SPLIT_BOTTOMRIGHT) : nullptr);
assert(pLeft && "ScNoteOverlay - missing top-left grid window");
/* If caption is shown from right or bottom windows, adjust
mapmode to include size of top-left window. */
Size aSizePixel(pLeft->GetOutputSizePixel());
MapMode aMapMode(mrScGridWindow.GetDrawMapMode(true)); const Size aLeftSize(pLeft->PixelToLogic(aSizePixel, aMapMode));
Point aOrigin(aMapMode.GetOrigin());
if ((&mrScGridWindow == pRight) || (&mrScGridWindow == pDiagonal))
aOrigin.AdjustX(aLeftSize.Width());
if ((&mrScGridWindow == pBottom) || (&mrScGridWindow == pDiagonal))
aOrigin.AdjustY(aLeftSize.Height());
aMapMode.SetOrigin(aOrigin);
if (nullptr != pRight)
aSizePixel.AdjustWidth(pRight->GetOutputSizePixel().Width());
if (nullptr != pBottom)
aSizePixel.AdjustHeight(pBottom->GetOutputSizePixel().Height());
void ScNoteOverlay::createOverlaySubContent(
ScGridWindow* pTarget, const basegfx::B2DHomMatrix& rTransformToPixels, const basegfx::B2DPoint& rTopLeft)
{ // create additional visualization in given ScGridWindow // with given partial transform and discrete offset
rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager(pTarget->getOverlayManager()); if (!xOverlayManager.is()) // no OverlayManager, no visualization return;
// create a transformation from initial ScGridWindow for which the // visualization was created and in who's DrawMapMode it is to the // target ScGridWindow. That transformation spans over the merged // SplitWindow display. To do so, transform: // 1 from initial ScGridWindow logic DrawMapMode to discrete (pixels) // in the displaying window // 2 to merged SplitWindow display (may have different top-left) // 3 to window displaying target ScGridWindow // 4 to logic coordinates in its DrawMapMode // NOTE: 1+2 are already in rTransformToPixels
basegfx::B2DHomMatrix aTransformToTarget(rTransformToPixels);
aTransformToTarget.translate(-rTopLeft); const MapMode aOrig(pTarget->GetMapMode());
pTarget->SetMapMode(pTarget->GetDrawMapMode(true));
aTransformToTarget = pTarget->GetOutDev()->GetInverseViewTransformation() * aTransformToTarget;
pTarget->SetMapMode(aOrig);
// embed to TransformPrimitive
drawinglayer::primitive2d::Primitive2DContainer aSequence(getOrCreatePrimitive2DSequence());
aSequence = drawinglayer::primitive2d::Primitive2DContainer{
rtl::Reference<drawinglayer::primitive2d::TransformPrimitive2D>( new drawinglayer::primitive2d::TransformPrimitive2D(
aTransformToTarget,
std::move(aSequence)))};
// create OverlayObject
std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject( new sdr::overlay::OverlayPrimitive2DSequenceObject(
std::move(aSequence)));
// add to OverlayManager and local data holder (for // destruction)
xOverlayManager->add(*pOverlayObject);
maNoteOverlayGroup.append(std::move(pOverlayObject));
}
void ScNoteOverlay::createAdditionalRepresentations()
{ // check if we have a split at all const ScViewData& rViewData(mrScGridWindow.getViewData()); const ScTabView* pScTabView(rViewData.GetView()); constbool bHSplit(SC_SPLIT_NONE != rViewData.GetHSplitMode()); constbool bVSplit(SC_SPLIT_NONE != rViewData.GetVSplitMode());
if (!bHSplit && !bVSplit) // no split screen, no additional visualizations needed return;
if (getOrCreatePrimitive2DSequence().empty()) // no visualization, done return;
// if we have a split screen with multiple ScGridWindow's // the visualization might overlap with other ones than the // one this gets initially constructed. get the logic range // of the original visualization in the original ScGridWindow const drawinglayer::geometry::ViewInformation2D aViewInformation2D; const basegfx::B2DRange aContentRange(getOrCreatePrimitive2DSequence().getB2DRange(aViewInformation2D));
// prep values to be filled in own scope to not hold the vars
basegfx::B2DRange aGlobalPixel(aContentRange);
basegfx::B2DVector aTopLeftOffset;
basegfx::B2DHomMatrix aTransformToPixels;
{ // calculate general TopLeft offsets for potential other windows // from top-left window const ScSplitPos myScSplitPos(mrScGridWindow.getScSplitPos()); const ScGridWindow* pLeft(static_cast<ScGridWindow*>(
pScTabView->GetWindowByPos(bVSplit ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT)));
aTopLeftOffset.setX(pLeft->GetOutputSizePixel().Width());
aTopLeftOffset.setY(pLeft->GetOutputSizePixel().Height());
// create transformation from logic coordinates in original // ScGridWindow to discrete coordinates (pixels), then to // merged SplitWindow display const MapMode aOrig(mrScGridWindow.GetMapMode());
mrScGridWindow.SetMapMode(mrScGridWindow.GetDrawMapMode(true));
aTransformToPixels = mrScGridWindow.GetOutDev()->GetViewTransformation(); if (SC_SPLIT_TOPRIGHT == myScSplitPos || SC_SPLIT_BOTTOMRIGHT == myScSplitPos)
aTransformToPixels.translate(aTopLeftOffset.getX(), 0); if (SC_SPLIT_BOTTOMLEFT == myScSplitPos || SC_SPLIT_BOTTOMRIGHT == myScSplitPos)
aTransformToPixels.translate(0, aTopLeftOffset.getY());
aGlobalPixel.transform(aTransformToPixels);
mrScGridWindow.SetMapMode(aOrig);
}
// try all four possible ScGridWindows
ScGridWindow* pBottomLeft(static_cast<ScGridWindow*>(pScTabView->GetWindowByPos(SC_SPLIT_BOTTOMLEFT)));
// nothing to do when ScGridWindow does not exists or is same as // original ScGridWindow for which visualization is already done if (nullptr != pBottomLeft && pBottomLeft != &mrScGridWindow)
{ // calculate pixel range relative to merged SplitWindow display const basegfx::B2DPoint aTopLeft(0, bVSplit ? aTopLeftOffset.getY() : 0); const basegfx::B2DVector aSize(pBottomLeft->GetOutputSizePixel().Width(), pBottomLeft->GetOutputSizePixel().Height()); const basegfx::B2DRange aLocalPixel(aTopLeft, aTopLeft + aSize);
if(aLocalPixel.overlaps(aGlobalPixel))
{ // if needed visualization is visible there, create an OverlayObject there // with the same content but at corrected position
createOverlaySubContent(pBottomLeft, aTransformToPixels, aTopLeft);
}
}
rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager(
mrScGridWindow.getOverlayManager()); if (!xOverlayManager.is()) // no OverlayManager, no display return;
if (getOrCreatePrimitive2DSequence().empty()) // no visualization data, no display return;
// create OverlayObject for initial ScGridWindow
drawinglayer::primitive2d::Primitive2DContainer aSequence(
getOrCreatePrimitive2DSequence());
std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject( new sdr::overlay::OverlayPrimitive2DSequenceObject(
std::move(aSequence)));
// add to OverlayManager and local data holder (for // destruction)
xOverlayManager->add(*pNewOverlayObject);
maNoteOverlayGroup.append(std::move(pNewOverlayObject));
// check and evtl. create visualizations for other ScGridWindows // in SplitScreen mode
createAdditionalRepresentations();
}
ScNoteOverlay::~ScNoteOverlay()
{ // cleanup OverlayObjects - would also be done by destructor
maNoteOverlayGroup.clear();
// destruct temporary SdrObject. It *needs* to be kept alive // during visualization due to it being used for decompose // of the TextPrimitive. That is an old compromize in the // primitives: the text primitive is not self-contained in // the sense that it needs the SdrTextObj for decompose. // Would be hard to correct, but would be good for the future
mxObject.clear();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.