Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  svdpntv.cxx   Sprache: C

 
/* -*- 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 .
 */


#include <memory>
#include <svx/svdpntv.hxx>
#include <vcl/weld.hxx>
#include <vcl/window.hxx>
#include <svx/sdrpaintwindow.hxx>
#include <svx/svdmodel.hxx>

#include <svx/svdpage.hxx>
#include <svx/svdpagv.hxx>
#include <svl/hint.hxx>

#include <svx/svdview.hxx>
#include <svx/svdglue.hxx>
#include <svx/svdobj.hxx>
#include <sxlayitm.hxx>
#include <svl/itemiter.hxx>
#include <editeng/eeitem.hxx>
#include <svl/whiter.hxx>
#include <svl/style.hxx>
#include <svx/sdrpagewindow.hxx>
#include <vcl/svapp.hxx>
#include <svx/sdr/contact/objectcontact.hxx>
#include <svx/sdr/animation/objectanimator.hxx>
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
#include <drawinglayer/converters.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <comphelper/lok.hxx>
#include <svx/svdviter.hxx>
#include <osl/diagnose.h>
#include <officecfg/Office/Common.hxx>

using namespace ::com::sun::star;

// interface to SdrPaintWindow

SdrPaintWindow* SdrPaintView::FindPaintWindow(const OutputDevice& rOut) const
{
    // back to loop - there is more to test than a std::find_if and a lambda can do
    for(auto& candidate : maPaintWindows)
    {
        if(&(candidate->GetOutputDevice()) == &rOut)
        {
            return candidate.get();
        }

        // check for patched to allow finding in that state, too
        if(nullptr != candidate->getPatched() && &(candidate->getPatched()->GetOutputDevice()) == &rOut)
        {
            return candidate->getPatched();
        }
    }

    return nullptr;
}

SdrPaintWindow* SdrPaintView::GetPaintWindow(sal_uInt32 nIndex) const
{
    return maPaintWindows[nIndex].get();
}

void SdrPaintView::DeletePaintWindow(const SdrPaintWindow& rOld)
{
    auto aFindResult = ::std::find_if(maPaintWindows.begin(), maPaintWindows.end(),
                            [&](const std::unique_ptr<SdrPaintWindow>& p) { return p.get() == &rOld; });

    if(aFindResult != maPaintWindows.end())
    {
        maPaintWindows.erase(aFindResult);
    }
}

OutputDevice* SdrPaintView::GetFirstOutputDevice() const
{
    if(PaintWindowCount())
    {
        return &(GetPaintWindow(0)->GetOutputDevice());
    }

    return nullptr;
}


SvxViewChangedHint::SvxViewChangedHint() : SfxHint(SfxHintId::SvxViewChanged)
{
}


BitmapEx convertMetafileToBitmapEx(
    const GDIMetaFile& rMtf,
    const basegfx::B2DRange& rTargetRange,
    const sal_uInt32 nMaximumQuadraticPixels)
{
    BitmapEx aBitmapEx;

    if(rMtf.GetActionSize())
    {
        const drawinglayer::primitive2d::Primitive2DReference aMtf(
            new drawinglayer::primitive2d::MetafilePrimitive2D(
                basegfx::utils::createScaleTranslateB2DHomMatrix(
                    rTargetRange.getRange(),
                    rTargetRange.getMinimum()),
                rMtf));
        aBitmapEx = drawinglayer::convertPrimitive2DContainerToBitmapEx(
            drawinglayer::primitive2d::Primitive2DContainer { aMtf },
            rTargetRange,
            nMaximumQuadraticPixels);
    }

    return aBitmapEx;
}

SdrPaintView::SdrPaintView(SdrModel& rSdrModel, OutputDevice* pOut)
    : mrModel(rSdrModel)
    , mpActualOutDev(nullptr)
    , mpDragWin(nullptr)
    , mpDefaultStyleSheet(nullptr)
    , maDefaultAttr(rSdrModel.GetItemPool())
    , maComeBackIdle( "svx::SdrPaintView aComeBackIdle" )
    , meAnimationMode(SdrAnimationMode::Animate)
    , mnHitTolPix(2)
    , mnMinMovPix(3)
    , mnHitTolLog(0)
    , mnMinMovLog(0)
    , mbPageVisible(true)
    , mbPageShadowVisible(true)
    , mbPageBorderVisible(true)
    , mbBordVisible(true)
    , mbGridVisible(true)
    , mbGridFront(false)
    , mbHlplVisible(true)
    , mbHlplFront(true)
    , mbGlueVisible(false)
    , mbGlueVisible2(false)
    , mbGlueVisible3(false)
    , mbGlueVisible4(false)
    , mbSomeObjChgdFlag(false)
    , mbSwapAsynchron(false)
    , mbPrintPreview(false)
    , mbAnimationPause(false)
    , mbBufferedOutputAllowed(false)
    , mbBufferedOverlayAllowed(false)
    , mbPageDecorationAllowed(true)
    , mbMasterPageVisualizationAllowed(true)
    , mbPreviewRenderer(false)
    , mbHideOle(false)
    , mbHideChart(false)
    , mbHideDraw(false)
    , mbHideFormControl(false)
    , mbHideBackground(false)
    , mbPaintTextEdit(true)
    , maGridColor(COL_BLACK)
{
    maComeBackIdle.SetPriority(TaskPriority::REPAINT);
    maComeBackIdle.SetInvokeHandler(LINK(this,SdrPaintView,ImpComeBackHdl));

    SetDefaultStyleSheet(GetModel().GetDefaultStyleSheet(), true);

    if (pOut)
        AddDeviceToPaintView(*pOut, nullptr);

    maColorConfig.AddListener(this);
    onChangeColorConfig();
}

SdrPaintView::~SdrPaintView()
{
    if (mpDefaultStyleSheet)
        EndListening(*mpDefaultStyleSheet);

    maColorConfig.RemoveListener(this);
    ClearPageView();

    // delete existing SdrPaintWindows
    maPaintWindows.clear();
}


void SdrPaintView::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
{
    //If the stylesheet has been destroyed
    if (&rBC == mpDefaultStyleSheet)
    {
        if (rHint.GetId() == SfxHintId::Dying)
            mpDefaultStyleSheet = nullptr;
        return;
    }

    if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
        return;
    const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint);
    SdrHintKind eKind = pSdrHint->GetKind();
    if (eKind==SdrHintKind::ObjectChange || eKind==SdrHintKind::ObjectInserted || eKind==SdrHintKind::ObjectRemoved)
    {
        bool bObjChg = !mbSomeObjChgdFlag; // if true, evaluate for ComeBack timer
        if (bObjChg)
        {
            mbSomeObjChgdFlag=true;
            const SdrModel& rModel = GetModel();
            if (rModel.IsWriterIdle())
            {
                // We're inside Writer idle layout: don't pick a high priority.
                maComeBackIdle.SetPriority(TaskPriority::DEFAULT_IDLE);
            }
            else
            {
                maComeBackIdle.SetPriority(TaskPriority::REPAINT);
            }
            maComeBackIdle.Start();
        }
    }

    if (eKind==SdrHintKind::PageOrderChange)
    {
        const SdrPage* pPg=pSdrHint->GetPage();
        if (pPg && !pPg->IsInserted())
        {
            if(mpPageView && mpPageView->GetPage() == pPg)
            {
                HideSdrPage();
            }
        }
    }
}

void SdrPaintView::ConfigurationChanged( ::utl::ConfigurationBroadcaster* , ConfigurationHints eHint)
{
    if (eHint == ConfigurationHints::OnlyCurrentDocumentColorScheme)
        return;
    onChangeColorConfig();
    InvalidateAllWin();
}

IMPL_LINK_NOARG(SdrPaintView, ImpComeBackHdl, Timer *, void)
{
    if (mbSomeObjChgdFlag) {
        mbSomeObjChgdFlag=false;
        ModelHasChanged();
    }
}

void SdrPaintView::FlushComeBackTimer() const
{
    if (mbSomeObjChgdFlag) {
        // casting to nonconst
        const_cast<SdrPaintView*>(this)->ImpComeBackHdl(&const_cast<SdrPaintView*>(this)->maComeBackIdle);
        const_cast<SdrPaintView*>(this)->maComeBackIdle.Stop();
    }
}

void SdrPaintView::ModelHasChanged()
{
    // broadcast to all PageViews
    if(mpPageView && !mpPageView->GetPage()->IsInserted())
    {
        HideSdrPage();
    }

    // test mpPageView here again, HideSdrPage() may have invalidated it.
    if(mpPageView)
    {
        mpPageView->ModelHasChanged();
    }
}


bool SdrPaintView::IsAction() const
{
    return false;
}

void SdrPaintView::MovAction(const Point&)
{
}

void SdrPaintView::EndAction()
{
}

void SdrPaintView::BckAction()
{
}

void SdrPaintView::BrkAction()
{
}

void SdrPaintView::TakeActionRect(tools::Rectangle&) const
{
}


// info about TextEdit. Default is false.
bool SdrPaintView::IsTextEdit() const
{
    return false;
}

sal_uInt16 SdrPaintView::ImpGetMinMovLogic(short nMinMov, const OutputDevice* pOut) const
{
    if (nMinMov>=0) return sal_uInt16(nMinMov);
    if (pOut==nullptr)
    {
        pOut = GetFirstOutputDevice();
    }
    if (pOut!=nullptr) {
        return short(-pOut->PixelToLogic(Size(nMinMov,0)).Width());
    } else {
        return 0;
    }
}

sal_uInt16 SdrPaintView::ImpGetHitTolLogic(short nHitTol, const OutputDevice* pOut) const
{
    if (nHitTol>=0) return sal_uInt16(nHitTol);
    if (pOut==nullptr)
    {
        pOut = GetFirstOutputDevice();
    }
    if (pOut!=nullptr) {
        return short(-pOut->PixelToLogic(Size(nHitTol,0)).Width());
    } else {
        return 0;
    }
}

void SdrPaintView::TheresNewMapMode()
{
    if (mpActualOutDev) {
        if (comphelper::LibreOfficeKit::isActive())
        {
            mnHitTolLog=static_cast<sal_uInt16>(OutputDevice::LogicToLogic(Size(mnHitTolPix,0), MapMode(MapUnit::MapPixel), mpActualOutDev->GetMapMode()).Width());
            mnMinMovLog=static_cast<sal_uInt16>(OutputDevice::LogicToLogic(Size(mnMinMovPix,0), MapMode(MapUnit::MapPixel), mpActualOutDev->GetMapMode()).Width());
        }
        else
        {
            mnHitTolLog=static_cast<sal_uInt16>(mpActualOutDev->PixelToLogic(Size(mnHitTolPix,0)).Width());
            mnMinMovLog=static_cast<sal_uInt16>(mpActualOutDev->PixelToLogic(Size(mnMinMovPix,0)).Width());
        }
    }
}

void SdrPaintView::SetActualWin(const OutputDevice* pWin)
{
    mpActualOutDev = const_cast<OutputDevice *>(pWin);
    TheresNewMapMode();
}


void SdrPaintView::ClearPageView()
{
    BrkAction();

    if(mpPageView)
    {
        InvalidateAllWin();
        mpPageView.reset();
    }
}

SdrPageView* SdrPaintView::ShowSdrPage(SdrPage* pPage)
{
    if(pPage && (!mpPageView || mpPageView->GetPage() != pPage))
    {
        if(mpPageView)
        {
            InvalidateAllWin();
            mpPageView.reset();
        }

        if (SdrView *pView = dynamic_cast<SdrView*>(this))
        {
            mpPageView.reset(new SdrPageView(pPage, *pView));
            mpPageView->Show();
        }
    }

    return mpPageView.get();
}

void SdrPaintView::HideSdrPage()
{
    if(mpPageView)
    {
        mpPageView->Hide();
        mpPageView.reset();
    }
}

void SdrPaintView::AddDeviceToPaintView(OutputDevice& rNewDev, vcl::Window *pWindow)
{
    SdrPaintWindow* pNewPaintWindow = new SdrPaintWindow(*this, rNewDev, pWindow);
    maPaintWindows.emplace_back(pNewPaintWindow);

    if(mpPageView)
    {
        mpPageView->AddPaintWindowToPageView(*pNewPaintWindow);
    }
}

void SdrPaintView::DeleteDeviceFromPaintView(OutputDevice& rOldDev)
{
    SdrPaintWindow* pCandidate = FindPaintWindow(rOldDev);

    if(pCandidate)
    {
        if(mpPageView)
        {
            mpPageView->RemovePaintWindowFromPageView(*pCandidate);
        }

        DeletePaintWindow(*pCandidate);
    }
}

void SdrPaintView::SetLayerVisible(const OUString& rName, bool bShow)
{
    const bool bChanged = mpPageView && mpPageView->SetLayerVisible(rName, bShow);
    if (!bChanged)
        return;
    InvalidateAllWin();
}

bool SdrPaintView::IsLayerVisible(const OUString& rName) const
{
    return mpPageView && mpPageView->IsLayerVisible(rName);
}

void SdrPaintView::SetLayerLocked(const OUString& rName, bool bLock)
{
    if(mpPageView)
    {
        mpPageView->SetLayerLocked(rName,bLock);
    }
}

bool SdrPaintView::IsLayerLocked(const OUString& rName) const
{
    if(mpPageView)
    {
        return mpPageView->IsLayerLocked(rName);
    }

    return false;
}

void SdrPaintView::SetLayerPrintable(const OUString& rName, bool bPrn)
{
    if(mpPageView)
    {
        mpPageView->SetLayerPrintable(rName,bPrn);
    }
}

bool SdrPaintView::IsLayerPrintable(const OUString& rName) const
{
    if(mpPageView)
    {
        return mpPageView->IsLayerPrintable(rName);
    }

    return false;
}

void SdrPaintView::PrePaint()
{
    if(mpPageView)
    {
        mpPageView->PrePaint();
    }
}


// #define SVX_REPAINT_TIMER_TEST

void SdrPaintView::CompleteRedraw(OutputDevice* pOut, const vcl::Region& rReg, sdr::contact::ViewObjectContactRedirector* pRedirector)
{
#ifdef SVX_REPAINT_TIMER_TEST
#define REMEMBERED_TIMES_COUNT  (10)
    static bool bDoTimerTest(false);
    static bool bTimesInited(false);
    static sal_uInt32 nRepeatCount(10);
    static double fLastTimes[REMEMBERED_TIMES_COUNT];
    const sal_uInt64 nStartTime(tools::Time::GetSystemTicks());
    sal_uInt32 count(1);
    sal_uInt32 a;

    if(bDoTimerTest)
    {
        count = nRepeatCount;
    }

    for(a = 0; a < count; a++)
    {
#endif // SVX_REPAINT_TIMER_TEST

    // #i74769# check if pOut is a win and has a ClipRegion. If Yes, the Region
    // rReg may be made more granular (fine) with using it. Normally, rReg
    // does come from Window::Paint() anyways and thus is based on a single
    // rectangle which was derived from exactly that repaint region
    vcl::Region aOptimizedRepaintRegion(rReg);

    if(pOut && OUTDEV_WINDOW == pOut->GetOutDevType())
    {
        vcl::Window* pWindow = pOut->GetOwnerWindow();

        if(pWindow->IsInPaint())
        {
            if(!pWindow->GetPaintRegion().IsEmpty())
            {
                aOptimizedRepaintRegion.Intersect(pWindow->GetPaintRegion());
            }
        }
    }

    SdrPaintWindow* pPaintWindow = BeginCompleteRedraw(pOut);
    assert(pPaintWindow && "SdrPaintView::CompleteRedraw: No OutDev (!)");

    DoCompleteRedraw(*pPaintWindow, aOptimizedRepaintRegion, pRedirector);
    EndCompleteRedraw(*pPaintWindow, true);

#ifdef SVX_REPAINT_TIMER_TEST
    }

    if(bDoTimerTest)
    {
        const sal_uInt64 nStopTime(tools::Time::GetSystemTicks());
        const sal_uInt64 nNeededTime(nStopTime - nStartTime);
        const double fTimePerPaint((double)nNeededTime / (double)nRepeatCount);

        if(!bTimesInited)
        {
            for(a = 0; a < REMEMBERED_TIMES_COUNT; a++)
            {
                fLastTimes[a] = fTimePerPaint;
            }

            bTimesInited = true;
        }
        else
        {
            for(a = 1; a < REMEMBERED_TIMES_COUNT; a++)
            {
                fLastTimes[a - 1] = fLastTimes[a];
            }

            fLastTimes[REMEMBERED_TIMES_COUNT - 1] = fTimePerPaint;
        }

        double fAddedTimes(0.0);

        for(a = 0; a < REMEMBERED_TIMES_COUNT; a++)
        {
            fAddedTimes += fLastTimes[a];
        }

        const double fAverageTimePerPaint(fAddedTimes / (double)REMEMBERED_TIMES_COUNT);

        fprintf(stderr, "-----------(start result)----------\n");
        fprintf(stderr, "StartTime : %" SAL_PRIuUINT64 ", StopTime: %" SAL_PRIuUINT64 ", NeededTime: %" SAL_PRIuUINT64 ", TimePerPaint: %f\n", nStartTime, nStopTime, nNeededTime, fTimePerPaint);
        fprintf(stderr, "Remembered times: ");

        for(a = 0; a < REMEMBERED_TIMES_COUNT; a++)
        {
            fprintf(stderr, "%d: %f ", a, fLastTimes[a]);
        }

        fprintf(stderr, "\n");
        fprintf(stderr, "AverageTimePerPaint: %f\n", fAverageTimePerPaint);
        fprintf(stderr, "-----------(stop result)----------\n");
    }
#endif // SVX_REPAINT_TIMER_TEST
}


// #i72889#

SdrPaintWindow* SdrPaintView::BeginCompleteRedraw(OutputDevice* pOut)
{
    assert(pOut && "SdrPaintView::BeginCompleteRedraw: No OutDev (!)");
    SdrPaintWindow* pPaintWindow = FindPaintWindow(*pOut);

    if(pPaintWindow)
    {
        // draw preprocessing, only for known devices
        // prepare PreRendering
        pPaintWindow->PreparePreRenderDevice();
    }
    else
    {
        // None of the known OutputDevices is the target of this paint, use
        // a temporary SdrPaintWindow for this Redraw.
        pPaintWindow = new SdrPaintWindow(*this, *pOut);
        pPaintWindow->setTemporaryTarget(true);
    }

    return pPaintWindow;
}

void SdrPaintView::DoCompleteRedraw(SdrPaintWindow& rPaintWindow, const vcl::Region& rReg, sdr::contact::ViewObjectContactRedirector* pRedirector)
{
    // redraw all PageViews with the target. This may expand the RedrawRegion
    // at the PaintWindow, plus taking care of FormLayer expansion
    if(mpPageView)
    {
        mpPageView->CompleteRedraw(rPaintWindow, rReg, pRedirector);
    }
}

void SdrPaintView::EndCompleteRedraw(SdrPaintWindow& rPaintWindow, bool bPaintFormLayer,
        sdr::contact::ViewObjectContactRedirector* pRedirector)
{
    std::unique_ptr<SdrPaintWindow> pPaintWindow;
    if (comphelper::LibreOfficeKit::isActive() && rPaintWindow.getTemporaryTarget())
    {
        // Tiled rendering, we must paint the TextEdit to the output device.
        pPaintWindow.reset(&rPaintWindow);
        pPaintWindow->setTemporaryTarget(false);
    }

    if(rPaintWindow.getTemporaryTarget())
    {
        // get rid of temp target again
        delete &rPaintWindow;
    }
    else
    {
        // draw postprocessing, only for known devices
        // it is necessary to always paint FormLayer
        // In the LOK case control rendering is performed through LokControlHandler
        // except when the document is exported to PDF or printed,
        // so we use isTiledPainting() in place of the more generic isActive()
        if(!comphelper::LibreOfficeKit::isTiledPainting() && bPaintFormLayer)
        {
            ImpFormLayerDrawing(rPaintWindow, pRedirector);
        }

        // look for active TextEdit. As long as this cannot be painted to a VDev,
        // it cannot get part of buffering. In that case, output evtl. prerender
        // early and paint text edit to window.
        SdrPageView* pPageView = GetSdrPageView();
        if(IsTextEdit() && pPageView)
        {
            if (!comphelper::LibreOfficeKit::isActive() || mbPaintTextEdit)
                static_cast< SdrView* >(this)->TextEditDrawing(rPaintWindow);
        }

        if (comphelper::LibreOfficeKit::isActive() && pPageView)
        {
            // Look for active text edits in other views showing the same page,
            // and show them as well. Show only if Page/MasterPage mode is matching.
            bool bRequireMasterPage = pPageView->GetPage() ? pPageView->GetPage()->IsMasterPage() : false;
            SdrViewIter::ForAllViews(pPageView->GetPage(),
                [this, &bRequireMasterPage, &rPaintWindow] (SdrView* pView)
                {
                    SdrPageView* pCurrentPageView = pView->GetSdrPageView();
                    bool bIsCurrentMasterPage = (pCurrentPageView && pCurrentPageView->GetPage()) ?
                        pCurrentPageView->GetPage()->IsMasterPage() : false;

                    if (pView == this || bRequireMasterPage != bIsCurrentMasterPage)
                        return false;

                    if (pView->IsTextEdit() && pView->GetSdrPageView())
                    {
                        pView->TextEditDrawing(rPaintWindow);
                    }
                    return false;
                });
        }

        // draw Overlay, also to PreRender device if exists
        rPaintWindow.DrawOverlay(rPaintWindow.GetRedrawRegion());

        // output PreRendering
        rPaintWindow.OutputPreRenderDevice(rPaintWindow.GetRedrawRegion());
    }
}

SdrPaintWindow* SdrPaintView::BeginDrawLayers(OutputDevice* pOut, const vcl::Region&&nbsp;rReg, bool bDisableIntersect)
{
    // #i74769# use BeginCompleteRedraw() as common base
    SdrPaintWindow* pPaintWindow = BeginCompleteRedraw(pOut);
    assert(pPaintWindow && "SdrPaintView::BeginDrawLayers: No SdrPaintWindow (!)");

    if(mpPageView)
    {
        SdrPageWindow* pKnownTarget = mpPageView->FindPageWindow(*pPaintWindow);

        if(pKnownTarget)
        {
            vcl::Region aOptimizedRepaintRegion = OptimizeDrawLayersRegion( pOut, rReg, bDisableIntersect );

            // prepare redraw
            pKnownTarget->PrepareRedraw(aOptimizedRepaintRegion);

            // remember prepared SdrPageWindow
            mpPageView->setPreparedPageWindow(pKnownTarget);
        }
    }

    return pPaintWindow;
}

void SdrPaintView::EndDrawLayers(SdrPaintWindow& rPaintWindow, bool bPaintFormLayer,
    sdr::contact::ViewObjectContactRedirector* pRedirector)
{
    // #i74769# use EndCompleteRedraw() as common base
    EndCompleteRedraw(rPaintWindow, bPaintFormLayer, pRedirector);

    if(mpPageView)
    {
        // forget prepared SdrPageWindow
        mpPageView->setPreparedPageWindow(nullptr);
    }
}

void SdrPaintView::UpdateDrawLayersRegion(const OutputDevice* pOut, const vcl::Region&&nbsp;rReg)
{
    SdrPaintWindow* pPaintWindow = FindPaintWindow(*pOut);
    assert(pPaintWindow && "SdrPaintView::UpdateDrawLayersRegion: No SdrPaintWindow (!)");

    if(mpPageView)
    {
        SdrPageWindow* pKnownTarget = mpPageView->FindPageWindow(*pPaintWindow);

        if(pKnownTarget)
        {
            vcl::Region aOptimizedRepaintRegion = OptimizeDrawLayersRegion( pOut, rReg, false/*bDisableIntersect*/ );
            pKnownTarget->GetPaintWindow().SetRedrawRegion(aOptimizedRepaintRegion);
            mpPageView->setPreparedPageWindow(pKnownTarget); // already set actually
        }
    }
}

vcl::Region SdrPaintView::OptimizeDrawLayersRegion(const OutputDevice* pOut, const vcl::Region& rReg, bool bDisableIntersect)
{
    // #i74769# check if pOut is a win and has a ClipRegion. If Yes, the Region
    // rReg may be made more granular (fine) with using it. Normally, rReg
    // does come from Window::Paint() anyways and thus is based on a single
    // rectangle which was derived from exactly that repaint region
    vcl::Region aOptimizedRepaintRegion(rReg);

    // #i76114# Intersecting the region with the Window's paint region is disabled
    // for print preview in Calc, because the intersection can be empty (if the paint
    // region is outside of the table area of the page), and then no clip region
    // would be set.
    if(pOut && OUTDEV_WINDOW == pOut->GetOutDevType() && !bDisableIntersect)
    {
        vcl::Window* pWindow = pOut->GetOwnerWindow();

        if(pWindow->IsInPaint())
        {
            if(!pWindow->GetPaintRegion().IsEmpty())
            {
                aOptimizedRepaintRegion.Intersect(pWindow->GetPaintRegion());
            }
        }
    }
    return aOptimizedRepaintRegion;
}


void SdrPaintView::ImpFormLayerDrawing( SdrPaintWindow& rPaintWindow,
        sdr::contact::ViewObjectContactRedirector* pRedirector )
{
    if(!mpPageView)
        return;

    SdrPageWindow* pKnownTarget = mpPageView->FindPageWindow(rPaintWindow);

    if(pKnownTarget)
    {
        const SdrModel& rModel = GetModel();
        const SdrLayerAdmin& rLayerAdmin = rModel.GetLayerAdmin();
        const SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID(rLayerAdmin.GetControlLayerName());

        // BUFFERED use GetTargetOutputDevice() now, it may be targeted to VDevs, too
        // need to set PreparedPageWindow to make DrawLayer use the correct ObjectContact
        mpPageView->setPreparedPageWindow(pKnownTarget);
        mpPageView->DrawLayer(nControlLayerId, &rPaintWindow.GetTargetOutputDevice(),
        pRedirector);
        mpPageView->setPreparedPageWindow(nullptr);
    }
}


bool SdrPaintView::KeyInput(const KeyEvent& /*rKEvt*/, vcl::Window* /*pWin*/)
{
    return false;
}

void SdrPaintView::GlueInvalidate() const
{
    // Do not invalidate GluePoints in Online
    // They are handled on front-end
    if (comphelper::LibreOfficeKit::isActive())
        return;

    const sal_uInt32 nWindowCount(PaintWindowCount());

    for(sal_uInt32 nWinNum(0); nWinNum < nWindowCount; nWinNum++)
    {
        SdrPaintWindow* pPaintWindow = GetPaintWindow(nWinNum);

        if(pPaintWindow->OutputToWindow())
        {
            OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();

            if(mpPageView)
            {
                const SdrObjList* pOL=mpPageView->GetObjList();
                for (const rtl::Reference<SdrObject>& pObj : *pOL) {
                    const SdrGluePointList* pGPL=pObj->GetGluePointList();
                    if (pGPL!=nullptr && pGPL->GetCount()!=0) {
                        pGPL->Invalidate(*rOutDev.GetOwnerWindow(), pObj.get());
                    }
                }
            }
        }
    }
}

void SdrPaintView::InvalidateAllWin()
{
    const sal_uInt32 nWindowCount(PaintWindowCount());

    for(sal_uInt32 a(0); a < nWindowCount; a++)
    {
        SdrPaintWindow* pPaintWindow = GetPaintWindow(a);

        if(pPaintWindow->OutputToWindow())
        {
            InvalidateOneWin(pPaintWindow->GetOutputDevice());
        }
    }
}

void SdrPaintView::InvalidateAllWin(const tools::Rectangle& rRect)
{
    const sal_uInt32 nWindowCount(PaintWindowCount());

    for(sal_uInt32 a(0); a < nWindowCount; a++)
    {
        SdrPaintWindow* pPaintWindow = GetPaintWindow(a);

        if(pPaintWindow->OutputToWindow())
        {
            OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
            tools::Rectangle aRect(rRect);

            Point aOrg(rOutDev.GetMapMode().GetOrigin());
            aOrg.setX(-aOrg.X() ); aOrg.setY(-aOrg.Y() );
            tools::Rectangle aOutRect(aOrg, rOutDev.GetOutputSize());

            // In case of tiled rendering we want to get all invalidations, so visual area is not interesting.
            if (aRect.Overlaps(aOutRect) || comphelper::LibreOfficeKit::isActive())
            {
                InvalidateOneWin(rOutDev, aRect);
            }
        }
    }
}

void SdrPaintView::InvalidateOneWin(OutputDevice& rDevice)
{
    // do not erase background, that causes flicker (!)
    // tdf#160444 check device's owner window is a nullptr
    // Since commit 563f7077f1dbce31ff95ee8d2e8d17b629693db1, the
    // device's owner window gets deleted before this object is
    // deleted.
    if (rDevice.GetOwnerWindow())
        rDevice.GetOwnerWindow()->Invalidate(InvalidateFlags::NoErase);
}

void SdrPaintView::InvalidateOneWin(OutputDevice& rDevice, const tools::Rectangle& rRect)
{
    // do not erase background, that causes flicker (!)
    rDevice.GetOwnerWindow()->Invalidate(rRect, InvalidateFlags::NoErase);
}

void SdrPaintView::LeaveOneGroup()
{
    if(mpPageView)
    {
        mpPageView->LeaveOneGroup();
    }
}

void SdrPaintView::LeaveAllGroup()
{
    if(mpPageView)
    {
        mpPageView->LeaveAllGroup();
    }
}

bool SdrPaintView::IsGroupEntered() const
{
    if(mpPageView)
    {
        return (mpPageView->GetEnteredLevel() != 0);
    }

    return false;
}

void SdrPaintView::SetNotPersistDefaultAttr(const SfxItemSet& rAttr)
{
    // bReplaceAll has no effect here at all.
    bool bMeasure= dynamic_cast<const SdrView*>(this) != nullptr && static_cast<SdrView*>(this)->IsMeasureTool();

    if (const SdrLayerIdItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_LAYERID))
    {
        SdrLayerID nLayerId = pPoolItem->GetValue();
        const SdrLayer* pLayer = GetModel().GetLayerAdmin().GetLayerPerID(nLayerId);
        if (pLayer!=nullptr) {
            if (bMeasure) maMeasureLayer=pLayer->GetName();
            else maActualLayer=pLayer->GetName();
        }
    }
    if (const SdrLayerNameItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_LAYERNAME))
    {
        if (bMeasure) maMeasureLayer = pPoolItem->GetValue();
        else maActualLayer = pPoolItem->GetValue();
    }
}

void SdrPaintView::MergeNotPersistDefaultAttr(SfxItemSet& rAttr) const
{
    // bOnlyHardAttr has no effect here at all.
    bool bMeasure= dynamic_cast<const SdrView*>(this) != nullptr && static_cast<const SdrView*>(this)->IsMeasureTool();
    const OUString& aNam = bMeasure ? maMeasureLayer : maActualLayer;
    rAttr.Put(SdrLayerNameItem(aNam));
    SdrLayerID nLayer = GetModel().GetLayerAdmin().GetLayerID(aNam);
    if (nLayer!=SDRLAYER_NOTFOUND) {
        rAttr.Put(SdrLayerIdItem(nLayer));
    }
}

void SdrPaintView::SetDefaultAttr(const SfxItemSet& rAttr, bool bReplaceAll)
{
#ifdef DBG_UTIL
    {
        bool bHasEEFeatureItems=false;
        SfxItemIter aIter(rAttr);
        for (const SfxPoolItem* pItem = aIter.GetCurItem(); !bHasEEFeatureItems && pItem;
             pItem = aIter.NextItem())
        {
            if (!IsInvalidItem(pItem)) {
                sal_uInt16 nW=pItem->Which();
                if (nW>=EE_FEATURE_START && nW<=EE_FEATURE_END) bHasEEFeatureItems=true;
            }
        }

        if(bHasEEFeatureItems)
        {
            std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr,
                                                          VclMessageType::Info, VclButtonsType::Ok,
                                                          u"SdrPaintView::SetDefaultAttr(): Setting EE_FEATURE items at the SdrView does not make sense! It only leads to overhead and unreadable documents."_ustr));
            xInfoBox->run();
        }
    }
#endif
    if (bReplaceAll) maDefaultAttr.Set(rAttr);
    else maDefaultAttr.Put(rAttr,false); // if FALSE, regard InvalidItems as "holes," not as Default
    SetNotPersistDefaultAttr(rAttr);
}

void SdrPaintView::SetDefaultStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
{
    if (mpDefaultStyleSheet)
        EndListening(*mpDefaultStyleSheet);
    mpDefaultStyleSheet=pStyleSheet;
    if (mpDefaultStyleSheet)
        StartListening(*mpDefaultStyleSheet);

    if (pStyleSheet!=nullptr && !bDontRemoveHardAttr) {
        SfxWhichIter aIter(pStyleSheet->GetItemSet());
        sal_uInt16 nWhich=aIter.FirstWhich();
        while (nWhich!=0) {
            if (aIter.GetItemState()==SfxItemState::SET) {
                maDefaultAttr.ClearItem(nWhich);
            }
            nWhich=aIter.NextWhich();
        }
    }
}

void SdrPaintView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
{
    if(bOnlyHardAttr || !mpDefaultStyleSheet)
    {
        rTargetSet.Put(maDefaultAttr, false);
    }
    else
    {
        // else merge with DefStyleSheet
        rTargetSet.Put(mpDefaultStyleSheet->GetItemSet(), false);
        rTargetSet.Put(maDefaultAttr, false);
    }
    MergeNotPersistDefaultAttr(rTargetSet);
}

void SdrPaintView::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
{
    SetDefaultAttr(rSet,bReplaceAll);
}

SfxStyleSheet* SdrPaintView::GetStyleSheet() const
{
    return mpDefaultStyleSheet;
}

void SdrPaintView::SetStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
{
    SetDefaultStyleSheet(pStyleSheet,bDontRemoveHardAttr);
}

void SdrPaintView::MakeVisible(const tools::Rectangle& rRect, vcl::Window& rWin)
{
    // TODO: handle when the text cursor goes out of the chart area
    // However this hack avoids that the cursor gets misplaced wrt the text.
    if (comphelper::LibreOfficeKit::isActive() && rWin.IsChart())
    {
        return;
    }

    MapMode aMap(rWin.GetMapMode());
    Size aActualSize(rWin.GetOutDev()->GetOutputSize());

    if( aActualSize.IsEmpty() )
        return;

    Size aNewSize(rRect.GetSize());
    bool bNewScale=false;
    bool bNeedMoreX=aNewSize.Width()>aActualSize.Width();
    bool bNeedMoreY=aNewSize.Height()>aActualSize.Height();
    if (bNeedMoreX || bNeedMoreY)
    {
        bNewScale=true;
        // set new MapMode (Size+Org) and invalidate everything
        Fraction aXFact(aNewSize.Width(),aActualSize.Width());
        Fraction aYFact(aNewSize.Height(),aActualSize.Height());
        if (aYFact>aXFact) aXFact=aYFact;
        aXFact*=aMap.GetScaleX();
        aXFact.ReduceInaccurate(10); // to avoid runovers and BigInt mapping
        aMap.SetScaleX(aXFact);
        aMap.SetScaleY(aYFact);
        rWin.SetMapMode(aMap);
        aActualSize=rWin.GetOutDev()->GetOutputSize();
    }
    Point aOrg(aMap.GetOrigin());
    tools::Long dx=0,dy=0;
    tools::Long l=-aOrg.X();
    tools::Long r=-aOrg.X()+aActualSize.Width()-1;
    tools::Long o=-aOrg.Y();
    tools::Long u=-aOrg.Y()+aActualSize.Height()-1;
    if (l>rRect.Left()) dx=rRect.Left()-l;
    else if (r<rRect.Right()) dx=rRect.Right()-r;
    if (o>rRect.Top()) dy=rRect.Top()-o;
    else if (u<rRect.Bottom()) dy=rRect.Bottom()-u;
    aMap.SetOrigin(Point(aOrg.X()-dx,aOrg.Y()-dy));
    if (!bNewScale) {
        if (dx!=0 || dy!=0) {
            rWin.Scroll(-dx,-dy);
            rWin.SetMapMode(aMap);
            rWin.PaintImmediately();
        }
    } else {
        rWin.SetMapMode(aMap);
        InvalidateOneWin(*rWin.GetOutDev());
    }
}

void SdrPaintView::DoConnect(SdrOle2Obj* /*pOleObj*/)
{
}

void SdrPaintView::SetAnimationEnabled( bool bEnable )
{
    SetAnimationMode( bEnable ? SdrAnimationMode::Animate : SdrAnimationMode::Disable );
}

void SdrPaintView::SetAnimationPause( bool bSet )
{
    if(mbAnimationPause == bSet)
        return;

    mbAnimationPause = bSet;

    if(!mpPageView)
        return;

    for(sal_uInt32 b(0); b < mpPageView->PageWindowCount(); b++)
    {
        SdrPageWindow& rPageWindow = *(mpPageView->GetPageWindow(b));
        sdr::contact::ObjectContact& rObjectContact = rPageWindow.GetObjectContact();
        sdr::animation::primitiveAnimator& rAnimator = rObjectContact.getPrimitiveAnimator();

        if(rAnimator.IsPaused() != bSet)
        {
            rAnimator.SetPaused(bSet);
        }
    }
}

void SdrPaintView::SetAnimationMode( const SdrAnimationMode eMode )
{
    meAnimationMode = eMode;
}

void SdrPaintView::VisAreaChanged(const OutputDevice* pOut)
{
    if(!mpPageView)
        return;

    if (pOut)
    {
        SdrPageWindow* pWindow = mpPageView->FindPageWindow(*const_cast<OutputDevice*>(pOut));

        if(pWindow)
        {
            VisAreaChanged();
        }
    }
    else
    {
        VisAreaChanged();
    }
}

void SdrPaintView::VisAreaChanged()
{
    // notify SfxListener
    Broadcast(SvxViewChangedHint());
}


void SdrPaintView::onChangeColorConfig()
{
    maGridColor = maColorConfig.GetColorValue( svtools::DRAWGRID ).nColor;
}


// Set background color for svx at SdrPageViews
void SdrPaintView::SetApplicationBackgroundColor(Color aBackgroundColor)
{
    if(mpPageView)
    {
        mpPageView->SetApplicationBackgroundColor(aBackgroundColor);
    }
}

// Set document color for svx at SdrPageViews
void SdrPaintView::SetApplicationDocumentColor(Color aDocumentColor)
{
    if(mpPageView)
    {
        mpPageView->SetApplicationDocumentColor(aDocumentColor);
    }
}

bool SdrPaintView::IsBufferedOutputAllowed() const
{
    return (mbBufferedOutputAllowed && officecfg::Office::Common::Drawinglayer::PaintBuffer::get());
}

void SdrPaintView::SetBufferedOutputAllowed(bool bNew)
{
    if(bNew != mbBufferedOutputAllowed)
    {
        mbBufferedOutputAllowed = bNew;
    }
}

bool SdrPaintView::IsBufferedOverlayAllowed() const
{
    return (mbBufferedOverlayAllowed && officecfg::Office::Common::Drawinglayer::OverlayBuffer::get());
}

void SdrPaintView::SetBufferedOverlayAllowed(bool bNew)
{
    if(bNew != mbBufferedOverlayAllowed)
    {
        mbBufferedOverlayAllowed = bNew;
    }
}


void SdrPaintView::SetPageDecorationAllowed(bool bNew)
{
    if(bNew != mbPageDecorationAllowed)
    {
        mbPageDecorationAllowed = bNew;
    }
}

void SdrPaintView::SetMasterPageVisualizationAllowed(bool bNew)
{
    if(bNew != mbMasterPageVisualizationAllowed)
    {
        mbMasterPageVisualizationAllowed = bNew;
    }
}

// #i38135# Sets the timer for Object animations and restarts.
void SdrPaintView::SetAnimationTimer(sal_uInt32 nTime)
{
    if(mpPageView)
    {
        // first, reset all timers at all windows to 0L
        for(sal_uInt32 a(0); a < mpPageView->PageWindowCount(); a++)
        {
            SdrPageWindow& rPageWindow = *mpPageView->GetPageWindow(a);
            sdr::contact::ObjectContact& rObjectContact = rPageWindow.GetObjectContact();
            sdr::animation::primitiveAnimator& rAnimator = rObjectContact.getPrimitiveAnimator();
            rAnimator.SetTime(nTime);
        }
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=94 H=95 G=94

¤ Dauer der Verarbeitung: 0.9 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge