1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <vcl/themecolors.hxx>
21 #include <officecfg/Office/Common.hxx>
22 #include <config_wasm_strip.h>
24 #include <com/sun/star/accessibility/XAccessible.hpp>
25 #include <sfx2/viewfrm.hxx>
26 #include <sfx2/progress.hxx>
27 #include <svx/srchdlg.hxx>
28 #include <sfx2/viewsh.hxx>
29 #include <sfx2/ipclient.hxx>
30 #include <sal/log.hxx>
31 #include <drawdoc.hxx>
35 #include <IDocumentDeviceAccess.hxx>
36 #include <IDocumentDrawModelAccess.hxx>
37 #include <IDocumentOutlineNodes.hxx>
38 #include <IDocumentFieldsAccess.hxx>
39 #include <IDocumentLayoutAccess.hxx>
40 #include <IDocumentState.hxx>
41 #include <rootfrm.hxx>
42 #include <pagefrm.hxx>
43 #include <viewimp.hxx>
44 #include <frmtool.hxx>
45 #include <viewopt.hxx>
47 #include <swregion.hxx>
49 #include <docufld.hxx>
53 #include <fntcache.hxx>
54 #include <ptqueue.hxx>
56 #include <bookmark.hxx>
58 #include <ndindex.hxx>
60 #include <vcl/bitmapex.hxx>
61 #include <accessibilityoptions.hxx>
62 #include <strings.hrc>
63 #include <bitmaps.hlst>
64 #include <pagepreviewlayout.hxx>
65 #include <sortedobjs.hxx>
66 #include <anchoredobject.hxx>
67 #include <DocumentSettingManager.hxx>
68 #include <DocumentRedlineManager.hxx>
69 #include <DocumentLayoutManager.hxx>
71 #include <unotxdoc.hxx>
73 #include <PostItMgr.hxx>
74 #include <unotools/configmgr.hxx>
75 #include <vcl/virdev.hxx>
76 #include <vcl/svapp.hxx>
77 #include <svx/sdrpaintwindow.hxx>
78 #include <svx/sdrpagewindow.hxx>
79 #include <svx/svdpagv.hxx>
80 #include <comphelper/lok.hxx>
81 #include <sfx2/lokhelper.hxx>
82 #include <tools/UnitConversion.hxx>
84 #if !HAVE_FEATURE_DESKTOP
85 #include <vcl/sysdata.hxx>
88 #include <frameformats.hxx>
89 #include <fmtcntnt.hxx>
91 bool SwViewShell::sbLstAct
= false;
92 ShellResource
*SwViewShell::spShellRes
= nullptr;
94 static tools::DeleteOnDeinit
<std::shared_ptr
<weld::Window
>>& getCareDialog()
96 static tools::DeleteOnDeinit
<std::shared_ptr
<weld::Window
>> spCareDialog
{}; ///< Avoid this window.
100 static bool bInSizeNotify
= false;
103 using namespace ::com::sun::star
;
105 void SwViewShell::SetShowHeaderFooterSeparator( FrameControlType eControl
, bool bShow
) {
107 //tdf#118621 - Optionally disable floating header/footer menu
109 bShow
= GetViewOptions()->IsUseHeaderFooterMenu();
111 if ( eControl
== FrameControlType::Header
)
112 mbShowHeaderSeparator
= bShow
;
114 mbShowFooterSeparator
= bShow
;
117 void SwViewShell::ToggleHeaderFooterEdit()
119 mbHeaderFooterEdit
= !mbHeaderFooterEdit
;
120 if ( !mbHeaderFooterEdit
)
122 SetShowHeaderFooterSeparator( FrameControlType::Header
, false );
123 SetShowHeaderFooterSeparator( FrameControlType::Footer
, false );
127 if ( ( GetViewOptions()->IsUseHeaderFooterMenu() ) &&
128 ( !IsShowHeaderFooterSeparator( FrameControlType::Header
) &&
129 !IsShowHeaderFooterSeparator( FrameControlType::Footer
) ) )
131 mbHeaderFooterEdit
= false;
134 InvalidatePageAndHFSubsidiaryLines();
137 // Invalidate Subsidiary Lines around headers/footers and page frames to repaint
138 void SwViewShell::InvalidatePageAndHFSubsidiaryLines()
140 RectangleVector aInvalidRects
;
141 SwPageFrame
*pPg
= static_cast<SwPageFrame
*>(GetLayout()->Lower());
144 pPg
->AddSubsidiaryLinesBounds(*this, aInvalidRects
);
145 pPg
= static_cast<SwPageFrame
*>(pPg
->GetNext());
148 for (const auto &rRect
: aInvalidRects
)
149 GetWin()->Invalidate(rRect
);
152 void SwViewShell::setOutputToWindow(bool bOutputToWindow
)
154 mbOutputToWindow
= bOutputToWindow
;
157 bool SwViewShell::isOutputToWindow() const
159 return mbOutputToWindow
;
162 void SwViewShell::dumpAsXml(xmlTextWriterPtr pWriter
) const
164 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SwViewShell"));
165 mpOpt
->dumpAsXml(pWriter
);
166 (void)xmlTextWriterEndElement(pWriter
);
170 lcl_PaintTransparentFormControls(SwViewShell
const & rShell
, SwRect
const& rRect
)
172 // Direct paint has been performed: the background of transparent child
173 // windows has been painted, so need to paint the child windows now.
176 vcl::Window
& rWindow
= *(rShell
.GetWin());
177 const tools::Rectangle
aRectanglePixel(rShell
.GetOut()->LogicToPixel(rRect
.SVRect()));
178 PaintTransparentChildren(rWindow
, aRectanglePixel
);
182 // #i72754# 2nd set of Pre/PostPaints
183 // This time it uses the lock counter (mPrePostPaintRegions empty/non-empty) to allow only one activation
184 // and deactivation and mpPrePostOutDev to remember the OutDev from the BeginDrawLayers
185 // call. That way, all places where paint take place can be handled the same way, even
186 // when calling other paint methods. This is the case at the places where SW paints
187 // buffered into VDevs to avoid flicker. It is in general problematic and should be
188 // solved once using the BufferedOutput functionality of the DrawView.
190 void SwViewShell::PrePaint()
192 // forward PrePaint event from VCL Window to DrawingLayer
195 Imp()->GetDrawView()->PrePaint();
199 void SwViewShell::DLPrePaint2(const vcl::Region
& rRegion
)
201 if(mPrePostPaintRegions
.empty())
203 mPrePostPaintRegions
.push( rRegion
);
204 // #i75172# ensure DrawView to use DrawingLayer bufferings
205 if ( !HasDrawView() )
208 // Prefer window; if not available, get mpOut (e.g. printer)
209 const bool bWindow
= GetWin() && !comphelper::LibreOfficeKit::isActive() && !isOutputToWindow();
210 mpPrePostOutDev
= bWindow
? GetWin()->GetOutDev() : GetOut();
212 // #i74769# use SdrPaintWindow now direct
213 mpTargetPaintWindow
= Imp()->GetDrawView()->BeginDrawLayers(mpPrePostOutDev
, rRegion
);
214 assert(mpTargetPaintWindow
&& "BeginDrawLayers: Got no SdrPaintWindow (!)");
216 // #i74769# if prerender, save OutDev and redirect to PreRenderDevice
217 if(mpTargetPaintWindow
->GetPreRenderDevice())
219 mpBufferedOut
= mpOut
;
220 mpOut
= &(mpTargetPaintWindow
->GetTargetOutputDevice());
222 else if (isOutputToWindow())
223 // In case mpOut is used without buffering and we're not printing, need to set clipping.
224 mpOut
->SetClipRegion(rRegion
);
226 // remember original paint MapMode for wrapped FlyFrame paints
227 maPrePostMapMode
= mpOut
->GetMapMode();
231 // region needs to be updated to the given one
232 if( mPrePostPaintRegions
.top() != rRegion
)
233 Imp()->GetDrawView()->UpdateDrawLayersRegion(mpPrePostOutDev
, rRegion
);
234 mPrePostPaintRegions
.push( rRegion
);
238 void SwViewShell::DLPostPaint2(bool bPaintFormLayer
)
240 OSL_ENSURE(!mPrePostPaintRegions
.empty(), "SwViewShell::DLPostPaint2: Pre/PostPaint encapsulation broken (!)");
242 if( mPrePostPaintRegions
.size() > 1 )
244 vcl::Region current
= std::move(mPrePostPaintRegions
.top());
245 mPrePostPaintRegions
.pop();
246 if( current
!= mPrePostPaintRegions
.top())
247 Imp()->GetDrawView()->UpdateDrawLayersRegion(mpPrePostOutDev
, mPrePostPaintRegions
.top());
250 mPrePostPaintRegions
.pop(); // clear
251 if(nullptr != mpTargetPaintWindow
)
253 // #i74769# restore buffered OutDev
254 if(mpTargetPaintWindow
->GetPreRenderDevice())
256 mpOut
= mpBufferedOut
;
259 // #i74769# use SdrPaintWindow now direct
260 SwViewObjectContactRedirector
aSwRedirector(*this);
261 Imp()->GetDrawView()->EndDrawLayers(*mpTargetPaintWindow
, bPaintFormLayer
, &aSwRedirector
);
262 mpTargetPaintWindow
= nullptr;
265 // end of Pre/PostPaints
267 void SwViewShell::StartAllAction()
269 for (SwViewShell
& rCurrentShell
: GetRingContainer())
271 rCurrentShell
.StartAction();
275 void SwViewShell::EndAllAction()
277 for (SwViewShell
& rCurrentShell
: GetRingContainer())
279 rCurrentShell
.EndAction();
283 void SwViewShell::StartAction()
285 if (!mnStartAction
++)
289 void SwViewShell::EndAction(const bool bIdleEnd
)
291 if (0 == (mnStartAction
- 1))
292 ImplEndAction(bIdleEnd
);
296 void SwViewShell::ImplEndAction( const bool bIdleEnd
)
298 // Nothing to do for the printer?
299 if ( !GetWin() || IsPreview() )
303 // tdf#101464 print preview may generate events if another view shell
304 // performs layout...
305 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
306 if (IsPreview() && Imp()->IsAccessible())
308 Imp()->FireAccessibleEvents();
314 mbInEndAction
= true;
315 //will this put the EndAction of the last shell in the sequence?
317 SwViewShell::sbLstAct
= true;
318 for(SwViewShell
& rShell
: GetRingContainer())
320 if(&rShell
!= this && rShell
.ActionPend())
322 SwViewShell::sbLstAct
= false;
327 const bool bIsShellForCheckViewLayout
= ( this == GetLayout()->GetCurrShell() );
329 CurrShell
aCurr( this );
330 if ( Imp()->HasDrawView() && !Imp()->GetDrawView()->areMarkHandlesHidden() )
331 Imp()->StartAction();
333 if ( Imp()->HasPaintRegion() && Imp()->GetPaintRegion()->GetOrigin() != VisArea() )
334 Imp()->DeletePaintRegion();
336 const bool bExtraData
= ::IsExtraData( GetDoc() );
340 SwLayAction
aAction( GetLayout(), Imp() );
341 aAction
.SetComplete( false );
343 aAction
.SetPaint( false );
344 aAction
.SetInputType( VclInputFlags::KEYBOARD
);
345 aAction
.Action(GetWin()->GetOutDev());
348 if ( bIsShellForCheckViewLayout
)
349 GetLayout()->CheckViewLayout( GetViewOptions(), &maVisArea
);
351 //If we don't call Paints, we wait for the Paint of the system.
352 //Then the clipping is set correctly; e.g. shifting of a Draw object
353 if ( Imp()->HasPaintRegion() ||
354 maInvalidRect
.HasArea() ||
359 SolarMutexGuard aGuard
;
361 bool bPaintsFromSystem
= maInvalidRect
.HasArea();
362 GetWin()->PaintImmediately();
363 if ( maInvalidRect
.HasArea() )
365 if ( bPaintsFromSystem
)
366 Imp()->AddPaintRect( maInvalidRect
);
369 bPaintsFromSystem
= true;
373 std::optional
<SwRegionRects
> oRegion
= Imp()->TakePaintRegion();
375 //JP 27.11.97: what hid the selection, must also Show it,
376 // else we get Paint errors!
377 // e.g. additional mode, page half visible vertically, in the
378 // middle a selection and with another cursor jump to left
379 // right border. Without ShowCursor the selection disappears.
380 bool bShowCursor
= oRegion
&& dynamic_cast<const SwCursorShell
*>(this) != nullptr;
382 static_cast<SwCursorShell
*>(this)->HideCursors();
386 SwRootFrame
* pCurrentLayout
= GetLayout();
388 oRegion
->LimitToOrigin();
389 oRegion
->Compress( SwRegionRects::CompressFuzzy
);
391 while ( !oRegion
->empty() )
393 SwRect
aRect( oRegion
->back() );
396 if (GetWin()->SupportsDoubleBuffering())
397 InvalidateWindows(aRect
);
400 // #i75172# begin DrawingLayer paint
401 // need to do begin/end DrawingLayer preparation for each single rectangle of the
402 // repaint region. I already tried to prepare only once for the whole Region. This
403 // seems to work (and does technically) but fails with transparent objects. Since the
404 // region given to BeginDrawLayers() defines the clip region for DrawingLayer paint,
405 // transparent objects in the single rectangles will indeed be painted multiple times.
406 if (!comphelper::LibreOfficeKit::isActive())
408 DLPrePaint2(vcl::Region(aRect
.SVRect()));
411 if ( bPaintsFromSystem
)
412 PaintDesktop(*GetOut(), aRect
);
413 if (!comphelper::LibreOfficeKit::isActive())
414 pCurrentLayout
->PaintSwFrame( *mpOut
, aRect
);
416 pCurrentLayout
->GetCurrShell()->InvalidateWindows(aRect
);
418 // #i75172# end DrawingLayer paint
419 if (!comphelper::LibreOfficeKit::isActive())
425 lcl_PaintTransparentFormControls(*this, aRect
); // i#107365
429 static_cast<SwCursorShell
*>(this)->ShowCursors( true );
433 Imp()->DeletePaintRegion();
440 mbInEndAction
= false;
441 SwViewShell::sbLstAct
= false;
444 //We artificially end the action here to enable the automatic scrollbars
445 //to adjust themselves correctly
446 //EndAction sends a Notify, and that must call Start-/EndAction to
447 //adjust the scrollbars correctly
452 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
453 if( Imp()->IsAccessible() )
454 Imp()->FireAccessibleEvents();
458 void SwViewShell::ImplStartAction()
460 mbPaintWorks
= false;
461 Imp()->StartAction();
464 void SwViewShell::ImplLockPaint()
466 if ( GetWin() && GetWin()->IsVisible() && !comphelper::LibreOfficeKit::isActive())
467 GetWin()->EnablePaint( false ); //Also cut off the controls.
471 void SwViewShell::ImplUnlockPaint(std::vector
<LockPaintReason
>& rReasons
, bool bVirDev
)
473 CurrShell
aCurr( this );
474 if ( GetWin() && GetWin()->IsVisible() )
476 if ( (bInSizeNotify
|| bVirDev
) && VisArea().HasArea() && !comphelper::LibreOfficeKit::isActive())
478 //Refresh with virtual device to avoid flickering.
479 VclPtrInstance
<VirtualDevice
> pVout( *mpOut
);
480 pVout
->SetMapMode( mpOut
->GetMapMode() );
481 Size
aSize( VisArea().SSize() );
482 aSize
.AdjustWidth(20 );
483 aSize
.AdjustHeight(20 );
484 if( pVout
->SetOutputSize( aSize
) )
486 GetWin()->EnablePaint( true );
487 GetWin()->Validate();
489 Imp()->UnlockPaint();
490 pVout
->SetLineColor( mpOut
->GetLineColor() );
491 pVout
->SetFillColor( mpOut
->GetFillColor() );
493 // #i72754# start Pre/PostPaint encapsulation before mpOut is changed to the buffering VDev
494 const vcl::Region
aRepaintRegion(VisArea().SVRect());
495 DLPrePaint2(aRepaintRegion
);
497 OutputDevice
*pOld
= mpOut
;
499 Paint(*mpOut
, VisArea().SVRect());
501 mpOut
->DrawOutDev( VisArea().Pos(), aSize
,
502 VisArea().Pos(), aSize
, *pVout
);
504 // #i72754# end Pre/PostPaint encapsulation when mpOut is back and content is painted
507 lcl_PaintTransparentFormControls(*this, VisArea()); // fdo#63949
511 Imp()->UnlockPaint();
512 GetWin()->EnablePaint( true );
513 InvalidateAll(rReasons
);
515 pVout
.disposeAndClear();
519 Imp()->UnlockPaint();
520 GetWin()->EnablePaint( true );
521 InvalidateAll(rReasons
);
525 Imp()->UnlockPaint();
530 std::string_view
to_string(LockPaintReason eReason
)
534 case LockPaintReason::ViewLayout
:
536 case LockPaintReason::OuterResize
:
537 return "OuterResize";
538 case LockPaintReason::Undo
:
540 case LockPaintReason::Redo
:
542 case LockPaintReason::OutlineFolding
:
543 return "OutlineFolding";
544 case LockPaintReason::EndSdrCreate
:
545 return "EndSdrCreate";
546 case LockPaintReason::SwLayIdle
:
548 case LockPaintReason::InvalidateLayout
:
549 return "InvalidateLayout";
550 case LockPaintReason::StartDrag
:
552 case LockPaintReason::DataChanged
:
553 return "DataChanged";
554 case LockPaintReason::InsertFrame
:
555 return "InsertFrame";
556 case LockPaintReason::GotoPage
:
558 case LockPaintReason::InsertGraphic
:
559 return "InsertGraphic";
560 case LockPaintReason::SetZoom
:
562 case LockPaintReason::ExampleFrame
:
563 return "ExampleFram";
569 void SwViewShell::InvalidateAll(std::vector
<LockPaintReason
>& rReasons
)
571 assert(!rReasons
.empty() && "there must be a reason to InvalidateAll");
573 for (const auto& reason
: rReasons
)
574 SAL_INFO("sw.core", "InvalidateAll because of: " << to_string(reason
));
576 if (comphelper::LibreOfficeKit::isActive())
578 // https://github.com/CollaboraOnline/online/issues/6379
579 // ditch OuterResize as a reason to invalidate all in the online case
580 std::erase(rReasons
, LockPaintReason::OuterResize
);
583 if (!rReasons
.empty())
584 GetWin()->Invalidate(InvalidateFlags::Children
);
588 bool SwViewShell::AddPaintRect( const SwRect
& rRect
)
591 for(SwViewShell
& rSh
: GetRingContainer())
595 if ( rSh
.IsPreview() && rSh
.GetWin() )
596 ::RepaintPagePreview( &rSh
, rRect
);
598 bRet
|= rSh
.Imp()->AddPaintRect( rRect
);
604 void SwViewShell::InvalidateWindows( const SwRect
&rRect
)
606 if ( Imp()->IsCalcLayoutProgress() )
609 if(comphelper::LibreOfficeKit::isActive())
611 // If we are inside tiled painting, invalidations are ignored.
612 // Ignore them right now to save work, but also to avoid the problem
613 // that this state could be reset before FlushPendingLOKInvalidateTiles()
615 if(comphelper::LibreOfficeKit::isTiledPainting())
617 // First collect all invalidations and perform them only later,
618 // otherwise the number of Invalidate() calls would be at least
619 // O(n^2) if not worse. The problem is that if any change in a document
620 // is made, SwEditShell::EndAllAction() is called, which calls EndAction()
621 // for every view. And every view does it own handling of paint rectangles,
622 // and then calls InvalidateWindows() based on that. On then this code
623 // would call Invalidate() for all views for each rectangle.
624 // So collect the rectangles, avoid duplicates (which there usually will
625 // be many because of the repetitions), FlushPendingLOKInvalidateTiles()
626 // will collect all rectangles from all related views, compress them
627 // and only with those relatively few rectangle it'd call Invalidate()
629 Imp()->AddPendingLOKInvalidation(rRect
);
633 for(SwViewShell
& rSh
: GetRingContainer())
637 if ( rSh
.IsPreview() )
638 ::RepaintPagePreview( &rSh
, rRect
);
639 // In case of tiled rendering, invalidation is wanted even if
640 // the rectangle is outside the visual area.
641 else if ( rSh
.VisArea().Overlaps( rRect
) || comphelper::LibreOfficeKit::isActive() )
642 rSh
.GetWin()->Invalidate( rRect
.SVRect() );
647 void SwViewShell::FlushPendingLOKInvalidateTiles()
649 assert(comphelper::LibreOfficeKit::isActive());
651 for(SwViewShell
& rSh
: GetRingContainer())
653 std::vector
<SwRect
> tmpRects
= rSh
.Imp()->TakePendingLOKInvalidations();
654 rects
.insert( rects
.end(), tmpRects
.begin(), tmpRects
.end());
656 rects
.Compress( SwRegionRects::CompressFuzzy
);
659 // This is basically the loop from SwViewShell::InvalidateWindows().
660 for(SwViewShell
& rSh
: GetRingContainer())
664 if ( rSh
.IsPreview() )
666 for( const SwRect
& rect
: rects
)
667 ::RepaintPagePreview( &rSh
, rect
);
671 for( const SwRect
& rect
: rects
)
672 rSh
.GetWin()->Invalidate( rect
.SVRect() );
678 const SwRect
& SwViewShell::VisArea() const
680 // when using the tiled rendering, consider the entire document as our
682 return comphelper::LibreOfficeKit::isActive()? GetLayout()->getFrameArea(): maVisArea
;
685 void SwViewShell::MakeVisible( const SwRect
&rRect
, ScrollSizeMode eScrollSizeMode
)
687 if ( !(!VisArea().Contains( rRect
) || IsScrollMDI( this, rRect
) || GetCareDialog(*this)) )
690 if ( IsViewLocked() )
695 const SwFrame
* pRoot
= GetLayout();
699 nOldH
= pRoot
->getFrameArea().Height();
700 SwViewShell::StartAction();
701 ScrollMDI( this, rRect
, USHRT_MAX
, USHRT_MAX
, eScrollSizeMode
);
702 SwViewShell::EndAction(); // DO NOT call virtual here!
703 } while( nOldH
!= pRoot
->getFrameArea().Height() && nLoopCnt
-- );
705 #if OSL_DEBUG_LEVEL > 0
708 //MA: 04. Nov. 94, no one needs this, does one?
709 OSL_ENSURE( false, "Is MakeVisible still needed for printers?" );
715 weld::Window
* SwViewShell::CareChildWin(SwViewShell
const & rVSh
)
717 if (!rVSh
.mpSfxViewShell
)
719 #if HAVE_FEATURE_DESKTOP
720 const sal_uInt16 nId
= SvxSearchDialogWrapper::GetChildWindowId();
721 SfxViewFrame
& rVFrame
= rVSh
.mpSfxViewShell
->GetViewFrame();
722 SfxChildWindow
* pChWin
= rVFrame
.GetChildWindow( nId
);
725 weld::DialogController
* pController
= pChWin
->GetController().get();
728 weld::Window
* pWin
= pController
->getDialog();
729 if (pWin
&& pWin
->get_visible())
735 Point
SwViewShell::GetPagePos( sal_uInt16 nPageNum
) const
737 return GetLayout()->GetPagePos( nPageNum
);
740 sal_uInt16
SwViewShell::GetNumPages() const
742 //It is possible that no layout exists when the method from
743 //root-Ctor is called.
744 return GetLayout() ? GetLayout()->GetPageNum() : 0;
747 bool SwViewShell::IsDummyPage( sal_uInt16 nPageNum
) const
749 return GetLayout() && GetLayout()->IsDummyPage( nPageNum
);
753 * Forces update of each field.
754 * It notifies all fields with pNewHt. If that is 0 (default), the field
755 * type is sent (???).
756 * @param[in] bCloseDB Passed in to GetDoc()->UpdateFields. [TODO] Purpose???
758 void SwViewShell::UpdateFields(bool bCloseDB
, bool bSetModified
)
760 CurrShell
aCurr( this );
764 GetDoc()->getIDocumentFieldsAccess().UpdateFields(bCloseDB
, bSetModified
);
769 void SwViewShell::UpdateOleObjectPreviews()
771 SwDoc
* pDoc
= GetDoc();
772 for(sw::SpzFrameFormat
* pFormat
: *pDoc
->GetSpzFrameFormats())
774 if (pFormat
->Which() != RES_FLYFRMFMT
)
779 const SwNodeIndex
* pNodeIndex
= pFormat
->GetContent().GetContentIdx();
780 if (!pNodeIndex
|| !pNodeIndex
->GetNodes().IsDocNodes())
785 SwNode
* pNode
= pDoc
->GetNodes()[pNodeIndex
->GetIndex() + 1];
786 SwOLENode
* pOleNode
= pNode
->GetOLENode();
792 SwOLEObj
& rOleObj
= pOleNode
->GetOLEObj();
793 svt::EmbeddedObjectRef
& rObject
= rOleObj
.GetObject();
794 rObject
.UpdateReplacement( true );
795 // Trigger the repaint.
796 pOleNode
->SetChanged();
800 /** update all charts for which any table exists */
801 void SwViewShell::UpdateAllCharts()
803 CurrShell
aCurr( this );
804 // Start-/EndAction handled in the SwDoc-Method!
805 GetDoc()->UpdateAllCharts();
808 bool SwViewShell::HasCharts() const
811 SwNodeIndex
aIdx( *GetDoc()->GetNodes().GetEndOfAutotext().
812 StartOfSectionNode(), 1 );
813 while (aIdx
.GetNode().GetStartNode())
816 const SwOLENode
*pNd
= aIdx
.GetNode().GetOLENode();
817 if( pNd
&& !pNd
->GetChartTableName().isEmpty() )
826 void SwViewShell::LayoutIdle()
828 if( !mpOpt
->IsIdle() || !GetWin() || HasDrawViewDrag() )
831 //No idle when printing is going on.
832 for(const SwViewShell
& rSh
: GetRingContainer())
838 CurrShell
aCurr( this );
841 // If Test5 has been set, the IdleFormatter is disabled.
842 if( mpOpt
->IsTest5() )
847 // Preserve top of the text frame cache.
848 SwSaveSetLRUOfst aSaveLRU
;
849 // #125243# there are lots of stacktraces indicating that Imp() returns NULL
850 // this SwViewShell seems to be invalid - but it's not clear why
851 // this return is only a workaround!
852 OSL_ENSURE(Imp(), "SwViewShell already deleted?");
855 SwLayIdle
aIdle( GetLayout(), Imp() );
859 static void lcl_InvalidateAllContent( SwViewShell
& rSh
, SwInvalidateFlags nInv
)
862 rSh
.GetLayout()->InvalidateAllContent( nInv
);
865 rSh
.GetDoc()->getIDocumentState().SetModified();
868 /** local method to invalidate/re-calculate positions of floating screen
869 * objects (Writer fly frame and drawing objects), which are anchored
870 * to paragraph or to character. #i11860#
872 static void lcl_InvalidateAllObjPos( SwViewShell
&_rSh
)
876 _rSh
.GetLayout()->InvalidateAllObjPos();
880 _rSh
.GetDoc()->getIDocumentState().SetModified();
883 void SwViewShell::SetParaSpaceMax( bool bNew
)
885 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
886 if( rIDSA
.get(DocumentSettingId::PARA_SPACE_MAX
) != bNew
)
888 SwWait
aWait( *GetDoc()->GetDocShell(), true );
889 rIDSA
.set(DocumentSettingId::PARA_SPACE_MAX
, bNew
);
890 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Table
| SwInvalidateFlags::Section
;
891 lcl_InvalidateAllContent( *this, nInv
);
895 void SwViewShell::SetParaSpaceMaxAtPages( bool bNew
)
897 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
898 if( rIDSA
.get(DocumentSettingId::PARA_SPACE_MAX_AT_PAGES
) != bNew
)
900 SwWait
aWait( *GetDoc()->GetDocShell(), true );
901 rIDSA
.set(DocumentSettingId::PARA_SPACE_MAX_AT_PAGES
, bNew
);
902 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Table
| SwInvalidateFlags::Section
;
903 lcl_InvalidateAllContent( *this, nInv
);
907 void SwViewShell::SetTabCompat( bool bNew
)
909 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
910 if( rIDSA
.get(DocumentSettingId::TAB_COMPAT
) != bNew
)
912 SwWait
aWait( *GetDoc()->GetDocShell(), true );
913 rIDSA
.set(DocumentSettingId::TAB_COMPAT
, bNew
);
914 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Size
| SwInvalidateFlags::Table
| SwInvalidateFlags::Section
;
915 lcl_InvalidateAllContent( *this, nInv
);
919 void SwViewShell::SetAddExtLeading( bool bNew
)
921 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
922 if ( rIDSA
.get(DocumentSettingId::ADD_EXT_LEADING
) != bNew
)
924 SwWait
aWait( *GetDoc()->GetDocShell(), true );
925 rIDSA
.set(DocumentSettingId::ADD_EXT_LEADING
, bNew
);
926 SwDrawModel
* pTmpDrawModel
= getIDocumentDrawModelAccess().GetDrawModel();
928 pTmpDrawModel
->SetAddExtLeading( bNew
);
929 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Size
| SwInvalidateFlags::Table
| SwInvalidateFlags::Section
;
930 lcl_InvalidateAllContent( *this, nInv
);
934 /** Sets if paragraph and table spacing is added at bottom of table cells.
936 * @param[in] (bool) setting of the new value
938 void SwViewShell::SetAddParaSpacingToTableCells( bool _bAddParaSpacingToTableCells
)
940 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
941 if (rIDSA
.get(DocumentSettingId::ADD_PARA_SPACING_TO_TABLE_CELLS
) != _bAddParaSpacingToTableCells
942 || rIDSA
.get(DocumentSettingId::ADD_PARA_LINE_SPACING_TO_TABLE_CELLS
) != _bAddParaSpacingToTableCells
)
944 SwWait
aWait( *GetDoc()->GetDocShell(), true );
945 rIDSA
.set(DocumentSettingId::ADD_PARA_SPACING_TO_TABLE_CELLS
, _bAddParaSpacingToTableCells
);
946 // note: the dialog can't change the value to indeterminate, so only false/false and true/true
947 rIDSA
.set(DocumentSettingId::ADD_PARA_LINE_SPACING_TO_TABLE_CELLS
, _bAddParaSpacingToTableCells
);
948 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
;
949 lcl_InvalidateAllContent( *this, nInv
);
954 * Sets if former formatting of text lines with proportional line spacing should used.
956 * @param[in] (bool) setting of the new value
958 void SwViewShell::SetUseFormerLineSpacing( bool _bUseFormerLineSpacing
)
960 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
961 if ( rIDSA
.get(DocumentSettingId::OLD_LINE_SPACING
) != _bUseFormerLineSpacing
)
963 SwWait
aWait( *GetDoc()->GetDocShell(), true );
964 rIDSA
.set(DocumentSettingId::OLD_LINE_SPACING
, _bUseFormerLineSpacing
);
965 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
;
966 lcl_InvalidateAllContent( *this, nInv
);
971 * Sets IDocumentSettingAccess if former object positioning should be used.
973 * @param[in] (bool) setting the new value
975 void SwViewShell::SetUseFormerObjectPositioning( bool _bUseFormerObjPos
)
977 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
978 if ( rIDSA
.get(DocumentSettingId::USE_FORMER_OBJECT_POS
) != _bUseFormerObjPos
)
980 SwWait
aWait( *GetDoc()->GetDocShell(), true );
981 rIDSA
.set(DocumentSettingId::USE_FORMER_OBJECT_POS
, _bUseFormerObjPos
);
982 lcl_InvalidateAllObjPos( *this );
987 void SwViewShell::SetConsiderWrapOnObjPos( bool _bConsiderWrapOnObjPos
)
989 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
990 if ( rIDSA
.get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION
) != _bConsiderWrapOnObjPos
)
992 SwWait
aWait( *GetDoc()->GetDocShell(), true );
993 rIDSA
.set(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION
, _bConsiderWrapOnObjPos
);
994 lcl_InvalidateAllObjPos( *this );
998 void SwViewShell::SetUseFormerTextWrapping( bool _bUseFormerTextWrapping
)
1000 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1001 if ( rIDSA
.get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING
) != _bUseFormerTextWrapping
)
1003 SwWait
aWait( *GetDoc()->GetDocShell(), true );
1004 rIDSA
.set(DocumentSettingId::USE_FORMER_TEXT_WRAPPING
, _bUseFormerTextWrapping
);
1005 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Size
| SwInvalidateFlags::Table
| SwInvalidateFlags::Section
;
1006 lcl_InvalidateAllContent( *this, nInv
);
1011 void SwViewShell::SetDoNotJustifyLinesWithManualBreak( bool _bDoNotJustifyLinesWithManualBreak
)
1013 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1014 if ( rIDSA
.get(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK
) != _bDoNotJustifyLinesWithManualBreak
)
1016 SwWait
aWait( *GetDoc()->GetDocShell(), true );
1017 rIDSA
.set(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK
, _bDoNotJustifyLinesWithManualBreak
);
1018 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Size
| SwInvalidateFlags::Table
| SwInvalidateFlags::Section
;
1019 lcl_InvalidateAllContent( *this, nInv
);
1023 void SwViewShell::SetProtectForm( bool _bProtectForm
)
1025 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1026 rIDSA
.set(DocumentSettingId::PROTECT_FORM
, _bProtectForm
);
1029 void SwViewShell::SetMsWordCompTrailingBlanks( bool _bMsWordCompTrailingBlanks
)
1031 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1032 if (rIDSA
.get(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS
) != _bMsWordCompTrailingBlanks
)
1034 SwWait
aWait(*GetDoc()->GetDocShell(), true);
1035 rIDSA
.set(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS
, _bMsWordCompTrailingBlanks
);
1036 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Size
| SwInvalidateFlags::Table
| SwInvalidateFlags::Section
;
1037 lcl_InvalidateAllContent(*this, nInv
);
1041 void SwViewShell::SetSubtractFlysAnchoredAtFlys(bool bSubtractFlysAnchoredAtFlys
)
1043 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1044 rIDSA
.set(DocumentSettingId::SUBTRACT_FLYS
, bSubtractFlysAnchoredAtFlys
);
1047 void SwViewShell::SetEmptyDbFieldHidesPara(bool bEmptyDbFieldHidesPara
)
1049 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1050 if (rIDSA
.get(DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA
) == bEmptyDbFieldHidesPara
)
1053 SwWait
aWait(*GetDoc()->GetDocShell(), true);
1054 rIDSA
.set(DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA
, bEmptyDbFieldHidesPara
);
1055 SwViewShell::StartAction();
1056 GetDoc()->getIDocumentState().SetModified();
1057 for (auto const & pFieldType
: *GetDoc()->getIDocumentFieldsAccess().GetFieldTypes())
1059 if(pFieldType
->Which() == SwFieldIds::Database
)
1060 pFieldType
->UpdateFields();
1062 SwViewShell::EndAction();
1065 void SwViewShell::SetNoGapAfterNoteNumber(bool bNew
)
1067 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1068 if (rIDSA
.get(DocumentSettingId::NO_GAP_AFTER_NOTE_NUMBER
) != bNew
)
1070 SwWait
aWait(*GetDoc()->GetDocShell(), true);
1071 rIDSA
.set(DocumentSettingId::NO_GAP_AFTER_NOTE_NUMBER
, bNew
);
1072 const SwInvalidateFlags nInv
= SwInvalidateFlags::Size
| SwInvalidateFlags::Pos
| SwInvalidateFlags::PrtArea
;
1073 lcl_InvalidateAllContent(*this, nInv
);
1077 void SwViewShell::SetTabsRelativeToIndent(bool bNew
)
1079 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1080 if (rIDSA
.get(DocumentSettingId::TABS_RELATIVE_TO_INDENT
) != bNew
)
1082 SwWait
aWait(*GetDoc()->GetDocShell(), true);
1083 rIDSA
.set(DocumentSettingId::TABS_RELATIVE_TO_INDENT
, bNew
);
1084 const SwInvalidateFlags nInv
= SwInvalidateFlags::Size
| SwInvalidateFlags::Section
| SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Table
| SwInvalidateFlags::Pos
;
1085 lcl_InvalidateAllContent(*this, nInv
);
1089 void SwViewShell::SetTabOverMargin(bool bNew
)
1091 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1092 if (rIDSA
.get(DocumentSettingId::TAB_OVER_MARGIN
) != bNew
)
1094 SwWait
aWait(*GetDoc()->GetDocShell(), true);
1095 rIDSA
.set(DocumentSettingId::TAB_OVER_MARGIN
, bNew
);
1096 const SwInvalidateFlags nInv
= SwInvalidateFlags::Size
| SwInvalidateFlags::Section
| SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Table
| SwInvalidateFlags::Pos
;
1097 lcl_InvalidateAllContent(*this, nInv
);
1101 void SwViewShell::SetDoNotMirrorRtlDrawObjs(bool bDoNotMirrorRtlDrawObjs
)
1103 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1104 if (rIDSA
.get(DocumentSettingId::DO_NOT_MIRROR_RTL_DRAW_OBJS
) != bDoNotMirrorRtlDrawObjs
)
1106 SwWait
aWait(*GetDoc()->GetDocShell(), true);
1107 rIDSA
.set(DocumentSettingId::DO_NOT_MIRROR_RTL_DRAW_OBJS
, bDoNotMirrorRtlDrawObjs
);
1108 lcl_InvalidateAllObjPos(*this);
1112 void SwViewShell::SetContinuousEndnotes(bool bContinuousEndnotes
)
1114 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1115 if (rIDSA
.get(DocumentSettingId::CONTINUOUS_ENDNOTES
) != bContinuousEndnotes
)
1117 SwWait
aWait(*GetDoc()->GetDocShell(), true);
1118 rIDSA
.set(DocumentSettingId::CONTINUOUS_ENDNOTES
, bContinuousEndnotes
);
1119 SwViewShell::StartAction();
1120 GetLayout()->RemoveFootnotes(/*pPage=*/nullptr, /*pPageOnly=*/false, /*bEndNotes=*/true);
1121 SwViewShell::EndAction();
1122 GetDoc()->getIDocumentState().SetModified();
1126 void SwViewShell::SetMsWordCompGridMetrics(bool _bMsWordCompGridMetrics
)
1128 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1129 if (rIDSA
.get(DocumentSettingId::MS_WORD_COMP_GRID_METRICS
) != _bMsWordCompGridMetrics
)
1131 SwWait
aWait(*GetDoc()->GetDocShell(), true);
1132 rIDSA
.set(DocumentSettingId::MS_WORD_COMP_GRID_METRICS
, _bMsWordCompGridMetrics
);
1133 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Pos
1134 | SwInvalidateFlags::Size
| SwInvalidateFlags::Table
1135 | SwInvalidateFlags::Section
;
1136 lcl_InvalidateAllContent(*this, nInv
);
1140 void SwViewShell::SetIgnoreTabsAndBlanksForLineCalculation(bool val
)
1142 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1143 if (rIDSA
.get(DocumentSettingId::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION
) != val
)
1145 SwWait
aWait(*GetDoc()->GetDocShell(), true);
1146 rIDSA
.set(DocumentSettingId::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION
, val
);
1147 const SwInvalidateFlags nInv
= SwInvalidateFlags::Size
| SwInvalidateFlags::Section
1148 | SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Table
1149 | SwInvalidateFlags::Pos
;
1150 lcl_InvalidateAllContent(*this, nInv
);
1154 void SwViewShell::Reformat()
1156 SwWait
aWait( *GetDoc()->GetDocShell(), true );
1158 // we go for safe: get rid of the old font information,
1159 // when the printer resolution or zoom factor changes.
1160 // Init() and Reformat() are the safest locations.
1161 pFntCache
->Flush( );
1163 if( GetLayout()->IsCallbackActionEnabled() )
1165 SwViewShell::StartAction();
1166 GetLayout()->InvalidateAllContent( SwInvalidateFlags::Size
| SwInvalidateFlags::Pos
| SwInvalidateFlags::PrtArea
);
1167 SwViewShell::EndAction();
1171 void SwViewShell::ChgNumberDigits()
1173 SdrModel
* pTmpDrawModel
= getIDocumentDrawModelAccess().GetDrawModel();
1174 if ( pTmpDrawModel
)
1175 pTmpDrawModel
->ReformatAllTextObjects();
1179 void SwViewShell::CalcLayout()
1181 // extremely likely to be a Bad Idea to call this without StartAction
1182 // (except the Page Preview apparently only has a non-subclassed ViewShell)
1183 assert((typeid(*this) == typeid(SwViewShell
)) || mnStartAction
);
1185 CurrShell
aCurr( this );
1186 SwWait
aWait( *GetDoc()->GetDocShell(), true );
1188 // Preserve top of the text frame cache.
1189 SwSaveSetLRUOfst aSaveLRU
;
1191 //switch on Progress when none is running yet.
1192 const bool bEndProgress
= SfxProgress::GetActiveProgress( GetDoc()->GetDocShell() ) == nullptr;
1195 tools::Long nEndPage
= GetLayout()->GetPageNum();
1196 nEndPage
+= nEndPage
* 10 / 100;
1197 ::StartProgress( STR_STATSTR_REFORMAT
, 0, nEndPage
, GetDoc()->GetDocShell() );
1200 SwLayAction
aAction( GetLayout(), Imp() );
1201 aAction
.SetPaint( false );
1202 aAction
.SetStatBar( true );
1203 aAction
.SetCalcLayout( true );
1204 aAction
.SetReschedule( true );
1205 GetDoc()->getIDocumentFieldsAccess().LockExpFields();
1206 aAction
.Action(GetOut());
1207 GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
1209 //the SetNewFieldLst() on the Doc was cut off and must be fetched again
1210 //(see flowfrm.cxx, txtfld.cxx)
1211 if ( aAction
.IsExpFields() )
1214 aAction
.SetPaint( false );
1215 aAction
.SetStatBar( true );
1216 aAction
.SetReschedule( true );
1218 GetDoc()->getIDocumentFieldsAccess().UpdatePageFields(0);
1219 GetDoc()->getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
1221 aAction
.Action(GetOut());
1224 if ( VisArea().HasArea() )
1225 InvalidateWindows( VisArea() );
1227 ::EndProgress( GetDoc()->GetDocShell() );
1230 void SwViewShell::SetFirstVisPageInvalid()
1232 for(SwViewShell
& rSh
: GetRingContainer())
1235 rSh
.Imp()->SetFirstVisPageInvalid();
1239 void SwViewShell::SizeChgNotify()
1242 mbDocSizeChgd
= true;
1243 else if( ActionPend() || Imp()->IsCalcLayoutProgress() || mbPaintInProgress
)
1245 mbDocSizeChgd
= true;
1247 if ( !Imp()->IsCalcLayoutProgress() && dynamic_cast<const SwCursorShell
*>( this ) != nullptr )
1249 PageNumNotify(this);
1251 if (comphelper::LibreOfficeKit::isActive())
1253 Size aDocSize
= GetDocSize();
1254 OString sPayload
= OString::number(aDocSize
.Width() + 2 * DOCUMENTBORDER
) +
1255 ", " + OString::number(aDocSize
.Height() + 2 * DOCUMENTBORDER
);
1257 SwXTextDocument
* pModel
= comphelper::getFromUnoTunnel
<SwXTextDocument
>(GetSfxViewShell()->GetCurrentDocument());
1258 SfxLokHelper::notifyDocumentSizeChanged(GetSfxViewShell(), sPayload
, pModel
);
1264 mbDocSizeChgd
= false;
1265 ::SizeNotify( this, GetDocSize() );
1269 void SwViewShell::VisPortChgd( const SwRect
&rRect
)
1271 OSL_ENSURE( GetWin(), "VisPortChgd without Window." );
1273 if ( rRect
== VisArea() )
1276 // Is someone spuriously rescheduling again?
1277 SAL_WARN_IF(mbInEndAction
, "sw.core", "Scrolling during EndAction");
1279 //First get the old visible page, so we don't have to look
1280 //for it afterwards.
1281 const SwFrame
*pOldPage
= Imp()->GetFirstVisPage(GetWin()->GetOutDev());
1283 const SwRect
aPrevArea( VisArea() );
1284 const bool bFull
= aPrevArea
.IsEmpty();
1286 SetFirstVisPageInvalid();
1288 //When there a PaintRegion still exists and the VisArea has changed,
1289 //the PaintRegion is at least by now obsolete. The PaintRegion can
1290 //have been created by RootFrame::PaintSwFrame.
1291 if ( !mbInEndAction
&&
1292 Imp()->HasPaintRegion() && Imp()->GetPaintRegion()->GetOrigin() != VisArea() )
1293 Imp()->DeletePaintRegion();
1295 CurrShell
aCurr( this );
1297 bool bScrolled
= false;
1299 SwPostItMgr
* pPostItMgr
= GetPostItMgr();
1302 GetWin()->Invalidate();
1305 //Calculate amount to be scrolled.
1306 const tools::Long nXDiff
= aPrevArea
.Left() - VisArea().Left();
1307 const tools::Long nYDiff
= aPrevArea
.Top() - VisArea().Top();
1309 if( !nXDiff
&& !GetViewOptions()->getBrowseMode() &&
1310 (!Imp()->HasDrawView() || !Imp()->GetDrawView()->IsGridVisible() ) )
1312 // If possible, don't scroll the application background
1313 // (PaintDesktop). Also limit the left and right side of
1314 // the scroll range to the pages.
1315 const SwPageFrame
*pPage
= static_cast<SwPageFrame
*>(GetLayout()->Lower());
1316 if ( pPage
->getFrameArea().Top() > pOldPage
->getFrameArea().Top() )
1317 pPage
= static_cast<const SwPageFrame
*>(pOldPage
);
1318 SwRect
aBoth( VisArea() );
1319 aBoth
.Union( aPrevArea
);
1320 const SwTwips nBottom
= aBoth
.Bottom();
1321 SwTwips nMinLeft
= SAL_MAX_INT32
;
1322 SwTwips nMaxRight
= 0;
1324 const bool bBookMode
= GetViewOptions()->IsViewLayoutBookMode();
1326 while ( pPage
&& pPage
->getFrameArea().Top() <= nBottom
)
1328 SwRect
aPageRect( pPage
->GetBoundRect(GetWin()->GetOutDev()) );
1331 const SwPageFrame
& rFormatPage
= pPage
->GetFormatPage();
1332 aPageRect
.SSize( rFormatPage
.GetBoundRect(GetWin()->GetOutDev()).SSize() );
1335 // #i9719# - consider new border and shadow width
1336 if ( aPageRect
.Overlaps( aBoth
) )
1338 SwTwips nPageLeft
= 0;
1339 SwTwips nPageRight
= 0;
1340 const sw::sidebarwindows::SidebarPosition aSidebarPos
= pPage
->SidebarPosition();
1342 if( aSidebarPos
!= sw::sidebarwindows::SidebarPosition::NONE
)
1344 nPageLeft
= aPageRect
.Left();
1345 nPageRight
= aPageRect
.Right();
1348 if( nPageLeft
< nMinLeft
)
1349 nMinLeft
= nPageLeft
;
1350 if( nPageRight
> nMaxRight
)
1351 nMaxRight
= nPageRight
;
1352 //match with the draw objects
1353 //take nOfst into account as the objects have been
1354 //selected and have handles attached.
1355 if ( pPage
->GetSortedObjs() )
1357 const tools::Long nOfst
= GetOut()->PixelToLogic(
1358 Size(Imp()->GetDrawView()->GetMarkHdlSizePixel()/2,0)).Width();
1359 for (SwAnchoredObject
* pObj
: *pPage
->GetSortedObjs())
1361 // ignore objects that are not actually placed on the page
1362 if (pObj
->IsFormatPossible())
1364 const tools::Rectangle aBound
= pObj
->GetObjRect().SVRect();
1365 if (aBound
.Left() != FAR_AWAY
) {
1366 // OD 03.03.2003 #107927# - use correct datatype
1367 const SwTwips nL
= std::max( SwTwips(0), SwTwips(aBound
.Left() - nOfst
) );
1368 if ( nL
< nMinLeft
)
1370 if( aBound
.Right() + nOfst
> nMaxRight
)
1371 nMaxRight
= aBound
.Right() + nOfst
;
1377 pPage
= static_cast<const SwPageFrame
*>(pPage
->GetNext());
1379 tools::Rectangle
aRect( aPrevArea
.SVRect() );
1380 aRect
.SetLeft( nMinLeft
);
1381 aRect
.SetRight( nMaxRight
);
1382 if( VisArea().Overlaps( aPrevArea
) && !mnLockPaint
)
1385 maVisArea
.Pos() = aPrevArea
.Pos();
1386 if ( SmoothScroll( nXDiff
, nYDiff
, &aRect
) )
1388 maVisArea
.Pos() = rRect
.Pos();
1390 else if (!comphelper::LibreOfficeKit::isActive())
1391 GetWin()->Invalidate( aRect
);
1393 else if ( !mnLockPaint
) //will be released in Unlock
1395 if( VisArea().Overlaps( aPrevArea
) )
1398 maVisArea
.Pos() = aPrevArea
.Pos();
1399 if ( SmoothScroll( nXDiff
, nYDiff
, nullptr ) )
1401 maVisArea
.Pos() = rRect
.Pos();
1404 GetWin()->Invalidate();
1408 // When tiled rendering, the map mode of the window is disabled, avoid
1409 // enabling it here.
1410 if (!comphelper::LibreOfficeKit::isActive())
1412 Point
aPt( VisArea().Pos() );
1413 aPt
.setX( -aPt
.X() ); aPt
.setY( -aPt
.Y() );
1414 MapMode
aMapMode( GetWin()->GetMapMode() );
1415 aMapMode
.SetOrigin( aPt
);
1416 GetWin()->SetMapMode( aMapMode
);
1419 if ( HasDrawView() )
1421 Imp()->GetDrawView()->VisAreaChanged( GetWin()->GetOutDev() );
1422 Imp()->GetDrawView()->SetActualWin( GetWin()->GetOutDev() );
1424 GetWin()->PaintImmediately();
1426 if ( pPostItMgr
) // #i88070#
1428 pPostItMgr
->Rescale();
1429 pPostItMgr
->CalcRects();
1430 pPostItMgr
->LayoutPostIts();
1433 if ( !bScrolled
&& pPostItMgr
&& pPostItMgr
->HasNotes() && pPostItMgr
->ShowNotes() )
1434 pPostItMgr
->CorrectPositions();
1436 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1437 if( Imp()->IsAccessible() )
1438 Imp()->UpdateAccessible();
1442 bool SwViewShell::SmoothScroll( tools::Long lXDiff
, tools::Long lYDiff
, const tools::Rectangle
*pRect
)
1444 #if !defined(MACOSX) && !defined(ANDROID) && !defined(IOS)
1445 // #i98766# - disable smooth scrolling for Mac
1447 const sal_uLong nBitCnt
= mpOut
->GetBitCount();
1448 tools::Long lMult
= 1, lMax
= LONG_MAX
;
1449 if ( nBitCnt
== 16 )
1454 if ( nBitCnt
== 24 )
1459 else if ( nBitCnt
== 1 )
1465 // #i75172# isolated static conditions
1466 const bool bOnlyYScroll(!lXDiff
&& std::abs(lYDiff
) != 0 && std::abs(lYDiff
) < lMax
);
1467 const bool bAllowedWithChildWindows(GetWin()->GetWindowClipRegionPixel().IsNull());
1468 const bool bSmoothScrollAllowed(bOnlyYScroll
&& mbEnableSmooth
&& GetViewOptions()->IsSmoothScroll() && bAllowedWithChildWindows
);
1470 if(bSmoothScrollAllowed
)
1472 Imp()->m_bStopSmooth
= false;
1474 const SwRect
aOldVis( VisArea() );
1476 //create virtual device and set.
1477 const Size aPixSz
= GetWin()->PixelToLogic(Size(1,1));
1478 VclPtrInstance
<VirtualDevice
> pVout( *GetWin()->GetOutDev() );
1479 pVout
->SetLineColor( GetWin()->GetOutDev()->GetLineColor() );
1480 pVout
->SetFillColor( GetWin()->GetOutDev()->GetFillColor() );
1481 MapMode
aMapMode( GetWin()->GetMapMode() );
1482 pVout
->SetMapMode( aMapMode
);
1483 Size
aSize( maVisArea
.Width()+2*aPixSz
.Width(), std::abs(lYDiff
)+(2*aPixSz
.Height()) );
1485 aSize
.setWidth( std::min(aSize
.Width(), pRect
->GetWidth()+2*aPixSz
.Width()) );
1486 if ( pVout
->SetOutputSize( aSize
) )
1490 //First Paint everything in the virtual device.
1491 SwRect
aRect( VisArea() );
1492 aRect
.Height( aSize
.Height() );
1495 aRect
.Pos().setX( std::max(aRect
.Left(),pRect
->Left()-aPixSz
.Width()) );
1496 aRect
.Right( std::min(aRect
.Right()+2*aPixSz
.Width(), pRect
->Right()+aPixSz
.Width()));
1499 aRect
.AddWidth(2*aPixSz
.Width() );
1500 aRect
.Pos().setY( lYDiff
< 0 ? aOldVis
.Bottom() - aPixSz
.Height()
1501 : aRect
.Top() - aSize
.Height() + aPixSz
.Height() );
1502 aRect
.Pos().setX( std::max( tools::Long(0), aRect
.Left()-aPixSz
.Width() ) );
1503 aRect
.Pos() = GetWin()->PixelToLogic( GetWin()->LogicToPixel( aRect
.Pos()));
1504 aRect
.SSize( GetWin()->PixelToLogic( GetWin()->LogicToPixel( aRect
.SSize())) );
1506 const Point
aPt( -aRect
.Left(), -aRect
.Top() );
1507 aMapMode
.SetOrigin( aPt
);
1508 pVout
->SetMapMode( aMapMode
);
1509 OutputDevice
*pOld
= mpOut
;
1510 mpOut
= pVout
.get();
1513 // #i75172# To get a clean repaint, a new ObjectContact is needed here. Without, the
1514 // repaint would not be correct since it would use the wrong DrawPage visible region.
1515 // This repaint IS about painting something currently outside the visible part (!).
1516 // For that purpose, AddDeviceToPaintView is used which creates a new SdrPageViewWindow
1517 // and all the necessary stuff. It's not cheap, but necessary here. Alone because repaint
1518 // target really is NOT the current window.
1519 // Also will automatically NOT use PreRendering and overlay (since target is VirtualDevice)
1522 SdrView
* pDrawView
= GetDrawView();
1523 pDrawView
->AddDeviceToPaintView(*pVout
, nullptr);
1525 // clear mpWin during DLPrePaint2 to get paint preparation for mpOut, but set it again
1526 // immediately afterwards. There are many decisions in SW which imply that Printing
1527 // is used when mpWin == 0 (wrong but widely used).
1528 vcl::Window
* pOldWin
= mpWin
;
1530 DLPrePaint2(vcl::Region(aRect
.SVRect()));
1534 PaintDesktop(*GetOut(), aRect
);
1535 SwViewShell::sbLstAct
= true;
1536 GetLayout()->PaintSwFrame( *GetOut(), aRect
);
1537 SwViewShell::sbLstAct
= false;
1539 // end paint and destroy ObjectContact again
1541 pDrawView
->DeleteDeviceFromPaintView(*pVout
);
1545 maVisArea
= aOldVis
;
1547 //Now shift in parts and copy the new Pixel from the virtual device.
1549 // ??????????????????????
1550 // or is it better to get the scrollfactor from the User
1552 // ??????????????????????
1553 tools::Long lMaDelta
= aPixSz
.Height();
1554 if ( std::abs(lYDiff
) > ( maVisArea
.Height() / 3 ) )
1562 lMaDelta
= -lMaDelta
;
1564 tools::Long lDiff
= lYDiff
;
1567 tools::Long lScroll
;
1568 if ( Imp()->m_bStopSmooth
|| std::abs(lDiff
) <= std::abs(lMaDelta
) )
1579 const SwRect aTmpOldVis
= VisArea();
1580 maVisArea
.Pos().AdjustY( -lScroll
);
1581 maVisArea
.Pos() = GetWin()->PixelToLogic( GetWin()->LogicToPixel( VisArea().Pos()));
1582 lScroll
= aTmpOldVis
.Top() - VisArea().Top();
1585 tools::Rectangle
aTmp( aTmpOldVis
.SVRect() );
1586 aTmp
.SetLeft( pRect
->Left() );
1587 aTmp
.SetRight( pRect
->Right() );
1588 GetWin()->Scroll( 0, lScroll
, aTmp
, ScrollFlags::Children
);
1591 GetWin()->Scroll( 0, lScroll
, ScrollFlags::Children
);
1593 const Point
aTmpPt( -VisArea().Left(), -VisArea().Top() );
1594 MapMode
aTmpMapMode( GetWin()->GetMapMode() );
1595 aTmpMapMode
.SetOrigin( aTmpPt
);
1596 GetWin()->SetMapMode( aTmpMapMode
);
1598 if ( Imp()->HasDrawView() )
1599 Imp()->GetDrawView()->VisAreaChanged( GetWin()->GetOutDev() );
1601 SetFirstVisPageInvalid();
1602 if ( !Imp()->m_bStopSmooth
)
1604 const bool bScrollDirectionIsUp(lScroll
> 0);
1605 Imp()->m_aSmoothRect
= VisArea();
1607 if(bScrollDirectionIsUp
)
1609 Imp()->m_aSmoothRect
.Bottom( VisArea().Top() + lScroll
+ aPixSz
.Height());
1613 Imp()->m_aSmoothRect
.Top( VisArea().Bottom() + lScroll
- aPixSz
.Height());
1616 Imp()->m_bSmoothUpdate
= true;
1617 GetWin()->PaintImmediately();
1618 Imp()->m_bSmoothUpdate
= false;
1620 if(!Imp()->m_bStopSmooth
)
1622 // start paint on logic base
1623 const tools::Rectangle
aTargetLogic(Imp()->m_aSmoothRect
.SVRect());
1624 DLPrePaint2(vcl::Region(aTargetLogic
));
1626 // get target rectangle in discrete pixels
1627 OutputDevice
& rTargetDevice
= mpTargetPaintWindow
->GetTargetOutputDevice();
1628 const tools::Rectangle
aTargetPixel(rTargetDevice
.LogicToPixel(aTargetLogic
));
1630 // get source top-left in discrete pixels
1631 const Point
aSourceTopLeft(pVout
->LogicToPixel(aTargetLogic
.TopLeft()));
1633 // switch off MapModes
1634 const bool bMapModeWasEnabledDest(rTargetDevice
.IsMapModeEnabled());
1635 const bool bMapModeWasEnabledSource(pVout
->IsMapModeEnabled());
1636 rTargetDevice
.EnableMapMode(false);
1637 pVout
->EnableMapMode(false);
1639 rTargetDevice
.DrawOutDev(
1640 aTargetPixel
.TopLeft(), aTargetPixel
.GetSize(), // dest
1641 aSourceTopLeft
, aTargetPixel
.GetSize(), // source
1645 rTargetDevice
.EnableMapMode(bMapModeWasEnabledDest
);
1646 pVout
->EnableMapMode(bMapModeWasEnabledSource
);
1648 // end paint on logoc base
1655 pVout
.disposeAndClear();
1656 GetWin()->PaintImmediately();
1657 if ( !Imp()->m_bStopSmooth
)
1659 SetFirstVisPageInvalid();
1662 pVout
.disposeAndClear();
1666 maVisArea
.Pos().AdjustX( -lXDiff
);
1667 maVisArea
.Pos().AdjustY( -lYDiff
);
1669 GetWin()->Scroll( lXDiff
, lYDiff
, *pRect
, ScrollFlags::Children
);
1671 GetWin()->Scroll( lXDiff
, lYDiff
, ScrollFlags::Children
);
1675 void SwViewShell::PaintDesktop(const vcl::RenderContext
& rRenderContext
, const SwRect
&rRect
)
1677 if ( !GetWin() && !GetOut()->GetConnectMetaFile() )
1678 return; //for the printer we don't do anything here.
1680 if(comphelper::LibreOfficeKit::isActive())
1683 //Catch exceptions, so that it doesn't look so surprising.
1684 //Can e.g. happen during Idle.
1685 //Unfortunately we must at any rate Paint the rectangles next to the pages,
1686 //as these are not painted at VisPortChgd.
1687 bool bBorderOnly
= false;
1688 const SwRootFrame
*pRoot
= GetLayout();
1689 if ( rRect
.Top() > pRoot
->getFrameArea().Bottom() )
1691 const SwFrame
*pPg
= pRoot
->Lower();
1692 while ( pPg
&& pPg
->GetNext() )
1693 pPg
= pPg
->GetNext();
1694 if ( !pPg
|| !pPg
->getFrameArea().Overlaps( VisArea() ) )
1698 const bool bBookMode
= GetViewOptions()->IsViewLayoutBookMode();
1700 SwRegionRects
aRegion( rRect
);
1702 //mod #i6193: remove sidebar area to avoid flickering
1703 const SwPostItMgr
* pPostItMgr
= GetPostItMgr();
1704 const SwTwips nSidebarWidth
= pPostItMgr
&& pPostItMgr
->HasNotes() && pPostItMgr
->ShowNotes() ?
1705 pPostItMgr
->GetSidebarWidth() + pPostItMgr
->GetSidebarBorderWidth() :
1710 const SwFrame
*pPage
=pRoot
->Lower();
1711 SwRect
aLeft( rRect
), aRight( rRect
);
1714 tools::Long nTmp
= pPage
->getFrameArea().Left();
1715 if ( nTmp
< aLeft
.Right() )
1716 aLeft
.Right( nTmp
);
1717 nTmp
= pPage
->getFrameArea().Right();
1718 if ( nTmp
> aRight
.Left() )
1720 aRight
.Left( nTmp
+ nSidebarWidth
);
1722 pPage
= pPage
->GetNext();
1725 if ( aLeft
.HasArea() )
1726 aRegion
.push_back( aLeft
);
1727 if ( aRight
.HasArea() )
1728 aRegion
.push_back( aRight
);
1732 const SwFrame
*pPage
= Imp()->GetFirstVisPage(&rRenderContext
);
1733 const SwTwips nBottom
= rRect
.Bottom();
1734 while ( pPage
&& !aRegion
.empty() &&
1735 (pPage
->getFrameArea().Top() <= nBottom
) )
1737 SwRect
aPageRect( pPage
->getFrameArea() );
1740 const SwPageFrame
& rFormatPage
= static_cast<const SwPageFrame
*>(pPage
)->GetFormatPage();
1741 aPageRect
.SSize( rFormatPage
.getFrameArea().SSize() );
1744 const bool bSidebarRight
=
1745 static_cast<const SwPageFrame
*>(pPage
)->SidebarPosition() == sw::sidebarwindows::SidebarPosition::RIGHT
;
1746 aPageRect
.Pos().AdjustX( -(bSidebarRight
? 0 : nSidebarWidth
) );
1747 aPageRect
.AddWidth(nSidebarWidth
);
1749 if ( aPageRect
.Overlaps( rRect
) )
1750 aRegion
-= aPageRect
;
1752 pPage
= pPage
->GetNext();
1755 if ( !aRegion
.empty() )
1756 PaintDesktop_(aRegion
);
1759 bool SwViewShell::DrawAppBackgroundBitmap(vcl::RenderContext
* rRenderContext
, const SwRect
& rRect
)
1761 if (Application::IsHeadlessModeEnabled()
1762 || !ThemeColors::GetThemeColors().GetAppBackUseBitmap())
1765 const BitmapEx
& aAppBackImg
1766 = Application::GetSettings().GetStyleSettings().GetAppBackgroundBitmap();
1767 if (aAppBackImg
.IsEmpty())
1770 Wallpaper
aWallpaper(aAppBackImg
);
1771 aWallpaper
.SetStyle(WallpaperStyle::Tile
);
1773 rRenderContext
->DrawWallpaper(rRect
.SVRect(), aWallpaper
);
1777 // PaintDesktop is split in two, this part is also used by PreviewPage
1778 void SwViewShell::PaintDesktop_(const SwRegionRects
&rRegion
)
1780 if (DrawAppBackgroundBitmap(GetOut(), rRegion
.GetOrigin()))
1783 // OD 2004-04-23 #116347#
1784 GetOut()->Push( vcl::PushFlags::FILLCOLOR
|vcl::PushFlags::LINECOLOR
);
1785 GetOut()->SetLineColor();
1787 for ( auto &rRgn
: rRegion
)
1789 const tools::Rectangle
aRectangle(rRgn
.SVRect());
1792 // Here we have a real Problem. On the one hand we have the buffering for paint
1793 // and overlay which needs an embracing pair of DLPrePaint2/DLPostPaint2 calls,
1794 // on the other hand the MapMode is not set correctly when this code is executed.
1795 // This is done in the users of this method, for each SWpage before painting it.
1796 // Since the MapMode is not correct here, the call to DLPostPaint2 will paint
1797 // existing FormControls due to the current MapMode.
1799 // There are basically three solutions for this:
1801 // (1) Set the MapMode correct, move the background painting to the users of
1804 // (2) Do no DLPrePaint2/DLPostPaint2 here; no SdrObjects are allowed to lie in
1805 // the desktop region. Disadvantage: the desktop will not be part of the
1806 // buffers, e.g. overlay. Thus, as soon as overlay will be used over the
1807 // desktop, it will not work.
1809 // (3) expand DLPostPaint2 with a flag to signal if FormControl paints shall
1812 // Currently, (3) will be the best possible solution. It will keep overlay and
1813 // buffering intact and work without MapMode for single pages. In the medium
1814 // to long run, (1) will need to be used and the bool bPaintFormLayer needs
1815 // to be removed again
1817 // #i68597# inform Drawinglayer about display change
1818 DLPrePaint2(vcl::Region(aRectangle
));
1820 // #i75172# needed to move line/Fill color setters into loop since DLPrePaint2
1821 // may exchange GetOut(), that's it's purpose. This happens e.g. at print preview.
1822 GetOut()->SetFillColor( GetViewOptions()->GetAppBackgroundColor());
1823 GetOut()->SetLineColor();
1824 GetOut()->DrawRect(aRectangle
);
1826 DLPostPaint2(false);
1832 bool SwViewShell::CheckInvalidForPaint( const SwRect
&rRect
)
1837 const SwPageFrame
*pPage
= Imp()->GetFirstVisPage(GetOut());
1838 const SwTwips nBottom
= VisArea().Bottom();
1839 const SwTwips nRight
= VisArea().Right();
1841 while ( !bRet
&& pPage
&& ((pPage
->getFrameArea().Top() <= nBottom
) &&
1842 (pPage
->getFrameArea().Left() <= nRight
)))
1844 if ( pPage
->IsInvalid() || pPage
->IsInvalidFly() )
1846 pPage
= static_cast<const SwPageFrame
*>(pPage
->GetNext());
1851 //Unfortunately Start/EndAction won't help here, as the Paint originated
1852 //from GUI and so Clipping has been set against getting through.
1853 //Ergo: do it all yourself (see ImplEndAction())
1854 if ( Imp()->HasPaintRegion() && Imp()->GetPaintRegion()->GetOrigin() != VisArea())
1855 Imp()->DeletePaintRegion();
1857 SwLayAction
aAction( GetLayout(), Imp() );
1858 aAction
.SetComplete( false );
1859 // We increment the action counter to avoid a recursive call of actions
1860 // e.g. from a SwFEShell::RequestObjectResize(..) in bug 95829.
1861 // A recursive call of actions is no good idea because the inner action
1862 // can't format frames which are locked by the outer action. This may
1863 // cause and endless loop.
1865 aAction
.Action(GetWin()->GetOutDev());
1868 std::optional
<SwRegionRects
> oRegion
= Imp()->TakePaintRegion();
1869 if ( oRegion
&& aAction
.IsBrowseActionStop() )
1871 //only of interest when something has changed in the visible range
1872 bool bAllNoOverlap
= std::all_of(oRegion
->begin(), oRegion
->end(), [this](const SwRect
&rTmp
) {
1873 return rTmp
.Overlaps( VisArea() );
1875 if ( bAllNoOverlap
)
1881 oRegion
->LimitToOrigin();
1882 oRegion
->Compress( SwRegionRects::CompressFuzzy
);
1884 if ( !oRegion
->empty() )
1886 SwRegionRects
aRegion( rRect
);
1887 for ( const SwRect
&rTmp
: *oRegion
)
1889 if ( !rRect
.Contains( rTmp
) )
1891 InvalidateWindows( rTmp
);
1892 if ( rTmp
.Overlaps( VisArea() ) )
1900 for ( size_t i
= 0; i
< aRegion
.size(); ++i
)
1901 GetWin()->Invalidate( aRegion
[i
].SVRect() );
1903 if ( rRect
!= VisArea() )
1905 //rRect == VisArea is the special case for new or
1906 //Shift-Ctrl-R, when it shouldn't be necessary to
1907 //hold the rRect again in Document coordinates.
1908 if ( maInvalidRect
.IsEmpty() )
1909 maInvalidRect
= rRect
;
1911 maInvalidRect
.Union( rRect
);
1926 /// Similar to comphelper::FlagRestorationGuard, but for vcl::RenderContext.
1927 class RenderContextGuard
1929 std::unique_ptr
<SdrPaintWindow
> m_TemporaryPaintWindow
;
1930 SdrPageWindow
* m_pPatchedPageWindow
;
1931 SdrPaintWindow
* m_pPreviousPaintWindow
= nullptr;
1934 RenderContextGuard(VclPtr
<vcl::RenderContext
>& pRef
, vcl::RenderContext
* pValue
, SwViewShell
* pShell
)
1935 : m_pPatchedPageWindow(nullptr)
1939 if (pValue
== pShell
->GetWin()->GetOutDev())
1942 SdrView
* pDrawView(pShell
->Imp()->GetDrawView());
1944 if (nullptr == pDrawView
)
1947 SdrPageView
* pSdrPageView(pDrawView
->GetSdrPageView());
1949 if (nullptr != pSdrPageView
)
1951 m_pPatchedPageWindow
= pSdrPageView
->FindPageWindow(*pShell
->GetWin()->GetOutDev());
1953 if (nullptr != m_pPatchedPageWindow
)
1955 m_TemporaryPaintWindow
.reset(new SdrPaintWindow(*pDrawView
, *pValue
));
1956 m_pPreviousPaintWindow
= m_pPatchedPageWindow
->patchPaintWindow(*m_TemporaryPaintWindow
);
1961 ~RenderContextGuard()
1963 if(nullptr != m_pPatchedPageWindow
)
1965 m_pPatchedPageWindow
->unpatchPaintWindow(m_pPreviousPaintWindow
);
1971 void SwViewShell::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&rRect
)
1973 RenderContextGuard
aGuard(mpOut
, &rRenderContext
, this);
1976 if ( Imp()->m_bSmoothUpdate
)
1978 SwRect
aTmp( rRect
);
1979 if ( !Imp()->m_aSmoothRect
.Contains( aTmp
) )
1980 Imp()->m_bStopSmooth
= true;
1983 Imp()->m_aSmoothRect
= aTmp
;
1991 if ( SwRootFrame::IsInPaint() )
1993 //During the publication of a page at printing the Paint is buffered.
1994 SwPaintQueue::Add( this, SwRect( rRect
) );
1998 //With !nStartAction I try to protect me against erroneous code at other places.
1999 //Hopefully it will not lead to problems!?
2000 if ( mbPaintWorks
&& !mnStartAction
)
2002 if( GetWin() && GetWin()->IsVisible() )
2004 SwRect
aRect( rRect
);
2005 if ( mbPaintInProgress
) //Guard against double Paints!
2007 GetWin()->Invalidate( rRect
);
2011 mbPaintInProgress
= true;
2012 CurrShell
aCurr( this );
2013 SwRootFrame::SetNoVirDev( true );
2015 //We don't want to Clip to and from, we trust that all are limited
2016 //to the rectangle and only need to calculate the clipping once.
2017 //The ClipRect is removed here once and not recovered, as externally
2018 //no one needs it anymore anyway.
2019 //Not when we paint a Metafile.
2020 if( !GetOut()->GetConnectMetaFile() && GetOut()->IsClipRegion())
2021 GetOut()->SetClipRegion();
2025 //When useful, process or destroy the old InvalidRect.
2026 if ( aRect
.Contains( maInvalidRect
) )
2028 SwViewShell::sbLstAct
= true;
2029 GetLayout()->PaintSwFrame( rRenderContext
, aRect
);
2030 SwViewShell::sbLstAct
= false;
2034 //When one of the visible pages still has anything entered for
2035 //Repaint, Repaint must be triggered.
2036 if ( !CheckInvalidForPaint( aRect
) )
2038 // --> OD 2009-08-12 #i101192#
2039 // start Pre/PostPaint encapsulation to avoid screen blinking
2040 const vcl::Region
aRepaintRegion(aRect
.SVRect());
2041 DLPrePaint2(aRepaintRegion
);
2044 PaintDesktop(rRenderContext
, aRect
);
2046 //When useful, process or destroy the old InvalidRect.
2047 if ( aRect
.Contains( maInvalidRect
) )
2049 SwViewShell::sbLstAct
= true;
2050 GetLayout()->PaintSwFrame( rRenderContext
, aRect
);
2051 SwViewShell::sbLstAct
= false;
2052 // --> OD 2009-08-12 #i101192#
2053 // end Pre/PostPaint encapsulation
2058 SwRootFrame::SetNoVirDev( false );
2059 mbPaintInProgress
= false;
2065 if ( maInvalidRect
.IsEmpty() )
2066 maInvalidRect
= SwRect( rRect
);
2068 maInvalidRect
.Union( SwRect( rRect
) );
2070 if ( mbInEndAction
&& GetWin() )
2072 const vcl::Region
aRegion(GetWin()->GetPaintRegion());
2073 RectangleVector aRectangles
;
2074 aRegion
.GetRegionRectangles(aRectangles
);
2076 for(const auto& rRectangle
: aRectangles
)
2078 Imp()->AddPaintRect(SwRect(rRectangle
));
2081 //RegionHandle hHdl( aRegion.BeginEnumRects() );
2083 //while ( aRegion.GetEnumRects( hHdl, aRect ) )
2084 // Imp()->AddPaintRect( aRect );
2085 //aRegion.EndEnumRects( hHdl );
2087 else if ( SfxProgress::GetActiveProgress( GetDoc()->GetDocShell() ) &&
2088 GetOut() == GetWin()->GetOutDev() )
2091 const vcl::Region
aDLRegion(rRect
);
2092 DLPrePaint2(aDLRegion
);
2094 rRenderContext
.Push( vcl::PushFlags::FILLCOLOR
|vcl::PushFlags::LINECOLOR
);
2095 rRenderContext
.SetFillColor( Imp()->GetRetoucheColor() );
2096 rRenderContext
.SetLineColor();
2097 rRenderContext
.DrawRect( rRect
);
2098 rRenderContext
.Pop();
2105 void SwViewShell::PaintTile(VirtualDevice
&rDevice
, int contextWidth
, int contextHeight
, int tilePosX
, int tilePosY
, tools::Long tileWidth
, tools::Long tileHeight
)
2107 // SwViewShell's output device setup
2108 // TODO clean up SwViewShell's approach to output devices (the many of
2109 // them - mpBufferedOut, mpOut, mpWin, ...)
2110 OutputDevice
*pSaveOut
= mpOut
;
2111 comphelper::LibreOfficeKit::setTiledPainting(true);
2114 // resizes the virtual device so to contain the entries context
2115 rDevice
.SetOutputSizePixel(Size(contextWidth
, contextHeight
), /*bErase*/false);
2117 // setup the output device to draw the tile
2118 MapMode
aMapMode(rDevice
.GetMapMode());
2119 aMapMode
.SetMapUnit(MapUnit::MapTwip
);
2120 aMapMode
.SetOrigin(Point(-tilePosX
, -tilePosY
));
2122 // Scaling. Must convert from pixels to twips. We know
2123 // that VirtualDevices use a DPI of 96.
2124 const Fraction scale
= conversionFract(o3tl::Length::px
, o3tl::Length::twip
);
2125 Fraction scaleX
= Fraction(contextWidth
, tileWidth
) * scale
;
2126 Fraction scaleY
= Fraction(contextHeight
, tileHeight
) * scale
;
2127 aMapMode
.SetScaleX(scaleX
);
2128 aMapMode
.SetScaleY(scaleY
);
2129 rDevice
.SetMapMode(aMapMode
);
2131 // Update scaling of SwEditWin and its sub-widgets, needed for comments.
2132 sal_uInt16 nOldZoomValue
= 0;
2133 if (GetWin() && GetWin()->GetMapMode().GetScaleX() != scaleX
)
2135 double fScale
= double(scaleX
);
2136 SwViewOption
aOption(*GetViewOptions());
2137 nOldZoomValue
= aOption
.GetZoom();
2138 aOption
.SetZoom(fScale
* 100);
2139 ApplyViewOptions(aOption
);
2140 // Make sure the map mode (disabled in SwXTextDocument::initializeForTiledRendering()) is still disabled.
2141 GetWin()->EnableMapMode(false);
2144 tools::Rectangle
aOutRect(Point(tilePosX
, tilePosY
),
2145 rDevice
.PixelToLogic(Size(contextWidth
, contextHeight
)));
2147 // Make the requested area visible -- we can't use MakeVisible as that will
2148 // only scroll the contents, but won't zoom/resize if needed.
2149 // Without this, items/text that are outside the visible area (in the SwView)
2150 // won't be painted when rendering tiles (at least when using either the
2151 // tiledrendering app, or the gtktiledviewer) -- although ultimately we
2152 // probably want to fix things so that the SwView's area doesn't affect
2154 VisPortChgd(SwRect(aOutRect
));
2156 // Invoke SwLayAction if layout is not yet ready.
2157 CheckInvalidForPaint(SwRect(aOutRect
));
2159 // draw - works in logic coordinates
2160 Paint(rDevice
, aOutRect
);
2162 SwPostItMgr
* pPostItMgr
= GetPostItMgr();
2163 if (GetViewOptions()->IsPostIts() && pPostItMgr
)
2164 pPostItMgr
->PaintTile(rDevice
);
2166 // SwViewShell's output device tear down
2168 // A view shell can get a PaintTile call for a tile at a zoom level
2169 // different from the one, the related client really is.
2170 // In such a case it is better to reset the current scale value to
2171 // the original one, since such a value should be in synchronous with
2172 // the zoom level in the client (see setClientZoom).
2173 // At present the zoom value returned by GetViewOptions()->GetZoom() is
2174 // used in SwXTextDocument methods (postMouseEvent and setGraphicSelection)
2175 // for passing the correct mouse position to an edited chart (if any).
2176 if (nOldZoomValue
!=0)
2178 SwViewOption
aOption(*GetViewOptions());
2179 aOption
.SetZoom(nOldZoomValue
);
2180 ApplyViewOptions(aOption
);
2182 // Changing the zoom value doesn't always trigger the updating of
2183 // the client ole object area, so we call it directly.
2184 SfxInPlaceClient
* pIPClient
= GetSfxViewShell()->GetIPClient();
2187 pIPClient
->VisAreaChanged();
2189 // Make sure the map mode (disabled in SwXTextDocument::initializeForTiledRendering()) is still disabled.
2190 GetWin()->EnableMapMode(false);
2194 comphelper::LibreOfficeKit::setTiledPainting(false);
2197 void SwViewShell::SetBrowseBorder( const Size
& rNew
)
2199 if( rNew
!= maBrowseBorder
)
2201 maBrowseBorder
= rNew
;
2202 if ( maVisArea
.HasArea() )
2203 InvalidateLayout( false );
2207 const Size
& SwViewShell::GetBrowseBorder() const
2209 return maBrowseBorder
;
2212 sal_Int32
SwViewShell::GetBrowseWidth() const
2214 const SwPostItMgr
* pPostItMgr
= GetPostItMgr();
2215 if ( pPostItMgr
&& pPostItMgr
->HasNotes() && pPostItMgr
->ShowNotes() )
2217 Size
aBorder( maBrowseBorder
);
2218 aBorder
.AdjustWidth(maBrowseBorder
.Width() );
2219 aBorder
.AdjustWidth(pPostItMgr
->GetSidebarWidth(true) + pPostItMgr
->GetSidebarBorderWidth(true) );
2220 return maVisArea
.Width() - GetOut()->PixelToLogic(aBorder
).Width();
2223 return maVisArea
.Width() - 2 * GetOut()->PixelToLogic(maBrowseBorder
).Width();
2226 void SwViewShell::InvalidateLayout( bool bSizeChanged
)
2228 if ( !bSizeChanged
&& !GetViewOptions()->getBrowseMode() &&
2229 !GetViewOptions()->IsWhitespaceHidden() )
2232 CurrShell
aCurr( this );
2234 OSL_ENSURE( GetLayout(), "Layout not ready" );
2236 // When the Layout doesn't have a height yet, nothing is formatted.
2237 // That leads to problems with Invalidate, e.g. when setting up a new View
2238 // the content is inserted and formatted (regardless of empty VisArea).
2239 // Therefore the pages must be roused for formatting.
2240 if( !GetLayout()->getFrameArea().Height() )
2242 SwFrame
* pPage
= GetLayout()->Lower();
2245 pPage
->InvalidateSize_();
2246 pPage
= pPage
->GetNext();
2251 LockPaint(LockPaintReason::InvalidateLayout
);
2252 SwViewShell::StartAction();
2254 SwPageFrame
*pPg
= static_cast<SwPageFrame
*>(GetLayout()->Lower());
2256 { pPg
->InvalidateSize();
2257 pPg
->InvalidatePrt_();
2258 pPg
->InvaPercentLowers();
2261 pPg
->PrepareHeader();
2262 pPg
->PrepareFooter();
2264 pPg
= static_cast<SwPageFrame
*>(pPg
->GetNext());
2267 // When the size ratios in browse mode change,
2268 // the Position and PrtArea of the Content and Tab frames must be Invalidated.
2269 SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Table
| SwInvalidateFlags::Pos
;
2270 // In case of layout or mode change, the ContentFrames need a size-Invalidate
2271 // because of printer/screen formatting.
2273 nInv
|= SwInvalidateFlags::Size
| SwInvalidateFlags::Direction
;
2275 GetLayout()->InvalidateAllContent( nInv
);
2277 SwFrame::CheckPageDescs( static_cast<SwPageFrame
*>(GetLayout()->Lower()) );
2279 SwViewShell::EndAction();
2283 SwRootFrame
*SwViewShell::GetLayout() const
2285 return mpLayout
.get();
2288 vcl::RenderContext
& SwViewShell::GetRefDev() const
2290 OutputDevice
* pTmpOut
= nullptr;
2292 GetViewOptions()->getBrowseMode() &&
2293 !GetViewOptions()->IsPrtFormat() )
2294 pTmpOut
= GetWin()->GetOutDev();
2296 pTmpOut
= GetDoc()->getIDocumentDeviceAccess().getReferenceDevice( true );
2301 const SwNodes
& SwViewShell::GetNodes() const
2303 return mxDoc
->GetNodes();
2306 void SwViewShell::DrawSelChanged()
2310 Size
SwViewShell::GetDocSize() const
2313 const SwRootFrame
* pRoot
= GetLayout();
2315 aSz
= pRoot
->getFrameArea().SSize();
2320 SfxItemPool
& SwViewShell::GetAttrPool()
2322 return GetDoc()->GetAttrPool();
2325 void SwViewShell::ApplyViewOptions( const SwViewOption
&rOpt
)
2327 for(SwViewShell
& rSh
: GetRingContainer())
2328 rSh
.SwViewShell::StartAction();
2330 ImplApplyViewOptions( rOpt
);
2332 // With one layout per view it is no longer necessary
2333 // to sync these "layout related" view options
2334 // But as long as we have to disable "multiple layout"
2336 for(SwViewShell
& rSh
: GetRingContainer())
2340 SwViewOption
aOpt( *rSh
.GetViewOptions() );
2341 aOpt
.SyncLayoutRelatedViewOptions(rOpt
);
2342 if ( !(aOpt
== *rSh
.GetViewOptions()) )
2343 rSh
.ImplApplyViewOptions( aOpt
);
2345 // End of disabled multiple window
2347 for(SwViewShell
& rSh
: GetRingContainer())
2348 rSh
.SwViewShell::EndAction();
2352 IsCursorInFieldmarkHidden(SwPaM
const& rCursor
, sw::FieldmarkMode
const eMode
)
2354 if (eMode
== sw::FieldmarkMode::ShowBoth
)
2358 IDocumentMarkAccess
const& rIDMA(*rCursor
.GetDoc().getIDocumentMarkAccess());
2359 // iterate, for nested fieldmarks
2360 for (auto iter
= rIDMA
.getFieldmarksBegin(); iter
!= rIDMA
.getFieldmarksEnd(); ++iter
)
2362 if (*rCursor
.GetPoint() <= (**iter
).GetMarkStart())
2366 if (*rCursor
.GetPoint() < (**iter
).GetMarkEnd())
2368 SwPosition
const sepPos(sw::mark::FindFieldSep(**iter
));
2369 if (eMode
== sw::FieldmarkMode::ShowResult
)
2371 if (*rCursor
.GetPoint() <= sepPos
2372 && *rCursor
.GetPoint() != (**iter
).GetMarkStart())
2379 if (sepPos
< *rCursor
.GetPoint())
2389 void SwViewShell::ImplApplyViewOptions( const SwViewOption
&rOpt
)
2394 vcl::Window
*pMyWin
= GetWin();
2397 OSL_ENSURE( pMyWin
, "SwViewShell::ApplyViewOptions: no window" );
2401 CurrShell
aCurr( this );
2403 bool bReformat
= false;
2405 if( mpOpt
->IsShowHiddenField() != rOpt
.IsShowHiddenField() )
2407 static_cast<SwHiddenTextFieldType
*>(mxDoc
->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::HiddenText
))->
2408 SetHiddenFlag( !rOpt
.IsShowHiddenField() );
2411 if ( mpOpt
->IsShowHiddenPara() != rOpt
.IsShowHiddenPara() )
2413 SwHiddenParaFieldType
* pFieldType
= static_cast<SwHiddenParaFieldType
*>(GetDoc()->
2414 getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::HiddenPara
));
2415 if( pFieldType
&& pFieldType
->HasWriterListeners() )
2416 pFieldType
->PrintHiddenPara();
2419 if ( !bReformat
&& mpOpt
->IsShowHiddenChar() != rOpt
.IsShowHiddenChar() )
2421 bReformat
= GetDoc()->ContainsHiddenChars();
2423 if ( mpOpt
->IsShowChangesInMargin() != rOpt
.IsShowChangesInMargin() ||
2424 mpOpt
->IsShowChangesInMargin2() != rOpt
.IsShowChangesInMargin2() )
2426 if (rOpt
.IsShowChangesInMargin())
2427 GetDoc()->GetDocumentRedlineManager().HideAll(
2428 /*bDeletion=*/!rOpt
.IsShowChangesInMargin2() );
2430 GetDoc()->GetDocumentRedlineManager().ShowAll();
2431 GetLayout()->SetHideRedlines( false );
2434 // bReformat becomes true, if ...
2435 // - fieldnames apply or not ...
2436 // ( - SwEndPortion must _no_ longer be generated. )
2437 // - Of course, the screen is something completely different than the printer ...
2438 bool const isToggleFieldNames(mpOpt
->IsFieldName() != rOpt
.IsFieldName());
2440 if (mpOpt
->IsFieldName() != rOpt
.IsFieldName()
2441 || mpOpt
->IsParagraph() != rOpt
.IsParagraph())
2443 GetLayout()->SetFieldmarkMode( rOpt
.IsFieldName()
2444 ? sw::FieldmarkMode::ShowCommand
2445 : sw::FieldmarkMode::ShowResult
,
2447 ? sw::ParagraphBreakMode::Shown
2448 : sw::ParagraphBreakMode::Hidden
);
2452 // The map mode is changed, minima/maxima will be attended by UI
2453 if( mpOpt
->GetZoom() != rOpt
.GetZoom() && !IsPreview() )
2455 MapMode
aMode( pMyWin
->GetMapMode() );
2456 Fraction
aNewFactor( rOpt
.GetZoom(), 100 );
2457 aMode
.SetScaleX( aNewFactor
);
2458 aMode
.SetScaleY( aNewFactor
);
2459 pMyWin
->SetMapMode( aMode
);
2460 // if not a reference device (printer) is used for formatting,
2461 // but the screen, new formatting is needed for zoomfactor changes.
2462 if (mpOpt
->getBrowseMode() || mpOpt
->IsWhitespaceHidden())
2466 bool bBrowseModeChanged
= false;
2467 if( mpOpt
->getBrowseMode() != rOpt
.getBrowseMode() )
2469 bBrowseModeChanged
= true;
2472 else if( mpOpt
->getBrowseMode() && mpOpt
->IsPrtFormat() != rOpt
.IsPrtFormat() )
2475 bool bHideWhitespaceModeChanged
= false;
2476 if (mpOpt
->IsWhitespaceHidden() != rOpt
.IsWhitespaceHidden())
2478 // When whitespace is hidden, view change needs reformatting.
2479 bHideWhitespaceModeChanged
= true;
2483 if ( HasDrawView() || rOpt
.IsGridVisible() )
2485 if ( !HasDrawView() )
2488 SwDrawView
*pDView
= Imp()->GetDrawView();
2489 if ( pDView
->IsDragStripes() != rOpt
.IsCrossHair() )
2490 pDView
->SetDragStripes( rOpt
.IsCrossHair() );
2492 if ( pDView
->IsGridSnap() != rOpt
.IsSnap() )
2493 pDView
->SetGridSnap( rOpt
.IsSnap() );
2495 if ( pDView
->IsGridVisible() != rOpt
.IsGridVisible() )
2496 pDView
->SetGridVisible( rOpt
.IsGridVisible() );
2498 const Size
&rSz
= rOpt
.GetSnapSize();
2499 pDView
->SetGridCoarse( rSz
);
2502 ( rSz
.Width() ? rSz
.Width() / (rOpt
.GetDivisionX()+1) : 0,
2503 rSz
.Height()? rSz
.Height()/ (rOpt
.GetDivisionY()+1) : 0);
2504 pDView
->SetGridFine( aFSize
);
2505 Fraction
aSnGrWdtX(rSz
.Width(), rOpt
.GetDivisionX() + 1);
2506 Fraction
aSnGrWdtY(rSz
.Height(), rOpt
.GetDivisionY() + 1);
2507 pDView
->SetSnapGridWidth( aSnGrWdtX
, aSnGrWdtY
);
2509 // set handle size to 9 pixels, always
2510 pDView
->SetMarkHdlSizePixel(9);
2513 bool bOnlineSpellChgd
= mpOpt
->IsOnlineSpell() != rOpt
.IsOnlineSpell();
2515 *mpOpt
= rOpt
; // First the options are taken.
2516 mpOpt
->SetUIOptions(rOpt
);
2518 mxDoc
->GetDocumentSettingManager().set(DocumentSettingId::HTML_MODE
, 0 != ::GetHtmlMode(mxDoc
->GetDocShell()));
2520 if( bBrowseModeChanged
|| bHideWhitespaceModeChanged
)
2522 // #i44963# Good occasion to check if page sizes in
2523 // page descriptions are still set to (LONG_MAX, LONG_MAX) (html import)
2524 mxDoc
->CheckDefaultPageFormat();
2525 InvalidateLayout( true );
2528 SwXTextDocument
* pModel
= comphelper::getFromUnoTunnel
<SwXTextDocument
>(GetSfxViewShell()->GetCurrentDocument());
2529 SfxLokHelper::notifyViewRenderState(GetSfxViewShell(), pModel
);
2531 pMyWin
->Invalidate();
2534 // Nothing helps, we need to send all ContentFrames a
2535 // Prepare, we format anew:
2536 SwViewShell::StartAction();
2538 SwViewShell::EndAction();
2541 if (isToggleFieldNames
)
2543 for(SwViewShell
& rSh
: GetRingContainer())
2545 if (SwCursorShell
*const pSh
= dynamic_cast<SwCursorShell
*>(&rSh
))
2547 if ((mpOpt
->IsFieldName() && pSh
->CursorInsideInputField())
2548 || IsCursorInFieldmarkHidden(*pSh
->GetCursor(),
2549 pSh
->GetLayout()->GetFieldmarkMode()))
2550 { // move cursor out of field
2551 pSh
->Left(1, SwCursorSkipMode::Chars
);
2555 // the layout changes but SetModified() wasn't called so do it here:
2556 mxDoc
->GetDocumentLayoutManager().ClearSwLayouterEntries();
2559 if( !bOnlineSpellChgd
)
2562 if ( !comphelper::LibreOfficeKit::isActive() )
2564 bool bOnlineSpl
= rOpt
.IsOnlineSpell();
2565 for(SwViewShell
& rSh
: GetRingContainer())
2569 rSh
.mpOpt
->SetOnlineSpell( bOnlineSpl
);
2570 vcl::Window
*pTmpWin
= rSh
.GetWin();
2572 pTmpWin
->Invalidate();
2577 void SwViewShell::SetUIOptions( const SwViewOption
&rOpt
)
2579 mpOpt
->SetUIOptions(rOpt
);
2580 //the API-Flag of the view options is set but never reset
2581 //it is required to set scroll bars in readonly documents
2582 if(rOpt
.IsStarOneSetting())
2583 mpOpt
->SetStarOneSetting(true);
2585 mpOpt
->SetSymbolFont(rOpt
.GetSymbolFont());
2588 void SwViewShell::SetReadonlyOption(bool bSet
)
2590 //JP 01.02.99: at readonly flag query properly
2591 // and if need be format; Bug 61335
2593 // Are we switching from readonly to edit?
2594 if( bSet
== mpOpt
->IsReadonly() )
2597 // so that the flags can be queried properly.
2598 mpOpt
->SetReadonly( false );
2600 bool bReformat
= mpOpt
->IsFieldName();
2602 mpOpt
->SetReadonly( bSet
);
2606 SwViewShell::StartAction();
2608 if ( GetWin() && !comphelper::LibreOfficeKit::isActive() )
2609 GetWin()->Invalidate();
2610 SwViewShell::EndAction();
2612 else if ( GetWin() && !comphelper::LibreOfficeKit::isActive() )
2613 GetWin()->Invalidate();
2614 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
2615 if( Imp()->IsAccessible() )
2616 Imp()->InvalidateAccessibleEditableState( false );
2620 void SwViewShell::SetPDFExportOption(bool bSet
)
2622 if( bSet
!= mpOpt
->IsPDFExport() )
2624 if( bSet
&& mpOpt
->getBrowseMode() )
2625 mpOpt
->SetPrtFormat( true );
2626 mpOpt
->SetPDFExport(bSet
);
2630 void SwViewShell::SetReadonlySelectionOption(bool bSet
)
2632 if( bSet
!= mpOpt
->IsSelectionInReadonly() )
2634 mpOpt
->SetSelectionInReadonly(bSet
);
2638 void SwViewShell::SetPrtFormatOption( bool bSet
)
2640 mpOpt
->SetPrtFormat( bSet
);
2643 void SwViewShell::UISizeNotify()
2645 if ( mbDocSizeChgd
)
2647 mbDocSizeChgd
= false;
2648 bool bOld
= bInSizeNotify
;
2649 bInSizeNotify
= true;
2650 ::SizeNotify( this, GetDocSize() );
2651 bInSizeNotify
= bOld
;
2655 void SwViewShell::SetRestoreActions(sal_uInt16 nSet
)
2657 OSL_ENSURE(!GetRestoreActions()||!nSet
, "multiple restore of the Actions ?");
2658 Imp()->SetRestoreActions(nSet
);
2660 sal_uInt16
SwViewShell::GetRestoreActions() const
2662 return Imp()->GetRestoreActions();
2665 bool SwViewShell::IsNewLayout() const
2667 return GetLayout()->IsNewLayout();
2670 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
2671 uno::Reference
< css::accessibility::XAccessible
> SwViewShell::CreateAccessible()
2673 uno::Reference
< css::accessibility::XAccessible
> xAcc
;
2675 // We require a layout and an XModel to be accessible.
2676 OSL_ENSURE( mpLayout
, "no layout, no access" );
2677 OSL_ENSURE( GetWin(), "no window, no access" );
2679 if( mxDoc
->getIDocumentLayoutAccess().GetCurrentViewShell() && GetWin() )
2680 xAcc
= Imp()->GetAccessibleMap().GetDocumentView();
2685 uno::Reference
< css::accessibility::XAccessible
> SwViewShell::CreateAccessiblePreview()
2687 OSL_ENSURE( IsPreview(),
2688 "Can't create accessible preview for non-preview SwViewShell" );
2690 // We require a layout and an XModel to be accessible.
2691 OSL_ENSURE( mpLayout
, "no layout, no access" );
2692 OSL_ENSURE( GetWin(), "no window, no access" );
2694 if ( IsPreview() && GetLayout()&& GetWin() )
2696 return Imp()->GetAccessibleMap().GetDocumentPreview(
2697 PagePreviewLayout()->maPreviewPages
,
2698 GetWin()->GetMapMode().GetScaleX(),
2699 GetLayout()->GetPageByPageNum( PagePreviewLayout()->mnSelectedPageNum
),
2700 PagePreviewLayout()->maWinSize
);
2705 void SwViewShell::InvalidateAccessibleFocus()
2707 if( Imp() && Imp()->IsAccessible() )
2708 Imp()->GetAccessibleMap().InvalidateFocus();
2712 * invalidate CONTENT_FLOWS_FROM/_TO relation for paragraphs #i27138#
2714 void SwViewShell::InvalidateAccessibleParaFlowRelation( const SwTextFrame
* _pFromTextFrame
,
2715 const SwTextFrame
* _pToTextFrame
)
2717 if ( GetLayout() && GetLayout()->IsAnyShellAccessible() )
2719 Imp()->InvalidateAccessibleParaFlowRelation_( _pFromTextFrame
, _pToTextFrame
);
2724 * invalidate text selection for paragraphs #i27301#
2726 void SwViewShell::InvalidateAccessibleParaTextSelection()
2728 if ( GetLayout() && GetLayout()->IsAnyShellAccessible() )
2730 Imp()->InvalidateAccessibleParaTextSelection_();
2735 * invalidate attributes for paragraphs #i88069#
2737 void SwViewShell::InvalidateAccessibleParaAttrs( const SwTextFrame
& rTextFrame
)
2739 if ( GetLayout() && GetLayout()->IsAnyShellAccessible() )
2741 Imp()->InvalidateAccessibleParaAttrs_( rTextFrame
);
2745 SwAccessibleMap
* SwViewShell::GetAccessibleMap()
2747 if ( Imp()->IsAccessible() )
2749 return &(Imp()->GetAccessibleMap());
2755 void SwViewShell::ApplyAccessibilityOptions()
2757 if (comphelper::IsFuzzing())
2759 if (mpOpt
->IsPagePreview() && !officecfg::Office::Common::Accessibility::IsForPagePreviews::get())
2761 mpAccOptions
->SetAlwaysAutoColor(false);
2762 mpAccOptions
->SetStopAnimatedGraphics(false);
2766 mpAccOptions
->SetAlwaysAutoColor(officecfg::Office::Common::Accessibility::IsAutomaticFontColor::get());
2767 // tdf#161765: Let user choose which animation settings to use: OS's / LO's
2768 // New options: "System"/"No"/"Yes".
2769 // Do respect OS's animation setting if the user has selected the option "System"
2770 mpAccOptions
->SetStopAnimatedGraphics(! MiscSettings::IsAnimatedGraphicAllowed());
2773 // Always set this option, not only if document is read-only:
2774 mpOpt
->SetSelectionInReadonly(officecfg::Office::Common::Accessibility::IsSelectionInReadonly::get());
2777 #endif // ENABLE_WASM_STRIP_ACCESSIBILITY
2779 ShellResource
* SwViewShell::GetShellRes()
2785 void SwViewShell::SetCareDialog(const std::shared_ptr
<weld::Window
>& rNew
)
2787 auto& spCareDialog
= getCareDialog();
2788 (*spCareDialog
.get()) = rNew
;
2792 weld::Window
* SwViewShell::GetCareDialog(SwViewShell
const & rVSh
)
2794 auto& spCareDialog
= getCareDialog();
2795 return (*spCareDialog
.get()) ? spCareDialog
.get()->get() : CareChildWin(rVSh
);
2798 sal_uInt16
SwViewShell::GetPageCount() const
2800 return GetLayout() ? GetLayout()->GetPageNum() : 1;
2803 Size
SwViewShell::GetPageSize( sal_uInt16 nPageNum
, bool bSkipEmptyPages
) const
2806 const SwRootFrame
* pTmpRoot
= GetLayout();
2807 if( pTmpRoot
&& nPageNum
)
2809 const SwPageFrame
* pPage
= static_cast<const SwPageFrame
*>
2810 (pTmpRoot
->Lower());
2812 while( --nPageNum
&& pPage
&& pPage
->GetNext() )
2813 pPage
= static_cast<const SwPageFrame
*>( pPage
->GetNext() );
2815 if( !bSkipEmptyPages
&& pPage
&& pPage
->IsEmptyPage() && pPage
->GetNext() )
2816 pPage
= static_cast<const SwPageFrame
*>( pPage
->GetNext() );
2819 aSize
= pPage
->getFrameArea().SSize();
2824 void SwViewShell::OnGraphicArrived(const SwRect
& rRect
)
2826 for(SwViewShell
& rShell
: GetRingContainer())
2828 CurrShell
aCurr(&rShell
);
2829 if(rShell
.IsPreview())
2832 ::RepaintPagePreview(&rShell
, rRect
);
2834 else if(rShell
.VisArea().Overlaps(rRect
) && OUTDEV_WINDOW
== rShell
.GetOut()->GetOutDevType())
2836 // invalidate instead of painting
2837 rShell
.GetWin()->Invalidate(rRect
.SVRect());
2841 // #i12836# enhanced pdf export
2842 sal_Int32
SwViewShell::GetPageNumAndSetOffsetForPDF( OutputDevice
& rOut
, const SwRect
& rRect
) const
2844 OSL_ENSURE( GetLayout(), "GetPageNumAndSetOffsetForPDF assumes presence of layout" );
2846 sal_Int32 nRet
= -1;
2848 // #i40059# Position out of bounds:
2849 SwRect
aRect( rRect
);
2850 aRect
.Pos().setX( std::max( aRect
.Left(), GetLayout()->getFrameArea().Left() ) );
2852 const SwPageFrame
* pPage
= GetLayout()->GetPageAtPos( aRect
.Center() );
2855 OSL_ENSURE( pPage
, "GetPageNumAndSetOffsetForPDF: No page found" );
2857 Point
aOffset( pPage
->getFrameArea().Pos() );
2858 aOffset
.setX( -aOffset
.X() );
2859 aOffset
.setY( -aOffset
.Y() );
2861 MapMode
aMapMode( rOut
.GetMapMode() );
2862 aMapMode
.SetOrigin( aOffset
);
2863 rOut
.SetMapMode( aMapMode
);
2865 nRet
= pPage
->GetPhyPageNum() - 1;
2871 // --> PB 2007-05-30 #146850#
2872 const BitmapEx
& SwViewShell::GetReplacementBitmap( bool bIsErrorState
)
2877 m_xErrorBmp
.reset(new BitmapEx(RID_GRAPHIC_ERRORBMP
));
2878 return *m_xErrorBmp
;
2882 m_xReplaceBmp
.reset(new BitmapEx(RID_GRAPHIC_REPLACEBMP
));
2883 return *m_xReplaceBmp
;
2886 void SwViewShell::DeleteReplacementBitmaps()
2888 m_xErrorBmp
.reset();
2889 m_xReplaceBmp
.reset();
2892 SwPostItMgr
* SwViewShell::GetPostItMgr()
2894 SwView
* pView
= GetDoc()->GetDocShell() ? GetDoc()->GetDocShell()->GetView() : nullptr;
2896 return pView
->GetPostItMgr();
2901 void SwViewShell::GetFirstLastVisPageNumbers(SwVisiblePageNumbers
& rVisiblePageNumbers
, SwView
& rView
)
2903 SwRect
rViewVisArea(rView
.GetVisArea());
2904 vcl::RenderContext
* pRenderContext
= GetOut();
2905 const SwPageFrame
* pPageFrame
= Imp()->GetFirstVisPage(pRenderContext
);
2906 SwRect rPageRect
= pPageFrame
->getFrameArea();
2907 rPageRect
.AddBottom(-pPageFrame
->GetBottomMargin());
2908 while (!rPageRect
.Overlaps(rViewVisArea
) && pPageFrame
->GetNext())
2910 pPageFrame
= static_cast<const SwPageFrame
*>(pPageFrame
->GetNext());
2911 rPageRect
= pPageFrame
->getFrameArea();
2912 if (rPageRect
.Top() > 0)
2913 rPageRect
.AddBottom(-pPageFrame
->GetBottomMargin());
2915 rVisiblePageNumbers
.nFirstPhy
= pPageFrame
->GetPhyPageNum();
2916 rVisiblePageNumbers
.nFirstVirt
= pPageFrame
->GetVirtPageNum();
2917 const SvxNumberType
& rFirstVisNum
= pPageFrame
->GetPageDesc()->GetNumType();
2918 rVisiblePageNumbers
.sFirstCustomPhy
= rFirstVisNum
.GetNumStr(rVisiblePageNumbers
.nFirstPhy
);
2919 rVisiblePageNumbers
.sFirstCustomVirt
= rFirstVisNum
.GetNumStr(rVisiblePageNumbers
.nFirstVirt
);
2920 pPageFrame
= Imp()->GetLastVisPage(pRenderContext
);
2921 rPageRect
= pPageFrame
->getFrameArea();
2922 rPageRect
.AddTop(pPageFrame
->GetTopMargin());
2923 while (!rPageRect
.Overlaps(rViewVisArea
) && pPageFrame
->GetPrev())
2925 pPageFrame
= static_cast<const SwPageFrame
*>(pPageFrame
->GetPrev());
2926 rPageRect
= pPageFrame
->getFrameArea();
2927 rPageRect
.AddTop(pPageFrame
->GetTopMargin());
2929 rVisiblePageNumbers
.nLastPhy
= pPageFrame
->GetPhyPageNum();
2930 rVisiblePageNumbers
.nLastVirt
= pPageFrame
->GetVirtPageNum();
2931 const SvxNumberType
& rLastVisNum
= pPageFrame
->GetPageDesc()->GetNumType();
2932 rVisiblePageNumbers
.sLastCustomPhy
= rLastVisNum
.GetNumStr(rVisiblePageNumbers
.nLastPhy
);
2933 rVisiblePageNumbers
.sLastCustomVirt
= rLastVisNum
.GetNumStr(rVisiblePageNumbers
.nLastVirt
);
2937 * Document Interface Access
2939 const IDocumentSettingAccess
& SwViewShell::getIDocumentSettingAccess() const { return mxDoc
->GetDocumentSettingManager(); }
2940 IDocumentSettingAccess
& SwViewShell::getIDocumentSettingAccess() { return mxDoc
->GetDocumentSettingManager(); }
2941 const IDocumentDeviceAccess
& SwViewShell::getIDocumentDeviceAccess() const { return mxDoc
->getIDocumentDeviceAccess(); }
2942 IDocumentDeviceAccess
& SwViewShell::getIDocumentDeviceAccess() { return mxDoc
->getIDocumentDeviceAccess(); }
2943 const IDocumentMarkAccess
* SwViewShell::getIDocumentMarkAccess() const { return mxDoc
->getIDocumentMarkAccess(); }
2944 IDocumentMarkAccess
* SwViewShell::getIDocumentMarkAccess() { return mxDoc
->getIDocumentMarkAccess(); }
2945 const IDocumentDrawModelAccess
& SwViewShell::getIDocumentDrawModelAccess() const { return mxDoc
->getIDocumentDrawModelAccess(); }
2946 IDocumentDrawModelAccess
& SwViewShell::getIDocumentDrawModelAccess() { return mxDoc
->getIDocumentDrawModelAccess(); }
2947 const IDocumentRedlineAccess
& SwViewShell::getIDocumentRedlineAccess() const { return mxDoc
->getIDocumentRedlineAccess(); }
2948 IDocumentRedlineAccess
& SwViewShell::getIDocumentRedlineAccess() { return mxDoc
->getIDocumentRedlineAccess(); }
2949 const IDocumentLayoutAccess
& SwViewShell::getIDocumentLayoutAccess() const { return mxDoc
->getIDocumentLayoutAccess(); }
2950 IDocumentLayoutAccess
& SwViewShell::getIDocumentLayoutAccess() { return mxDoc
->getIDocumentLayoutAccess(); }
2951 IDocumentContentOperations
& SwViewShell::getIDocumentContentOperations() { return mxDoc
->getIDocumentContentOperations(); }
2952 IDocumentStylePoolAccess
& SwViewShell::getIDocumentStylePoolAccess() { return mxDoc
->getIDocumentStylePoolAccess(); }
2953 const IDocumentStatistics
& SwViewShell::getIDocumentStatistics() const { return mxDoc
->getIDocumentStatistics(); }
2955 IDocumentUndoRedo
& SwViewShell::GetIDocumentUndoRedo()
2956 { return mxDoc
->GetIDocumentUndoRedo(); }
2957 IDocumentUndoRedo
const& SwViewShell::GetIDocumentUndoRedo() const
2958 { return mxDoc
->GetIDocumentUndoRedo(); }
2960 // --> OD 2007-11-14 #i83479#
2961 const IDocumentListItems
* SwViewShell::getIDocumentListItemsAccess() const
2963 return &mxDoc
->getIDocumentListItems();
2966 const IDocumentOutlineNodes
* SwViewShell::getIDocumentOutlineNodesAccess() const
2968 return &mxDoc
->getIDocumentOutlineNodes();
2971 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */