Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / view / viewimp.cxx
blob3f427ed773168fd1ac05c145e0483ea7bcaa573c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_wasm_strip.h>
22 #include <rootfrm.hxx>
23 #include <pagefrm.hxx>
24 #include <viewimp.hxx>
25 #include <viewopt.hxx>
26 #include <flyfrm.hxx>
27 #include <layact.hxx>
28 #include <dview.hxx>
29 #include <svx/svdpage.hxx>
30 #include <accmap.hxx>
32 #include <officecfg/Office/Common.hxx>
33 #include <pagepreviewlayout.hxx>
34 #include <comphelper/lok.hxx>
35 #include <comphelper/diagnose_ex.hxx>
36 #include <IDocumentLayoutAccess.hxx>
37 #include <IDocumentDrawModelAccess.hxx>
38 #include <drawdoc.hxx>
39 #include <prevwpage.hxx>
40 #include <sfx2/viewsh.hxx>
42 void SwViewShellImp::Init( const SwViewOption *pNewOpt )
44 OSL_ENSURE( m_pDrawView, "SwViewShellImp::Init without DrawView" );
45 //Create PageView if it doesn't exist
46 SwRootFrame *pRoot = m_pShell->GetLayout();
47 if ( !m_pSdrPageView )
49 IDocumentDrawModelAccess& rIDDMA = m_pShell->getIDocumentDrawModelAccess();
50 if ( !pRoot->GetDrawPage() )
51 pRoot->SetDrawPage( rIDDMA.GetDrawModel()->GetPage( 0 ) );
53 if ( pRoot->GetDrawPage()->GetSize() != pRoot->getFrameArea().SSize() )
54 pRoot->GetDrawPage()->SetSize( pRoot->getFrameArea().SSize() );
56 m_pSdrPageView = m_pDrawView->ShowSdrPage( pRoot->GetDrawPage());
57 // Notify drawing page view about invisible layers
58 rIDDMA.NotifyInvisibleLayers( *m_pSdrPageView );
60 m_pDrawView->SetDragStripes( pNewOpt->IsCrossHair() );
61 m_pDrawView->SetGridSnap( pNewOpt->IsSnap() );
62 m_pDrawView->SetGridVisible( pNewOpt->IsGridVisible() );
63 const Size &rSz = pNewOpt->GetSnapSize();
64 m_pDrawView->SetGridCoarse( rSz );
65 const Size aFSize
66 ( rSz.Width() ? rSz.Width() /std::max(short(1),pNewOpt->GetDivisionX()):0,
67 rSz.Height()? rSz.Height()/std::max(short(1),pNewOpt->GetDivisionY()):0);
68 m_pDrawView->SetGridFine( aFSize );
69 Fraction aSnGrWdtX(rSz.Width(), pNewOpt->GetDivisionX() + 1);
70 Fraction aSnGrWdtY(rSz.Height(), pNewOpt->GetDivisionY() + 1);
71 m_pDrawView->SetSnapGridWidth( aSnGrWdtX, aSnGrWdtY );
73 if ( pRoot->getFrameArea().HasArea() )
74 m_pDrawView->SetWorkArea( pRoot->getFrameArea().SVRect() );
76 if ( GetShell()->IsPreview() )
77 m_pDrawView->SetAnimationEnabled( false );
79 m_pDrawView->SetUseIncompatiblePathCreateInterface( false );
81 // set handle size to 9 pixels, always
82 m_pDrawView->SetMarkHdlSizePixel(9);
85 /// CTor for the core internals
86 SwViewShellImp::SwViewShellImp( SwViewShell *pParent ) :
87 m_pShell( pParent ),
88 m_pSdrPageView( nullptr ),
89 m_pFirstVisiblePage( nullptr ),
90 m_pLayAction( nullptr ),
91 m_pIdleAct( nullptr ),
92 m_bFirstPageInvalid( true ),
93 m_bResetHdlHiddenPaint( false ),
94 m_bSmoothUpdate( false ),
95 m_bStopSmooth( false ),
96 m_nRestoreActions( 0 )
100 SwViewShellImp::~SwViewShellImp()
102 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
103 m_pAccessibleMap.reset();
104 #endif
106 m_pPagePreviewLayout.reset();
108 // Make sure HideSdrPage is also executed after ShowSdrPage.
109 if( m_pDrawView )
110 m_pDrawView->HideSdrPage();
112 m_pDrawView.reset();
114 DeletePaintRegion();
116 OSL_ENSURE( !m_pLayAction, "Have action for the rest of your life." );
117 OSL_ENSURE( !m_pIdleAct,"Be idle for the rest of your life." );
120 bool SwViewShellImp::AddPaintRect( const SwRect &rRect )
122 // In case of tiled rendering the visual area is the last painted tile -> not interesting.
123 if ( rRect.Overlaps( m_pShell->VisArea() ) || comphelper::LibreOfficeKit::isActive() )
125 if ( !m_oPaintRegion )
127 // In case of normal rendering, this makes sure only visible rectangles are painted.
128 // Otherwise get the rectangle of the full document, so all paint rectangles are invalidated.
129 const SwRect& rArea = comphelper::LibreOfficeKit::isActive() ? m_pShell->GetLayout()->getFrameArea() : m_pShell->VisArea();
130 m_oPaintRegion.emplace();
131 m_oPaintRegion->ChangeOrigin(rArea);
133 if(!m_oPaintRegion->empty())
135 // This function often gets called with rectangles that line up vertically.
136 // Try to extend the last one downwards to include the new one (use Union()
137 // in case the new one is actually already contained in the last one).
138 SwRect& last = m_oPaintRegion->back();
139 if(last.Left() == rRect.Left() && last.Width() == rRect.Width()
140 && last.Bottom() + 1 >= rRect.Top() && last.Bottom() <= rRect.Bottom())
142 last.Union(rRect);
143 // And these rectangles lined up vertically often come up in groups
144 // that line up horizontally. Try to extend the previous rectangle
145 // to the right to include the last one.
146 if(m_oPaintRegion->size() > 1)
148 SwRect& last2 = (*m_oPaintRegion)[m_oPaintRegion->size() - 2];
149 if(last2.Top() == last.Top() && last2.Height() == last.Height()
150 && last2.Right() + 1 >= last.Left() && last2.Right() <= last2.Right())
152 last2.Union(last);
153 m_oPaintRegion->pop_back();
154 return true;
157 return true;
160 (*m_oPaintRegion) += rRect;
161 return true;
163 return false;
166 void SwViewShellImp::AddPendingLOKInvalidation( const SwRect& rRect )
168 std::vector<SwRect>& l = m_pendingLOKInvalidations;
169 if(l.empty() && m_pShell && m_pShell->GetSfxViewShell()) // Announce that these invalidations will need flushing.
170 m_pShell->GetSfxViewShell()->libreOfficeKitViewAddPendingInvalidateTiles();
171 // These are often repeated, so check first for duplicates.
172 if( std::find( l.begin(), l.end(), rRect ) == l.end())
173 l.push_back( rRect );
176 std::vector<SwRect> SwViewShellImp::TakePendingLOKInvalidations()
178 std::vector<SwRect> ret;
179 std::swap(ret, m_pendingLOKInvalidations);
180 return ret;
183 void SwViewShellImp::CheckWaitCursor()
185 if ( m_pLayAction )
186 m_pLayAction->CheckWaitCursor();
189 bool SwViewShellImp::IsCalcLayoutProgress() const
191 return m_pLayAction && m_pLayAction->IsCalcLayout();
194 bool SwViewShellImp::IsUpdateExpFields()
196 if ( m_pLayAction && m_pLayAction->IsCalcLayout() )
198 m_pLayAction->SetUpdateExpFields();
199 return true;
201 return false;
204 void SwViewShellImp::SetFirstVisPage(OutputDevice const * pRenderContext)
206 if ( m_pShell->mbDocSizeChgd && m_pShell->VisArea().Top() > m_pShell->GetLayout()->getFrameArea().Height() )
208 //We are in an action and because of erase actions the VisArea is
209 //after the first visible page.
210 //To avoid excessive formatting, hand back the last page.
211 m_pFirstVisiblePage = static_cast<SwPageFrame*>(m_pShell->GetLayout()->Lower());
212 while ( m_pFirstVisiblePage && m_pFirstVisiblePage->GetNext() )
213 m_pFirstVisiblePage = static_cast<SwPageFrame*>(m_pFirstVisiblePage->GetNext());
215 else
217 const SwViewOption* pSwViewOption = GetShell()->GetViewOptions();
218 const bool bBookMode = pSwViewOption->IsViewLayoutBookMode();
220 SwPageFrame *pPage = static_cast<SwPageFrame*>(m_pShell->GetLayout()->Lower());
221 SwRect aPageRect = pPage->GetBoundRect(pRenderContext);
222 while ( pPage && !aPageRect.Overlaps( m_pShell->VisArea() ) )
224 pPage = static_cast<SwPageFrame*>(pPage->GetNext());
225 if ( pPage )
227 aPageRect = pPage->GetBoundRect(pRenderContext);
228 if ( bBookMode && pPage->IsEmptyPage() )
230 const SwPageFrame& rFormatPage = pPage->GetFormatPage();
231 aPageRect.SSize( rFormatPage.GetBoundRect(pRenderContext).SSize() );
235 m_pFirstVisiblePage = pPage ? pPage : static_cast<SwPageFrame*>(m_pShell->GetLayout()->Lower());
237 m_bFirstPageInvalid = false;
240 void SwViewShellImp::MakeDrawView()
242 IDocumentDrawModelAccess& rIDDMA = GetShell()->getIDocumentDrawModelAccess();
244 // the else here is not an error, MakeDrawModel_() calls this method again
245 // after the DrawModel is created to create DrawViews for all shells...
246 if( !rIDDMA.GetDrawModel() )
248 rIDDMA.MakeDrawModel_();
250 else
252 if ( !m_pDrawView )
254 // #i72809#
255 // Discussed with FME, he also thinks that the getPrinter is old and not correct. When i got
256 // him right, it anyways returns GetOut() when it's a printer, but NULL when not. He suggested
257 // to use GetOut() and check the existing cases.
258 // Check worked well. Took a look at viewing, printing, PDF export and print preview with a test
259 // document which has an empty 2nd page (right page, see bug)
260 auto pWin = GetShell()->GetWin();
261 OutputDevice* pOutDevForDrawView = pWin ? pWin->GetOutDev() : nullptr;
263 if(!pOutDevForDrawView)
265 pOutDevForDrawView = GetShell()->GetOut();
268 m_pDrawView.reset( new SwDrawView(
269 *this,
270 *rIDDMA.GetOrCreateDrawModel(),
271 pOutDevForDrawView) );
274 GetDrawView()->SetActiveLayer("Heaven");
275 const SwViewOption* pSwViewOption = GetShell()->GetViewOptions();
276 Init(pSwViewOption);
278 // #i68597# If document is read-only, we will not profit from overlay,
279 // so switch it off.
280 if (m_pDrawView->IsBufferedOverlayAllowed())
282 if(pSwViewOption->IsReadonly())
284 m_pDrawView->SetBufferedOverlayAllowed(false);
290 Color SwViewShellImp::GetRetoucheColor() const
292 Color aRet( COL_TRANSPARENT );
293 const SwViewShell &rSh = *GetShell();
294 if (rSh.GetWin() || rSh.isOutputToWindow())
296 if ( rSh.GetViewOptions()->getBrowseMode() &&
297 COL_TRANSPARENT != rSh.GetViewOptions()->GetRetoucheColor() )
298 aRet = rSh.GetViewOptions()->GetRetoucheColor();
299 else if(rSh.GetViewOptions()->IsPagePreview() &&
300 !officecfg::Office::Common::Accessibility::IsForPagePreviews::get())
301 aRet = COL_WHITE;
302 else
303 aRet = rSh.GetViewOptions()->GetDocColor();
305 return aRet;
308 SwPageFrame *SwViewShellImp::GetFirstVisPage(OutputDevice const * pRenderContext)
310 if ( m_bFirstPageInvalid )
311 SetFirstVisPage(pRenderContext);
312 return m_pFirstVisiblePage;
315 const SwPageFrame *SwViewShellImp::GetFirstVisPage(OutputDevice const * pRenderContext) const
317 if ( m_bFirstPageInvalid )
318 const_cast<SwViewShellImp*>(this)->SetFirstVisPage(pRenderContext);
319 return m_pFirstVisiblePage;
322 const SwPageFrame* SwViewShellImp::GetLastVisPage(const OutputDevice* pRenderContext) const
324 const SwViewOption* pSwViewOption = m_pShell->GetViewOptions();
325 const bool bBookMode = pSwViewOption->IsViewLayoutBookMode();
326 const SwPageFrame* pPage = GetFirstVisPage(pRenderContext);
327 const SwPageFrame* pLastVisPage = pPage;
328 SwRect aPageRect = pPage->GetBoundRect(pRenderContext);
329 while (pPage && (pPage->IsEmptyPage() || aPageRect.Overlaps(m_pShell->VisArea())))
331 pLastVisPage = pPage;
332 pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
333 if (pPage)
335 aPageRect = pPage->GetBoundRect(pRenderContext);
336 if (bBookMode && pPage->IsEmptyPage())
338 const SwPageFrame& rFormatPage = pPage->GetFormatPage();
339 aPageRect.SSize(rFormatPage.GetBoundRect(pRenderContext).SSize());
343 return pLastVisPage;
346 // create page preview layout
347 void SwViewShellImp::InitPagePreviewLayout()
349 OSL_ENSURE( m_pShell->GetLayout(), "no layout - page preview layout can not be created.");
350 if ( m_pShell->GetLayout() )
351 m_pPagePreviewLayout.reset( new SwPagePreviewLayout( *m_pShell, *(m_pShell->GetLayout()) ) );
354 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
355 void SwViewShellImp::UpdateAccessible()
357 // We require a layout and an XModel to be accessible.
358 IDocumentLayoutAccess& rIDLA = GetShell()->getIDocumentLayoutAccess();
359 vcl::Window *pWin = GetShell()->GetWin();
360 OSL_ENSURE( GetShell()->GetLayout(), "no layout, no access" );
361 OSL_ENSURE( pWin, "no window, no access" );
363 if( IsAccessible() && rIDLA.GetCurrentViewShell() && pWin )
367 GetAccessibleMap().GetDocumentView();
369 catch (uno::Exception const&)
371 TOOLS_WARN_EXCEPTION("sw.a11y", "");
372 assert(!"SwViewShellImp::UpdateAccessible: unhandled exception");
377 void SwViewShellImp::DisposeAccessible(const SwFrame *pFrame,
378 const SdrObject *pObj,
379 bool bRecursive,
380 bool bCanSkipInvisible)
382 OSL_ENSURE( !pFrame || pFrame->IsAccessibleFrame(), "frame is not accessible" );
383 for(SwViewShell& rTmp : GetShell()->GetRingContainer())
385 if( rTmp.Imp()->IsAccessible() )
386 rTmp.Imp()->GetAccessibleMap().A11yDispose( pFrame, pObj, nullptr, bRecursive, bCanSkipInvisible );
390 void SwViewShellImp::MoveAccessible( const SwFrame *pFrame, const SdrObject *pObj,
391 const SwRect& rOldFrame )
393 OSL_ENSURE( !pFrame || pFrame->IsAccessibleFrame(), "frame is not accessible" );
394 for(SwViewShell& rTmp : GetShell()->GetRingContainer())
396 if( rTmp.Imp()->IsAccessible() )
397 rTmp.Imp()->GetAccessibleMap().InvalidatePosOrSize( pFrame, pObj, nullptr,
398 rOldFrame );
402 void SwViewShellImp::InvalidateAccessibleFrameContent( const SwFrame *pFrame )
404 OSL_ENSURE( pFrame->IsAccessibleFrame(), "frame is not accessible" );
405 for(SwViewShell& rTmp : GetShell()->GetRingContainer())
407 if( rTmp.Imp()->IsAccessible() )
408 rTmp.Imp()->GetAccessibleMap().InvalidateContent( pFrame );
412 void SwViewShellImp::InvalidateAccessibleCursorPosition( const SwFrame *pFrame )
414 if( IsAccessible() )
415 GetAccessibleMap().InvalidateCursorPosition( pFrame );
418 void SwViewShellImp::InvalidateAccessibleEditableState( bool bAllShells,
419 const SwFrame *pFrame )
421 if( bAllShells )
423 for(SwViewShell& rTmp : GetShell()->GetRingContainer())
425 if( rTmp.Imp()->IsAccessible() )
426 rTmp.Imp()->GetAccessibleMap().InvalidateEditableStates( pFrame );
429 else if( IsAccessible() )
431 GetAccessibleMap().InvalidateEditableStates( pFrame );
435 void SwViewShellImp::InvalidateAccessibleRelationSet( const SwFlyFrame *pMaster,
436 const SwFlyFrame *pFollow )
438 for(SwViewShell& rTmp : GetShell()->GetRingContainer())
440 if( rTmp.Imp()->IsAccessible() )
441 rTmp.Imp()->GetAccessibleMap().InvalidateRelationSet( pMaster,
442 pFollow );
446 /// invalidate CONTENT_FLOWS_FROM/_TO relation for paragraphs
447 void SwViewShellImp::InvalidateAccessibleParaFlowRelation_( const SwTextFrame* _pFromTextFrame,
448 const SwTextFrame* _pToTextFrame )
450 if ( !_pFromTextFrame && !_pToTextFrame )
452 // No text frame provided. Thus, nothing to do.
453 return;
456 for(SwViewShell& rTmp : GetShell()->GetRingContainer())
458 if ( rTmp.Imp()->IsAccessible() )
460 if ( _pFromTextFrame )
462 rTmp.Imp()->GetAccessibleMap().
463 InvalidateParaFlowRelation( *_pFromTextFrame, true );
465 if ( _pToTextFrame )
467 rTmp.Imp()->GetAccessibleMap().
468 InvalidateParaFlowRelation( *_pToTextFrame, false );
474 /// invalidate text selection for paragraphs
475 void SwViewShellImp::InvalidateAccessibleParaTextSelection_()
477 for(SwViewShell& rTmp : GetShell()->GetRingContainer())
479 if ( rTmp.Imp()->IsAccessible() )
481 rTmp.Imp()->GetAccessibleMap().InvalidateTextSelectionOfAllParas();
486 /// invalidate attributes for paragraphs
487 void SwViewShellImp::InvalidateAccessibleParaAttrs_( const SwTextFrame& rTextFrame )
489 for(SwViewShell& rTmp : GetShell()->GetRingContainer())
491 if ( rTmp.Imp()->IsAccessible() )
493 rTmp.Imp()->GetAccessibleMap().InvalidateAttr( rTextFrame );
498 void SwViewShellImp::UpdateAccessiblePreview( const std::vector<std::unique_ptr<PreviewPage>>& _rPreviewPages,
499 const Fraction& _rScale,
500 const SwPageFrame* _pSelectedPageFrame,
501 const Size& _rPreviewWinSize )
503 if( IsAccessible() )
504 GetAccessibleMap().UpdatePreview( _rPreviewPages, _rScale,
505 _pSelectedPageFrame, _rPreviewWinSize );
508 void SwViewShellImp::InvalidateAccessiblePreviewSelection( sal_uInt16 nSelPage )
510 if( IsAccessible() )
511 GetAccessibleMap().InvalidatePreviewSelection( nSelPage );
514 SwAccessibleMap *SwViewShellImp::CreateAccessibleMap()
516 assert(!m_pAccessibleMap);
517 m_pAccessibleMap = std::make_shared<SwAccessibleMap>(GetShell());
518 return m_pAccessibleMap.get();
521 void SwViewShellImp::FireAccessibleEvents()
523 if( IsAccessible() )
524 GetAccessibleMap().FireEvents();
526 #endif // ENABLE_WASM_STRIP_ACCESSIBILITY
528 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */