/* -*- 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 .
*/
namespace { /** Wrapper around the SlideSorterView that supports the IPainter interface and that allows the LayeredDevice to hold the SlideSorterView (held as unique_ptr by the SlideSorter) as shared_ptr.
*/ class Painter : public ILayerPainter
{ public: explicit Painter (SlideSorterView& rView) : mrView(rView) {}
SlideSorterView::SlideSorterView (SlideSorter& rSlideSorter)
: ::sd::View (
*rSlideSorter.GetModel().GetDocument(),
rSlideSorter.GetContentWindow()->GetOutDev(),
&rSlideSorter.GetViewShell()),
mrSlideSorter(rSlideSorter),
mrModel(rSlideSorter.GetModel()),
mbIsDisposed(false),
mpLayouter (new Layouter(rSlideSorter.GetContentWindow(), rSlideSorter.GetTheme())),
mbPageObjectVisibilitiesValid (false),
mpLayeredDevice(std::make_shared<LayeredDevice>(rSlideSorter.GetContentWindow())),
maVisiblePageRange(-1,-1),
maPreviewSize(0,0),
mbPreciousFlagUpdatePending(true),
meOrientation(Layouter::GRID),
mpBackgroundPainter(
std::make_shared<BackgroundPainter>(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background))),
mpToolTip(new ToolTip(mrSlideSorter)),
mbIsRearrangePending(true)
{ // Hide the page that contains the page objects.
SetPageVisible (false);
// Register the background painter on level 1 to avoid the creation of a // background buffer.
mpLayeredDevice->RegisterPainter(mpBackgroundPainter, 1);
// Wrap a shared_ptr-held-wrapper around this view and register it as // painter at the layered device. There is no explicit destruction: in // the SlideSorterView destructor the layered device is destroyed and // with it the only reference to the wrapper which therefore is also // destroyed.
SharedILayerPainter pPainter = std::make_shared<Painter>(*this);
// The painter is placed on level 1 to avoid buffering. This should be // a little faster during animations because the previews are painted // directly into the window, not via the buffer.
mpLayeredDevice->RegisterPainter(pPainter, 1);
}
void SlideSorterView::ModelHasChanged()
{ // Ignore this call. Rely on hints sent by the model to get informed of // model changes.
}
void SlideSorterView::PreModelChange()
{ // Reset the slide under the mouse. It will be re-set in PostModelChange().
SetPageUnderMouse(SharedPageDescriptor());
}
void SlideSorterView::PostModelChange()
{ // In PreModelChange() the page objects have been released. Here we // create new ones.
::osl::MutexGuard aGuard (mrModel.GetMutex());
// The new page objects have to be scaled and positioned.
RequestRearrange();
RequestRepaint();
}
/** At the moment for every model change all page objects are destroyed and re-created again. This can be optimized by accepting hints that describe the type of change so that existing page objects can be reused.
*/ void SlideSorterView::HandleModelChange()
{
PreModelChange ();
PostModelChange();
}
void SlideSorterView::HandleDrawModeChange()
{ // Replace the preview cache with a new and empty one. The // PreviewRenderer that is used by the cache is replaced by this as // well.
mpPreviewCache.reset();
GetPreviewCache()->InvalidateCache();
// Update the color used by the background painter.
std::shared_ptr<BackgroundPainter> pPainter (
std::dynamic_pointer_cast<BackgroundPainter>(mpBackgroundPainter)); if (pPainter)
pPainter->SetColor(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background));
void SlideSorterView::UpdateOrientation()
{ // The layout of slides depends on whether the slide sorter is // displayed in the center or the side pane. if (mrSlideSorter.GetViewShell().IsMainViewShell())
SetOrientation(Layouter::GRID); else
{ // Get access to the docking window.
vcl::Window* pWindow = mrSlideSorter.GetContentWindow();
TitledDockingWindow* pDockingWindow = nullptr; while (pWindow!=nullptr && pDockingWindow==nullptr)
{
pDockingWindow = dynamic_cast<TitledDockingWindow*>(pWindow);
pWindow = pWindow->GetParent();
}
if (pDockingWindow != nullptr)
{ const ::tools::Long nScrollBarSize (
Application::GetSettings().GetStyleSettings().GetScrollBarSize()); switch (pDockingWindow->GetOrientation())
{ case TitledDockingWindow::HorizontalOrientation: if (SetOrientation(Layouter::HORIZONTAL))
{ const Range aRange (mpLayouter->GetValidVerticalSizeRange());
pDockingWindow->SetValidSizeRange(Range(
aRange.Min() + nScrollBarSize,
aRange.Max() + nScrollBarSize));
} break;
case TitledDockingWindow::VerticalOrientation: if (SetOrientation(Layouter::VERTICAL))
{ const Range aRange (mpLayouter->GetValidHorizontalSizeRange());
pDockingWindow->SetValidSizeRange(Range(
aRange.Min() + nScrollBarSize,
aRange.Max() + nScrollBarSize));
} break;
case TitledDockingWindow::UnknownOrientation: if (SetOrientation(Layouter::GRID))
{ const sal_Int32 nAdditionalSize (10);
pDockingWindow->SetMinOutputSizePixel(Size(
mpLayouter->GetValidHorizontalSizeRange().Min()
+ nScrollBarSize
+ nAdditionalSize,
mpLayouter->GetValidVerticalSizeRange().Min()
+ nScrollBarSize
+ nAdditionalSize));
} return;
}
} else
{ // We are not placed in a docking window. One possible reason // is that the slide sorter is temporarily into a cache and was // reparented to a non-docking window.
SetOrientation(Layouter::GRID);
}
}
}
void SlideSorterView::Layout ()
{
sd::Window *pWindow (mrSlideSorter.GetContentWindow().get()); if (pWindow)
{ // Set the model area, i.e. the smallest rectangle that includes all // page objects. const ::tools::Rectangle aViewBox (mpLayouter->GetTotalBoundingBox());
pWindow->SetViewOrigin (aViewBox.TopLeft());
pWindow->SetViewSize (aViewBox.GetSize());
// Iterate over all page objects and place them relative to the // containing page.
model::PageEnumeration aPageEnumeration (
model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel)); while (aPageEnumeration.HasMoreElements())
{
model::SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
pDescriptor->SetBoundingBox(mpLayouter->GetPageObjectBox(pDescriptor->GetPageIndex(), false));
}
}
void SlideSorterView::DeterminePageObjectVisibilities()
{
sd::Window *pWindow (mrSlideSorter.GetContentWindow().get()); if (!pWindow) return;
// Set this flag to true here so that an invalidate during the // visibility calculation can correctly invalidate it again.
mbPageObjectVisibilitiesValid = true;
::tools::Rectangle aViewArea (pWindow->PixelToLogic(::tools::Rectangle(Point(0,0),pWindow->GetSizePixel()))); const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(aViewArea)); const Range aUnion(
::std::min(maVisiblePageRange.Min(), aRange.Min()),
::std::max(maVisiblePageRange.Max(), aRange.Max()));
// For page objects that just dropped off the visible area we // decrease the priority of pending requests for preview bitmaps. if (maVisiblePageRange != aRange)
mbPreciousFlagUpdatePending |= true;
model::SharedPageDescriptor pDescriptor; for (::tools::Long nIndex=aUnion.Min(); nIndex<=aUnion.Max(); nIndex++)
{
pDescriptor = mrModel.GetPageDescriptor(nIndex); if (pDescriptor)
SetState(
pDescriptor,
PageDescriptor::ST_Visible,
aRange.Contains(nIndex));
}
// Broadcast a change of the set of visible page objects. if (maVisiblePageRange != aRange)
{
maVisiblePageRange = aRange;
// Tell the listeners that the visibility of some objects has // changed.
::std::vector<Link<LinkParamNone*,void>>& aChangeListeners (maVisibilityChangeListeners); for (constauto& rLink : aChangeListeners)
{
rLink.Call(nullptr);
}
}
// Restore the mouse over state.
UpdatePageUnderMouse();
}
void SlideSorterView::UpdatePreciousFlags()
{ if (!mbPreciousFlagUpdatePending) return;
for (int nIndex=0; nIndex<=nPageCount; ++nIndex)
{
pDescriptor = mrModel.GetPageDescriptor(nIndex); if (pDescriptor)
{
pCache->SetPreciousFlag(
pDescriptor->GetPage(),
maVisiblePageRange.Contains(nIndex));
} else
{ // At least one cache entry can not be updated. Remember to // repeat the whole updating later and leave the loop now.
mbPreciousFlagUpdatePending = true; break;
}
}
}
// The parent implementation of CompleteRedraw is called only when // painting is locked. We do all the painting ourself. When painting // is locked the parent implementation keeps track of the repaint // requests and later, when painting is unlocked, calls CompleteRedraw // for all missed repaints.
if (mnLockRedrawSmph == 0)
{ if (mpLayeredDevice->HandleMapModeChange())
DeterminePageObjectVisibilities();
mpLayeredDevice->Repaint(rPaintArea);
} else
{
maRedrawRegion.Union(rPaintArea);
}
if ( ! mpPageObjectPainter) if ( ! GetPageObjectPainter()) return;
// Update the page visibilities when they have been invalidated. if ( ! mbPageObjectVisibilitiesValid)
DeterminePageObjectVisibilities();
if (mbPreciousFlagUpdatePending)
UpdatePreciousFlags();
if (mbIsRearrangePending)
Rearrange();
// Paint all page objects that are fully or partially inside the // repaint region. const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(rRepaintArea)); // Try to prefetch all graphics from the pages to paint. This will be done // in threads to be more efficient than loading them on-demand one by one.
std::vector<Graphic*> graphics; for (::tools::Long nIndex=aRange.Min(); nIndex<=aRange.Max(); ++nIndex)
{
model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex)); if (!pDescriptor || ! pDescriptor->HasState(PageDescriptor::ST_Visible)) continue;
pDescriptor->GetPage()->getGraphicsForPrefetch(graphics);
} // Handle also one page before and after to have those in advance on scrolling. for (::tools::Long nIndex : { aRange.Min() - 1, aRange.Max() + 1 })
{
model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex)); if (!pDescriptor) continue;
pDescriptor->GetPage()->getGraphicsForPrefetch(graphics);
} if(graphics.size() > 1) // threading does not help with loading just one
GraphicFilter::GetGraphicFilter().MakeGraphicsAvailableThreaded(graphics);
for (::tools::Long nIndex=aRange.Min(); nIndex<=aRange.Max(); ++nIndex)
{
model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex)); if (!pDescriptor || ! pDescriptor->HasState(PageDescriptor::ST_Visible)) continue;
void SlideSorterView::ConfigurationChanged (
utl::ConfigurationBroadcaster* pBroadcaster,
ConfigurationHints nHint)
{ // Some changes of the configuration (some of the colors for example) // may affect the previews. Throw away the old ones and create new ones.
cache::PageCacheManager::Instance()->InvalidateAllCaches();
void SlideSorterView::UpdatePageUnderMouse ()
{ // Tracking TODO check
VclPtr<ScrollAdaptor> pVScrollBar (mrSlideSorter.GetVerticalScrollBar());
VclPtr<ScrollAdaptor> pHScrollBar (mrSlideSorter.GetHorizontalScrollBar()); if ((pVScrollBar && pVScrollBar->IsVisible() && pVScrollBar->HasGrab())
|| (pHScrollBar && pHScrollBar->IsVisible() && pHScrollBar->HasGrab()))
{ // One of the scroll bars is tracking mouse movement. Do not // highlight the slide under the mouse in this case.
SetPageUnderMouse(SharedPageDescriptor()); return;
}
constbool bModified (rpDescriptor->SetState(eState, bStateValue)); if ( ! bModified) returnfalse;
// When the page object is not visible (i.e. not on the screen then // nothing has to be painted. if (rpDescriptor->HasState(PageDescriptor::ST_Visible))
{ // For most states a change of that state leads to visible // difference and we have to request a repaint. if (eState != PageDescriptor::ST_WasSelected)
RequestRepaint(rpDescriptor);
}
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.