nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / core / view / viewsh.cxx
blobc53be1dea5b7a501949fbf8580b81debc1906b7a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/accessibility/XAccessible.hpp>
21 #include <sfx2/viewfrm.hxx>
22 #include <sfx2/progress.hxx>
23 #include <svx/srchdlg.hxx>
24 #include <sfx2/viewsh.hxx>
25 #include <sfx2/ipclient.hxx>
26 #include <sal/log.hxx>
27 #include <drawdoc.hxx>
28 #include <swwait.hxx>
29 #include <crsrsh.hxx>
30 #include <doc.hxx>
31 #include <IDocumentDeviceAccess.hxx>
32 #include <IDocumentDrawModelAccess.hxx>
33 #include <IDocumentOutlineNodes.hxx>
34 #include <IDocumentFieldsAccess.hxx>
35 #include <IDocumentLayoutAccess.hxx>
36 #include <IDocumentState.hxx>
37 #include <rootfrm.hxx>
38 #include <pagefrm.hxx>
39 #include <cntfrm.hxx>
40 #include <viewimp.hxx>
41 #include <frmtool.hxx>
42 #include <viewopt.hxx>
43 #include <dview.hxx>
44 #include <swregion.hxx>
45 #include <hints.hxx>
46 #include <docufld.hxx>
47 #include <txtfrm.hxx>
48 #include <layact.hxx>
49 #include <mdiexp.hxx>
50 #include <fntcache.hxx>
51 #include <ptqueue.hxx>
52 #include <docsh.hxx>
53 #include <pagedesc.hxx>
54 #include <bookmrk.hxx>
55 #include <ndole.hxx>
56 #include <ndindex.hxx>
57 #include <accmap.hxx>
58 #include <vcl/bitmapex.hxx>
59 #include <svtools/accessibilityoptions.hxx>
60 #include <accessibilityoptions.hxx>
61 #include <strings.hrc>
62 #include <bitmaps.hlst>
63 #include <pagepreviewlayout.hxx>
64 #include <sortedobjs.hxx>
65 #include <anchoredobject.hxx>
66 #include <DocumentSettingManager.hxx>
68 #include <unotxdoc.hxx>
69 #include <view.hxx>
70 #include <PostItMgr.hxx>
71 #include <unotools/configmgr.hxx>
72 #include <vcl/virdev.hxx>
73 #include <vcl/svapp.hxx>
74 #include <svx/sdrpaintwindow.hxx>
75 #include <svx/sdr/overlay/overlaymanager.hxx>
76 #include <svx/sdrpagewindow.hxx>
77 #include <svx/svdpagv.hxx>
78 #include <comphelper/lok.hxx>
79 #include <sfx2/lokhelper.hxx>
81 #if !HAVE_FEATURE_DESKTOP
82 #include <vcl/sysdata.hxx>
83 #endif
85 bool SwViewShell::mbLstAct = false;
86 ShellResource *SwViewShell::mpShellRes = nullptr;
87 vcl::DeleteOnDeinit<std::shared_ptr<weld::Window>> SwViewShell::mpCareDialog(new std::shared_ptr<weld::Window>);
89 static bool bInSizeNotify = false;
92 using namespace ::com::sun::star;
94 void SwViewShell::SetShowHeaderFooterSeparator( FrameControlType eControl, bool bShow ) {
96 //tdf#118621 - Optionally disable floating header/footer menu
97 if ( bShow )
98 bShow = GetViewOptions()->IsUseHeaderFooterMenu();
100 if ( eControl == FrameControlType::Header )
101 mbShowHeaderSeparator = bShow;
102 else
103 mbShowFooterSeparator = bShow;
106 void SwViewShell::ToggleHeaderFooterEdit()
108 mbHeaderFooterEdit = !mbHeaderFooterEdit;
109 if ( !mbHeaderFooterEdit )
111 SetShowHeaderFooterSeparator( FrameControlType::Header, false );
112 SetShowHeaderFooterSeparator( FrameControlType::Footer, false );
115 // Avoid corner case
116 if ( ( GetViewOptions()->IsUseHeaderFooterMenu() ) &&
117 ( !IsShowHeaderFooterSeparator( FrameControlType::Header ) &&
118 !IsShowHeaderFooterSeparator( FrameControlType::Footer ) ) )
120 mbHeaderFooterEdit = false;
123 // Repaint everything
124 GetWin()->Invalidate();
127 void SwViewShell::setOutputToWindow(bool bOutputToWindow)
129 mbOutputToWindow = bOutputToWindow;
132 bool SwViewShell::isOutputToWindow() const
134 return mbOutputToWindow;
137 void SwViewShell::dumpAsXml(xmlTextWriterPtr pWriter) const
139 xmlTextWriterStartElement(pWriter, BAD_CAST("SwViewShell"));
140 xmlTextWriterEndElement(pWriter);
143 static void
144 lcl_PaintTransparentFormControls(SwViewShell const & rShell, SwRect const& rRect)
146 // Direct paint has been performed: the background of transparent child
147 // windows has been painted, so need to paint the child windows now.
148 if (rShell.GetWin())
150 vcl::Window& rWindow = *(rShell.GetWin());
151 const tools::Rectangle aRectanglePixel(rShell.GetOut()->LogicToPixel(rRect.SVRect()));
152 PaintTransparentChildren(rWindow, aRectanglePixel);
156 // #i72754# 2nd set of Pre/PostPaints
157 // This time it uses the lock counter (mPrePostPaintRegions empty/non-empty) to allow only one activation
158 // and deactivation and mpPrePostOutDev to remember the OutDev from the BeginDrawLayers
159 // call. That way, all places where paint take place can be handled the same way, even
160 // when calling other paint methods. This is the case at the places where SW paints
161 // buffered into VDevs to avoid flicker. It is in general problematic and should be
162 // solved once using the BufferedOutput functionality of the DrawView.
164 void SwViewShell::PrePaint()
166 // forward PrePaint event from VCL Window to DrawingLayer
167 if(HasDrawView())
169 Imp()->GetDrawView()->PrePaint();
173 void SwViewShell::DLPrePaint2(const vcl::Region& rRegion)
175 if(mPrePostPaintRegions.empty())
177 mPrePostPaintRegions.push( rRegion );
178 // #i75172# ensure DrawView to use DrawingLayer bufferings
179 if ( !HasDrawView() )
180 MakeDrawView();
182 // Prefer window; if not available, get mpOut (e.g. printer)
183 const bool bWindow = GetWin() && !comphelper::LibreOfficeKit::isActive() && !isOutputToWindow();
184 mpPrePostOutDev = bWindow ? GetWin(): GetOut();
186 // #i74769# use SdrPaintWindow now direct
187 mpTargetPaintWindow = Imp()->GetDrawView()->BeginDrawLayers(mpPrePostOutDev, rRegion);
188 OSL_ENSURE(mpTargetPaintWindow, "BeginDrawLayers: Got no SdrPaintWindow (!)");
190 // #i74769# if prerender, save OutDev and redirect to PreRenderDevice
191 if(mpTargetPaintWindow->GetPreRenderDevice())
193 mpBufferedOut = mpOut;
194 mpOut = &(mpTargetPaintWindow->GetTargetOutputDevice());
196 else if (isOutputToWindow())
197 // In case mpOut is used without buffering and we're not printing, need to set clipping.
198 mpOut->SetClipRegion(rRegion);
200 // remember original paint MapMode for wrapped FlyFrame paints
201 maPrePostMapMode = mpOut->GetMapMode();
203 else
205 // region needs to be updated to the given one
206 if( mPrePostPaintRegions.top() != rRegion )
207 Imp()->GetDrawView()->UpdateDrawLayersRegion(mpPrePostOutDev, rRegion);
208 mPrePostPaintRegions.push( rRegion );
212 void SwViewShell::DLPostPaint2(bool bPaintFormLayer)
214 OSL_ENSURE(!mPrePostPaintRegions.empty(), "SwViewShell::DLPostPaint2: Pre/PostPaint encapsulation broken (!)");
216 if( mPrePostPaintRegions.size() > 1 )
218 vcl::Region current = std::move(mPrePostPaintRegions.top());
219 mPrePostPaintRegions.pop();
220 if( current != mPrePostPaintRegions.top())
221 Imp()->GetDrawView()->UpdateDrawLayersRegion(mpPrePostOutDev, mPrePostPaintRegions.top());
222 return;
224 mPrePostPaintRegions.pop(); // clear
225 if(nullptr != mpTargetPaintWindow)
227 // #i74769# restore buffered OutDev
228 if(mpTargetPaintWindow->GetPreRenderDevice())
230 mpOut = mpBufferedOut;
233 // #i74769# use SdrPaintWindow now direct
234 Imp()->GetDrawView()->EndDrawLayers(*mpTargetPaintWindow, bPaintFormLayer);
235 mpTargetPaintWindow = nullptr;
238 // end of Pre/PostPaints
240 void SwViewShell::ImplEndAction( const bool bIdleEnd )
242 // Nothing to do for the printer?
243 if ( !GetWin() || IsPreview() )
245 mbPaintWorks = true;
246 UISizeNotify();
247 // tdf#101464 print preview may generate events if another view shell
248 // performs layout...
249 if (IsPreview() && Imp()->IsAccessible())
251 Imp()->FireAccessibleEvents();
253 return;
256 mbInEndAction = true;
257 //will this put the EndAction of the last shell in the sequence?
259 SwViewShell::mbLstAct = true;
260 for(SwViewShell& rShell : GetRingContainer())
262 if(&rShell != this && rShell.ActionPend())
264 SwViewShell::mbLstAct = false;
265 break;
269 const bool bIsShellForCheckViewLayout = ( this == GetLayout()->GetCurrShell() );
271 CurrShell aCurr( this );
272 if ( Imp()->HasDrawView() && !Imp()->GetDrawView()->areMarkHandlesHidden() )
273 Imp()->StartAction();
275 if ( Imp()->GetRegion() && Imp()->GetRegion()->GetOrigin() != VisArea() )
276 Imp()->DelRegion();
278 const bool bExtraData = ::IsExtraData( GetDoc() );
280 if ( !bIdleEnd )
282 SwLayAction aAction( GetLayout(), Imp() );
283 aAction.SetComplete( false );
284 if ( mnLockPaint )
285 aAction.SetPaint( false );
286 aAction.SetInputType( VclInputFlags::KEYBOARD );
287 aAction.Action(GetWin());
290 if ( bIsShellForCheckViewLayout )
291 GetLayout()->CheckViewLayout( GetViewOptions(), &maVisArea );
293 //If we don't call Paints, we wait for the Paint of the system.
294 //Then the clipping is set correctly; e.g. shifting of a Draw object
295 if ( Imp()->GetRegion() ||
296 maInvalidRect.HasArea() ||
297 bExtraData )
299 if ( !mnLockPaint )
301 SolarMutexGuard aGuard;
303 bool bPaintsFromSystem = maInvalidRect.HasArea();
304 GetWin()->PaintImmediately();
305 if ( maInvalidRect.HasArea() )
307 if ( bPaintsFromSystem )
308 Imp()->AddPaintRect( maInvalidRect );
310 ResetInvalidRect();
311 bPaintsFromSystem = true;
313 mbPaintWorks = true;
315 std::unique_ptr<SwRegionRects> pRegion = std::move(Imp()->m_pRegion);
317 //JP 27.11.97: what hid the selection, must also Show it,
318 // else we get Paint errors!
319 // e.g. additional mode, page half visible vertically, in the
320 // middle a selection and with another cursor jump to left
321 // right border. Without ShowCursor the selection disappears.
322 bool bShowCursor = pRegion && dynamic_cast<const SwCursorShell*>(this) != nullptr;
323 if( bShowCursor )
324 static_cast<SwCursorShell*>(this)->HideCursors();
326 if ( pRegion )
328 SwRootFrame* pCurrentLayout = GetLayout();
330 //First Invert then Compress, never the other way round!
331 pRegion->Invert();
333 pRegion->Compress();
335 ScopedVclPtr<VirtualDevice> pVout;
336 while ( !pRegion->empty() )
338 SwRect aRect( pRegion->back() );
339 pRegion->pop_back();
341 bool bPaint = true;
342 if ( IsEndActionByVirDev() )
344 //create virtual device and set.
345 if ( !pVout )
346 pVout = VclPtr<VirtualDevice>::Create( *GetOut() );
347 MapMode aMapMode( GetOut()->GetMapMode() );
348 pVout->SetMapMode( aMapMode );
350 bool bSizeOK = true;
352 tools::Rectangle aTmp1( aRect.SVRect() );
353 aTmp1 = GetOut()->LogicToPixel( aTmp1 );
354 tools::Rectangle aTmp2( GetOut()->PixelToLogic( aTmp1 ) );
355 if ( aTmp2.Left() > aRect.Left() )
356 aTmp1.SetLeft( std::max( tools::Long(0), aTmp1.Left() - 1 ) );
357 if ( aTmp2.Top() > aRect.Top() )
358 aTmp1.SetTop( std::max<tools::Long>( 0, aTmp1.Top() - 1 ) );
359 aTmp1.AdjustRight(1 );
360 aTmp1.AdjustBottom(1 );
361 aTmp1 = GetOut()->PixelToLogic( aTmp1 );
362 aRect = SwRect( aTmp1 );
364 const Size aTmp( pVout->GetOutputSize() );
365 if ( aTmp.Height() < aRect.Height() ||
366 aTmp.Width() < aRect.Width() )
368 bSizeOK = pVout->SetOutputSize( aRect.SSize() );
370 if ( bSizeOK )
372 bPaint = false;
374 // --> OD 2007-07-26 #i79947#
375 // #i72754# start Pre/PostPaint encapsulation before mpOut is changed to the buffering VDev
376 const vcl::Region aRepaintRegion(aRect.SVRect());
377 DLPrePaint2(aRepaintRegion);
378 // <--
380 OutputDevice *pOld = GetOut();
381 pVout->SetLineColor( pOld->GetLineColor() );
382 pVout->SetFillColor( pOld->GetFillColor() );
383 Point aOrigin( aRect.Pos() );
384 aOrigin.setX( -aOrigin.X() ); aOrigin.setY( -aOrigin.Y() );
385 aMapMode.SetOrigin( aOrigin );
386 pVout->SetMapMode( aMapMode );
388 mpOut = pVout.get();
389 if ( bPaintsFromSystem )
390 PaintDesktop(*mpOut, aRect);
391 pCurrentLayout->PaintSwFrame( *mpOut, aRect );
392 pOld->DrawOutDev( aRect.Pos(), aRect.SSize(),
393 aRect.Pos(), aRect.SSize(), *pVout );
394 mpOut = pOld;
396 // #i72754# end Pre/PostPaint encapsulation when mpOut is back and content is painted
397 DLPostPaint2(true);
400 if ( bPaint )
402 if (GetWin()->SupportsDoubleBuffering())
403 InvalidateWindows(aRect.SVRect());
404 else
406 // #i75172# begin DrawingLayer paint
407 // need to do begin/end DrawingLayer preparation for each single rectangle of the
408 // repaint region. I already tried to prepare only once for the whole Region. This
409 // seems to work (and does technically) but fails with transparent objects. Since the
410 // region given to BeginDarwLayers() defines the clip region for DrawingLayer paint,
411 // transparent objects in the single rectangles will indeed be painted multiple times.
412 DLPrePaint2(vcl::Region(aRect.SVRect()));
414 if ( bPaintsFromSystem )
415 PaintDesktop(*GetOut(), aRect);
416 if (!comphelper::LibreOfficeKit::isActive())
417 pCurrentLayout->PaintSwFrame( *mpOut, aRect );
418 else
419 pCurrentLayout->GetCurrShell()->InvalidateWindows(aRect.SVRect());
421 // #i75172# end DrawingLayer paint
422 DLPostPaint2(true);
426 lcl_PaintTransparentFormControls(*this, aRect); // i#107365
429 if( bShowCursor )
430 static_cast<SwCursorShell*>(this)->ShowCursors( true );
432 else
434 Imp()->DelRegion();
435 mbPaintWorks = true;
438 else
439 mbPaintWorks = true;
441 mbInEndAction = false;
442 SwViewShell::mbLstAct = false;
443 Imp()->EndAction();
445 //We artificially end the action here to enable the automatic scrollbars
446 //to adjust themselves correctly
447 //EndAction sends a Notify, and that must call Start-/EndAction to
448 //adjust the scrollbars correctly
449 --mnStartAction;
450 UISizeNotify();
451 ++mnStartAction;
453 if( Imp()->IsAccessible() )
454 Imp()->FireAccessibleEvents();
457 void SwViewShell::ImplStartAction()
459 mbPaintWorks = false;
460 Imp()->StartAction();
463 void SwViewShell::ImplLockPaint()
465 if ( GetWin() && GetWin()->IsVisible() )
466 GetWin()->EnablePaint( false ); //Also cut off the controls.
467 Imp()->LockPaint();
470 void SwViewShell::ImplUnlockPaint( bool bVirDev )
472 CurrShell aCurr( this );
473 if ( GetWin() && GetWin()->IsVisible() )
475 if ( (bInSizeNotify || bVirDev ) && VisArea().HasArea() )
477 //Refresh with virtual device to avoid flickering.
478 VclPtrInstance<VirtualDevice> pVout( *mpOut );
479 pVout->SetMapMode( mpOut->GetMapMode() );
480 Size aSize( VisArea().SSize() );
481 aSize.AdjustWidth(20 );
482 aSize.AdjustHeight(20 );
483 if( pVout->SetOutputSize( aSize ) )
485 GetWin()->EnablePaint( true );
486 GetWin()->Validate();
488 Imp()->UnlockPaint();
489 pVout->SetLineColor( mpOut->GetLineColor() );
490 pVout->SetFillColor( mpOut->GetFillColor() );
492 // #i72754# start Pre/PostPaint encapsulation before mpOut is changed to the buffering VDev
493 const vcl::Region aRepaintRegion(VisArea().SVRect());
494 DLPrePaint2(aRepaintRegion);
496 OutputDevice *pOld = mpOut;
497 mpOut = pVout.get();
498 Paint(*mpOut, VisArea().SVRect());
499 mpOut = pOld;
500 mpOut->DrawOutDev( VisArea().Pos(), aSize,
501 VisArea().Pos(), aSize, *pVout );
503 // #i72754# end Pre/PostPaint encapsulation when mpOut is back and content is painted
504 DLPostPaint2(true);
506 lcl_PaintTransparentFormControls(*this, VisArea()); // fdo#63949
508 else
510 Imp()->UnlockPaint();
511 GetWin()->EnablePaint( true );
512 GetWin()->Invalidate( InvalidateFlags::Children );
514 pVout.disposeAndClear();
516 else
518 Imp()->UnlockPaint();
519 GetWin()->EnablePaint( true );
520 GetWin()->Invalidate( InvalidateFlags::Children );
523 else
524 Imp()->UnlockPaint();
527 bool SwViewShell::AddPaintRect( const SwRect & rRect )
529 bool bRet = false;
530 for(SwViewShell& rSh : GetRingContainer())
532 if( rSh.Imp() )
534 if ( rSh.IsPreview() && rSh.GetWin() )
535 ::RepaintPagePreview( &rSh, rRect );
536 else
537 bRet |= rSh.Imp()->AddPaintRect( rRect );
540 return bRet;
543 void SwViewShell::InvalidateWindows( const SwRect &rRect )
545 if ( Imp()->IsCalcLayoutProgress() )
546 return;
548 for(SwViewShell& rSh : GetRingContainer())
550 if ( rSh.GetWin() )
552 if ( rSh.IsPreview() )
553 ::RepaintPagePreview( &rSh, rRect );
554 // In case of tiled rendering, invalidation is wanted even if
555 // the rectangle is outside the visual area.
556 else if ( rSh.VisArea().IsOver( rRect ) || comphelper::LibreOfficeKit::isActive() )
557 rSh.GetWin()->Invalidate( rRect.SVRect() );
562 const SwRect& SwViewShell::VisArea() const
564 // when using the tiled rendering, consider the entire document as our
565 // visible area
566 return comphelper::LibreOfficeKit::isActive()? GetLayout()->getFrameArea(): maVisArea;
569 void SwViewShell::MakeVisible( const SwRect &rRect )
571 if ( !(!VisArea().IsInside( rRect ) || IsScrollMDI( this, rRect ) || GetCareDialog(*this)) )
572 return;
574 if ( IsViewLocked() )
575 return;
577 if( mpWin )
579 const SwFrame* pRoot = GetLayout();
580 int nLoopCnt = 3;
581 tools::Long nOldH;
583 nOldH = pRoot->getFrameArea().Height();
584 StartAction();
585 ScrollMDI( this, rRect, USHRT_MAX, USHRT_MAX );
586 EndAction();
587 } while( nOldH != pRoot->getFrameArea().Height() && nLoopCnt-- );
589 #if OSL_DEBUG_LEVEL > 0
590 else
592 //MA: 04. Nov. 94, no one needs this, does one?
593 OSL_ENSURE( false, "Is MakeVisible still needed for printers?" );
596 #endif
599 weld::Window* SwViewShell::CareChildWin(SwViewShell const & rVSh)
601 if (!rVSh.mpSfxViewShell)
602 return nullptr;
603 #if HAVE_FEATURE_DESKTOP
604 const sal_uInt16 nId = SvxSearchDialogWrapper::GetChildWindowId();
605 SfxViewFrame* pVFrame = rVSh.mpSfxViewShell->GetViewFrame();
606 SfxChildWindow* pChWin = pVFrame->GetChildWindow( nId );
607 if (!pChWin)
608 return nullptr;
609 weld::DialogController* pController = pChWin->GetController().get();
610 if (!pController)
611 return nullptr;
612 weld::Window* pWin = pController->getDialog();
613 if (pWin && pWin->get_visible())
614 return pWin;
615 #endif
616 return nullptr;
619 Point SwViewShell::GetPagePos( sal_uInt16 nPageNum ) const
621 return GetLayout()->GetPagePos( nPageNum );
624 sal_uInt16 SwViewShell::GetNumPages() const
626 //It is possible that no layout exists when the method from
627 //root-Ctor is called.
628 return GetLayout() ? GetLayout()->GetPageNum() : 0;
631 bool SwViewShell::IsDummyPage( sal_uInt16 nPageNum ) const
633 return GetLayout() && GetLayout()->IsDummyPage( nPageNum );
637 * Forces update of each field.
638 * It notifies all fields with pNewHt. If that is 0 (default), the field
639 * type is sent (???).
640 * @param[in] bCloseDB Passed in to GetDoc()->UpdateFields. [TODO] Purpose???
642 void SwViewShell::UpdateFields(bool bCloseDB)
644 CurrShell aCurr( this );
646 auto pCursorShell = dynamic_cast<SwCursorShell*>( this );
647 if ( pCursorShell )
648 pCursorShell->StartAction();
649 else
650 StartAction();
652 GetDoc()->getIDocumentFieldsAccess().UpdateFields(bCloseDB);
654 if ( pCursorShell )
655 pCursorShell->EndAction();
656 else
657 EndAction();
660 /** update all charts for which any table exists */
661 void SwViewShell::UpdateAllCharts()
663 CurrShell aCurr( this );
664 // Start-/EndAction handled in the SwDoc-Method!
665 GetDoc()->UpdateAllCharts();
668 bool SwViewShell::HasCharts() const
670 bool bRet = false;
671 SwNodeIndex aIdx( *GetDoc()->GetNodes().GetEndOfAutotext().
672 StartOfSectionNode(), 1 );
673 while (aIdx.GetNode().GetStartNode())
675 ++aIdx;
676 const SwOLENode *pNd = aIdx.GetNode().GetOLENode();
677 if( pNd && !pNd->GetChartTableName().isEmpty() )
679 bRet = true;
680 break;
683 return bRet;
686 void SwViewShell::LayoutIdle()
688 if( !mpOpt->IsIdle() || !GetWin() || HasDrawViewDrag() )
689 return;
691 //No idle when printing is going on.
692 for(const SwViewShell& rSh : GetRingContainer())
694 if ( !rSh.GetWin() )
695 return;
698 CurrShell aCurr( this );
700 #ifdef DBG_UTIL
701 // If Test5 has been set, the IdleFormatter is disabled.
702 if( mpOpt->IsTest5() )
703 return;
704 #endif
707 // Preserve top of the text frame cache.
708 SwSaveSetLRUOfst aSaveLRU;
709 // #125243# there are lots of stacktraces indicating that Imp() returns NULL
710 // this SwViewShell seems to be invalid - but it's not clear why
711 // this return is only a workaround!
712 OSL_ENSURE(Imp(), "SwViewShell already deleted?");
713 if(!Imp())
714 return;
715 SwLayIdle aIdle( GetLayout(), Imp() );
719 static void lcl_InvalidateAllContent( SwViewShell& rSh, SwInvalidateFlags nInv )
721 auto pCursorShell = dynamic_cast<SwCursorShell*>( &rSh);
722 if ( pCursorShell )
723 pCursorShell->StartAction();
724 else
725 rSh.StartAction();
726 rSh.GetLayout()->InvalidateAllContent( nInv );
727 if ( pCursorShell )
728 pCursorShell->EndAction();
729 else
730 rSh.EndAction();
732 rSh.GetDoc()->getIDocumentState().SetModified();
735 /** local method to invalidate/re-calculate positions of floating screen
736 * objects (Writer fly frame and drawing objects), which are anchored
737 * to paragraph or to character. #i11860#
739 static void lcl_InvalidateAllObjPos( SwViewShell &_rSh )
741 auto pCursorShell = dynamic_cast<SwCursorShell*>( &_rSh);
742 if ( pCursorShell )
743 pCursorShell->StartAction();
744 else
745 _rSh.StartAction();
747 _rSh.GetLayout()->InvalidateAllObjPos();
749 if ( pCursorShell )
750 pCursorShell->EndAction();
751 else
752 _rSh.EndAction();
754 _rSh.GetDoc()->getIDocumentState().SetModified();
757 void SwViewShell::SetParaSpaceMax( bool bNew )
759 IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
760 if( rIDSA.get(DocumentSettingId::PARA_SPACE_MAX) != bNew )
762 SwWait aWait( *GetDoc()->GetDocShell(), true );
763 rIDSA.set(DocumentSettingId::PARA_SPACE_MAX, bNew );
764 const SwInvalidateFlags nInv = SwInvalidateFlags::PrtArea | SwInvalidateFlags::Table | SwInvalidateFlags::Section;
765 lcl_InvalidateAllContent( *this, nInv );
769 void SwViewShell::SetParaSpaceMaxAtPages( bool bNew )
771 IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
772 if( rIDSA.get(DocumentSettingId::PARA_SPACE_MAX_AT_PAGES) != bNew )
774 SwWait aWait( *GetDoc()->GetDocShell(), true );
775 rIDSA.set(DocumentSettingId::PARA_SPACE_MAX_AT_PAGES, bNew );
776 const SwInvalidateFlags nInv = SwInvalidateFlags::PrtArea | SwInvalidateFlags::Table | SwInvalidateFlags::Section;
777 lcl_InvalidateAllContent( *this, nInv );
781 void SwViewShell::SetTabCompat( bool bNew )
783 IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
784 if( rIDSA.get(DocumentSettingId::TAB_COMPAT) != bNew )
786 SwWait aWait( *GetDoc()->GetDocShell(), true );
787 rIDSA.set(DocumentSettingId::TAB_COMPAT, bNew );
788 const SwInvalidateFlags nInv = SwInvalidateFlags::PrtArea | SwInvalidateFlags::Size | SwInvalidateFlags::Table | SwInvalidateFlags::Section;
789 lcl_InvalidateAllContent( *this, nInv );
793 void SwViewShell::SetAddExtLeading( bool bNew )
795 IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
796 if ( rIDSA.get(DocumentSettingId::ADD_EXT_LEADING) != bNew )
798 SwWait aWait( *GetDoc()->GetDocShell(), true );
799 rIDSA.set(DocumentSettingId::ADD_EXT_LEADING, bNew );
800 SwDrawModel* pTmpDrawModel = getIDocumentDrawModelAccess().GetDrawModel();
801 if ( pTmpDrawModel )
802 pTmpDrawModel->SetAddExtLeading( bNew );
803 const SwInvalidateFlags nInv = SwInvalidateFlags::PrtArea | SwInvalidateFlags::Size | SwInvalidateFlags::Table | SwInvalidateFlags::Section;
804 lcl_InvalidateAllContent( *this, nInv );
808 void SwViewShell::SetUseVirDev( bool bNewVirtual )
810 IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
811 if ( rIDSA.get(DocumentSettingId::USE_VIRTUAL_DEVICE) != bNewVirtual )
813 SwWait aWait( *GetDoc()->GetDocShell(), true );
814 // this sets the flag at the document and calls PrtDataChanged
815 IDocumentDeviceAccess& rIDDA = getIDocumentDeviceAccess();
816 rIDDA.setReferenceDeviceType( bNewVirtual, true );
820 /** Sets if paragraph and table spacing is added at bottom of table cells.
821 * #106629#
822 * @param[in] (bool) setting of the new value
824 void SwViewShell::SetAddParaSpacingToTableCells( bool _bAddParaSpacingToTableCells )
826 IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
827 if (rIDSA.get(DocumentSettingId::ADD_PARA_SPACING_TO_TABLE_CELLS) != _bAddParaSpacingToTableCells
828 || rIDSA.get(DocumentSettingId::ADD_PARA_LINE_SPACING_TO_TABLE_CELLS) != _bAddParaSpacingToTableCells)
830 SwWait aWait( *GetDoc()->GetDocShell(), true );
831 rIDSA.set(DocumentSettingId::ADD_PARA_SPACING_TO_TABLE_CELLS, _bAddParaSpacingToTableCells );
832 // note: the dialog can't change the value to indeterminate, so only false/false and true/true
833 rIDSA.set(DocumentSettingId::ADD_PARA_LINE_SPACING_TO_TABLE_CELLS, _bAddParaSpacingToTableCells );
834 const SwInvalidateFlags nInv = SwInvalidateFlags::PrtArea;
835 lcl_InvalidateAllContent( *this, nInv );
840 * Sets if former formatting of text lines with proportional line spacing should used.
841 * #i11859#
842 * @param[in] (bool) setting of the new value
844 void SwViewShell::SetUseFormerLineSpacing( bool _bUseFormerLineSpacing )
846 IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
847 if ( rIDSA.get(DocumentSettingId::OLD_LINE_SPACING) != _bUseFormerLineSpacing )
849 SwWait aWait( *GetDoc()->GetDocShell(), true );
850 rIDSA.set(DocumentSettingId::OLD_LINE_SPACING, _bUseFormerLineSpacing );
851 const SwInvalidateFlags nInv = SwInvalidateFlags::PrtArea;
852 lcl_InvalidateAllContent( *this, nInv );
857 * Sets IDocumentSettingAccess if former object positioning should be used.
858 * #i11860#
859 * @param[in] (bool) setting the new value
861 void SwViewShell::SetUseFormerObjectPositioning( bool _bUseFormerObjPos )
863 IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
864 if ( rIDSA.get(DocumentSettingId::USE_FORMER_OBJECT_POS) != _bUseFormerObjPos )
866 SwWait aWait( *GetDoc()->GetDocShell(), true );
867 rIDSA.set(DocumentSettingId::USE_FORMER_OBJECT_POS, _bUseFormerObjPos );
868 lcl_InvalidateAllObjPos( *this );
872 // #i28701#
873 void SwViewShell::SetConsiderWrapOnObjPos( bool _bConsiderWrapOnObjPos )
875 IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
876 if ( rIDSA.get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) != _bConsiderWrapOnObjPos )
878 SwWait aWait( *GetDoc()->GetDocShell(), true );
879 rIDSA.set(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION, _bConsiderWrapOnObjPos );
880 lcl_InvalidateAllObjPos( *this );
884 void SwViewShell::SetUseFormerTextWrapping( bool _bUseFormerTextWrapping )
886 IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
887 if ( rIDSA.get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING) != _bUseFormerTextWrapping )
889 SwWait aWait( *GetDoc()->GetDocShell(), true );
890 rIDSA.set(DocumentSettingId::USE_FORMER_TEXT_WRAPPING, _bUseFormerTextWrapping );
891 const SwInvalidateFlags nInv = SwInvalidateFlags::PrtArea | SwInvalidateFlags::Size | SwInvalidateFlags::Table | SwInvalidateFlags::Section;
892 lcl_InvalidateAllContent( *this, nInv );
896 // #i45491#
897 void SwViewShell::SetDoNotJustifyLinesWithManualBreak( bool _bDoNotJustifyLinesWithManualBreak )
899 IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
900 if ( rIDSA.get(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK) != _bDoNotJustifyLinesWithManualBreak )
902 SwWait aWait( *GetDoc()->GetDocShell(), true );
903 rIDSA.set(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, _bDoNotJustifyLinesWithManualBreak );
904 const SwInvalidateFlags nInv = SwInvalidateFlags::PrtArea | SwInvalidateFlags::Size | SwInvalidateFlags::Table | SwInvalidateFlags::Section;
905 lcl_InvalidateAllContent( *this, nInv );
909 void SwViewShell::SetProtectForm( bool _bProtectForm )
911 IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
912 rIDSA.set(DocumentSettingId::PROTECT_FORM, _bProtectForm );
915 void SwViewShell::SetMsWordCompTrailingBlanks( bool _bMsWordCompTrailingBlanks )
917 IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
918 if (rIDSA.get(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS) != _bMsWordCompTrailingBlanks)
920 SwWait aWait(*GetDoc()->GetDocShell(), true);
921 rIDSA.set(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS, _bMsWordCompTrailingBlanks);
922 const SwInvalidateFlags nInv = SwInvalidateFlags::PrtArea | SwInvalidateFlags::Size | SwInvalidateFlags::Table | SwInvalidateFlags::Section;
923 lcl_InvalidateAllContent(*this, nInv);
927 void SwViewShell::SetSubtractFlysAnchoredAtFlys(bool bSubtractFlysAnchoredAtFlys)
929 IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
930 rIDSA.set(DocumentSettingId::SUBTRACT_FLYS, bSubtractFlysAnchoredAtFlys);
933 void SwViewShell::SetEmptyDbFieldHidesPara(bool bEmptyDbFieldHidesPara)
935 IDocumentSettingAccess& rIDSA = getIDocumentSettingAccess();
936 if (rIDSA.get(DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA) == bEmptyDbFieldHidesPara)
937 return;
939 SwWait aWait(*GetDoc()->GetDocShell(), true);
940 rIDSA.set(DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA, bEmptyDbFieldHidesPara);
941 StartAction();
942 GetDoc()->getIDocumentState().SetModified();
943 for (auto const & pFieldType : *GetDoc()->getIDocumentFieldsAccess().GetFieldTypes())
945 if(pFieldType->Which() == SwFieldIds::Database)
946 pFieldType->UpdateFields();
948 EndAction();
951 void SwViewShell::Reformat()
953 SwWait aWait( *GetDoc()->GetDocShell(), true );
955 // we go for safe: get rid of the old font information,
956 // when the printer resolution or zoom factor changes.
957 // Init() and Reformat() are the safest locations.
958 pFntCache->Flush( );
960 if( GetLayout()->IsCallbackActionEnabled() )
962 StartAction();
963 GetLayout()->InvalidateAllContent( SwInvalidateFlags::Size | SwInvalidateFlags::Pos | SwInvalidateFlags::PrtArea );
964 EndAction();
968 void SwViewShell::ChgNumberDigits()
970 SdrModel* pTmpDrawModel = getIDocumentDrawModelAccess().GetDrawModel();
971 if ( pTmpDrawModel )
972 pTmpDrawModel->ReformatAllTextObjects();
973 Reformat();
976 void SwViewShell::CalcLayout()
978 // extremely likely to be a Bad Idea to call this without StartAction
979 // (except the Page Preview apparently only has a non-subclassed ViewShell)
980 assert((typeid(*this) == typeid(SwViewShell)) || mnStartAction);
982 CurrShell aCurr( this );
983 SwWait aWait( *GetDoc()->GetDocShell(), true );
985 // Preserve top of the text frame cache.
986 SwSaveSetLRUOfst aSaveLRU;
988 //switch on Progress when none is running yet.
989 const bool bEndProgress = SfxProgress::GetActiveProgress( GetDoc()->GetDocShell() ) == nullptr;
990 if ( bEndProgress )
992 tools::Long nEndPage = GetLayout()->GetPageNum();
993 nEndPage += nEndPage * 10 / 100;
994 ::StartProgress( STR_STATSTR_REFORMAT, 0, nEndPage, GetDoc()->GetDocShell() );
997 SwLayAction aAction( GetLayout(), Imp() );
998 aAction.SetPaint( false );
999 aAction.SetStatBar( true );
1000 aAction.SetCalcLayout( true );
1001 aAction.SetReschedule( true );
1002 GetDoc()->getIDocumentFieldsAccess().LockExpFields();
1003 aAction.Action(GetOut());
1004 GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
1006 //the SetNewFieldLst() on the Doc was cut off and must be fetched again
1007 //(see flowfrm.cxx, txtfld.cxx)
1008 if ( aAction.IsExpFields() )
1010 aAction.Reset();
1011 aAction.SetPaint( false );
1012 aAction.SetStatBar( true );
1013 aAction.SetReschedule( true );
1015 SwDocPosUpdate aMsgHint( 0 );
1016 GetDoc()->getIDocumentFieldsAccess().UpdatePageFields( &aMsgHint );
1017 GetDoc()->getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
1019 aAction.Action(GetOut());
1022 if ( VisArea().HasArea() )
1023 InvalidateWindows( VisArea() );
1024 if ( bEndProgress )
1025 ::EndProgress( GetDoc()->GetDocShell() );
1028 void SwViewShell::SetFirstVisPageInvalid()
1030 for(SwViewShell& rSh : GetRingContainer())
1032 if ( rSh.Imp() )
1033 rSh.Imp()->SetFirstVisPageInvalid();
1037 void SwViewShell::SizeChgNotify()
1039 if ( !mpWin )
1040 mbDocSizeChgd = true;
1041 else if( ActionPend() || Imp()->IsCalcLayoutProgress() || mbPaintInProgress )
1043 mbDocSizeChgd = true;
1045 if ( !Imp()->IsCalcLayoutProgress() && dynamic_cast<const SwCursorShell*>( this ) != nullptr )
1047 PageNumNotify(this);
1049 if (comphelper::LibreOfficeKit::isActive())
1051 Size aDocSize = GetDocSize();
1052 std::stringstream ss;
1053 ss << aDocSize.Width() + 2 * DOCUMENTBORDER << ", " << aDocSize.Height() + 2 * DOCUMENTBORDER;
1054 OString sSize = ss.str().c_str();
1056 SwXTextDocument* pModel = comphelper::getUnoTunnelImplementation<SwXTextDocument>(GetSfxViewShell()->GetCurrentDocument());
1057 SfxLokHelper::notifyDocumentSizeChanged(GetSfxViewShell(), sSize, pModel);
1061 else
1063 mbDocSizeChgd = false;
1064 ::SizeNotify( this, GetDocSize() );
1068 void SwViewShell::VisPortChgd( const SwRect &rRect)
1070 OSL_ENSURE( GetWin(), "VisPortChgd without Window." );
1072 if ( rRect == VisArea() )
1073 return;
1075 // Is someone spuriously rescheduling again?
1076 SAL_WARN_IF(mbInEndAction, "sw.core", "Scrolling during EndAction");
1078 //First get the old visible page, so we don't have to look
1079 //for it afterwards.
1080 const SwFrame *pOldPage = Imp()->GetFirstVisPage(GetWin());
1082 const SwRect aPrevArea( VisArea() );
1083 const bool bFull = aPrevArea.IsEmpty();
1084 maVisArea = rRect;
1085 SetFirstVisPageInvalid();
1087 //When there a PaintRegion still exists and the VisArea has changed,
1088 //the PaintRegion is at least by now obsolete. The PaintRegion can
1089 //have been created by RootFrame::PaintSwFrame.
1090 if ( !mbInEndAction &&
1091 Imp()->GetRegion() && Imp()->GetRegion()->GetOrigin() != VisArea() )
1092 Imp()->DelRegion();
1094 CurrShell aCurr( this );
1096 bool bScrolled = false;
1098 SwPostItMgr* pPostItMgr = GetPostItMgr();
1100 if ( bFull )
1101 GetWin()->Invalidate();
1102 else
1104 //Calculate amount to be scrolled.
1105 const tools::Long nXDiff = aPrevArea.Left() - VisArea().Left();
1106 const tools::Long nYDiff = aPrevArea.Top() - VisArea().Top();
1108 if( !nXDiff && !GetViewOptions()->getBrowseMode() &&
1109 (!Imp()->HasDrawView() || !Imp()->GetDrawView()->IsGridVisible() ) )
1111 // If possible, don't scroll the application background
1112 // (PaintDesktop). Also limit the left and right side of
1113 // the scroll range to the pages.
1114 const SwPageFrame *pPage = static_cast<SwPageFrame*>(GetLayout()->Lower());
1115 if ( pPage->getFrameArea().Top() > pOldPage->getFrameArea().Top() )
1116 pPage = static_cast<const SwPageFrame*>(pOldPage);
1117 SwRect aBoth( VisArea() );
1118 aBoth.Union( aPrevArea );
1119 const SwTwips nBottom = aBoth.Bottom();
1120 SwTwips nMinLeft = SAL_MAX_INT32;
1121 SwTwips nMaxRight= 0;
1123 const bool bBookMode = GetViewOptions()->IsViewLayoutBookMode();
1125 while ( pPage && pPage->getFrameArea().Top() <= nBottom )
1127 SwRect aPageRect( pPage->GetBoundRect(GetWin()) );
1128 if ( bBookMode )
1130 const SwPageFrame& rFormatPage = pPage->GetFormatPage();
1131 aPageRect.SSize( rFormatPage.GetBoundRect(GetWin()).SSize() );
1134 // #i9719# - consider new border and shadow width
1135 if ( aPageRect.IsOver( aBoth ) )
1137 SwTwips nPageLeft = 0;
1138 SwTwips nPageRight = 0;
1139 const sw::sidebarwindows::SidebarPosition aSidebarPos = pPage->SidebarPosition();
1141 if( aSidebarPos != sw::sidebarwindows::SidebarPosition::NONE )
1143 nPageLeft = aPageRect.Left();
1144 nPageRight = aPageRect.Right();
1147 if( nPageLeft < nMinLeft )
1148 nMinLeft = nPageLeft;
1149 if( nPageRight > nMaxRight )
1150 nMaxRight = nPageRight;
1151 //match with the draw objects
1152 //take nOfst into account as the objects have been
1153 //selected and have handles attached.
1154 if ( pPage->GetSortedObjs() )
1156 const tools::Long nOfst = GetOut()->PixelToLogic(
1157 Size(Imp()->GetDrawView()->GetMarkHdlSizePixel()/2,0)).Width();
1158 for (SwAnchoredObject* pObj : *pPage->GetSortedObjs())
1160 // ignore objects that are not actually placed on the page
1161 if (pObj->IsFormatPossible())
1163 const tools::Rectangle &rBound = pObj->GetObjRect().SVRect();
1164 if (rBound.Left() != FAR_AWAY) {
1165 // OD 03.03.2003 #107927# - use correct datatype
1166 const SwTwips nL = std::max( SwTwips(0), SwTwips(rBound.Left() - nOfst) );
1167 if ( nL < nMinLeft )
1168 nMinLeft = nL;
1169 if( rBound.Right() + nOfst > nMaxRight )
1170 nMaxRight = rBound.Right() + nOfst;
1176 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
1178 tools::Rectangle aRect( aPrevArea.SVRect() );
1179 aRect.SetLeft( nMinLeft );
1180 aRect.SetRight( nMaxRight );
1181 if( VisArea().IsOver( aPrevArea ) && !mnLockPaint )
1183 bScrolled = true;
1184 maVisArea.Pos() = aPrevArea.Pos();
1185 if ( SmoothScroll( nXDiff, nYDiff, &aRect ) )
1186 return;
1187 maVisArea.Pos() = rRect.Pos();
1189 else
1190 GetWin()->Invalidate( aRect );
1192 else if ( !mnLockPaint ) //will be released in Unlock
1194 if( VisArea().IsOver( aPrevArea ) )
1196 bScrolled = true;
1197 maVisArea.Pos() = aPrevArea.Pos();
1198 if ( SmoothScroll( nXDiff, nYDiff, nullptr ) )
1199 return;
1200 maVisArea.Pos() = rRect.Pos();
1202 else
1203 GetWin()->Invalidate();
1207 // When tiled rendering, the map mode of the window is disabled, avoid
1208 // enabling it here.
1209 if (!comphelper::LibreOfficeKit::isActive())
1211 Point aPt( VisArea().Pos() );
1212 aPt.setX( -aPt.X() ); aPt.setY( -aPt.Y() );
1213 MapMode aMapMode( GetWin()->GetMapMode() );
1214 aMapMode.SetOrigin( aPt );
1215 GetWin()->SetMapMode( aMapMode );
1218 if ( HasDrawView() )
1220 Imp()->GetDrawView()->VisAreaChanged( GetWin() );
1221 Imp()->GetDrawView()->SetActualWin( GetWin() );
1223 GetWin()->PaintImmediately();
1225 if ( pPostItMgr ) // #i88070#
1227 pPostItMgr->Rescale();
1228 pPostItMgr->CalcRects();
1229 pPostItMgr->LayoutPostIts();
1232 if ( !bScrolled && pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() )
1233 pPostItMgr->CorrectPositions();
1235 if( Imp()->IsAccessible() )
1236 Imp()->UpdateAccessible();
1239 bool SwViewShell::SmoothScroll( tools::Long lXDiff, tools::Long lYDiff, const tools::Rectangle *pRect )
1241 #if !defined(MACOSX) && !defined(ANDROID) && !defined(IOS)
1242 // #i98766# - disable smooth scrolling for Mac
1244 const sal_uLong nBitCnt = mpOut->GetBitCount();
1245 tools::Long lMult = 1, lMax = LONG_MAX;
1246 if ( nBitCnt == 16 )
1248 lMax = 7000;
1249 lMult = 2;
1251 if ( nBitCnt == 24 )
1253 lMax = 5000;
1254 lMult = 6;
1256 else if ( nBitCnt == 1 )
1258 lMax = 3000;
1259 lMult = 12;
1262 // #i75172# isolated static conditions
1263 const bool bOnlyYScroll(!lXDiff && std::abs(lYDiff) != 0 && std::abs(lYDiff) < lMax);
1264 const bool bAllowedWithChildWindows(GetWin()->GetWindowClipRegionPixel().IsNull());
1265 const bool bSmoothScrollAllowed(bOnlyYScroll && mbEnableSmooth && GetViewOptions()->IsSmoothScroll() && bAllowedWithChildWindows);
1267 if(bSmoothScrollAllowed)
1269 Imp()->m_bStopSmooth = false;
1271 const SwRect aOldVis( VisArea() );
1273 //create virtual device and set.
1274 const Size aPixSz = GetWin()->PixelToLogic(Size(1,1));
1275 VclPtrInstance<VirtualDevice> pVout( *GetWin() );
1276 pVout->SetLineColor( GetWin()->GetLineColor() );
1277 pVout->SetFillColor( GetWin()->GetFillColor() );
1278 MapMode aMapMode( GetWin()->GetMapMode() );
1279 pVout->SetMapMode( aMapMode );
1280 Size aSize( maVisArea.Width()+2*aPixSz.Width(), std::abs(lYDiff)+(2*aPixSz.Height()) );
1281 if ( pRect )
1282 aSize.setWidth( std::min(aSize.Width(), pRect->GetWidth()+2*aPixSz.Width()) );
1283 if ( pVout->SetOutputSize( aSize ) )
1285 mnLockPaint++;
1287 //First Paint everything in the virtual device.
1288 SwRect aRect( VisArea() );
1289 aRect.Height( aSize.Height() );
1290 if ( pRect )
1292 aRect.Pos().setX( std::max(aRect.Left(),pRect->Left()-aPixSz.Width()) );
1293 aRect.Right( std::min(aRect.Right()+2*aPixSz.Width(), pRect->Right()+aPixSz.Width()));
1295 else
1296 aRect.AddWidth(2*aPixSz.Width() );
1297 aRect.Pos().setY( lYDiff < 0 ? aOldVis.Bottom() - aPixSz.Height()
1298 : aRect.Top() - aSize.Height() + aPixSz.Height() );
1299 aRect.Pos().setX( std::max( tools::Long(0), aRect.Left()-aPixSz.Width() ) );
1300 aRect.Pos() = GetWin()->PixelToLogic( GetWin()->LogicToPixel( aRect.Pos()));
1301 aRect.SSize( GetWin()->PixelToLogic( GetWin()->LogicToPixel( aRect.SSize())) );
1302 maVisArea = aRect;
1303 const Point aPt( -aRect.Left(), -aRect.Top() );
1304 aMapMode.SetOrigin( aPt );
1305 pVout->SetMapMode( aMapMode );
1306 OutputDevice *pOld = mpOut;
1307 mpOut = pVout.get();
1310 // #i75172# To get a clean repaint, a new ObjectContact is needed here. Without, the
1311 // repaint would not be correct since it would use the wrong DrawPage visible region.
1312 // This repaint IS about painting something currently outside the visible part (!).
1313 // For that purpose, AddWindowToPaintView is used which creates a new SdrPageViewWindow
1314 // and all the necessary stuff. It's not cheap, but necessary here. Alone because repaint
1315 // target really is NOT the current window.
1316 // Also will automatically NOT use PreRendering and overlay (since target is VirtualDevice)
1317 if(!HasDrawView())
1318 MakeDrawView();
1319 SdrView* pDrawView = GetDrawView();
1320 pDrawView->AddWindowToPaintView(pVout, nullptr);
1322 // clear mpWin during DLPrePaint2 to get paint preparation for mpOut, but set it again
1323 // immediately afterwards. There are many decisions in SW which imply that Printing
1324 // is used when mpWin == 0 (wrong but widely used).
1325 vcl::Window* pOldWin = mpWin;
1326 mpWin = nullptr;
1327 DLPrePaint2(vcl::Region(aRect.SVRect()));
1328 mpWin = pOldWin;
1330 // SW paint stuff
1331 PaintDesktop(*GetOut(), aRect);
1332 SwViewShell::mbLstAct = true;
1333 GetLayout()->PaintSwFrame( *GetOut(), aRect );
1334 SwViewShell::mbLstAct = false;
1336 // end paint and destroy ObjectContact again
1337 DLPostPaint2(true);
1338 pDrawView->DeleteWindowFromPaintView(pVout);
1341 mpOut = pOld;
1342 maVisArea = aOldVis;
1344 //Now shift in parts and copy the new Pixel from the virtual device.
1346 // ??????????????????????
1347 // or is it better to get the scrollfactor from the User
1348 // as option?
1349 // ??????????????????????
1350 tools::Long lMaDelta = aPixSz.Height();
1351 if ( std::abs(lYDiff) > ( maVisArea.Height() / 3 ) )
1352 lMaDelta *= 6;
1353 else
1354 lMaDelta *= 2;
1356 lMaDelta *= lMult;
1358 if ( lYDiff < 0 )
1359 lMaDelta = -lMaDelta;
1361 tools::Long lDiff = lYDiff;
1362 while ( lDiff )
1364 tools::Long lScroll;
1365 if ( Imp()->m_bStopSmooth || std::abs(lDiff) <= std::abs(lMaDelta) )
1367 lScroll = lDiff;
1368 lDiff = 0;
1370 else
1372 lScroll = lMaDelta;
1373 lDiff -= lMaDelta;
1376 const SwRect aTmpOldVis = VisArea();
1377 maVisArea.Pos().AdjustY( -lScroll );
1378 maVisArea.Pos() = GetWin()->PixelToLogic( GetWin()->LogicToPixel( VisArea().Pos()));
1379 lScroll = aTmpOldVis.Top() - VisArea().Top();
1380 if ( pRect )
1382 tools::Rectangle aTmp( aTmpOldVis.SVRect() );
1383 aTmp.SetLeft( pRect->Left() );
1384 aTmp.SetRight( pRect->Right() );
1385 GetWin()->Scroll( 0, lScroll, aTmp, ScrollFlags::Children);
1387 else
1388 GetWin()->Scroll( 0, lScroll, ScrollFlags::Children );
1390 const Point aTmpPt( -VisArea().Left(), -VisArea().Top() );
1391 MapMode aTmpMapMode( GetWin()->GetMapMode() );
1392 aTmpMapMode.SetOrigin( aTmpPt );
1393 GetWin()->SetMapMode( aTmpMapMode );
1395 if ( Imp()->HasDrawView() )
1396 Imp()->GetDrawView()->VisAreaChanged( GetWin() );
1398 SetFirstVisPageInvalid();
1399 if ( !Imp()->m_bStopSmooth )
1401 const bool bScrollDirectionIsUp(lScroll > 0);
1402 Imp()->m_aSmoothRect = VisArea();
1404 if(bScrollDirectionIsUp)
1406 Imp()->m_aSmoothRect.Bottom( VisArea().Top() + lScroll + aPixSz.Height());
1408 else
1410 Imp()->m_aSmoothRect.Top( VisArea().Bottom() + lScroll - aPixSz.Height());
1413 Imp()->m_bSmoothUpdate = true;
1414 GetWin()->PaintImmediately();
1415 Imp()->m_bSmoothUpdate = false;
1417 if(!Imp()->m_bStopSmooth)
1419 // start paint on logic base
1420 const tools::Rectangle aTargetLogic(Imp()->m_aSmoothRect.SVRect());
1421 DLPrePaint2(vcl::Region(aTargetLogic));
1423 // get target rectangle in discrete pixels
1424 OutputDevice& rTargetDevice = mpTargetPaintWindow->GetTargetOutputDevice();
1425 const tools::Rectangle aTargetPixel(rTargetDevice.LogicToPixel(aTargetLogic));
1427 // get source top-left in discrete pixels
1428 const Point aSourceTopLeft(pVout->LogicToPixel(aTargetLogic.TopLeft()));
1430 // switch off MapModes
1431 const bool bMapModeWasEnabledDest(rTargetDevice.IsMapModeEnabled());
1432 const bool bMapModeWasEnabledSource(pVout->IsMapModeEnabled());
1433 rTargetDevice.EnableMapMode(false);
1434 pVout->EnableMapMode(false);
1436 rTargetDevice.DrawOutDev(
1437 aTargetPixel.TopLeft(), aTargetPixel.GetSize(), // dest
1438 aSourceTopLeft, aTargetPixel.GetSize(), // source
1439 *pVout);
1441 // restore MapModes
1442 rTargetDevice.EnableMapMode(bMapModeWasEnabledDest);
1443 pVout->EnableMapMode(bMapModeWasEnabledSource);
1445 // end paint on logoc base
1446 DLPostPaint2(true);
1448 else
1449 --mnLockPaint;
1452 pVout.disposeAndClear();
1453 GetWin()->PaintImmediately();
1454 if ( !Imp()->m_bStopSmooth )
1455 --mnLockPaint;
1456 SetFirstVisPageInvalid();
1457 return true;
1459 pVout.disposeAndClear();
1461 #endif
1463 maVisArea.Pos().AdjustX( -lXDiff );
1464 maVisArea.Pos().AdjustY( -lYDiff );
1465 if ( pRect )
1466 GetWin()->Scroll( lXDiff, lYDiff, *pRect, ScrollFlags::Children);
1467 else
1468 GetWin()->Scroll( lXDiff, lYDiff, ScrollFlags::Children);
1469 return false;
1472 void SwViewShell::PaintDesktop(vcl::RenderContext& rRenderContext, const SwRect &rRect)
1474 if ( !GetWin() && !GetOut()->GetConnectMetaFile() )
1475 return; //for the printer we don't do anything here.
1477 //Catch exceptions, so that it doesn't look so surprising.
1478 //Can e.g. happen during Idle.
1479 //Unfortunately we must at any rate Paint the rectangles next to the pages,
1480 //as these are not painted at VisPortChgd.
1481 bool bBorderOnly = false;
1482 const SwRootFrame *pRoot = GetLayout();
1483 if ( rRect.Top() > pRoot->getFrameArea().Bottom() )
1485 const SwFrame *pPg = pRoot->Lower();
1486 while ( pPg && pPg->GetNext() )
1487 pPg = pPg->GetNext();
1488 if ( !pPg || !pPg->getFrameArea().IsOver( VisArea() ) )
1489 bBorderOnly = true;
1492 const bool bBookMode = GetViewOptions()->IsViewLayoutBookMode();
1494 SwRegionRects aRegion( rRect );
1496 //mod #i6193: remove sidebar area to avoid flickering
1497 const SwPostItMgr* pPostItMgr = GetPostItMgr();
1498 const SwTwips nSidebarWidth = pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() ?
1499 pPostItMgr->GetSidebarWidth() + pPostItMgr->GetSidebarBorderWidth() :
1502 if ( bBorderOnly )
1504 const SwFrame *pPage =pRoot->Lower();
1505 SwRect aLeft( rRect ), aRight( rRect );
1506 while ( pPage )
1508 tools::Long nTmp = pPage->getFrameArea().Left();
1509 if ( nTmp < aLeft.Right() )
1510 aLeft.Right( nTmp );
1511 nTmp = pPage->getFrameArea().Right();
1512 if ( nTmp > aRight.Left() )
1514 aRight.Left( nTmp + nSidebarWidth );
1516 pPage = pPage->GetNext();
1518 aRegion.clear();
1519 if ( aLeft.HasArea() )
1520 aRegion.push_back( aLeft );
1521 if ( aRight.HasArea() )
1522 aRegion.push_back( aRight );
1524 else
1526 const SwFrame *pPage = Imp()->GetFirstVisPage(&rRenderContext);
1527 const SwTwips nBottom = rRect.Bottom();
1528 while ( pPage && !aRegion.empty() &&
1529 (pPage->getFrameArea().Top() <= nBottom) )
1531 SwRect aPageRect( pPage->getFrameArea() );
1532 if ( bBookMode )
1534 const SwPageFrame& rFormatPage = static_cast<const SwPageFrame*>(pPage)->GetFormatPage();
1535 aPageRect.SSize( rFormatPage.getFrameArea().SSize() );
1538 const bool bSidebarRight =
1539 static_cast<const SwPageFrame*>(pPage)->SidebarPosition() == sw::sidebarwindows::SidebarPosition::RIGHT;
1540 aPageRect.Pos().AdjustX( -(bSidebarRight ? 0 : nSidebarWidth) );
1541 aPageRect.AddWidth(nSidebarWidth );
1543 if ( aPageRect.IsOver( rRect ) )
1544 aRegion -= aPageRect;
1546 pPage = pPage->GetNext();
1549 if ( !aRegion.empty() )
1550 PaintDesktop_(aRegion);
1553 // PaintDesktop is split in two, this part is also used by PreviewPage
1554 void SwViewShell::PaintDesktop_(const SwRegionRects &rRegion)
1556 // OD 2004-04-23 #116347#
1557 GetOut()->Push( PushFlags::FILLCOLOR|PushFlags::LINECOLOR );
1558 GetOut()->SetLineColor();
1560 for ( auto &rRgn : rRegion )
1562 const tools::Rectangle aRectangle(rRgn.SVRect());
1564 // #i93170#
1565 // Here we have a real Problem. On the one hand we have the buffering for paint
1566 // and overlay which needs an embracing pair of DLPrePaint2/DLPostPaint2 calls,
1567 // on the other hand the MapMode is not set correctly when this code is executed.
1568 // This is done in the users of this method, for each SWpage before painting it.
1569 // Since the MapMode is not correct here, the call to DLPostPaint2 will paint
1570 // existing FormControls due to the current MapMode.
1572 // There are basically three solutions for this:
1574 // (1) Set the MapMode correct, move the background painting to the users of
1575 // this code
1577 // (2) Do no DLPrePaint2/DLPostPaint2 here; no SdrObjects are allowed to lie in
1578 // the desktop region. Disadvantage: the desktop will not be part of the
1579 // buffers, e.g. overlay. Thus, as soon as overlay will be used over the
1580 // desktop, it will not work.
1582 // (3) expand DLPostPaint2 with a flag to signal if FormControl paints shall
1583 // be done or not
1585 // Currently, (3) will be the best possible solution. It will keep overlay and
1586 // buffering intact and work without MapMode for single pages. In the medium
1587 // to long run, (1) will need to be used and the bool bPaintFormLayer needs
1588 // to be removed again
1590 // #i68597# inform Drawinglayer about display change
1591 DLPrePaint2(vcl::Region(aRectangle));
1593 // #i75172# needed to move line/Fill color setters into loop since DLPrePaint2
1594 // may exchange GetOut(), that's it's purpose. This happens e.g. at print preview.
1595 GetOut()->SetFillColor( SwViewOption::GetAppBackgroundColor());
1596 GetOut()->SetLineColor();
1597 GetOut()->DrawRect(aRectangle);
1599 DLPostPaint2(false);
1602 GetOut()->Pop();
1605 bool SwViewShell::CheckInvalidForPaint( const SwRect &rRect )
1607 if ( !GetWin() )
1608 return false;
1610 const SwPageFrame *pPage = Imp()->GetFirstVisPage(GetOut());
1611 const SwTwips nBottom = VisArea().Bottom();
1612 const SwTwips nRight = VisArea().Right();
1613 bool bRet = false;
1614 while ( !bRet && pPage && ((pPage->getFrameArea().Top() <= nBottom) &&
1615 (pPage->getFrameArea().Left() <= nRight)))
1617 if ( pPage->IsInvalid() || pPage->IsInvalidFly() )
1618 bRet = true;
1619 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
1622 if ( bRet )
1624 //Unfortunately Start/EndAction won't help here, as the Paint originated
1625 //from GUI and so Clipping has been set against getting through.
1626 //Ergo: do it all yourself (see ImplEndAction())
1627 if ( Imp()->GetRegion() && Imp()->GetRegion()->GetOrigin() != VisArea())
1628 Imp()->DelRegion();
1630 SwLayAction aAction( GetLayout(), Imp() );
1631 aAction.SetComplete( false );
1632 // We increment the action counter to avoid a recursive call of actions
1633 // e.g. from a SwFEShell::RequestObjectResize(..) in bug 95829.
1634 // A recursive call of actions is no good idea because the inner action
1635 // can't format frames which are locked by the outer action. This may
1636 // cause and endless loop.
1637 ++mnStartAction;
1638 aAction.Action(GetWin());
1639 --mnStartAction;
1641 SwRegionRects *pRegion = Imp()->GetRegion();
1642 if ( pRegion && aAction.IsBrowseActionStop() )
1644 //only of interest when something has changed in the visible range
1645 bool bStop = true;
1646 for ( size_t i = 0; i < pRegion->size(); ++i )
1648 const SwRect &rTmp = (*pRegion)[i];
1649 bStop = rTmp.IsOver( VisArea() );
1650 if ( !bStop )
1651 break;
1653 if ( bStop )
1655 Imp()->DelRegion();
1656 pRegion = nullptr;
1660 if ( pRegion )
1662 //First Invert then Compress, never the other way round!
1663 pRegion->Invert();
1664 pRegion->Compress();
1665 bRet = false;
1666 if ( !pRegion->empty() )
1668 SwRegionRects aRegion( rRect );
1669 for ( size_t i = 0; i < pRegion->size(); ++i )
1670 { const SwRect &rTmp = (*pRegion)[i];
1671 if ( !rRect.IsInside( rTmp ) )
1673 InvalidateWindows( rTmp );
1674 if ( rTmp.IsOver( VisArea() ) )
1675 { aRegion -= rTmp;
1676 bRet = true;
1680 if ( bRet )
1682 for ( size_t i = 0; i < aRegion.size(); ++i )
1683 GetWin()->Invalidate( aRegion[i].SVRect() );
1685 if ( rRect != VisArea() )
1687 //rRect == VisArea is the special case for new or
1688 //Shift-Ctrl-R, when it shouldn't be necessary to
1689 //hold the rRect again in Document coordinates.
1690 if ( maInvalidRect.IsEmpty() )
1691 maInvalidRect = rRect;
1692 else
1693 maInvalidRect.Union( rRect );
1697 else
1698 bRet = false;
1699 Imp()->DelRegion();
1701 else
1702 bRet = false;
1704 return bRet;
1707 namespace
1709 /// Similar to comphelper::FlagRestorationGuard, but for vcl::RenderContext.
1710 class RenderContextGuard
1712 std::unique_ptr<SdrPaintWindow> m_TemporaryPaintWindow;
1713 SdrPageWindow* m_pPatchedPageWindow;
1714 SdrPaintWindow* m_pPreviousPaintWindow = nullptr;
1716 public:
1717 RenderContextGuard(VclPtr<vcl::RenderContext>& pRef, vcl::RenderContext* pValue, SwViewShell* pShell)
1718 : m_pPatchedPageWindow(nullptr)
1720 pRef = pValue;
1722 if (pValue == pShell->GetWin())
1723 return;
1725 SdrView* pDrawView(pShell->Imp()->GetDrawView());
1727 if (nullptr == pDrawView)
1728 return;
1730 SdrPageView* pSdrPageView(pDrawView->GetSdrPageView());
1732 if (nullptr != pSdrPageView)
1734 m_pPatchedPageWindow = pSdrPageView->FindPageWindow(*pShell->GetWin());
1736 if (nullptr != m_pPatchedPageWindow)
1738 m_TemporaryPaintWindow.reset(new SdrPaintWindow(*pDrawView, *pValue));
1739 m_pPreviousPaintWindow = m_pPatchedPageWindow->patchPaintWindow(*m_TemporaryPaintWindow);
1744 ~RenderContextGuard()
1746 if(nullptr != m_pPatchedPageWindow)
1748 m_pPatchedPageWindow->unpatchPaintWindow(m_pPreviousPaintWindow);
1754 void SwViewShell::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle &rRect)
1756 RenderContextGuard aGuard(mpOut, &rRenderContext, this);
1757 if ( mnLockPaint )
1759 if ( Imp()->m_bSmoothUpdate )
1761 SwRect aTmp( rRect );
1762 if ( !Imp()->m_aSmoothRect.IsInside( aTmp ) )
1763 Imp()->m_bStopSmooth = true;
1764 else
1766 Imp()->m_aSmoothRect = aTmp;
1767 return;
1770 else
1771 return;
1774 if ( SwRootFrame::IsInPaint() )
1776 //During the publication of a page at printing the Paint is buffered.
1777 SwPaintQueue::Add( this, SwRect( rRect ) );
1778 return;
1781 //With !nStartAction I try to protect me against erroneous code at other places.
1782 //Hopefully it will not lead to problems!?
1783 if ( mbPaintWorks && !mnStartAction )
1785 if( GetWin() && GetWin()->IsVisible() )
1787 SwRect aRect( rRect );
1788 if ( mbPaintInProgress ) //Guard against double Paints!
1790 GetWin()->Invalidate( rRect );
1791 return;
1794 mbPaintInProgress = true;
1795 CurrShell aCurr( this );
1796 SwRootFrame::SetNoVirDev( true );
1798 //We don't want to Clip to and from, we trust that all are limited
1799 //to the rectangle and only need to calculate the clipping once.
1800 //The ClipRect is removed here once and not recovered, as externally
1801 //no one needs it anymore anyway.
1802 //Not when we paint a Metafile.
1803 if( !GetOut()->GetConnectMetaFile() && GetOut()->IsClipRegion())
1804 GetOut()->SetClipRegion();
1806 if ( IsPreview() )
1808 //When useful, process or destroy the old InvalidRect.
1809 if ( aRect.IsInside( maInvalidRect ) )
1810 ResetInvalidRect();
1811 SwViewShell::mbLstAct = true;
1812 GetLayout()->PaintSwFrame( rRenderContext, aRect );
1813 SwViewShell::mbLstAct = false;
1815 else
1817 //When one of the visible pages still has anything entered for
1818 //Repaint, Repaint must be triggered.
1819 if ( !CheckInvalidForPaint( aRect ) )
1821 // --> OD 2009-08-12 #i101192#
1822 // start Pre/PostPaint encapsulation to avoid screen blinking
1823 const vcl::Region aRepaintRegion(aRect.SVRect());
1824 DLPrePaint2(aRepaintRegion);
1826 // <--
1827 PaintDesktop(rRenderContext, aRect);
1829 //When useful, process or destroy the old InvalidRect.
1830 if ( aRect.IsInside( maInvalidRect ) )
1831 ResetInvalidRect();
1832 SwViewShell::mbLstAct = true;
1833 GetLayout()->PaintSwFrame( rRenderContext, aRect );
1834 SwViewShell::mbLstAct = false;
1835 // --> OD 2009-08-12 #i101192#
1836 // end Pre/PostPaint encapsulation
1837 DLPostPaint2(true);
1838 // <--
1841 SwRootFrame::SetNoVirDev( false );
1842 mbPaintInProgress = false;
1843 UISizeNotify();
1846 else
1848 if ( maInvalidRect.IsEmpty() )
1849 maInvalidRect = SwRect( rRect );
1850 else
1851 maInvalidRect.Union( SwRect( rRect ) );
1853 if ( mbInEndAction && GetWin() )
1855 const vcl::Region aRegion(GetWin()->GetPaintRegion());
1856 RectangleVector aRectangles;
1857 aRegion.GetRegionRectangles(aRectangles);
1859 for(const auto& rRectangle : aRectangles)
1861 Imp()->AddPaintRect(rRectangle);
1864 //RegionHandle hHdl( aRegion.BeginEnumRects() );
1865 //Rectangle aRect;
1866 //while ( aRegion.GetEnumRects( hHdl, aRect ) )
1867 // Imp()->AddPaintRect( aRect );
1868 //aRegion.EndEnumRects( hHdl );
1870 else if ( SfxProgress::GetActiveProgress( GetDoc()->GetDocShell() ) &&
1871 GetOut() == GetWin() )
1873 // #i68597#
1874 const vcl::Region aDLRegion(rRect);
1875 DLPrePaint2(aDLRegion);
1877 rRenderContext.Push( PushFlags::FILLCOLOR|PushFlags::LINECOLOR );
1878 rRenderContext.SetFillColor( Imp()->GetRetoucheColor() );
1879 rRenderContext.SetLineColor();
1880 rRenderContext.DrawRect( rRect );
1881 rRenderContext.Pop();
1882 // #i68597#
1883 DLPostPaint2(true);
1888 void SwViewShell::PaintTile(VirtualDevice &rDevice, int contextWidth, int contextHeight, int tilePosX, int tilePosY, tools::Long tileWidth, tools::Long tileHeight)
1890 // SwViewShell's output device setup
1891 // TODO clean up SwViewShell's approach to output devices (the many of
1892 // them - mpBufferedOut, mpOut, mpWin, ...)
1893 OutputDevice *pSaveOut = mpOut;
1894 comphelper::LibreOfficeKit::setTiledPainting(true);
1895 mpOut = &rDevice;
1897 // resizes the virtual device so to contain the entries context
1898 rDevice.SetOutputSizePixel(Size(contextWidth, contextHeight));
1900 // setup the output device to draw the tile
1901 MapMode aMapMode(rDevice.GetMapMode());
1902 aMapMode.SetMapUnit(MapUnit::MapTwip);
1903 aMapMode.SetOrigin(Point(-tilePosX, -tilePosY));
1905 // Scaling. Must convert from pixels to twips. We know
1906 // that VirtualDevices use a DPI of 96.
1907 Fraction scaleX = Fraction(contextWidth, 96) * Fraction(1440) / Fraction(tileWidth);
1908 Fraction scaleY = Fraction(contextHeight, 96) * Fraction(1440) / Fraction(tileHeight);
1909 aMapMode.SetScaleX(scaleX);
1910 aMapMode.SetScaleY(scaleY);
1911 rDevice.SetMapMode(aMapMode);
1913 // Update scaling of SwEditWin and its sub-widgets, needed for comments.
1914 sal_uInt16 nOldZoomValue = 0;
1915 if (GetWin() && GetWin()->GetMapMode().GetScaleX() != scaleX)
1917 double fScale = double(scaleX);
1918 SwViewOption aOption(*GetViewOptions());
1919 nOldZoomValue = aOption.GetZoom();
1920 aOption.SetZoom(fScale * 100);
1921 ApplyViewOptions(aOption);
1922 // Make sure the map mode (disabled in SwXTextDocument::initializeForTiledRendering()) is still disabled.
1923 GetWin()->EnableMapMode(false);
1926 tools::Rectangle aOutRect(Point(tilePosX, tilePosY),
1927 rDevice.PixelToLogic(Size(contextWidth, contextHeight)));
1929 // Make the requested area visible -- we can't use MakeVisible as that will
1930 // only scroll the contents, but won't zoom/resize if needed.
1931 // Without this, items/text that are outside the visible area (in the SwView)
1932 // won't be painted when rendering tiles (at least when using either the
1933 // tiledrendering app, or the gtktiledviewer) -- although ultimately we
1934 // probably want to fix things so that the SwView's area doesn't affect
1935 // tiled rendering?
1936 VisPortChgd(SwRect(aOutRect));
1938 // Invoke SwLayAction if layout is not yet ready.
1939 CheckInvalidForPaint(aOutRect);
1941 // draw - works in logic coordinates
1942 Paint(rDevice, aOutRect);
1944 SwPostItMgr* pPostItMgr = GetPostItMgr();
1945 if (GetViewOptions()->IsPostIts() && pPostItMgr)
1946 pPostItMgr->PaintTile(rDevice);
1948 // SwViewShell's output device tear down
1950 // A view shell can get a PaintTile call for a tile at a zoom level
1951 // different from the one, the related client really is.
1952 // In such a case it is better to reset the current scale value to
1953 // the original one, since such a value should be in synchronous with
1954 // the zoom level in the client (see setClientZoom).
1955 // At present the zoom value returned by GetViewOptions()->GetZoom() is
1956 // used in SwXTextDocument methods (postMouseEvent and setGraphicSelection)
1957 // for passing the correct mouse position to an edited chart (if any).
1958 if (nOldZoomValue !=0)
1960 SwViewOption aOption(*GetViewOptions());
1961 aOption.SetZoom(nOldZoomValue);
1962 ApplyViewOptions(aOption);
1964 // Changing the zoom value doesn't always trigger the updating of
1965 // the client ole object area, so we call it directly.
1966 SfxInPlaceClient* pIPClient = GetSfxViewShell()->GetIPClient();
1967 if (pIPClient)
1969 pIPClient->VisAreaChanged();
1971 // Make sure the map mode (disabled in SwXTextDocument::initializeForTiledRendering()) is still disabled.
1972 GetWin()->EnableMapMode(false);
1975 mpOut = pSaveOut;
1976 comphelper::LibreOfficeKit::setTiledPainting(false);
1979 void SwViewShell::SetBrowseBorder( const Size& rNew )
1981 if( rNew != maBrowseBorder )
1983 maBrowseBorder = rNew;
1984 if ( maVisArea.HasArea() )
1985 InvalidateLayout( false );
1989 const Size& SwViewShell::GetBrowseBorder() const
1991 return maBrowseBorder;
1994 sal_Int32 SwViewShell::GetBrowseWidth() const
1996 const SwPostItMgr* pPostItMgr = GetPostItMgr();
1997 if ( pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() )
1999 Size aBorder( maBrowseBorder );
2000 aBorder.AdjustWidth(maBrowseBorder.Width() );
2001 aBorder.AdjustWidth(pPostItMgr->GetSidebarWidth(true) + pPostItMgr->GetSidebarBorderWidth(true) );
2002 return maVisArea.Width() - GetOut()->PixelToLogic(aBorder).Width();
2004 else
2005 return maVisArea.Width() - 2 * GetOut()->PixelToLogic(maBrowseBorder).Width();
2008 void SwViewShell::InvalidateLayout( bool bSizeChanged )
2010 if ( !bSizeChanged && !GetViewOptions()->getBrowseMode() &&
2011 !GetViewOptions()->IsWhitespaceHidden() )
2012 return;
2014 CurrShell aCurr( this );
2016 OSL_ENSURE( GetLayout(), "Layout not ready" );
2018 // When the Layout doesn't have a height yet, nothing is formatted.
2019 // That leads to problems with Invalidate, e.g. when setting up a new View
2020 // the content is inserted and formatted (regardless of empty VisArea).
2021 // Therefore the pages must be roused for formatting.
2022 if( !GetLayout()->getFrameArea().Height() )
2024 SwFrame* pPage = GetLayout()->Lower();
2025 while( pPage )
2027 pPage->InvalidateSize_();
2028 pPage = pPage->GetNext();
2030 return;
2033 LockPaint();
2034 StartAction();
2036 SwPageFrame *pPg = static_cast<SwPageFrame*>(GetLayout()->Lower());
2038 { pPg->InvalidateSize();
2039 pPg->InvalidatePrt_();
2040 pPg->InvaPercentLowers();
2041 if ( bSizeChanged )
2043 pPg->PrepareHeader();
2044 pPg->PrepareFooter();
2046 pPg = static_cast<SwPageFrame*>(pPg->GetNext());
2047 } while ( pPg );
2049 // When the size ratios in browse mode change,
2050 // the Position and PrtArea of the Content and Tab frames must be Invalidated.
2051 SwInvalidateFlags nInv = SwInvalidateFlags::PrtArea | SwInvalidateFlags::Table | SwInvalidateFlags::Pos;
2052 // In case of layout or mode change, the ContentFrames need a size-Invalidate
2053 // because of printer/screen formatting.
2054 if ( bSizeChanged )
2055 nInv |= SwInvalidateFlags::Size | SwInvalidateFlags::Direction;
2057 GetLayout()->InvalidateAllContent( nInv );
2059 SwFrame::CheckPageDescs( static_cast<SwPageFrame*>(GetLayout()->Lower()) );
2061 EndAction();
2062 UnlockPaint();
2065 SwRootFrame *SwViewShell::GetLayout() const
2067 return mpLayout.get();
2070 vcl::RenderContext& SwViewShell::GetRefDev() const
2072 OutputDevice* pTmpOut = nullptr;
2073 if ( GetWin() &&
2074 GetViewOptions()->getBrowseMode() &&
2075 !GetViewOptions()->IsPrtFormat() )
2076 pTmpOut = GetWin();
2077 else
2078 pTmpOut = GetDoc()->getIDocumentDeviceAccess().getReferenceDevice( true );
2080 return *pTmpOut;
2083 const SwNodes& SwViewShell::GetNodes() const
2085 return mxDoc->GetNodes();
2088 void SwViewShell::DrawSelChanged()
2092 Size SwViewShell::GetDocSize() const
2094 Size aSz;
2095 const SwRootFrame* pRoot = GetLayout();
2096 if( pRoot )
2097 aSz = pRoot->getFrameArea().SSize();
2099 return aSz;
2102 SfxItemPool& SwViewShell::GetAttrPool()
2104 return GetDoc()->GetAttrPool();
2107 void SwViewShell::ApplyViewOptions( const SwViewOption &rOpt )
2109 for(SwViewShell& rSh : GetRingContainer())
2110 rSh.StartAction();
2112 ImplApplyViewOptions( rOpt );
2114 // With one layout per view it is no longer necessary
2115 // to sync these "layout related" view options
2116 // But as long as we have to disable "multiple layout"
2118 for(SwViewShell& rSh : GetRingContainer())
2120 if(&rSh == this)
2121 continue;
2122 SwViewOption aOpt( *rSh.GetViewOptions() );
2123 aOpt.SetFieldName( rOpt.IsFieldName() );
2124 aOpt.SetShowHiddenField( rOpt.IsShowHiddenField() );
2125 aOpt.SetShowHiddenPara( rOpt.IsShowHiddenPara() );
2126 aOpt.SetShowHiddenChar( rOpt.IsShowHiddenChar() );
2127 aOpt.SetViewLayoutBookMode( rOpt.IsViewLayoutBookMode() );
2128 aOpt.SetHideWhitespaceMode(rOpt.IsHideWhitespaceMode());
2129 aOpt.SetViewLayoutColumns(rOpt.GetViewLayoutColumns());
2130 aOpt.SetPostIts(rOpt.IsPostIts());
2131 if ( !(aOpt == *rSh.GetViewOptions()) )
2132 rSh.ImplApplyViewOptions( aOpt );
2134 // End of disabled multiple window
2136 for(SwViewShell& rSh : GetRingContainer())
2137 rSh.EndAction();
2140 static bool
2141 IsCursorInFieldmarkHidden(SwPaM const& rCursor, sw::FieldmarkMode const eMode)
2143 if (eMode == sw::FieldmarkMode::ShowBoth)
2145 return false;
2147 IDocumentMarkAccess const& rIDMA(*rCursor.GetDoc().getIDocumentMarkAccess());
2148 // iterate, for nested fieldmarks
2149 for (auto iter = rIDMA.getFieldmarksBegin(); iter != rIDMA.getFieldmarksEnd(); ++iter)
2151 if (*rCursor.GetPoint() <= (**iter).GetMarkStart())
2153 return false;
2155 if (*rCursor.GetPoint() < (**iter).GetMarkEnd())
2157 SwPosition const sepPos(sw::mark::FindFieldSep(
2158 dynamic_cast<sw::mark::IFieldmark&>(**iter)));
2159 if (eMode == sw::FieldmarkMode::ShowResult)
2161 if (*rCursor.GetPoint() <= sepPos
2162 && *rCursor.GetPoint() != (**iter).GetMarkStart())
2164 return true;
2167 else
2169 if (sepPos < *rCursor.GetPoint())
2171 return true;
2176 return false;
2179 void SwViewShell::ImplApplyViewOptions( const SwViewOption &rOpt )
2181 if (*mpOpt == rOpt)
2182 return;
2184 vcl::Window *pMyWin = GetWin();
2185 if( !pMyWin )
2187 OSL_ENSURE( pMyWin, "SwViewShell::ApplyViewOptions: no window" );
2188 return;
2191 CurrShell aCurr( this );
2193 bool bReformat = false;
2195 if( mpOpt->IsShowHiddenField() != rOpt.IsShowHiddenField() )
2197 static_cast<SwHiddenTextFieldType*>(mxDoc->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::HiddenText ))->
2198 SetHiddenFlag( !rOpt.IsShowHiddenField() );
2199 bReformat = true;
2201 if ( mpOpt->IsShowHiddenPara() != rOpt.IsShowHiddenPara() )
2203 SwHiddenParaFieldType* pFieldType = static_cast<SwHiddenParaFieldType*>(GetDoc()->
2204 getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::HiddenPara));
2205 if( pFieldType && pFieldType->HasWriterListeners() )
2206 pFieldType->PrintHiddenPara();
2207 bReformat = true;
2209 if ( !bReformat && mpOpt->IsShowHiddenChar() != rOpt.IsShowHiddenChar() )
2211 bReformat = GetDoc()->ContainsHiddenChars();
2214 // bReformat becomes true, if ...
2215 // - fieldnames apply or not ...
2216 // ( - SwEndPortion must _no_ longer be generated. )
2217 // - Of course, the screen is something completely different than the printer ...
2218 bReformat = bReformat || mpOpt->IsFieldName() != rOpt.IsFieldName();
2219 bool const isToggleFieldNames(mpOpt->IsFieldName() != rOpt.IsFieldName());
2221 // The map mode is changed, minima/maxima will be attended by UI
2222 if( mpOpt->GetZoom() != rOpt.GetZoom() && !IsPreview() )
2224 MapMode aMode( pMyWin->GetMapMode() );
2225 Fraction aNewFactor( rOpt.GetZoom(), 100 );
2226 aMode.SetScaleX( aNewFactor );
2227 aMode.SetScaleY( aNewFactor );
2228 pMyWin->SetMapMode( aMode );
2229 // if not a reference device (printer) is used for formatting,
2230 // but the screen, new formatting is needed for zoomfactor changes.
2231 if (mpOpt->getBrowseMode() || mpOpt->IsWhitespaceHidden())
2232 bReformat = true;
2235 bool bBrowseModeChanged = false;
2236 if( mpOpt->getBrowseMode() != rOpt.getBrowseMode() )
2238 bBrowseModeChanged = true;
2239 bReformat = true;
2241 else if( mpOpt->getBrowseMode() && mpOpt->IsPrtFormat() != rOpt.IsPrtFormat() )
2242 bReformat = true;
2244 bool bHideWhitespaceModeChanged = false;
2245 if (mpOpt->IsWhitespaceHidden() != rOpt.IsWhitespaceHidden())
2247 // When whitespace is hidden, view change needs reformatting.
2248 bHideWhitespaceModeChanged = true;
2249 bReformat = true;
2252 if ( HasDrawView() || rOpt.IsGridVisible() )
2254 if ( !HasDrawView() )
2255 MakeDrawView();
2257 SwDrawView *pDView = Imp()->GetDrawView();
2258 if ( pDView->IsDragStripes() != rOpt.IsCrossHair() )
2259 pDView->SetDragStripes( rOpt.IsCrossHair() );
2261 if ( pDView->IsGridSnap() != rOpt.IsSnap() )
2262 pDView->SetGridSnap( rOpt.IsSnap() );
2264 if ( pDView->IsGridVisible() != rOpt.IsGridVisible() )
2265 pDView->SetGridVisible( rOpt.IsGridVisible() );
2267 const Size &rSz = rOpt.GetSnapSize();
2268 pDView->SetGridCoarse( rSz );
2270 const Size aFSize
2271 ( rSz.Width() ? rSz.Width() / (rOpt.GetDivisionX()+1) : 0,
2272 rSz.Height()? rSz.Height()/ (rOpt.GetDivisionY()+1) : 0);
2273 pDView->SetGridFine( aFSize );
2274 Fraction aSnGrWdtX(rSz.Width(), rOpt.GetDivisionX() + 1);
2275 Fraction aSnGrWdtY(rSz.Height(), rOpt.GetDivisionY() + 1);
2276 pDView->SetSnapGridWidth( aSnGrWdtX, aSnGrWdtY );
2278 // set handle size to 9 pixels, always
2279 pDView->SetMarkHdlSizePixel(9);
2282 bool bOnlineSpellChgd = mpOpt->IsOnlineSpell() != rOpt.IsOnlineSpell();
2284 *mpOpt = rOpt; // First the options are taken.
2285 mpOpt->SetUIOptions(rOpt);
2287 mxDoc->GetDocumentSettingManager().set(DocumentSettingId::HTML_MODE, 0 != ::GetHtmlMode(mxDoc->GetDocShell()));
2289 if( bBrowseModeChanged || bHideWhitespaceModeChanged )
2291 // #i44963# Good occasion to check if page sizes in
2292 // page descriptions are still set to (LONG_MAX, LONG_MAX) (html import)
2293 mxDoc->CheckDefaultPageFormat();
2294 InvalidateLayout( true );
2297 pMyWin->Invalidate();
2298 if ( bReformat )
2300 // Nothing helps, we need to send all ContentFrames a
2301 // Prepare, we format anew:
2302 StartAction();
2303 Reformat();
2304 EndAction();
2307 if (isToggleFieldNames)
2309 for(SwViewShell& rSh : GetRingContainer())
2311 if (SwCursorShell *const pSh = dynamic_cast<SwCursorShell *>(&rSh))
2313 if ((mpOpt->IsFieldName() && pSh->CursorInsideInputField())
2314 || IsCursorInFieldmarkHidden(*pSh->GetCursor(),
2315 pSh->GetLayout()->GetFieldmarkMode()))
2316 { // move cursor out of field
2317 pSh->Left(1, CRSR_SKIP_CHARS);
2323 if( !bOnlineSpellChgd )
2324 return;
2326 bool bOnlineSpl = rOpt.IsOnlineSpell();
2327 for(SwViewShell& rSh : GetRingContainer())
2329 if(&rSh == this)
2330 continue;
2331 rSh.mpOpt->SetOnlineSpell( bOnlineSpl );
2332 vcl::Window *pTmpWin = rSh.GetWin();
2333 if( pTmpWin )
2334 pTmpWin->Invalidate();
2339 void SwViewShell::SetUIOptions( const SwViewOption &rOpt )
2341 mpOpt->SetUIOptions(rOpt);
2342 //the API-Flag of the view options is set but never reset
2343 //it is required to set scroll bars in readonly documents
2344 if(rOpt.IsStarOneSetting())
2345 mpOpt->SetStarOneSetting(true);
2347 mpOpt->SetSymbolFont(rOpt.GetSymbolFont());
2350 void SwViewShell::SetReadonlyOption(bool bSet)
2352 //JP 01.02.99: at readonly flag query properly
2353 // and if need be format; Bug 61335
2355 // Are we switching from readonly to edit?
2356 if( bSet == mpOpt->IsReadonly() )
2357 return;
2359 // so that the flags can be queried properly.
2360 mpOpt->SetReadonly( false );
2362 bool bReformat = mpOpt->IsFieldName();
2364 mpOpt->SetReadonly( bSet );
2366 if( bReformat )
2368 StartAction();
2369 Reformat();
2370 if ( GetWin() )
2371 GetWin()->Invalidate();
2372 EndAction();
2374 else if ( GetWin() )
2375 GetWin()->Invalidate();
2376 if( Imp()->IsAccessible() )
2377 Imp()->InvalidateAccessibleEditableState( false );
2380 void SwViewShell::SetPDFExportOption(bool bSet)
2382 if( bSet != mpOpt->IsPDFExport() )
2384 if( bSet && mpOpt->getBrowseMode() )
2385 mpOpt->SetPrtFormat( true );
2386 mpOpt->SetPDFExport(bSet);
2390 void SwViewShell::SetReadonlySelectionOption(bool bSet)
2392 if( bSet != mpOpt->IsSelectionInReadonly() )
2394 mpOpt->SetSelectionInReadonly(bSet);
2398 void SwViewShell::SetPrtFormatOption( bool bSet )
2400 mpOpt->SetPrtFormat( bSet );
2403 void SwViewShell::UISizeNotify()
2405 if ( mbDocSizeChgd )
2407 mbDocSizeChgd = false;
2408 bool bOld = bInSizeNotify;
2409 bInSizeNotify = true;
2410 ::SizeNotify( this, GetDocSize() );
2411 bInSizeNotify = bOld;
2415 void SwViewShell::SetRestoreActions(sal_uInt16 nSet)
2417 OSL_ENSURE(!GetRestoreActions()||!nSet, "multiple restore of the Actions ?");
2418 Imp()->SetRestoreActions(nSet);
2420 sal_uInt16 SwViewShell::GetRestoreActions() const
2422 return Imp()->GetRestoreActions();
2425 bool SwViewShell::IsNewLayout() const
2427 return GetLayout()->IsNewLayout();
2430 uno::Reference< css::accessibility::XAccessible > SwViewShell::CreateAccessible()
2432 uno::Reference< css::accessibility::XAccessible > xAcc;
2434 // We require a layout and an XModel to be accessible.
2435 OSL_ENSURE( mpLayout, "no layout, no access" );
2436 OSL_ENSURE( GetWin(), "no window, no access" );
2438 if( mxDoc->getIDocumentLayoutAccess().GetCurrentViewShell() && GetWin() )
2439 xAcc = Imp()->GetAccessibleMap().GetDocumentView();
2441 return xAcc;
2444 uno::Reference< css::accessibility::XAccessible > SwViewShell::CreateAccessiblePreview()
2446 OSL_ENSURE( IsPreview(),
2447 "Can't create accessible preview for non-preview SwViewShell" );
2449 // We require a layout and an XModel to be accessible.
2450 OSL_ENSURE( mpLayout, "no layout, no access" );
2451 OSL_ENSURE( GetWin(), "no window, no access" );
2453 if ( IsPreview() && GetLayout()&& GetWin() )
2455 return Imp()->GetAccessibleMap().GetDocumentPreview(
2456 PagePreviewLayout()->maPreviewPages,
2457 GetWin()->GetMapMode().GetScaleX(),
2458 GetLayout()->GetPageByPageNum( PagePreviewLayout()->mnSelectedPageNum ),
2459 PagePreviewLayout()->maWinSize );
2461 return nullptr;
2464 void SwViewShell::InvalidateAccessibleFocus()
2466 if( Imp() && Imp()->IsAccessible() )
2467 Imp()->GetAccessibleMap().InvalidateFocus();
2471 * invalidate CONTENT_FLOWS_FROM/_TO relation for paragraphs #i27138#
2473 void SwViewShell::InvalidateAccessibleParaFlowRelation( const SwTextFrame* _pFromTextFrame,
2474 const SwTextFrame* _pToTextFrame )
2476 if ( GetLayout() && GetLayout()->IsAnyShellAccessible() )
2478 Imp()->InvalidateAccessibleParaFlowRelation_( _pFromTextFrame, _pToTextFrame );
2483 * invalidate text selection for paragraphs #i27301#
2485 void SwViewShell::InvalidateAccessibleParaTextSelection()
2487 if ( GetLayout() && GetLayout()->IsAnyShellAccessible() )
2489 Imp()->InvalidateAccessibleParaTextSelection_();
2494 * invalidate attributes for paragraphs #i88069#
2496 void SwViewShell::InvalidateAccessibleParaAttrs( const SwTextFrame& rTextFrame )
2498 if ( GetLayout() && GetLayout()->IsAnyShellAccessible() )
2500 Imp()->InvalidateAccessibleParaAttrs_( rTextFrame );
2504 SwAccessibleMap* SwViewShell::GetAccessibleMap()
2506 if ( Imp()->IsAccessible() )
2508 return &(Imp()->GetAccessibleMap());
2511 return nullptr;
2514 void SwViewShell::ApplyAccessibilityOptions(SvtAccessibilityOptions const & rAccessibilityOptions)
2516 if (utl::ConfigManager::IsFuzzing())
2517 return;
2518 if (mpOpt->IsPagePreview() && !rAccessibilityOptions.GetIsForPagePreviews())
2520 mpAccOptions->SetAlwaysAutoColor(false);
2521 mpAccOptions->SetStopAnimatedGraphics(false);
2523 else
2525 mpAccOptions->SetAlwaysAutoColor(rAccessibilityOptions.GetIsAutomaticFontColor());
2526 mpAccOptions->SetStopAnimatedGraphics(! rAccessibilityOptions.GetIsAllowAnimatedGraphics());
2528 // Form view
2529 // Always set this option, not only if document is read-only:
2530 mpOpt->SetSelectionInReadonly(rAccessibilityOptions.IsSelectionInReadonly());
2534 ShellResource* SwViewShell::GetShellRes()
2536 return mpShellRes;
2539 void SwViewShell::SetCareDialog(const std::shared_ptr<weld::Window>& rNew)
2541 (*mpCareDialog.get()) = rNew;
2544 sal_uInt16 SwViewShell::GetPageCount() const
2546 return GetLayout() ? GetLayout()->GetPageNum() : 1;
2549 Size SwViewShell::GetPageSize( sal_uInt16 nPageNum, bool bSkipEmptyPages ) const
2551 Size aSize;
2552 const SwRootFrame* pTmpRoot = GetLayout();
2553 if( pTmpRoot && nPageNum )
2555 const SwPageFrame* pPage = static_cast<const SwPageFrame*>
2556 (pTmpRoot->Lower());
2558 while( --nPageNum && pPage->GetNext() )
2559 pPage = static_cast<const SwPageFrame*>( pPage->GetNext() );
2561 if( !bSkipEmptyPages && pPage->IsEmptyPage() && pPage->GetNext() )
2562 pPage = static_cast<const SwPageFrame*>( pPage->GetNext() );
2564 aSize = pPage->getFrameArea().SSize();
2566 return aSize;
2569 void SwViewShell::OnGraphicArrived(const SwRect& rRect)
2571 for(SwViewShell& rShell : GetRingContainer())
2573 CurrShell aCurr(&rShell);
2574 if(rShell.IsPreview())
2576 if(rShell.GetWin())
2577 ::RepaintPagePreview(&rShell, rRect);
2579 else if(rShell.VisArea().IsOver(rRect) && OUTDEV_WINDOW == rShell.GetOut()->GetOutDevType())
2581 // invalidate instead of painting
2582 rShell.GetWin()->Invalidate(rRect.SVRect());
2586 // #i12836# enhanced pdf export
2587 sal_Int32 SwViewShell::GetPageNumAndSetOffsetForPDF( OutputDevice& rOut, const SwRect& rRect ) const
2589 OSL_ENSURE( GetLayout(), "GetPageNumAndSetOffsetForPDF assumes presence of layout" );
2591 sal_Int32 nRet = -1;
2593 // #i40059# Position out of bounds:
2594 SwRect aRect( rRect );
2595 aRect.Pos().setX( std::max( aRect.Left(), GetLayout()->getFrameArea().Left() ) );
2597 const SwPageFrame* pPage = GetLayout()->GetPageAtPos( aRect.Center() );
2598 if ( pPage )
2600 OSL_ENSURE( pPage, "GetPageNumAndSetOffsetForPDF: No page found" );
2602 Point aOffset( pPage->getFrameArea().Pos() );
2603 aOffset.setX( -aOffset.X() );
2604 aOffset.setY( -aOffset.Y() );
2606 MapMode aMapMode( rOut.GetMapMode() );
2607 aMapMode.SetOrigin( aOffset );
2608 rOut.SetMapMode( aMapMode );
2610 nRet = pPage->GetPhyPageNum() - 1;
2613 return nRet;
2616 // --> PB 2007-05-30 #146850#
2617 const BitmapEx& SwViewShell::GetReplacementBitmap( bool bIsErrorState )
2619 if (bIsErrorState)
2621 if (!m_xErrorBmp)
2622 m_xErrorBmp.reset(new BitmapEx(RID_GRAPHIC_ERRORBMP));
2623 return *m_xErrorBmp;
2626 if (!m_xReplaceBmp)
2627 m_xReplaceBmp.reset(new BitmapEx(RID_GRAPHIC_REPLACEBMP));
2628 return *m_xReplaceBmp;
2631 void SwViewShell::DeleteReplacementBitmaps()
2633 m_xErrorBmp.reset();
2634 m_xReplaceBmp.reset();
2637 SwPostItMgr* SwViewShell::GetPostItMgr()
2639 SwView* pView = GetDoc()->GetDocShell() ? GetDoc()->GetDocShell()->GetView() : nullptr;
2640 if ( pView )
2641 return pView->GetPostItMgr();
2643 return nullptr;
2647 * Document Interface Access
2649 const IDocumentSettingAccess& SwViewShell::getIDocumentSettingAccess() const { return mxDoc->GetDocumentSettingManager(); }
2650 IDocumentSettingAccess& SwViewShell::getIDocumentSettingAccess() { return mxDoc->GetDocumentSettingManager(); }
2651 const IDocumentDeviceAccess& SwViewShell::getIDocumentDeviceAccess() const { return mxDoc->getIDocumentDeviceAccess(); }
2652 IDocumentDeviceAccess& SwViewShell::getIDocumentDeviceAccess() { return mxDoc->getIDocumentDeviceAccess(); }
2653 const IDocumentMarkAccess* SwViewShell::getIDocumentMarkAccess() const { return mxDoc->getIDocumentMarkAccess(); }
2654 IDocumentMarkAccess* SwViewShell::getIDocumentMarkAccess() { return mxDoc->getIDocumentMarkAccess(); }
2655 const IDocumentDrawModelAccess& SwViewShell::getIDocumentDrawModelAccess() const { return mxDoc->getIDocumentDrawModelAccess(); }
2656 IDocumentDrawModelAccess& SwViewShell::getIDocumentDrawModelAccess() { return mxDoc->getIDocumentDrawModelAccess(); }
2657 const IDocumentRedlineAccess& SwViewShell::getIDocumentRedlineAccess() const { return mxDoc->getIDocumentRedlineAccess(); }
2658 IDocumentRedlineAccess& SwViewShell::getIDocumentRedlineAccess() { return mxDoc->getIDocumentRedlineAccess(); }
2659 const IDocumentLayoutAccess& SwViewShell::getIDocumentLayoutAccess() const { return mxDoc->getIDocumentLayoutAccess(); }
2660 IDocumentLayoutAccess& SwViewShell::getIDocumentLayoutAccess() { return mxDoc->getIDocumentLayoutAccess(); }
2661 IDocumentContentOperations& SwViewShell::getIDocumentContentOperations() { return mxDoc->getIDocumentContentOperations(); }
2662 IDocumentStylePoolAccess& SwViewShell::getIDocumentStylePoolAccess() { return mxDoc->getIDocumentStylePoolAccess(); }
2663 const IDocumentStatistics& SwViewShell::getIDocumentStatistics() const { return mxDoc->getIDocumentStatistics(); }
2665 IDocumentUndoRedo & SwViewShell::GetIDocumentUndoRedo()
2666 { return mxDoc->GetIDocumentUndoRedo(); }
2667 IDocumentUndoRedo const& SwViewShell::GetIDocumentUndoRedo() const
2668 { return mxDoc->GetIDocumentUndoRedo(); }
2670 // --> OD 2007-11-14 #i83479#
2671 const IDocumentListItems* SwViewShell::getIDocumentListItemsAccess() const
2673 return &mxDoc->getIDocumentListItems();
2676 const IDocumentOutlineNodes* SwViewShell::getIDocumentOutlineNodesAccess() const
2678 return &mxDoc->getIDocumentOutlineNodes();
2681 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */