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 <officecfg/Office/Common.hxx>
21 #include <config_wasm_strip.h>
23 #include <com/sun/star/accessibility/XAccessible.hpp>
24 #include <sfx2/viewfrm.hxx>
25 #include <sfx2/progress.hxx>
26 #include <svx/srchdlg.hxx>
27 #include <sfx2/viewsh.hxx>
28 #include <sfx2/ipclient.hxx>
29 #include <sal/log.hxx>
30 #include <drawdoc.hxx>
34 #include <IDocumentDeviceAccess.hxx>
35 #include <IDocumentDrawModelAccess.hxx>
36 #include <IDocumentOutlineNodes.hxx>
37 #include <IDocumentFieldsAccess.hxx>
38 #include <IDocumentLayoutAccess.hxx>
39 #include <IDocumentState.hxx>
40 #include <rootfrm.hxx>
41 #include <pagefrm.hxx>
42 #include <viewimp.hxx>
43 #include <frmtool.hxx>
44 #include <viewopt.hxx>
46 #include <swregion.hxx>
48 #include <docufld.hxx>
52 #include <fntcache.hxx>
53 #include <ptqueue.hxx>
55 #include <bookmark.hxx>
57 #include <ndindex.hxx>
59 #include <vcl/bitmapex.hxx>
60 #include <svtools/accessibilityoptions.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;
93 vcl::DeleteOnDeinit
<std::shared_ptr
<weld::Window
>> SwViewShell::spCareDialog
{};
95 static bool bInSizeNotify
= false;
98 using namespace ::com::sun::star
;
100 void SwViewShell::SetShowHeaderFooterSeparator( FrameControlType eControl
, bool bShow
) {
102 //tdf#118621 - Optionally disable floating header/footer menu
104 bShow
= GetViewOptions()->IsUseHeaderFooterMenu();
106 if ( eControl
== FrameControlType::Header
)
107 mbShowHeaderSeparator
= bShow
;
109 mbShowFooterSeparator
= bShow
;
112 void SwViewShell::ToggleHeaderFooterEdit()
114 mbHeaderFooterEdit
= !mbHeaderFooterEdit
;
115 if ( !mbHeaderFooterEdit
)
117 SetShowHeaderFooterSeparator( FrameControlType::Header
, false );
118 SetShowHeaderFooterSeparator( FrameControlType::Footer
, false );
122 if ( ( GetViewOptions()->IsUseHeaderFooterMenu() ) &&
123 ( !IsShowHeaderFooterSeparator( FrameControlType::Header
) &&
124 !IsShowHeaderFooterSeparator( FrameControlType::Footer
) ) )
126 mbHeaderFooterEdit
= false;
129 // Repaint everything
130 GetWin()->Invalidate();
133 void SwViewShell::setOutputToWindow(bool bOutputToWindow
)
135 mbOutputToWindow
= bOutputToWindow
;
138 bool SwViewShell::isOutputToWindow() const
140 return mbOutputToWindow
;
143 void SwViewShell::dumpAsXml(xmlTextWriterPtr pWriter
) const
145 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SwViewShell"));
146 (void)xmlTextWriterEndElement(pWriter
);
150 lcl_PaintTransparentFormControls(SwViewShell
const & rShell
, SwRect
const& rRect
)
152 // Direct paint has been performed: the background of transparent child
153 // windows has been painted, so need to paint the child windows now.
156 vcl::Window
& rWindow
= *(rShell
.GetWin());
157 const tools::Rectangle
aRectanglePixel(rShell
.GetOut()->LogicToPixel(rRect
.SVRect()));
158 PaintTransparentChildren(rWindow
, aRectanglePixel
);
162 // #i72754# 2nd set of Pre/PostPaints
163 // This time it uses the lock counter (mPrePostPaintRegions empty/non-empty) to allow only one activation
164 // and deactivation and mpPrePostOutDev to remember the OutDev from the BeginDrawLayers
165 // call. That way, all places where paint take place can be handled the same way, even
166 // when calling other paint methods. This is the case at the places where SW paints
167 // buffered into VDevs to avoid flicker. It is in general problematic and should be
168 // solved once using the BufferedOutput functionality of the DrawView.
170 void SwViewShell::PrePaint()
172 // forward PrePaint event from VCL Window to DrawingLayer
175 Imp()->GetDrawView()->PrePaint();
179 void SwViewShell::DLPrePaint2(const vcl::Region
& rRegion
)
181 if(mPrePostPaintRegions
.empty())
183 mPrePostPaintRegions
.push( rRegion
);
184 // #i75172# ensure DrawView to use DrawingLayer bufferings
185 if ( !HasDrawView() )
188 // Prefer window; if not available, get mpOut (e.g. printer)
189 const bool bWindow
= GetWin() && !comphelper::LibreOfficeKit::isActive() && !isOutputToWindow();
190 mpPrePostOutDev
= bWindow
? GetWin()->GetOutDev() : GetOut();
192 // #i74769# use SdrPaintWindow now direct
193 mpTargetPaintWindow
= Imp()->GetDrawView()->BeginDrawLayers(mpPrePostOutDev
, rRegion
);
194 OSL_ENSURE(mpTargetPaintWindow
, "BeginDrawLayers: Got no SdrPaintWindow (!)");
196 // #i74769# if prerender, save OutDev and redirect to PreRenderDevice
197 if(mpTargetPaintWindow
->GetPreRenderDevice())
199 mpBufferedOut
= mpOut
;
200 mpOut
= &(mpTargetPaintWindow
->GetTargetOutputDevice());
202 else if (isOutputToWindow())
203 // In case mpOut is used without buffering and we're not printing, need to set clipping.
204 mpOut
->SetClipRegion(rRegion
);
206 // remember original paint MapMode for wrapped FlyFrame paints
207 maPrePostMapMode
= mpOut
->GetMapMode();
211 // region needs to be updated to the given one
212 if( mPrePostPaintRegions
.top() != rRegion
)
213 Imp()->GetDrawView()->UpdateDrawLayersRegion(mpPrePostOutDev
, rRegion
);
214 mPrePostPaintRegions
.push( rRegion
);
218 void SwViewShell::DLPostPaint2(bool bPaintFormLayer
)
220 OSL_ENSURE(!mPrePostPaintRegions
.empty(), "SwViewShell::DLPostPaint2: Pre/PostPaint encapsulation broken (!)");
222 if( mPrePostPaintRegions
.size() > 1 )
224 vcl::Region current
= std::move(mPrePostPaintRegions
.top());
225 mPrePostPaintRegions
.pop();
226 if( current
!= mPrePostPaintRegions
.top())
227 Imp()->GetDrawView()->UpdateDrawLayersRegion(mpPrePostOutDev
, mPrePostPaintRegions
.top());
230 mPrePostPaintRegions
.pop(); // clear
231 if(nullptr != mpTargetPaintWindow
)
233 // #i74769# restore buffered OutDev
234 if(mpTargetPaintWindow
->GetPreRenderDevice())
236 mpOut
= mpBufferedOut
;
239 // #i74769# use SdrPaintWindow now direct
240 Imp()->GetDrawView()->EndDrawLayers(*mpTargetPaintWindow
, bPaintFormLayer
);
241 mpTargetPaintWindow
= nullptr;
244 // end of Pre/PostPaints
246 void SwViewShell::ImplEndAction( const bool bIdleEnd
)
248 // Nothing to do for the printer?
249 if ( !GetWin() || IsPreview() )
253 // tdf#101464 print preview may generate events if another view shell
254 // performs layout...
255 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
256 if (IsPreview() && Imp()->IsAccessible())
258 Imp()->FireAccessibleEvents();
264 mbInEndAction
= true;
265 //will this put the EndAction of the last shell in the sequence?
267 SwViewShell::sbLstAct
= true;
268 for(SwViewShell
& rShell
: GetRingContainer())
270 if(&rShell
!= this && rShell
.ActionPend())
272 SwViewShell::sbLstAct
= false;
277 const bool bIsShellForCheckViewLayout
= ( this == GetLayout()->GetCurrShell() );
279 CurrShell
aCurr( this );
280 if ( Imp()->HasDrawView() && !Imp()->GetDrawView()->areMarkHandlesHidden() )
281 Imp()->StartAction();
283 if ( Imp()->HasPaintRegion() && Imp()->GetPaintRegion()->GetOrigin() != VisArea() )
284 Imp()->DeletePaintRegion();
286 const bool bExtraData
= ::IsExtraData( GetDoc() );
290 SwLayAction
aAction( GetLayout(), Imp() );
291 aAction
.SetComplete( false );
293 aAction
.SetPaint( false );
294 aAction
.SetInputType( VclInputFlags::KEYBOARD
);
295 aAction
.Action(GetWin()->GetOutDev());
298 if ( bIsShellForCheckViewLayout
)
299 GetLayout()->CheckViewLayout( GetViewOptions(), &maVisArea
);
301 //If we don't call Paints, we wait for the Paint of the system.
302 //Then the clipping is set correctly; e.g. shifting of a Draw object
303 if ( Imp()->HasPaintRegion() ||
304 maInvalidRect
.HasArea() ||
309 SolarMutexGuard aGuard
;
311 bool bPaintsFromSystem
= maInvalidRect
.HasArea();
312 GetWin()->PaintImmediately();
313 if ( maInvalidRect
.HasArea() )
315 if ( bPaintsFromSystem
)
316 Imp()->AddPaintRect( maInvalidRect
);
319 bPaintsFromSystem
= true;
323 std::optional
<SwRegionRects
> oRegion
= Imp()->TakePaintRegion();
325 //JP 27.11.97: what hid the selection, must also Show it,
326 // else we get Paint errors!
327 // e.g. additional mode, page half visible vertically, in the
328 // middle a selection and with another cursor jump to left
329 // right border. Without ShowCursor the selection disappears.
330 bool bShowCursor
= oRegion
&& dynamic_cast<const SwCursorShell
*>(this) != nullptr;
332 static_cast<SwCursorShell
*>(this)->HideCursors();
336 SwRootFrame
* pCurrentLayout
= GetLayout();
338 oRegion
->LimitToOrigin();
339 oRegion
->Compress( SwRegionRects::CompressFuzzy
);
341 while ( !oRegion
->empty() )
343 SwRect
aRect( oRegion
->back() );
346 if (GetWin()->SupportsDoubleBuffering())
347 InvalidateWindows(aRect
);
350 // #i75172# begin DrawingLayer paint
351 // need to do begin/end DrawingLayer preparation for each single rectangle of the
352 // repaint region. I already tried to prepare only once for the whole Region. This
353 // seems to work (and does technically) but fails with transparent objects. Since the
354 // region given to BeginDrawLayers() defines the clip region for DrawingLayer paint,
355 // transparent objects in the single rectangles will indeed be painted multiple times.
356 if (!comphelper::LibreOfficeKit::isActive())
358 DLPrePaint2(vcl::Region(aRect
.SVRect()));
361 if ( bPaintsFromSystem
)
362 PaintDesktop(*GetOut(), aRect
);
363 if (!comphelper::LibreOfficeKit::isActive())
364 pCurrentLayout
->PaintSwFrame( *mpOut
, aRect
);
366 pCurrentLayout
->GetCurrShell()->InvalidateWindows(aRect
);
368 // #i75172# end DrawingLayer paint
369 if (!comphelper::LibreOfficeKit::isActive())
375 lcl_PaintTransparentFormControls(*this, aRect
); // i#107365
379 static_cast<SwCursorShell
*>(this)->ShowCursors( true );
383 Imp()->DeletePaintRegion();
390 mbInEndAction
= false;
391 SwViewShell::sbLstAct
= false;
394 //We artificially end the action here to enable the automatic scrollbars
395 //to adjust themselves correctly
396 //EndAction sends a Notify, and that must call Start-/EndAction to
397 //adjust the scrollbars correctly
402 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
403 if( Imp()->IsAccessible() )
404 Imp()->FireAccessibleEvents();
408 void SwViewShell::ImplStartAction()
410 mbPaintWorks
= false;
411 Imp()->StartAction();
414 void SwViewShell::ImplLockPaint()
416 if ( GetWin() && GetWin()->IsVisible() && !comphelper::LibreOfficeKit::isActive())
417 GetWin()->EnablePaint( false ); //Also cut off the controls.
421 void SwViewShell::ImplUnlockPaint(std::vector
<LockPaintReason
>& rReasons
, bool bVirDev
)
423 CurrShell
aCurr( this );
424 if ( GetWin() && GetWin()->IsVisible() )
426 if ( (bInSizeNotify
|| bVirDev
) && VisArea().HasArea() && !comphelper::LibreOfficeKit::isActive())
428 //Refresh with virtual device to avoid flickering.
429 VclPtrInstance
<VirtualDevice
> pVout( *mpOut
);
430 pVout
->SetMapMode( mpOut
->GetMapMode() );
431 Size
aSize( VisArea().SSize() );
432 aSize
.AdjustWidth(20 );
433 aSize
.AdjustHeight(20 );
434 if( pVout
->SetOutputSize( aSize
) )
436 GetWin()->EnablePaint( true );
437 GetWin()->Validate();
439 Imp()->UnlockPaint();
440 pVout
->SetLineColor( mpOut
->GetLineColor() );
441 pVout
->SetFillColor( mpOut
->GetFillColor() );
443 // #i72754# start Pre/PostPaint encapsulation before mpOut is changed to the buffering VDev
444 const vcl::Region
aRepaintRegion(VisArea().SVRect());
445 DLPrePaint2(aRepaintRegion
);
447 OutputDevice
*pOld
= mpOut
;
449 Paint(*mpOut
, VisArea().SVRect());
451 mpOut
->DrawOutDev( VisArea().Pos(), aSize
,
452 VisArea().Pos(), aSize
, *pVout
);
454 // #i72754# end Pre/PostPaint encapsulation when mpOut is back and content is painted
457 lcl_PaintTransparentFormControls(*this, VisArea()); // fdo#63949
461 Imp()->UnlockPaint();
462 GetWin()->EnablePaint( true );
463 InvalidateAll(rReasons
);
465 pVout
.disposeAndClear();
469 Imp()->UnlockPaint();
470 GetWin()->EnablePaint( true );
471 InvalidateAll(rReasons
);
475 Imp()->UnlockPaint();
480 std::string_view
to_string(LockPaintReason eReason
)
484 case LockPaintReason::ViewLayout
:
486 case LockPaintReason::OuterResize
:
487 return "OuterResize";
488 case LockPaintReason::Undo
:
490 case LockPaintReason::Redo
:
492 case LockPaintReason::OutlineFolding
:
493 return "OutlineFolding";
494 case LockPaintReason::EndSdrCreate
:
495 return "EndSdrCreate";
496 case LockPaintReason::SwLayIdle
:
498 case LockPaintReason::InvalidateLayout
:
499 return "InvalidateLayout";
500 case LockPaintReason::StartDrag
:
502 case LockPaintReason::DataChanged
:
503 return "DataChanged";
504 case LockPaintReason::InsertFrame
:
505 return "InsertFrame";
506 case LockPaintReason::GotoPage
:
508 case LockPaintReason::InsertGraphic
:
509 return "InsertGraphic";
510 case LockPaintReason::SetZoom
:
512 case LockPaintReason::ExampleFrame
:
513 return "ExampleFram";
519 void SwViewShell::InvalidateAll(std::vector
<LockPaintReason
>& rReasons
)
521 assert(!rReasons
.empty() && "there must be a reason to InvalidateAll");
523 for (const auto& reason
: rReasons
)
524 SAL_INFO("sw.core", "InvalidateAll because of: " << to_string(reason
));
526 if (comphelper::LibreOfficeKit::isActive())
528 // https://github.com/CollaboraOnline/online/issues/6379
529 // ditch OuterResize as a reason to invalidate all in the online case
530 rReasons
.erase(std::remove(rReasons
.begin(), rReasons
.end(), LockPaintReason::OuterResize
), rReasons
.end());
533 if (!rReasons
.empty())
534 GetWin()->Invalidate(InvalidateFlags::Children
);
538 bool SwViewShell::AddPaintRect( const SwRect
& rRect
)
541 for(SwViewShell
& rSh
: GetRingContainer())
545 if ( rSh
.IsPreview() && rSh
.GetWin() )
546 ::RepaintPagePreview( &rSh
, rRect
);
548 bRet
|= rSh
.Imp()->AddPaintRect( rRect
);
554 void SwViewShell::InvalidateWindows( const SwRect
&rRect
)
556 if ( Imp()->IsCalcLayoutProgress() )
559 if(comphelper::LibreOfficeKit::isActive())
561 // If we are inside tiled painting, invalidations are ignored.
562 // Ignore them right now to save work, but also to avoid the problem
563 // that this state could be reset before FlushPendingLOKInvalidateTiles()
565 if(comphelper::LibreOfficeKit::isTiledPainting())
567 // First collect all invalidations and perform them only later,
568 // otherwise the number of Invalidate() calls would be at least
569 // O(n^2) if not worse. The problem is that if any change in a document
570 // is made, SwEditShell::EndAllAction() is called, which calls EndAction()
571 // for every view. And every view does it own handling of paint rectangles,
572 // and then calls InvalidateWindows() based on that. On then this code
573 // would call Invalidate() for all views for each rectangle.
574 // So collect the rectangles, avoid duplicates (which there usually will
575 // be many because of the repetitions), FlushPendingLOKInvalidateTiles()
576 // will collect all rectangles from all related views, compress them
577 // and only with those relatively few rectangle it'd call Invalidate()
579 Imp()->AddPendingLOKInvalidation(rRect
);
583 for(SwViewShell
& rSh
: GetRingContainer())
587 if ( rSh
.IsPreview() )
588 ::RepaintPagePreview( &rSh
, rRect
);
589 // In case of tiled rendering, invalidation is wanted even if
590 // the rectangle is outside the visual area.
591 else if ( rSh
.VisArea().Overlaps( rRect
) || comphelper::LibreOfficeKit::isActive() )
592 rSh
.GetWin()->Invalidate( rRect
.SVRect() );
597 void SwViewShell::FlushPendingLOKInvalidateTiles()
599 assert(comphelper::LibreOfficeKit::isActive());
601 for(SwViewShell
& rSh
: GetRingContainer())
603 std::vector
<SwRect
> tmpRects
= rSh
.Imp()->TakePendingLOKInvalidations();
604 rects
.insert( rects
.end(), tmpRects
.begin(), tmpRects
.end());
606 rects
.Compress( SwRegionRects::CompressFuzzy
);
609 // This is basically the loop from SwViewShell::InvalidateWindows().
610 for(SwViewShell
& rSh
: GetRingContainer())
614 if ( rSh
.IsPreview() )
616 for( const SwRect
& rect
: rects
)
617 ::RepaintPagePreview( &rSh
, rect
);
621 for( const SwRect
& rect
: rects
)
622 rSh
.GetWin()->Invalidate( rect
.SVRect() );
628 const SwRect
& SwViewShell::VisArea() const
630 // when using the tiled rendering, consider the entire document as our
632 return comphelper::LibreOfficeKit::isActive()? GetLayout()->getFrameArea(): maVisArea
;
635 void SwViewShell::MakeVisible( const SwRect
&rRect
)
637 if ( !(!VisArea().Contains( rRect
) || IsScrollMDI( this, rRect
) || GetCareDialog(*this)) )
640 if ( IsViewLocked() )
645 const SwFrame
* pRoot
= GetLayout();
649 nOldH
= pRoot
->getFrameArea().Height();
651 ScrollMDI( this, rRect
, USHRT_MAX
, USHRT_MAX
);
653 } while( nOldH
!= pRoot
->getFrameArea().Height() && nLoopCnt
-- );
655 #if OSL_DEBUG_LEVEL > 0
658 //MA: 04. Nov. 94, no one needs this, does one?
659 OSL_ENSURE( false, "Is MakeVisible still needed for printers?" );
665 weld::Window
* SwViewShell::CareChildWin(SwViewShell
const & rVSh
)
667 if (!rVSh
.mpSfxViewShell
)
669 #if HAVE_FEATURE_DESKTOP
670 const sal_uInt16 nId
= SvxSearchDialogWrapper::GetChildWindowId();
671 SfxViewFrame
& rVFrame
= rVSh
.mpSfxViewShell
->GetViewFrame();
672 SfxChildWindow
* pChWin
= rVFrame
.GetChildWindow( nId
);
675 weld::DialogController
* pController
= pChWin
->GetController().get();
678 weld::Window
* pWin
= pController
->getDialog();
679 if (pWin
&& pWin
->get_visible())
685 Point
SwViewShell::GetPagePos( sal_uInt16 nPageNum
) const
687 return GetLayout()->GetPagePos( nPageNum
);
690 sal_uInt16
SwViewShell::GetNumPages() const
692 //It is possible that no layout exists when the method from
693 //root-Ctor is called.
694 return GetLayout() ? GetLayout()->GetPageNum() : 0;
697 bool SwViewShell::IsDummyPage( sal_uInt16 nPageNum
) const
699 return GetLayout() && GetLayout()->IsDummyPage( nPageNum
);
703 * Forces update of each field.
704 * It notifies all fields with pNewHt. If that is 0 (default), the field
705 * type is sent (???).
706 * @param[in] bCloseDB Passed in to GetDoc()->UpdateFields. [TODO] Purpose???
708 void SwViewShell::UpdateFields(bool bCloseDB
)
710 CurrShell
aCurr( this );
712 auto pCursorShell
= dynamic_cast<SwCursorShell
*>( this );
714 pCursorShell
->StartAction();
718 GetDoc()->getIDocumentFieldsAccess().UpdateFields(bCloseDB
);
721 pCursorShell
->EndAction();
726 void SwViewShell::UpdateOleObjectPreviews()
728 SwDoc
* pDoc
= GetDoc();
729 for(sw::SpzFrameFormat
* pFormat
: *pDoc
->GetSpzFrameFormats())
731 if (pFormat
->Which() != RES_FLYFRMFMT
)
736 const SwNodeIndex
* pNodeIndex
= pFormat
->GetContent().GetContentIdx();
737 if (!pNodeIndex
|| !pNodeIndex
->GetNodes().IsDocNodes())
742 SwNode
* pNode
= pDoc
->GetNodes()[pNodeIndex
->GetIndex() + 1];
743 SwOLENode
* pOleNode
= pNode
->GetOLENode();
749 SwOLEObj
& rOleObj
= pOleNode
->GetOLEObj();
750 svt::EmbeddedObjectRef
& rObject
= rOleObj
.GetObject();
751 rObject
.UpdateReplacement( true );
752 // Trigger the repaint.
753 pOleNode
->SetChanged();
757 /** update all charts for which any table exists */
758 void SwViewShell::UpdateAllCharts()
760 CurrShell
aCurr( this );
761 // Start-/EndAction handled in the SwDoc-Method!
762 GetDoc()->UpdateAllCharts();
765 bool SwViewShell::HasCharts() const
768 SwNodeIndex
aIdx( *GetDoc()->GetNodes().GetEndOfAutotext().
769 StartOfSectionNode(), 1 );
770 while (aIdx
.GetNode().GetStartNode())
773 const SwOLENode
*pNd
= aIdx
.GetNode().GetOLENode();
774 if( pNd
&& !pNd
->GetChartTableName().isEmpty() )
783 void SwViewShell::LayoutIdle()
785 if( !mpOpt
->IsIdle() || !GetWin() || HasDrawViewDrag() )
788 //No idle when printing is going on.
789 for(const SwViewShell
& rSh
: GetRingContainer())
795 CurrShell
aCurr( this );
798 // If Test5 has been set, the IdleFormatter is disabled.
799 if( mpOpt
->IsTest5() )
804 // Preserve top of the text frame cache.
805 SwSaveSetLRUOfst aSaveLRU
;
806 // #125243# there are lots of stacktraces indicating that Imp() returns NULL
807 // this SwViewShell seems to be invalid - but it's not clear why
808 // this return is only a workaround!
809 OSL_ENSURE(Imp(), "SwViewShell already deleted?");
812 SwLayIdle
aIdle( GetLayout(), Imp() );
816 static void lcl_InvalidateAllContent( SwViewShell
& rSh
, SwInvalidateFlags nInv
)
818 auto pCursorShell
= dynamic_cast<SwCursorShell
*>( &rSh
);
820 pCursorShell
->StartAction();
823 rSh
.GetLayout()->InvalidateAllContent( nInv
);
825 pCursorShell
->EndAction();
829 rSh
.GetDoc()->getIDocumentState().SetModified();
832 /** local method to invalidate/re-calculate positions of floating screen
833 * objects (Writer fly frame and drawing objects), which are anchored
834 * to paragraph or to character. #i11860#
836 static void lcl_InvalidateAllObjPos( SwViewShell
&_rSh
)
838 auto pCursorShell
= dynamic_cast<SwCursorShell
*>( &_rSh
);
840 pCursorShell
->StartAction();
844 _rSh
.GetLayout()->InvalidateAllObjPos();
847 pCursorShell
->EndAction();
851 _rSh
.GetDoc()->getIDocumentState().SetModified();
854 void SwViewShell::SetParaSpaceMax( bool bNew
)
856 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
857 if( rIDSA
.get(DocumentSettingId::PARA_SPACE_MAX
) != bNew
)
859 SwWait
aWait( *GetDoc()->GetDocShell(), true );
860 rIDSA
.set(DocumentSettingId::PARA_SPACE_MAX
, bNew
);
861 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Table
| SwInvalidateFlags::Section
;
862 lcl_InvalidateAllContent( *this, nInv
);
866 void SwViewShell::SetParaSpaceMaxAtPages( bool bNew
)
868 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
869 if( rIDSA
.get(DocumentSettingId::PARA_SPACE_MAX_AT_PAGES
) != bNew
)
871 SwWait
aWait( *GetDoc()->GetDocShell(), true );
872 rIDSA
.set(DocumentSettingId::PARA_SPACE_MAX_AT_PAGES
, bNew
);
873 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Table
| SwInvalidateFlags::Section
;
874 lcl_InvalidateAllContent( *this, nInv
);
878 void SwViewShell::SetTabCompat( bool bNew
)
880 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
881 if( rIDSA
.get(DocumentSettingId::TAB_COMPAT
) != bNew
)
883 SwWait
aWait( *GetDoc()->GetDocShell(), true );
884 rIDSA
.set(DocumentSettingId::TAB_COMPAT
, bNew
);
885 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Size
| SwInvalidateFlags::Table
| SwInvalidateFlags::Section
;
886 lcl_InvalidateAllContent( *this, nInv
);
890 void SwViewShell::SetAddExtLeading( bool bNew
)
892 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
893 if ( rIDSA
.get(DocumentSettingId::ADD_EXT_LEADING
) != bNew
)
895 SwWait
aWait( *GetDoc()->GetDocShell(), true );
896 rIDSA
.set(DocumentSettingId::ADD_EXT_LEADING
, bNew
);
897 SwDrawModel
* pTmpDrawModel
= getIDocumentDrawModelAccess().GetDrawModel();
899 pTmpDrawModel
->SetAddExtLeading( bNew
);
900 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Size
| SwInvalidateFlags::Table
| SwInvalidateFlags::Section
;
901 lcl_InvalidateAllContent( *this, nInv
);
905 /** Sets if paragraph and table spacing is added at bottom of table cells.
907 * @param[in] (bool) setting of the new value
909 void SwViewShell::SetAddParaSpacingToTableCells( bool _bAddParaSpacingToTableCells
)
911 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
912 if (rIDSA
.get(DocumentSettingId::ADD_PARA_SPACING_TO_TABLE_CELLS
) != _bAddParaSpacingToTableCells
913 || rIDSA
.get(DocumentSettingId::ADD_PARA_LINE_SPACING_TO_TABLE_CELLS
) != _bAddParaSpacingToTableCells
)
915 SwWait
aWait( *GetDoc()->GetDocShell(), true );
916 rIDSA
.set(DocumentSettingId::ADD_PARA_SPACING_TO_TABLE_CELLS
, _bAddParaSpacingToTableCells
);
917 // note: the dialog can't change the value to indeterminate, so only false/false and true/true
918 rIDSA
.set(DocumentSettingId::ADD_PARA_LINE_SPACING_TO_TABLE_CELLS
, _bAddParaSpacingToTableCells
);
919 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
;
920 lcl_InvalidateAllContent( *this, nInv
);
925 * Sets if former formatting of text lines with proportional line spacing should used.
927 * @param[in] (bool) setting of the new value
929 void SwViewShell::SetUseFormerLineSpacing( bool _bUseFormerLineSpacing
)
931 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
932 if ( rIDSA
.get(DocumentSettingId::OLD_LINE_SPACING
) != _bUseFormerLineSpacing
)
934 SwWait
aWait( *GetDoc()->GetDocShell(), true );
935 rIDSA
.set(DocumentSettingId::OLD_LINE_SPACING
, _bUseFormerLineSpacing
);
936 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
;
937 lcl_InvalidateAllContent( *this, nInv
);
942 * Sets IDocumentSettingAccess if former object positioning should be used.
944 * @param[in] (bool) setting the new value
946 void SwViewShell::SetUseFormerObjectPositioning( bool _bUseFormerObjPos
)
948 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
949 if ( rIDSA
.get(DocumentSettingId::USE_FORMER_OBJECT_POS
) != _bUseFormerObjPos
)
951 SwWait
aWait( *GetDoc()->GetDocShell(), true );
952 rIDSA
.set(DocumentSettingId::USE_FORMER_OBJECT_POS
, _bUseFormerObjPos
);
953 lcl_InvalidateAllObjPos( *this );
958 void SwViewShell::SetConsiderWrapOnObjPos( bool _bConsiderWrapOnObjPos
)
960 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
961 if ( rIDSA
.get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION
) != _bConsiderWrapOnObjPos
)
963 SwWait
aWait( *GetDoc()->GetDocShell(), true );
964 rIDSA
.set(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION
, _bConsiderWrapOnObjPos
);
965 lcl_InvalidateAllObjPos( *this );
969 void SwViewShell::SetUseFormerTextWrapping( bool _bUseFormerTextWrapping
)
971 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
972 if ( rIDSA
.get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING
) != _bUseFormerTextWrapping
)
974 SwWait
aWait( *GetDoc()->GetDocShell(), true );
975 rIDSA
.set(DocumentSettingId::USE_FORMER_TEXT_WRAPPING
, _bUseFormerTextWrapping
);
976 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Size
| SwInvalidateFlags::Table
| SwInvalidateFlags::Section
;
977 lcl_InvalidateAllContent( *this, nInv
);
982 void SwViewShell::SetDoNotJustifyLinesWithManualBreak( bool _bDoNotJustifyLinesWithManualBreak
)
984 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
985 if ( rIDSA
.get(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK
) != _bDoNotJustifyLinesWithManualBreak
)
987 SwWait
aWait( *GetDoc()->GetDocShell(), true );
988 rIDSA
.set(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK
, _bDoNotJustifyLinesWithManualBreak
);
989 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Size
| SwInvalidateFlags::Table
| SwInvalidateFlags::Section
;
990 lcl_InvalidateAllContent( *this, nInv
);
994 void SwViewShell::SetProtectForm( bool _bProtectForm
)
996 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
997 rIDSA
.set(DocumentSettingId::PROTECT_FORM
, _bProtectForm
);
1000 void SwViewShell::SetMsWordCompTrailingBlanks( bool _bMsWordCompTrailingBlanks
)
1002 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1003 if (rIDSA
.get(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS
) != _bMsWordCompTrailingBlanks
)
1005 SwWait
aWait(*GetDoc()->GetDocShell(), true);
1006 rIDSA
.set(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS
, _bMsWordCompTrailingBlanks
);
1007 const SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Size
| SwInvalidateFlags::Table
| SwInvalidateFlags::Section
;
1008 lcl_InvalidateAllContent(*this, nInv
);
1012 void SwViewShell::SetSubtractFlysAnchoredAtFlys(bool bSubtractFlysAnchoredAtFlys
)
1014 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1015 rIDSA
.set(DocumentSettingId::SUBTRACT_FLYS
, bSubtractFlysAnchoredAtFlys
);
1018 void SwViewShell::SetEmptyDbFieldHidesPara(bool bEmptyDbFieldHidesPara
)
1020 IDocumentSettingAccess
& rIDSA
= getIDocumentSettingAccess();
1021 if (rIDSA
.get(DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA
) == bEmptyDbFieldHidesPara
)
1024 SwWait
aWait(*GetDoc()->GetDocShell(), true);
1025 rIDSA
.set(DocumentSettingId::EMPTY_DB_FIELD_HIDES_PARA
, bEmptyDbFieldHidesPara
);
1027 GetDoc()->getIDocumentState().SetModified();
1028 for (auto const & pFieldType
: *GetDoc()->getIDocumentFieldsAccess().GetFieldTypes())
1030 if(pFieldType
->Which() == SwFieldIds::Database
)
1031 pFieldType
->UpdateFields();
1036 void SwViewShell::Reformat()
1038 SwWait
aWait( *GetDoc()->GetDocShell(), true );
1040 // we go for safe: get rid of the old font information,
1041 // when the printer resolution or zoom factor changes.
1042 // Init() and Reformat() are the safest locations.
1043 pFntCache
->Flush( );
1045 if( GetLayout()->IsCallbackActionEnabled() )
1048 GetLayout()->InvalidateAllContent( SwInvalidateFlags::Size
| SwInvalidateFlags::Pos
| SwInvalidateFlags::PrtArea
);
1053 void SwViewShell::ChgNumberDigits()
1055 SdrModel
* pTmpDrawModel
= getIDocumentDrawModelAccess().GetDrawModel();
1056 if ( pTmpDrawModel
)
1057 pTmpDrawModel
->ReformatAllTextObjects();
1061 void SwViewShell::CalcLayout()
1063 // extremely likely to be a Bad Idea to call this without StartAction
1064 // (except the Page Preview apparently only has a non-subclassed ViewShell)
1065 assert((typeid(*this) == typeid(SwViewShell
)) || mnStartAction
);
1067 CurrShell
aCurr( this );
1068 SwWait
aWait( *GetDoc()->GetDocShell(), true );
1070 // Preserve top of the text frame cache.
1071 SwSaveSetLRUOfst aSaveLRU
;
1073 //switch on Progress when none is running yet.
1074 const bool bEndProgress
= SfxProgress::GetActiveProgress( GetDoc()->GetDocShell() ) == nullptr;
1077 tools::Long nEndPage
= GetLayout()->GetPageNum();
1078 nEndPage
+= nEndPage
* 10 / 100;
1079 ::StartProgress( STR_STATSTR_REFORMAT
, 0, nEndPage
, GetDoc()->GetDocShell() );
1082 SwLayAction
aAction( GetLayout(), Imp() );
1083 aAction
.SetPaint( false );
1084 aAction
.SetStatBar( true );
1085 aAction
.SetCalcLayout( true );
1086 aAction
.SetReschedule( true );
1087 GetDoc()->getIDocumentFieldsAccess().LockExpFields();
1088 aAction
.Action(GetOut());
1089 GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
1091 //the SetNewFieldLst() on the Doc was cut off and must be fetched again
1092 //(see flowfrm.cxx, txtfld.cxx)
1093 if ( aAction
.IsExpFields() )
1096 aAction
.SetPaint( false );
1097 aAction
.SetStatBar( true );
1098 aAction
.SetReschedule( true );
1100 GetDoc()->getIDocumentFieldsAccess().UpdatePageFields(0);
1101 GetDoc()->getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
1103 aAction
.Action(GetOut());
1106 if ( VisArea().HasArea() )
1107 InvalidateWindows( VisArea() );
1109 ::EndProgress( GetDoc()->GetDocShell() );
1112 void SwViewShell::SetFirstVisPageInvalid()
1114 for(SwViewShell
& rSh
: GetRingContainer())
1117 rSh
.Imp()->SetFirstVisPageInvalid();
1121 void SwViewShell::SizeChgNotify()
1124 mbDocSizeChgd
= true;
1125 else if( ActionPend() || Imp()->IsCalcLayoutProgress() || mbPaintInProgress
)
1127 mbDocSizeChgd
= true;
1129 if ( !Imp()->IsCalcLayoutProgress() && dynamic_cast<const SwCursorShell
*>( this ) != nullptr )
1131 PageNumNotify(this);
1133 if (comphelper::LibreOfficeKit::isActive())
1135 Size aDocSize
= GetDocSize();
1136 OString sPayload
= OString::number(aDocSize
.Width() + 2 * DOCUMENTBORDER
) +
1137 ", " + OString::number(aDocSize
.Height() + 2 * DOCUMENTBORDER
);
1139 SwXTextDocument
* pModel
= comphelper::getFromUnoTunnel
<SwXTextDocument
>(GetSfxViewShell()->GetCurrentDocument());
1140 SfxLokHelper::notifyDocumentSizeChanged(GetSfxViewShell(), sPayload
, pModel
);
1146 mbDocSizeChgd
= false;
1147 ::SizeNotify( this, GetDocSize() );
1151 void SwViewShell::VisPortChgd( const SwRect
&rRect
)
1153 OSL_ENSURE( GetWin(), "VisPortChgd without Window." );
1155 if ( rRect
== VisArea() )
1158 // Is someone spuriously rescheduling again?
1159 SAL_WARN_IF(mbInEndAction
, "sw.core", "Scrolling during EndAction");
1161 //First get the old visible page, so we don't have to look
1162 //for it afterwards.
1163 const SwFrame
*pOldPage
= Imp()->GetFirstVisPage(GetWin()->GetOutDev());
1165 const SwRect
aPrevArea( VisArea() );
1166 const bool bFull
= aPrevArea
.IsEmpty();
1168 SetFirstVisPageInvalid();
1170 //When there a PaintRegion still exists and the VisArea has changed,
1171 //the PaintRegion is at least by now obsolete. The PaintRegion can
1172 //have been created by RootFrame::PaintSwFrame.
1173 if ( !mbInEndAction
&&
1174 Imp()->HasPaintRegion() && Imp()->GetPaintRegion()->GetOrigin() != VisArea() )
1175 Imp()->DeletePaintRegion();
1177 CurrShell
aCurr( this );
1179 bool bScrolled
= false;
1181 SwPostItMgr
* pPostItMgr
= GetPostItMgr();
1184 GetWin()->Invalidate();
1187 //Calculate amount to be scrolled.
1188 const tools::Long nXDiff
= aPrevArea
.Left() - VisArea().Left();
1189 const tools::Long nYDiff
= aPrevArea
.Top() - VisArea().Top();
1191 if( !nXDiff
&& !GetViewOptions()->getBrowseMode() &&
1192 (!Imp()->HasDrawView() || !Imp()->GetDrawView()->IsGridVisible() ) )
1194 // If possible, don't scroll the application background
1195 // (PaintDesktop). Also limit the left and right side of
1196 // the scroll range to the pages.
1197 const SwPageFrame
*pPage
= static_cast<SwPageFrame
*>(GetLayout()->Lower());
1198 if ( pPage
->getFrameArea().Top() > pOldPage
->getFrameArea().Top() )
1199 pPage
= static_cast<const SwPageFrame
*>(pOldPage
);
1200 SwRect
aBoth( VisArea() );
1201 aBoth
.Union( aPrevArea
);
1202 const SwTwips nBottom
= aBoth
.Bottom();
1203 SwTwips nMinLeft
= SAL_MAX_INT32
;
1204 SwTwips nMaxRight
= 0;
1206 const bool bBookMode
= GetViewOptions()->IsViewLayoutBookMode();
1208 while ( pPage
&& pPage
->getFrameArea().Top() <= nBottom
)
1210 SwRect
aPageRect( pPage
->GetBoundRect(GetWin()->GetOutDev()) );
1213 const SwPageFrame
& rFormatPage
= pPage
->GetFormatPage();
1214 aPageRect
.SSize( rFormatPage
.GetBoundRect(GetWin()->GetOutDev()).SSize() );
1217 // #i9719# - consider new border and shadow width
1218 if ( aPageRect
.Overlaps( aBoth
) )
1220 SwTwips nPageLeft
= 0;
1221 SwTwips nPageRight
= 0;
1222 const sw::sidebarwindows::SidebarPosition aSidebarPos
= pPage
->SidebarPosition();
1224 if( aSidebarPos
!= sw::sidebarwindows::SidebarPosition::NONE
)
1226 nPageLeft
= aPageRect
.Left();
1227 nPageRight
= aPageRect
.Right();
1230 if( nPageLeft
< nMinLeft
)
1231 nMinLeft
= nPageLeft
;
1232 if( nPageRight
> nMaxRight
)
1233 nMaxRight
= nPageRight
;
1234 //match with the draw objects
1235 //take nOfst into account as the objects have been
1236 //selected and have handles attached.
1237 if ( pPage
->GetSortedObjs() )
1239 const tools::Long nOfst
= GetOut()->PixelToLogic(
1240 Size(Imp()->GetDrawView()->GetMarkHdlSizePixel()/2,0)).Width();
1241 for (SwAnchoredObject
* pObj
: *pPage
->GetSortedObjs())
1243 // ignore objects that are not actually placed on the page
1244 if (pObj
->IsFormatPossible())
1246 const tools::Rectangle
&rBound
= pObj
->GetObjRect().SVRect();
1247 if (rBound
.Left() != FAR_AWAY
) {
1248 // OD 03.03.2003 #107927# - use correct datatype
1249 const SwTwips nL
= std::max( SwTwips(0), SwTwips(rBound
.Left() - nOfst
) );
1250 if ( nL
< nMinLeft
)
1252 if( rBound
.Right() + nOfst
> nMaxRight
)
1253 nMaxRight
= rBound
.Right() + nOfst
;
1259 pPage
= static_cast<const SwPageFrame
*>(pPage
->GetNext());
1261 tools::Rectangle
aRect( aPrevArea
.SVRect() );
1262 aRect
.SetLeft( nMinLeft
);
1263 aRect
.SetRight( nMaxRight
);
1264 if( VisArea().Overlaps( aPrevArea
) && !mnLockPaint
)
1267 maVisArea
.Pos() = aPrevArea
.Pos();
1268 if ( SmoothScroll( nXDiff
, nYDiff
, &aRect
) )
1270 maVisArea
.Pos() = rRect
.Pos();
1272 else if (!comphelper::LibreOfficeKit::isActive())
1273 GetWin()->Invalidate( aRect
);
1275 else if ( !mnLockPaint
) //will be released in Unlock
1277 if( VisArea().Overlaps( aPrevArea
) )
1280 maVisArea
.Pos() = aPrevArea
.Pos();
1281 if ( SmoothScroll( nXDiff
, nYDiff
, nullptr ) )
1283 maVisArea
.Pos() = rRect
.Pos();
1286 GetWin()->Invalidate();
1290 // When tiled rendering, the map mode of the window is disabled, avoid
1291 // enabling it here.
1292 if (!comphelper::LibreOfficeKit::isActive())
1294 Point
aPt( VisArea().Pos() );
1295 aPt
.setX( -aPt
.X() ); aPt
.setY( -aPt
.Y() );
1296 MapMode
aMapMode( GetWin()->GetMapMode() );
1297 aMapMode
.SetOrigin( aPt
);
1298 GetWin()->SetMapMode( aMapMode
);
1301 if ( HasDrawView() )
1303 Imp()->GetDrawView()->VisAreaChanged( GetWin()->GetOutDev() );
1304 Imp()->GetDrawView()->SetActualWin( GetWin()->GetOutDev() );
1306 GetWin()->PaintImmediately();
1308 if ( pPostItMgr
) // #i88070#
1310 pPostItMgr
->Rescale();
1311 pPostItMgr
->CalcRects();
1312 pPostItMgr
->LayoutPostIts();
1315 if ( !bScrolled
&& pPostItMgr
&& pPostItMgr
->HasNotes() && pPostItMgr
->ShowNotes() )
1316 pPostItMgr
->CorrectPositions();
1318 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1319 if( Imp()->IsAccessible() )
1320 Imp()->UpdateAccessible();
1324 bool SwViewShell::SmoothScroll( tools::Long lXDiff
, tools::Long lYDiff
, const tools::Rectangle
*pRect
)
1326 #if !defined(MACOSX) && !defined(ANDROID) && !defined(IOS)
1327 // #i98766# - disable smooth scrolling for Mac
1329 const sal_uLong nBitCnt
= mpOut
->GetBitCount();
1330 tools::Long lMult
= 1, lMax
= LONG_MAX
;
1331 if ( nBitCnt
== 16 )
1336 if ( nBitCnt
== 24 )
1341 else if ( nBitCnt
== 1 )
1347 // #i75172# isolated static conditions
1348 const bool bOnlyYScroll(!lXDiff
&& std::abs(lYDiff
) != 0 && std::abs(lYDiff
) < lMax
);
1349 const bool bAllowedWithChildWindows(GetWin()->GetWindowClipRegionPixel().IsNull());
1350 const bool bSmoothScrollAllowed(bOnlyYScroll
&& mbEnableSmooth
&& GetViewOptions()->IsSmoothScroll() && bAllowedWithChildWindows
);
1352 if(bSmoothScrollAllowed
)
1354 Imp()->m_bStopSmooth
= false;
1356 const SwRect
aOldVis( VisArea() );
1358 //create virtual device and set.
1359 const Size aPixSz
= GetWin()->PixelToLogic(Size(1,1));
1360 VclPtrInstance
<VirtualDevice
> pVout( *GetWin()->GetOutDev() );
1361 pVout
->SetLineColor( GetWin()->GetOutDev()->GetLineColor() );
1362 pVout
->SetFillColor( GetWin()->GetOutDev()->GetFillColor() );
1363 MapMode
aMapMode( GetWin()->GetMapMode() );
1364 pVout
->SetMapMode( aMapMode
);
1365 Size
aSize( maVisArea
.Width()+2*aPixSz
.Width(), std::abs(lYDiff
)+(2*aPixSz
.Height()) );
1367 aSize
.setWidth( std::min(aSize
.Width(), pRect
->GetWidth()+2*aPixSz
.Width()) );
1368 if ( pVout
->SetOutputSize( aSize
) )
1372 //First Paint everything in the virtual device.
1373 SwRect
aRect( VisArea() );
1374 aRect
.Height( aSize
.Height() );
1377 aRect
.Pos().setX( std::max(aRect
.Left(),pRect
->Left()-aPixSz
.Width()) );
1378 aRect
.Right( std::min(aRect
.Right()+2*aPixSz
.Width(), pRect
->Right()+aPixSz
.Width()));
1381 aRect
.AddWidth(2*aPixSz
.Width() );
1382 aRect
.Pos().setY( lYDiff
< 0 ? aOldVis
.Bottom() - aPixSz
.Height()
1383 : aRect
.Top() - aSize
.Height() + aPixSz
.Height() );
1384 aRect
.Pos().setX( std::max( tools::Long(0), aRect
.Left()-aPixSz
.Width() ) );
1385 aRect
.Pos() = GetWin()->PixelToLogic( GetWin()->LogicToPixel( aRect
.Pos()));
1386 aRect
.SSize( GetWin()->PixelToLogic( GetWin()->LogicToPixel( aRect
.SSize())) );
1388 const Point
aPt( -aRect
.Left(), -aRect
.Top() );
1389 aMapMode
.SetOrigin( aPt
);
1390 pVout
->SetMapMode( aMapMode
);
1391 OutputDevice
*pOld
= mpOut
;
1392 mpOut
= pVout
.get();
1395 // #i75172# To get a clean repaint, a new ObjectContact is needed here. Without, the
1396 // repaint would not be correct since it would use the wrong DrawPage visible region.
1397 // This repaint IS about painting something currently outside the visible part (!).
1398 // For that purpose, AddDeviceToPaintView is used which creates a new SdrPageViewWindow
1399 // and all the necessary stuff. It's not cheap, but necessary here. Alone because repaint
1400 // target really is NOT the current window.
1401 // Also will automatically NOT use PreRendering and overlay (since target is VirtualDevice)
1404 SdrView
* pDrawView
= GetDrawView();
1405 pDrawView
->AddDeviceToPaintView(*pVout
, nullptr);
1407 // clear mpWin during DLPrePaint2 to get paint preparation for mpOut, but set it again
1408 // immediately afterwards. There are many decisions in SW which imply that Printing
1409 // is used when mpWin == 0 (wrong but widely used).
1410 vcl::Window
* pOldWin
= mpWin
;
1412 DLPrePaint2(vcl::Region(aRect
.SVRect()));
1416 PaintDesktop(*GetOut(), aRect
);
1417 SwViewShell::sbLstAct
= true;
1418 GetLayout()->PaintSwFrame( *GetOut(), aRect
);
1419 SwViewShell::sbLstAct
= false;
1421 // end paint and destroy ObjectContact again
1423 pDrawView
->DeleteDeviceFromPaintView(*pVout
);
1427 maVisArea
= aOldVis
;
1429 //Now shift in parts and copy the new Pixel from the virtual device.
1431 // ??????????????????????
1432 // or is it better to get the scrollfactor from the User
1434 // ??????????????????????
1435 tools::Long lMaDelta
= aPixSz
.Height();
1436 if ( std::abs(lYDiff
) > ( maVisArea
.Height() / 3 ) )
1444 lMaDelta
= -lMaDelta
;
1446 tools::Long lDiff
= lYDiff
;
1449 tools::Long lScroll
;
1450 if ( Imp()->m_bStopSmooth
|| std::abs(lDiff
) <= std::abs(lMaDelta
) )
1461 const SwRect aTmpOldVis
= VisArea();
1462 maVisArea
.Pos().AdjustY( -lScroll
);
1463 maVisArea
.Pos() = GetWin()->PixelToLogic( GetWin()->LogicToPixel( VisArea().Pos()));
1464 lScroll
= aTmpOldVis
.Top() - VisArea().Top();
1467 tools::Rectangle
aTmp( aTmpOldVis
.SVRect() );
1468 aTmp
.SetLeft( pRect
->Left() );
1469 aTmp
.SetRight( pRect
->Right() );
1470 GetWin()->Scroll( 0, lScroll
, aTmp
, ScrollFlags::Children
);
1473 GetWin()->Scroll( 0, lScroll
, ScrollFlags::Children
);
1475 const Point
aTmpPt( -VisArea().Left(), -VisArea().Top() );
1476 MapMode
aTmpMapMode( GetWin()->GetMapMode() );
1477 aTmpMapMode
.SetOrigin( aTmpPt
);
1478 GetWin()->SetMapMode( aTmpMapMode
);
1480 if ( Imp()->HasDrawView() )
1481 Imp()->GetDrawView()->VisAreaChanged( GetWin()->GetOutDev() );
1483 SetFirstVisPageInvalid();
1484 if ( !Imp()->m_bStopSmooth
)
1486 const bool bScrollDirectionIsUp(lScroll
> 0);
1487 Imp()->m_aSmoothRect
= VisArea();
1489 if(bScrollDirectionIsUp
)
1491 Imp()->m_aSmoothRect
.Bottom( VisArea().Top() + lScroll
+ aPixSz
.Height());
1495 Imp()->m_aSmoothRect
.Top( VisArea().Bottom() + lScroll
- aPixSz
.Height());
1498 Imp()->m_bSmoothUpdate
= true;
1499 GetWin()->PaintImmediately();
1500 Imp()->m_bSmoothUpdate
= false;
1502 if(!Imp()->m_bStopSmooth
)
1504 // start paint on logic base
1505 const tools::Rectangle
aTargetLogic(Imp()->m_aSmoothRect
.SVRect());
1506 DLPrePaint2(vcl::Region(aTargetLogic
));
1508 // get target rectangle in discrete pixels
1509 OutputDevice
& rTargetDevice
= mpTargetPaintWindow
->GetTargetOutputDevice();
1510 const tools::Rectangle
aTargetPixel(rTargetDevice
.LogicToPixel(aTargetLogic
));
1512 // get source top-left in discrete pixels
1513 const Point
aSourceTopLeft(pVout
->LogicToPixel(aTargetLogic
.TopLeft()));
1515 // switch off MapModes
1516 const bool bMapModeWasEnabledDest(rTargetDevice
.IsMapModeEnabled());
1517 const bool bMapModeWasEnabledSource(pVout
->IsMapModeEnabled());
1518 rTargetDevice
.EnableMapMode(false);
1519 pVout
->EnableMapMode(false);
1521 rTargetDevice
.DrawOutDev(
1522 aTargetPixel
.TopLeft(), aTargetPixel
.GetSize(), // dest
1523 aSourceTopLeft
, aTargetPixel
.GetSize(), // source
1527 rTargetDevice
.EnableMapMode(bMapModeWasEnabledDest
);
1528 pVout
->EnableMapMode(bMapModeWasEnabledSource
);
1530 // end paint on logoc base
1537 pVout
.disposeAndClear();
1538 GetWin()->PaintImmediately();
1539 if ( !Imp()->m_bStopSmooth
)
1541 SetFirstVisPageInvalid();
1544 pVout
.disposeAndClear();
1548 maVisArea
.Pos().AdjustX( -lXDiff
);
1549 maVisArea
.Pos().AdjustY( -lYDiff
);
1551 GetWin()->Scroll( lXDiff
, lYDiff
, *pRect
, ScrollFlags::Children
);
1553 GetWin()->Scroll( lXDiff
, lYDiff
, ScrollFlags::Children
);
1557 void SwViewShell::PaintDesktop(const vcl::RenderContext
& rRenderContext
, const SwRect
&rRect
)
1559 if ( !GetWin() && !GetOut()->GetConnectMetaFile() )
1560 return; //for the printer we don't do anything here.
1562 if(comphelper::LibreOfficeKit::isActive())
1565 //Catch exceptions, so that it doesn't look so surprising.
1566 //Can e.g. happen during Idle.
1567 //Unfortunately we must at any rate Paint the rectangles next to the pages,
1568 //as these are not painted at VisPortChgd.
1569 bool bBorderOnly
= false;
1570 const SwRootFrame
*pRoot
= GetLayout();
1571 if ( rRect
.Top() > pRoot
->getFrameArea().Bottom() )
1573 const SwFrame
*pPg
= pRoot
->Lower();
1574 while ( pPg
&& pPg
->GetNext() )
1575 pPg
= pPg
->GetNext();
1576 if ( !pPg
|| !pPg
->getFrameArea().Overlaps( VisArea() ) )
1580 const bool bBookMode
= GetViewOptions()->IsViewLayoutBookMode();
1582 SwRegionRects
aRegion( rRect
);
1584 //mod #i6193: remove sidebar area to avoid flickering
1585 const SwPostItMgr
* pPostItMgr
= GetPostItMgr();
1586 const SwTwips nSidebarWidth
= pPostItMgr
&& pPostItMgr
->HasNotes() && pPostItMgr
->ShowNotes() ?
1587 pPostItMgr
->GetSidebarWidth() + pPostItMgr
->GetSidebarBorderWidth() :
1592 const SwFrame
*pPage
=pRoot
->Lower();
1593 SwRect
aLeft( rRect
), aRight( rRect
);
1596 tools::Long nTmp
= pPage
->getFrameArea().Left();
1597 if ( nTmp
< aLeft
.Right() )
1598 aLeft
.Right( nTmp
);
1599 nTmp
= pPage
->getFrameArea().Right();
1600 if ( nTmp
> aRight
.Left() )
1602 aRight
.Left( nTmp
+ nSidebarWidth
);
1604 pPage
= pPage
->GetNext();
1607 if ( aLeft
.HasArea() )
1608 aRegion
.push_back( aLeft
);
1609 if ( aRight
.HasArea() )
1610 aRegion
.push_back( aRight
);
1614 const SwFrame
*pPage
= Imp()->GetFirstVisPage(&rRenderContext
);
1615 const SwTwips nBottom
= rRect
.Bottom();
1616 while ( pPage
&& !aRegion
.empty() &&
1617 (pPage
->getFrameArea().Top() <= nBottom
) )
1619 SwRect
aPageRect( pPage
->getFrameArea() );
1622 const SwPageFrame
& rFormatPage
= static_cast<const SwPageFrame
*>(pPage
)->GetFormatPage();
1623 aPageRect
.SSize( rFormatPage
.getFrameArea().SSize() );
1626 const bool bSidebarRight
=
1627 static_cast<const SwPageFrame
*>(pPage
)->SidebarPosition() == sw::sidebarwindows::SidebarPosition::RIGHT
;
1628 aPageRect
.Pos().AdjustX( -(bSidebarRight
? 0 : nSidebarWidth
) );
1629 aPageRect
.AddWidth(nSidebarWidth
);
1631 if ( aPageRect
.Overlaps( rRect
) )
1632 aRegion
-= aPageRect
;
1634 pPage
= pPage
->GetNext();
1637 if ( !aRegion
.empty() )
1638 PaintDesktop_(aRegion
);
1641 // PaintDesktop is split in two, this part is also used by PreviewPage
1642 void SwViewShell::PaintDesktop_(const SwRegionRects
&rRegion
)
1644 // OD 2004-04-23 #116347#
1645 GetOut()->Push( vcl::PushFlags::FILLCOLOR
|vcl::PushFlags::LINECOLOR
);
1646 GetOut()->SetLineColor();
1648 for ( auto &rRgn
: rRegion
)
1650 const tools::Rectangle
aRectangle(rRgn
.SVRect());
1653 // Here we have a real Problem. On the one hand we have the buffering for paint
1654 // and overlay which needs an embracing pair of DLPrePaint2/DLPostPaint2 calls,
1655 // on the other hand the MapMode is not set correctly when this code is executed.
1656 // This is done in the users of this method, for each SWpage before painting it.
1657 // Since the MapMode is not correct here, the call to DLPostPaint2 will paint
1658 // existing FormControls due to the current MapMode.
1660 // There are basically three solutions for this:
1662 // (1) Set the MapMode correct, move the background painting to the users of
1665 // (2) Do no DLPrePaint2/DLPostPaint2 here; no SdrObjects are allowed to lie in
1666 // the desktop region. Disadvantage: the desktop will not be part of the
1667 // buffers, e.g. overlay. Thus, as soon as overlay will be used over the
1668 // desktop, it will not work.
1670 // (3) expand DLPostPaint2 with a flag to signal if FormControl paints shall
1673 // Currently, (3) will be the best possible solution. It will keep overlay and
1674 // buffering intact and work without MapMode for single pages. In the medium
1675 // to long run, (1) will need to be used and the bool bPaintFormLayer needs
1676 // to be removed again
1678 // #i68597# inform Drawinglayer about display change
1679 DLPrePaint2(vcl::Region(aRectangle
));
1681 // #i75172# needed to move line/Fill color setters into loop since DLPrePaint2
1682 // may exchange GetOut(), that's it's purpose. This happens e.g. at print preview.
1683 GetOut()->SetFillColor( GetViewOptions()->GetAppBackgroundColor());
1684 GetOut()->SetLineColor();
1685 GetOut()->DrawRect(aRectangle
);
1687 DLPostPaint2(false);
1693 bool SwViewShell::CheckInvalidForPaint( const SwRect
&rRect
)
1698 const SwPageFrame
*pPage
= Imp()->GetFirstVisPage(GetOut());
1699 const SwTwips nBottom
= VisArea().Bottom();
1700 const SwTwips nRight
= VisArea().Right();
1702 while ( !bRet
&& pPage
&& ((pPage
->getFrameArea().Top() <= nBottom
) &&
1703 (pPage
->getFrameArea().Left() <= nRight
)))
1705 if ( pPage
->IsInvalid() || pPage
->IsInvalidFly() )
1707 pPage
= static_cast<const SwPageFrame
*>(pPage
->GetNext());
1712 //Unfortunately Start/EndAction won't help here, as the Paint originated
1713 //from GUI and so Clipping has been set against getting through.
1714 //Ergo: do it all yourself (see ImplEndAction())
1715 if ( Imp()->HasPaintRegion() && Imp()->GetPaintRegion()->GetOrigin() != VisArea())
1716 Imp()->DeletePaintRegion();
1718 SwLayAction
aAction( GetLayout(), Imp() );
1719 aAction
.SetComplete( false );
1720 // We increment the action counter to avoid a recursive call of actions
1721 // e.g. from a SwFEShell::RequestObjectResize(..) in bug 95829.
1722 // A recursive call of actions is no good idea because the inner action
1723 // can't format frames which are locked by the outer action. This may
1724 // cause and endless loop.
1726 aAction
.Action(GetWin()->GetOutDev());
1729 std::optional
<SwRegionRects
> oRegion
= Imp()->TakePaintRegion();
1730 if ( oRegion
&& aAction
.IsBrowseActionStop() )
1732 //only of interest when something has changed in the visible range
1734 for ( size_t i
= 0; i
< oRegion
->size(); ++i
)
1736 const SwRect
&rTmp
= (*oRegion
)[i
];
1737 bStop
= rTmp
.Overlaps( VisArea() );
1747 oRegion
->LimitToOrigin();
1748 oRegion
->Compress( SwRegionRects::CompressFuzzy
);
1750 if ( !oRegion
->empty() )
1752 SwRegionRects
aRegion( rRect
);
1753 for ( size_t i
= 0; i
< oRegion
->size(); ++i
)
1754 { const SwRect
&rTmp
= (*oRegion
)[i
];
1755 if ( !rRect
.Contains( rTmp
) )
1757 InvalidateWindows( rTmp
);
1758 if ( rTmp
.Overlaps( VisArea() ) )
1766 for ( size_t i
= 0; i
< aRegion
.size(); ++i
)
1767 GetWin()->Invalidate( aRegion
[i
].SVRect() );
1769 if ( rRect
!= VisArea() )
1771 //rRect == VisArea is the special case for new or
1772 //Shift-Ctrl-R, when it shouldn't be necessary to
1773 //hold the rRect again in Document coordinates.
1774 if ( maInvalidRect
.IsEmpty() )
1775 maInvalidRect
= rRect
;
1777 maInvalidRect
.Union( rRect
);
1792 /// Similar to comphelper::FlagRestorationGuard, but for vcl::RenderContext.
1793 class RenderContextGuard
1795 std::unique_ptr
<SdrPaintWindow
> m_TemporaryPaintWindow
;
1796 SdrPageWindow
* m_pPatchedPageWindow
;
1797 SdrPaintWindow
* m_pPreviousPaintWindow
= nullptr;
1800 RenderContextGuard(VclPtr
<vcl::RenderContext
>& pRef
, vcl::RenderContext
* pValue
, SwViewShell
* pShell
)
1801 : m_pPatchedPageWindow(nullptr)
1805 if (pValue
== pShell
->GetWin()->GetOutDev())
1808 SdrView
* pDrawView(pShell
->Imp()->GetDrawView());
1810 if (nullptr == pDrawView
)
1813 SdrPageView
* pSdrPageView(pDrawView
->GetSdrPageView());
1815 if (nullptr != pSdrPageView
)
1817 m_pPatchedPageWindow
= pSdrPageView
->FindPageWindow(*pShell
->GetWin()->GetOutDev());
1819 if (nullptr != m_pPatchedPageWindow
)
1821 m_TemporaryPaintWindow
.reset(new SdrPaintWindow(*pDrawView
, *pValue
));
1822 m_pPreviousPaintWindow
= m_pPatchedPageWindow
->patchPaintWindow(*m_TemporaryPaintWindow
);
1827 ~RenderContextGuard()
1829 if(nullptr != m_pPatchedPageWindow
)
1831 m_pPatchedPageWindow
->unpatchPaintWindow(m_pPreviousPaintWindow
);
1837 void SwViewShell::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&rRect
)
1839 RenderContextGuard
aGuard(mpOut
, &rRenderContext
, this);
1842 if ( Imp()->m_bSmoothUpdate
)
1844 SwRect
aTmp( rRect
);
1845 if ( !Imp()->m_aSmoothRect
.Contains( aTmp
) )
1846 Imp()->m_bStopSmooth
= true;
1849 Imp()->m_aSmoothRect
= aTmp
;
1857 if ( SwRootFrame::IsInPaint() )
1859 //During the publication of a page at printing the Paint is buffered.
1860 SwPaintQueue::Add( this, SwRect( rRect
) );
1864 //With !nStartAction I try to protect me against erroneous code at other places.
1865 //Hopefully it will not lead to problems!?
1866 if ( mbPaintWorks
&& !mnStartAction
)
1868 if( GetWin() && GetWin()->IsVisible() )
1870 SwRect
aRect( rRect
);
1871 if ( mbPaintInProgress
) //Guard against double Paints!
1873 GetWin()->Invalidate( rRect
);
1877 mbPaintInProgress
= true;
1878 CurrShell
aCurr( this );
1879 SwRootFrame::SetNoVirDev( true );
1881 //We don't want to Clip to and from, we trust that all are limited
1882 //to the rectangle and only need to calculate the clipping once.
1883 //The ClipRect is removed here once and not recovered, as externally
1884 //no one needs it anymore anyway.
1885 //Not when we paint a Metafile.
1886 if( !GetOut()->GetConnectMetaFile() && GetOut()->IsClipRegion())
1887 GetOut()->SetClipRegion();
1891 //When useful, process or destroy the old InvalidRect.
1892 if ( aRect
.Contains( maInvalidRect
) )
1894 SwViewShell::sbLstAct
= true;
1895 GetLayout()->PaintSwFrame( rRenderContext
, aRect
);
1896 SwViewShell::sbLstAct
= false;
1900 //When one of the visible pages still has anything entered for
1901 //Repaint, Repaint must be triggered.
1902 if ( !CheckInvalidForPaint( aRect
) )
1904 // --> OD 2009-08-12 #i101192#
1905 // start Pre/PostPaint encapsulation to avoid screen blinking
1906 const vcl::Region
aRepaintRegion(aRect
.SVRect());
1907 DLPrePaint2(aRepaintRegion
);
1910 PaintDesktop(rRenderContext
, aRect
);
1912 //When useful, process or destroy the old InvalidRect.
1913 if ( aRect
.Contains( maInvalidRect
) )
1915 SwViewShell::sbLstAct
= true;
1916 GetLayout()->PaintSwFrame( rRenderContext
, aRect
);
1917 SwViewShell::sbLstAct
= false;
1918 // --> OD 2009-08-12 #i101192#
1919 // end Pre/PostPaint encapsulation
1924 SwRootFrame::SetNoVirDev( false );
1925 mbPaintInProgress
= false;
1931 if ( maInvalidRect
.IsEmpty() )
1932 maInvalidRect
= SwRect( rRect
);
1934 maInvalidRect
.Union( SwRect( rRect
) );
1936 if ( mbInEndAction
&& GetWin() )
1938 const vcl::Region
aRegion(GetWin()->GetPaintRegion());
1939 RectangleVector aRectangles
;
1940 aRegion
.GetRegionRectangles(aRectangles
);
1942 for(const auto& rRectangle
: aRectangles
)
1944 Imp()->AddPaintRect(SwRect(rRectangle
));
1947 //RegionHandle hHdl( aRegion.BeginEnumRects() );
1949 //while ( aRegion.GetEnumRects( hHdl, aRect ) )
1950 // Imp()->AddPaintRect( aRect );
1951 //aRegion.EndEnumRects( hHdl );
1953 else if ( SfxProgress::GetActiveProgress( GetDoc()->GetDocShell() ) &&
1954 GetOut() == GetWin()->GetOutDev() )
1957 const vcl::Region
aDLRegion(rRect
);
1958 DLPrePaint2(aDLRegion
);
1960 rRenderContext
.Push( vcl::PushFlags::FILLCOLOR
|vcl::PushFlags::LINECOLOR
);
1961 rRenderContext
.SetFillColor( Imp()->GetRetoucheColor() );
1962 rRenderContext
.SetLineColor();
1963 rRenderContext
.DrawRect( rRect
);
1964 rRenderContext
.Pop();
1971 void SwViewShell::PaintTile(VirtualDevice
&rDevice
, int contextWidth
, int contextHeight
, int tilePosX
, int tilePosY
, tools::Long tileWidth
, tools::Long tileHeight
)
1973 // SwViewShell's output device setup
1974 // TODO clean up SwViewShell's approach to output devices (the many of
1975 // them - mpBufferedOut, mpOut, mpWin, ...)
1976 OutputDevice
*pSaveOut
= mpOut
;
1977 comphelper::LibreOfficeKit::setTiledPainting(true);
1980 // resizes the virtual device so to contain the entries context
1981 rDevice
.SetOutputSizePixel(Size(contextWidth
, contextHeight
));
1983 // setup the output device to draw the tile
1984 MapMode
aMapMode(rDevice
.GetMapMode());
1985 aMapMode
.SetMapUnit(MapUnit::MapTwip
);
1986 aMapMode
.SetOrigin(Point(-tilePosX
, -tilePosY
));
1988 // Scaling. Must convert from pixels to twips. We know
1989 // that VirtualDevices use a DPI of 96.
1990 const Fraction scale
= conversionFract(o3tl::Length::px
, o3tl::Length::twip
);
1991 Fraction scaleX
= Fraction(contextWidth
, tileWidth
) * scale
;
1992 Fraction scaleY
= Fraction(contextHeight
, tileHeight
) * scale
;
1993 aMapMode
.SetScaleX(scaleX
);
1994 aMapMode
.SetScaleY(scaleY
);
1995 rDevice
.SetMapMode(aMapMode
);
1997 // Update scaling of SwEditWin and its sub-widgets, needed for comments.
1998 sal_uInt16 nOldZoomValue
= 0;
1999 if (GetWin() && GetWin()->GetMapMode().GetScaleX() != scaleX
)
2001 double fScale
= double(scaleX
);
2002 SwViewOption
aOption(*GetViewOptions());
2003 nOldZoomValue
= aOption
.GetZoom();
2004 aOption
.SetZoom(fScale
* 100);
2005 ApplyViewOptions(aOption
);
2006 // Make sure the map mode (disabled in SwXTextDocument::initializeForTiledRendering()) is still disabled.
2007 GetWin()->EnableMapMode(false);
2010 tools::Rectangle
aOutRect(Point(tilePosX
, tilePosY
),
2011 rDevice
.PixelToLogic(Size(contextWidth
, contextHeight
)));
2013 // Make the requested area visible -- we can't use MakeVisible as that will
2014 // only scroll the contents, but won't zoom/resize if needed.
2015 // Without this, items/text that are outside the visible area (in the SwView)
2016 // won't be painted when rendering tiles (at least when using either the
2017 // tiledrendering app, or the gtktiledviewer) -- although ultimately we
2018 // probably want to fix things so that the SwView's area doesn't affect
2020 VisPortChgd(SwRect(aOutRect
));
2022 // Invoke SwLayAction if layout is not yet ready.
2023 CheckInvalidForPaint(SwRect(aOutRect
));
2025 // draw - works in logic coordinates
2026 Paint(rDevice
, aOutRect
);
2028 SwPostItMgr
* pPostItMgr
= GetPostItMgr();
2029 if (GetViewOptions()->IsPostIts() && pPostItMgr
)
2030 pPostItMgr
->PaintTile(rDevice
);
2032 // SwViewShell's output device tear down
2034 // A view shell can get a PaintTile call for a tile at a zoom level
2035 // different from the one, the related client really is.
2036 // In such a case it is better to reset the current scale value to
2037 // the original one, since such a value should be in synchronous with
2038 // the zoom level in the client (see setClientZoom).
2039 // At present the zoom value returned by GetViewOptions()->GetZoom() is
2040 // used in SwXTextDocument methods (postMouseEvent and setGraphicSelection)
2041 // for passing the correct mouse position to an edited chart (if any).
2042 if (nOldZoomValue
!=0)
2044 SwViewOption
aOption(*GetViewOptions());
2045 aOption
.SetZoom(nOldZoomValue
);
2046 ApplyViewOptions(aOption
);
2048 // Changing the zoom value doesn't always trigger the updating of
2049 // the client ole object area, so we call it directly.
2050 SfxInPlaceClient
* pIPClient
= GetSfxViewShell()->GetIPClient();
2053 pIPClient
->VisAreaChanged();
2055 // Make sure the map mode (disabled in SwXTextDocument::initializeForTiledRendering()) is still disabled.
2056 GetWin()->EnableMapMode(false);
2060 comphelper::LibreOfficeKit::setTiledPainting(false);
2063 void SwViewShell::SetBrowseBorder( const Size
& rNew
)
2065 if( rNew
!= maBrowseBorder
)
2067 maBrowseBorder
= rNew
;
2068 if ( maVisArea
.HasArea() )
2069 InvalidateLayout( false );
2073 const Size
& SwViewShell::GetBrowseBorder() const
2075 return maBrowseBorder
;
2078 sal_Int32
SwViewShell::GetBrowseWidth() const
2080 const SwPostItMgr
* pPostItMgr
= GetPostItMgr();
2081 if ( pPostItMgr
&& pPostItMgr
->HasNotes() && pPostItMgr
->ShowNotes() )
2083 Size
aBorder( maBrowseBorder
);
2084 aBorder
.AdjustWidth(maBrowseBorder
.Width() );
2085 aBorder
.AdjustWidth(pPostItMgr
->GetSidebarWidth(true) + pPostItMgr
->GetSidebarBorderWidth(true) );
2086 return maVisArea
.Width() - GetOut()->PixelToLogic(aBorder
).Width();
2089 return maVisArea
.Width() - 2 * GetOut()->PixelToLogic(maBrowseBorder
).Width();
2092 void SwViewShell::InvalidateLayout( bool bSizeChanged
)
2094 if ( !bSizeChanged
&& !GetViewOptions()->getBrowseMode() &&
2095 !GetViewOptions()->IsWhitespaceHidden() )
2098 CurrShell
aCurr( this );
2100 OSL_ENSURE( GetLayout(), "Layout not ready" );
2102 // When the Layout doesn't have a height yet, nothing is formatted.
2103 // That leads to problems with Invalidate, e.g. when setting up a new View
2104 // the content is inserted and formatted (regardless of empty VisArea).
2105 // Therefore the pages must be roused for formatting.
2106 if( !GetLayout()->getFrameArea().Height() )
2108 SwFrame
* pPage
= GetLayout()->Lower();
2111 pPage
->InvalidateSize_();
2112 pPage
= pPage
->GetNext();
2117 LockPaint(LockPaintReason::InvalidateLayout
);
2120 SwPageFrame
*pPg
= static_cast<SwPageFrame
*>(GetLayout()->Lower());
2122 { pPg
->InvalidateSize();
2123 pPg
->InvalidatePrt_();
2124 pPg
->InvaPercentLowers();
2127 pPg
->PrepareHeader();
2128 pPg
->PrepareFooter();
2130 pPg
= static_cast<SwPageFrame
*>(pPg
->GetNext());
2133 // When the size ratios in browse mode change,
2134 // the Position and PrtArea of the Content and Tab frames must be Invalidated.
2135 SwInvalidateFlags nInv
= SwInvalidateFlags::PrtArea
| SwInvalidateFlags::Table
| SwInvalidateFlags::Pos
;
2136 // In case of layout or mode change, the ContentFrames need a size-Invalidate
2137 // because of printer/screen formatting.
2139 nInv
|= SwInvalidateFlags::Size
| SwInvalidateFlags::Direction
;
2141 GetLayout()->InvalidateAllContent( nInv
);
2143 SwFrame::CheckPageDescs( static_cast<SwPageFrame
*>(GetLayout()->Lower()) );
2149 SwRootFrame
*SwViewShell::GetLayout() const
2151 return mpLayout
.get();
2154 vcl::RenderContext
& SwViewShell::GetRefDev() const
2156 OutputDevice
* pTmpOut
= nullptr;
2158 GetViewOptions()->getBrowseMode() &&
2159 !GetViewOptions()->IsPrtFormat() )
2160 pTmpOut
= GetWin()->GetOutDev();
2162 pTmpOut
= GetDoc()->getIDocumentDeviceAccess().getReferenceDevice( true );
2167 const SwNodes
& SwViewShell::GetNodes() const
2169 return mxDoc
->GetNodes();
2172 void SwViewShell::DrawSelChanged()
2176 Size
SwViewShell::GetDocSize() const
2179 const SwRootFrame
* pRoot
= GetLayout();
2181 aSz
= pRoot
->getFrameArea().SSize();
2186 SfxItemPool
& SwViewShell::GetAttrPool()
2188 return GetDoc()->GetAttrPool();
2191 void SwViewShell::ApplyViewOptions( const SwViewOption
&rOpt
)
2193 for(SwViewShell
& rSh
: GetRingContainer())
2196 ImplApplyViewOptions( rOpt
);
2198 // With one layout per view it is no longer necessary
2199 // to sync these "layout related" view options
2200 // But as long as we have to disable "multiple layout"
2202 for(SwViewShell
& rSh
: GetRingContainer())
2206 SwViewOption
aOpt( *rSh
.GetViewOptions() );
2207 aOpt
.SetFieldName( rOpt
.IsFieldName() );
2208 aOpt
.SetShowHiddenField( rOpt
.IsShowHiddenField() );
2209 aOpt
.SetShowHiddenPara( rOpt
.IsShowHiddenPara() );
2210 aOpt
.SetShowHiddenChar( rOpt
.IsShowHiddenChar() );
2211 aOpt
.SetViewLayoutBookMode( rOpt
.IsViewLayoutBookMode() );
2212 aOpt
.SetHideWhitespaceMode(rOpt
.IsHideWhitespaceMode());
2213 aOpt
.SetViewLayoutColumns(rOpt
.GetViewLayoutColumns());
2214 aOpt
.SetPostIts(rOpt
.IsPostIts());
2215 if ( !(aOpt
== *rSh
.GetViewOptions()) )
2216 rSh
.ImplApplyViewOptions( aOpt
);
2218 // End of disabled multiple window
2220 for(SwViewShell
& rSh
: GetRingContainer())
2225 IsCursorInFieldmarkHidden(SwPaM
const& rCursor
, sw::FieldmarkMode
const eMode
)
2227 if (eMode
== sw::FieldmarkMode::ShowBoth
)
2231 IDocumentMarkAccess
const& rIDMA(*rCursor
.GetDoc().getIDocumentMarkAccess());
2232 // iterate, for nested fieldmarks
2233 for (auto iter
= rIDMA
.getFieldmarksBegin(); iter
!= rIDMA
.getFieldmarksEnd(); ++iter
)
2235 if (*rCursor
.GetPoint() <= (**iter
).GetMarkStart())
2239 if (*rCursor
.GetPoint() < (**iter
).GetMarkEnd())
2241 SwPosition
const sepPos(sw::mark::FindFieldSep(
2242 dynamic_cast<sw::mark::IFieldmark
&>(**iter
)));
2243 if (eMode
== sw::FieldmarkMode::ShowResult
)
2245 if (*rCursor
.GetPoint() <= sepPos
2246 && *rCursor
.GetPoint() != (**iter
).GetMarkStart())
2253 if (sepPos
< *rCursor
.GetPoint())
2263 void SwViewShell::ImplApplyViewOptions( const SwViewOption
&rOpt
)
2268 vcl::Window
*pMyWin
= GetWin();
2271 OSL_ENSURE( pMyWin
, "SwViewShell::ApplyViewOptions: no window" );
2275 CurrShell
aCurr( this );
2277 bool bReformat
= false;
2279 if( mpOpt
->IsShowHiddenField() != rOpt
.IsShowHiddenField() )
2281 static_cast<SwHiddenTextFieldType
*>(mxDoc
->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::HiddenText
))->
2282 SetHiddenFlag( !rOpt
.IsShowHiddenField() );
2285 if ( mpOpt
->IsShowHiddenPara() != rOpt
.IsShowHiddenPara() )
2287 SwHiddenParaFieldType
* pFieldType
= static_cast<SwHiddenParaFieldType
*>(GetDoc()->
2288 getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::HiddenPara
));
2289 if( pFieldType
&& pFieldType
->HasWriterListeners() )
2290 pFieldType
->PrintHiddenPara();
2293 if ( !bReformat
&& mpOpt
->IsShowHiddenChar() != rOpt
.IsShowHiddenChar() )
2295 bReformat
= GetDoc()->ContainsHiddenChars();
2297 if ( mpOpt
->IsShowChangesInMargin() != rOpt
.IsShowChangesInMargin() ||
2298 mpOpt
->IsShowChangesInMargin2() != rOpt
.IsShowChangesInMargin2() )
2300 if (rOpt
.IsShowChangesInMargin())
2301 GetDoc()->GetDocumentRedlineManager().HideAll(
2302 /*bDeletion=*/!rOpt
.IsShowChangesInMargin2() );
2304 GetDoc()->GetDocumentRedlineManager().ShowAll();
2305 GetLayout()->SetHideRedlines( false );
2308 // bReformat becomes true, if ...
2309 // - fieldnames apply or not ...
2310 // ( - SwEndPortion must _no_ longer be generated. )
2311 // - Of course, the screen is something completely different than the printer ...
2312 bool const isToggleFieldNames(mpOpt
->IsFieldName() != rOpt
.IsFieldName());
2314 if (mpOpt
->IsFieldName() != rOpt
.IsFieldName()
2315 || mpOpt
->IsParagraph() != rOpt
.IsParagraph())
2317 GetLayout()->SetFieldmarkMode( rOpt
.IsFieldName()
2318 ? sw::FieldmarkMode::ShowCommand
2319 : sw::FieldmarkMode::ShowResult
,
2321 ? sw::ParagraphBreakMode::Shown
2322 : sw::ParagraphBreakMode::Hidden
);
2326 // The map mode is changed, minima/maxima will be attended by UI
2327 if( mpOpt
->GetZoom() != rOpt
.GetZoom() && !IsPreview() )
2329 MapMode
aMode( pMyWin
->GetMapMode() );
2330 Fraction
aNewFactor( rOpt
.GetZoom(), 100 );
2331 aMode
.SetScaleX( aNewFactor
);
2332 aMode
.SetScaleY( aNewFactor
);
2333 pMyWin
->SetMapMode( aMode
);
2334 // if not a reference device (printer) is used for formatting,
2335 // but the screen, new formatting is needed for zoomfactor changes.
2336 if (mpOpt
->getBrowseMode() || mpOpt
->IsWhitespaceHidden())
2340 bool bBrowseModeChanged
= false;
2341 if( mpOpt
->getBrowseMode() != rOpt
.getBrowseMode() )
2343 bBrowseModeChanged
= true;
2346 else if( mpOpt
->getBrowseMode() && mpOpt
->IsPrtFormat() != rOpt
.IsPrtFormat() )
2349 bool bHideWhitespaceModeChanged
= false;
2350 if (mpOpt
->IsWhitespaceHidden() != rOpt
.IsWhitespaceHidden())
2352 // When whitespace is hidden, view change needs reformatting.
2353 bHideWhitespaceModeChanged
= true;
2357 if ( HasDrawView() || rOpt
.IsGridVisible() )
2359 if ( !HasDrawView() )
2362 SwDrawView
*pDView
= Imp()->GetDrawView();
2363 if ( pDView
->IsDragStripes() != rOpt
.IsCrossHair() )
2364 pDView
->SetDragStripes( rOpt
.IsCrossHair() );
2366 if ( pDView
->IsGridSnap() != rOpt
.IsSnap() )
2367 pDView
->SetGridSnap( rOpt
.IsSnap() );
2369 if ( pDView
->IsGridVisible() != rOpt
.IsGridVisible() )
2370 pDView
->SetGridVisible( rOpt
.IsGridVisible() );
2372 const Size
&rSz
= rOpt
.GetSnapSize();
2373 pDView
->SetGridCoarse( rSz
);
2376 ( rSz
.Width() ? rSz
.Width() / (rOpt
.GetDivisionX()+1) : 0,
2377 rSz
.Height()? rSz
.Height()/ (rOpt
.GetDivisionY()+1) : 0);
2378 pDView
->SetGridFine( aFSize
);
2379 Fraction
aSnGrWdtX(rSz
.Width(), rOpt
.GetDivisionX() + 1);
2380 Fraction
aSnGrWdtY(rSz
.Height(), rOpt
.GetDivisionY() + 1);
2381 pDView
->SetSnapGridWidth( aSnGrWdtX
, aSnGrWdtY
);
2383 // set handle size to 9 pixels, always
2384 pDView
->SetMarkHdlSizePixel(9);
2387 bool bOnlineSpellChgd
= mpOpt
->IsOnlineSpell() != rOpt
.IsOnlineSpell();
2389 *mpOpt
= rOpt
; // First the options are taken.
2390 mpOpt
->SetUIOptions(rOpt
);
2392 mxDoc
->GetDocumentSettingManager().set(DocumentSettingId::HTML_MODE
, 0 != ::GetHtmlMode(mxDoc
->GetDocShell()));
2394 if( bBrowseModeChanged
|| bHideWhitespaceModeChanged
)
2396 // #i44963# Good occasion to check if page sizes in
2397 // page descriptions are still set to (LONG_MAX, LONG_MAX) (html import)
2398 mxDoc
->CheckDefaultPageFormat();
2399 InvalidateLayout( true );
2402 SwXTextDocument
* pModel
= comphelper::getFromUnoTunnel
<SwXTextDocument
>(GetSfxViewShell()->GetCurrentDocument());
2403 SfxLokHelper::notifyViewRenderState(GetSfxViewShell(), pModel
);
2405 pMyWin
->Invalidate();
2408 // Nothing helps, we need to send all ContentFrames a
2409 // Prepare, we format anew:
2415 if (isToggleFieldNames
)
2417 for(SwViewShell
& rSh
: GetRingContainer())
2419 if (SwCursorShell
*const pSh
= dynamic_cast<SwCursorShell
*>(&rSh
))
2421 if ((mpOpt
->IsFieldName() && pSh
->CursorInsideInputField())
2422 || IsCursorInFieldmarkHidden(*pSh
->GetCursor(),
2423 pSh
->GetLayout()->GetFieldmarkMode()))
2424 { // move cursor out of field
2425 pSh
->Left(1, SwCursorSkipMode::Chars
);
2429 // the layout changes but SetModified() wasn't called so do it here:
2430 mxDoc
->GetDocumentLayoutManager().ClearSwLayouterEntries();
2433 if( !bOnlineSpellChgd
)
2436 bool bOnlineSpl
= rOpt
.IsOnlineSpell();
2437 for(SwViewShell
& rSh
: GetRingContainer())
2441 rSh
.mpOpt
->SetOnlineSpell( bOnlineSpl
);
2442 vcl::Window
*pTmpWin
= rSh
.GetWin();
2444 pTmpWin
->Invalidate();
2449 void SwViewShell::SetUIOptions( const SwViewOption
&rOpt
)
2451 mpOpt
->SetUIOptions(rOpt
);
2452 //the API-Flag of the view options is set but never reset
2453 //it is required to set scroll bars in readonly documents
2454 if(rOpt
.IsStarOneSetting())
2455 mpOpt
->SetStarOneSetting(true);
2457 mpOpt
->SetSymbolFont(rOpt
.GetSymbolFont());
2460 void SwViewShell::SetReadonlyOption(bool bSet
)
2462 //JP 01.02.99: at readonly flag query properly
2463 // and if need be format; Bug 61335
2465 // Are we switching from readonly to edit?
2466 if( bSet
== mpOpt
->IsReadonly() )
2469 // so that the flags can be queried properly.
2470 mpOpt
->SetReadonly( false );
2472 bool bReformat
= mpOpt
->IsFieldName();
2474 mpOpt
->SetReadonly( bSet
);
2481 GetWin()->Invalidate();
2484 else if ( GetWin() )
2485 GetWin()->Invalidate();
2486 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
2487 if( Imp()->IsAccessible() )
2488 Imp()->InvalidateAccessibleEditableState( false );
2492 void SwViewShell::SetPDFExportOption(bool bSet
)
2494 if( bSet
!= mpOpt
->IsPDFExport() )
2496 if( bSet
&& mpOpt
->getBrowseMode() )
2497 mpOpt
->SetPrtFormat( true );
2498 mpOpt
->SetPDFExport(bSet
);
2502 void SwViewShell::SetReadonlySelectionOption(bool bSet
)
2504 if( bSet
!= mpOpt
->IsSelectionInReadonly() )
2506 mpOpt
->SetSelectionInReadonly(bSet
);
2510 void SwViewShell::SetPrtFormatOption( bool bSet
)
2512 mpOpt
->SetPrtFormat( bSet
);
2515 void SwViewShell::UISizeNotify()
2517 if ( mbDocSizeChgd
)
2519 mbDocSizeChgd
= false;
2520 bool bOld
= bInSizeNotify
;
2521 bInSizeNotify
= true;
2522 ::SizeNotify( this, GetDocSize() );
2523 bInSizeNotify
= bOld
;
2527 void SwViewShell::SetRestoreActions(sal_uInt16 nSet
)
2529 OSL_ENSURE(!GetRestoreActions()||!nSet
, "multiple restore of the Actions ?");
2530 Imp()->SetRestoreActions(nSet
);
2532 sal_uInt16
SwViewShell::GetRestoreActions() const
2534 return Imp()->GetRestoreActions();
2537 bool SwViewShell::IsNewLayout() const
2539 return GetLayout()->IsNewLayout();
2542 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
2543 uno::Reference
< css::accessibility::XAccessible
> SwViewShell::CreateAccessible()
2545 uno::Reference
< css::accessibility::XAccessible
> xAcc
;
2547 // We require a layout and an XModel to be accessible.
2548 OSL_ENSURE( mpLayout
, "no layout, no access" );
2549 OSL_ENSURE( GetWin(), "no window, no access" );
2551 if( mxDoc
->getIDocumentLayoutAccess().GetCurrentViewShell() && GetWin() )
2552 xAcc
= Imp()->GetAccessibleMap().GetDocumentView();
2557 uno::Reference
< css::accessibility::XAccessible
> SwViewShell::CreateAccessiblePreview()
2559 OSL_ENSURE( IsPreview(),
2560 "Can't create accessible preview for non-preview SwViewShell" );
2562 // We require a layout and an XModel to be accessible.
2563 OSL_ENSURE( mpLayout
, "no layout, no access" );
2564 OSL_ENSURE( GetWin(), "no window, no access" );
2566 if ( IsPreview() && GetLayout()&& GetWin() )
2568 return Imp()->GetAccessibleMap().GetDocumentPreview(
2569 PagePreviewLayout()->maPreviewPages
,
2570 GetWin()->GetMapMode().GetScaleX(),
2571 GetLayout()->GetPageByPageNum( PagePreviewLayout()->mnSelectedPageNum
),
2572 PagePreviewLayout()->maWinSize
);
2577 void SwViewShell::InvalidateAccessibleFocus()
2579 if( Imp() && Imp()->IsAccessible() )
2580 Imp()->GetAccessibleMap().InvalidateFocus();
2584 * invalidate CONTENT_FLOWS_FROM/_TO relation for paragraphs #i27138#
2586 void SwViewShell::InvalidateAccessibleParaFlowRelation( const SwTextFrame
* _pFromTextFrame
,
2587 const SwTextFrame
* _pToTextFrame
)
2589 if ( GetLayout() && GetLayout()->IsAnyShellAccessible() )
2591 Imp()->InvalidateAccessibleParaFlowRelation_( _pFromTextFrame
, _pToTextFrame
);
2596 * invalidate text selection for paragraphs #i27301#
2598 void SwViewShell::InvalidateAccessibleParaTextSelection()
2600 if ( GetLayout() && GetLayout()->IsAnyShellAccessible() )
2602 Imp()->InvalidateAccessibleParaTextSelection_();
2607 * invalidate attributes for paragraphs #i88069#
2609 void SwViewShell::InvalidateAccessibleParaAttrs( const SwTextFrame
& rTextFrame
)
2611 if ( GetLayout() && GetLayout()->IsAnyShellAccessible() )
2613 Imp()->InvalidateAccessibleParaAttrs_( rTextFrame
);
2617 SwAccessibleMap
* SwViewShell::GetAccessibleMap()
2619 if ( Imp()->IsAccessible() )
2621 return &(Imp()->GetAccessibleMap());
2627 void SwViewShell::ApplyAccessibilityOptions()
2629 if (utl::ConfigManager::IsFuzzing())
2631 if (mpOpt
->IsPagePreview() && !officecfg::Office::Common::Accessibility::IsForPagePreviews::get())
2633 mpAccOptions
->SetAlwaysAutoColor(false);
2634 mpAccOptions
->SetStopAnimatedGraphics(false);
2638 mpAccOptions
->SetAlwaysAutoColor(SvtAccessibilityOptions::GetIsAutomaticFontColor());
2639 mpAccOptions
->SetStopAnimatedGraphics(! SvtAccessibilityOptions::GetIsAllowAnimatedGraphics());
2642 // Always set this option, not only if document is read-only:
2643 mpOpt
->SetSelectionInReadonly(SvtAccessibilityOptions::IsSelectionInReadonly());
2646 #endif // ENABLE_WASM_STRIP_ACCESSIBILITY
2648 ShellResource
* SwViewShell::GetShellRes()
2653 void SwViewShell::SetCareDialog(const std::shared_ptr
<weld::Window
>& rNew
)
2655 (*spCareDialog
.get()) = rNew
;
2658 sal_uInt16
SwViewShell::GetPageCount() const
2660 return GetLayout() ? GetLayout()->GetPageNum() : 1;
2663 Size
SwViewShell::GetPageSize( sal_uInt16 nPageNum
, bool bSkipEmptyPages
) const
2666 const SwRootFrame
* pTmpRoot
= GetLayout();
2667 if( pTmpRoot
&& nPageNum
)
2669 const SwPageFrame
* pPage
= static_cast<const SwPageFrame
*>
2670 (pTmpRoot
->Lower());
2672 while( --nPageNum
&& pPage
->GetNext() )
2673 pPage
= static_cast<const SwPageFrame
*>( pPage
->GetNext() );
2675 if( !bSkipEmptyPages
&& pPage
->IsEmptyPage() && pPage
->GetNext() )
2676 pPage
= static_cast<const SwPageFrame
*>( pPage
->GetNext() );
2678 aSize
= pPage
->getFrameArea().SSize();
2683 void SwViewShell::OnGraphicArrived(const SwRect
& rRect
)
2685 for(SwViewShell
& rShell
: GetRingContainer())
2687 CurrShell
aCurr(&rShell
);
2688 if(rShell
.IsPreview())
2691 ::RepaintPagePreview(&rShell
, rRect
);
2693 else if(rShell
.VisArea().Overlaps(rRect
) && OUTDEV_WINDOW
== rShell
.GetOut()->GetOutDevType())
2695 // invalidate instead of painting
2696 rShell
.GetWin()->Invalidate(rRect
.SVRect());
2700 // #i12836# enhanced pdf export
2701 sal_Int32
SwViewShell::GetPageNumAndSetOffsetForPDF( OutputDevice
& rOut
, const SwRect
& rRect
) const
2703 OSL_ENSURE( GetLayout(), "GetPageNumAndSetOffsetForPDF assumes presence of layout" );
2705 sal_Int32 nRet
= -1;
2707 // #i40059# Position out of bounds:
2708 SwRect
aRect( rRect
);
2709 aRect
.Pos().setX( std::max( aRect
.Left(), GetLayout()->getFrameArea().Left() ) );
2711 const SwPageFrame
* pPage
= GetLayout()->GetPageAtPos( aRect
.Center() );
2714 OSL_ENSURE( pPage
, "GetPageNumAndSetOffsetForPDF: No page found" );
2716 Point
aOffset( pPage
->getFrameArea().Pos() );
2717 aOffset
.setX( -aOffset
.X() );
2718 aOffset
.setY( -aOffset
.Y() );
2720 MapMode
aMapMode( rOut
.GetMapMode() );
2721 aMapMode
.SetOrigin( aOffset
);
2722 rOut
.SetMapMode( aMapMode
);
2724 nRet
= pPage
->GetPhyPageNum() - 1;
2730 // --> PB 2007-05-30 #146850#
2731 const BitmapEx
& SwViewShell::GetReplacementBitmap( bool bIsErrorState
)
2736 m_xErrorBmp
.reset(new BitmapEx(RID_GRAPHIC_ERRORBMP
));
2737 return *m_xErrorBmp
;
2741 m_xReplaceBmp
.reset(new BitmapEx(RID_GRAPHIC_REPLACEBMP
));
2742 return *m_xReplaceBmp
;
2745 void SwViewShell::DeleteReplacementBitmaps()
2747 m_xErrorBmp
.reset();
2748 m_xReplaceBmp
.reset();
2751 SwPostItMgr
* SwViewShell::GetPostItMgr()
2753 SwView
* pView
= GetDoc()->GetDocShell() ? GetDoc()->GetDocShell()->GetView() : nullptr;
2755 return pView
->GetPostItMgr();
2760 void SwViewShell::GetFirstLastVisPageNumbers(SwVisiblePageNumbers
& rVisiblePageNumbers
)
2762 SwView
* pView
= GetDoc()->GetDocShell() ? GetDoc()->GetDocShell()->GetView() : nullptr;
2765 SwRect
rViewVisArea(pView
->GetVisArea());
2766 vcl::RenderContext
* pRenderContext
= GetOut();
2767 const SwPageFrame
* pPageFrame
= Imp()->GetFirstVisPage(pRenderContext
);
2768 SwRect rPageRect
= pPageFrame
->getFrameArea();
2769 rPageRect
.AddBottom(-pPageFrame
->GetBottomMargin());
2770 while (!rPageRect
.Overlaps(rViewVisArea
) && pPageFrame
->GetNext())
2772 pPageFrame
= static_cast<const SwPageFrame
*>(pPageFrame
->GetNext());
2773 rPageRect
= pPageFrame
->getFrameArea();
2774 if (rPageRect
.Top() > 0)
2775 rPageRect
.AddBottom(-pPageFrame
->GetBottomMargin());
2777 rVisiblePageNumbers
.nFirstPhy
= pPageFrame
->GetPhyPageNum();
2778 rVisiblePageNumbers
.nFirstVirt
= pPageFrame
->GetVirtPageNum();
2779 const SvxNumberType
& rFirstVisNum
= pPageFrame
->GetPageDesc()->GetNumType();
2780 rVisiblePageNumbers
.sFirstCustomPhy
= rFirstVisNum
.GetNumStr(rVisiblePageNumbers
.nFirstPhy
);
2781 rVisiblePageNumbers
.sFirstCustomVirt
= rFirstVisNum
.GetNumStr(rVisiblePageNumbers
.nFirstVirt
);
2782 pPageFrame
= Imp()->GetLastVisPage(pRenderContext
);
2783 rPageRect
= pPageFrame
->getFrameArea();
2784 rPageRect
.AddTop(pPageFrame
->GetTopMargin());
2785 while (!rPageRect
.Overlaps(rViewVisArea
) && pPageFrame
->GetPrev())
2787 pPageFrame
= static_cast<const SwPageFrame
*>(pPageFrame
->GetPrev());
2788 rPageRect
= pPageFrame
->getFrameArea();
2789 rPageRect
.AddTop(pPageFrame
->GetTopMargin());
2791 rVisiblePageNumbers
.nLastPhy
= pPageFrame
->GetPhyPageNum();
2792 rVisiblePageNumbers
.nLastVirt
= pPageFrame
->GetVirtPageNum();
2793 const SvxNumberType
& rLastVisNum
= pPageFrame
->GetPageDesc()->GetNumType();
2794 rVisiblePageNumbers
.sLastCustomPhy
= rLastVisNum
.GetNumStr(rVisiblePageNumbers
.nLastPhy
);
2795 rVisiblePageNumbers
.sLastCustomVirt
= rLastVisNum
.GetNumStr(rVisiblePageNumbers
.nLastVirt
);
2799 * Document Interface Access
2801 const IDocumentSettingAccess
& SwViewShell::getIDocumentSettingAccess() const { return mxDoc
->GetDocumentSettingManager(); }
2802 IDocumentSettingAccess
& SwViewShell::getIDocumentSettingAccess() { return mxDoc
->GetDocumentSettingManager(); }
2803 const IDocumentDeviceAccess
& SwViewShell::getIDocumentDeviceAccess() const { return mxDoc
->getIDocumentDeviceAccess(); }
2804 IDocumentDeviceAccess
& SwViewShell::getIDocumentDeviceAccess() { return mxDoc
->getIDocumentDeviceAccess(); }
2805 const IDocumentMarkAccess
* SwViewShell::getIDocumentMarkAccess() const { return mxDoc
->getIDocumentMarkAccess(); }
2806 IDocumentMarkAccess
* SwViewShell::getIDocumentMarkAccess() { return mxDoc
->getIDocumentMarkAccess(); }
2807 const IDocumentDrawModelAccess
& SwViewShell::getIDocumentDrawModelAccess() const { return mxDoc
->getIDocumentDrawModelAccess(); }
2808 IDocumentDrawModelAccess
& SwViewShell::getIDocumentDrawModelAccess() { return mxDoc
->getIDocumentDrawModelAccess(); }
2809 const IDocumentRedlineAccess
& SwViewShell::getIDocumentRedlineAccess() const { return mxDoc
->getIDocumentRedlineAccess(); }
2810 IDocumentRedlineAccess
& SwViewShell::getIDocumentRedlineAccess() { return mxDoc
->getIDocumentRedlineAccess(); }
2811 const IDocumentLayoutAccess
& SwViewShell::getIDocumentLayoutAccess() const { return mxDoc
->getIDocumentLayoutAccess(); }
2812 IDocumentLayoutAccess
& SwViewShell::getIDocumentLayoutAccess() { return mxDoc
->getIDocumentLayoutAccess(); }
2813 IDocumentContentOperations
& SwViewShell::getIDocumentContentOperations() { return mxDoc
->getIDocumentContentOperations(); }
2814 IDocumentStylePoolAccess
& SwViewShell::getIDocumentStylePoolAccess() { return mxDoc
->getIDocumentStylePoolAccess(); }
2815 const IDocumentStatistics
& SwViewShell::getIDocumentStatistics() const { return mxDoc
->getIDocumentStatistics(); }
2817 IDocumentUndoRedo
& SwViewShell::GetIDocumentUndoRedo()
2818 { return mxDoc
->GetIDocumentUndoRedo(); }
2819 IDocumentUndoRedo
const& SwViewShell::GetIDocumentUndoRedo() const
2820 { return mxDoc
->GetIDocumentUndoRedo(); }
2822 // --> OD 2007-11-14 #i83479#
2823 const IDocumentListItems
* SwViewShell::getIDocumentListItemsAccess() const
2825 return &mxDoc
->getIDocumentListItems();
2828 const IDocumentOutlineNodes
* SwViewShell::getIDocumentOutlineNodesAccess() const
2830 return &mxDoc
->getIDocumentOutlineNodes();
2833 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */