1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <sal/config.h>
21
22 #include <scitems.hxx>
23
24 #include <comphelper/SetFlagContextHelper.hxx>
25 #include <sfx2/app.hxx>
26 #include <editeng/sizeitem.hxx>
27 #include <svx/zoomslideritem.hxx>
28 #include <svx/svdview.hxx>
29 #include <sfx2/dispatch.hxx>
30 #include <sfx2/objface.hxx>
31 #include <sfx2/request.hxx>
32 #include <svl/stritem.hxx>
33 #include <svl/whiter.hxx>
34 #include <vcl/commandevent.hxx>
35 #include <vcl/help.hxx>
36 #include <vcl/settings.hxx>
37 #include <vcl/svapp.hxx>
38 #include <tools/urlobj.hxx>
39 #include <sfx2/docfile.hxx>
40 #include <sfx2/printer.hxx>
41 #include <sfx2/viewfrm.hxx>
42 #include <sfx2/viewfac.hxx>
43 #include <o3tl/unit_conversion.hxx>
44
45 #include <drwlayer.hxx>
46 #include <prevwsh.hxx>
47 #include <preview.hxx>
48 #include <printfun.hxx>
49 #include <scmod.hxx>
50 #include <inputhdl.hxx>
51 #include <docsh.hxx>
52 #include <tabvwsh.hxx>
53 #include <stlpool.hxx>
54 #include <editutil.hxx>
55 #include <globstr.hrc>
56 #include <scresid.hxx>
57 #include <sc.hrc>
58 #include <ViewSettingsSequenceDefines.hxx>
59 #include <viewuno.hxx>
60
61 #include <svx/svxdlg.hxx>
62 #include <svx/dialogs.hrc>
63
64 #include <basegfx/utils/zoomtools.hxx>
65 #include <svx/zoom_def.hxx>
66 #include <com/sun/star/document/XDocumentProperties.hpp>
67
68 #include <scabstdlg.hxx>
69 #include <vcl/EnumContext.hxx>
70 #include <vcl/notebookbar/notebookbar.hxx>
71
72 // for mouse wheel
73 #define MINZOOM_SLIDER 10
74 #define MAXZOOM_SLIDER 400
75
76 #define SC_USERDATA_SEP ';'
77
78 using namespace com::sun::star;
79
80 #define ShellClass_ScPreviewShell
81 #include <scslots.hxx>
82
83 #include <memory>
84
85
SFX_IMPL_INTERFACE(ScPreviewShell,SfxViewShell)86 SFX_IMPL_INTERFACE(ScPreviewShell, SfxViewShell)
87
88 void ScPreviewShell::InitInterface_Impl()
89 {
90 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT,
91 SfxVisibilityFlags::Standard|SfxVisibilityFlags::Server|SfxVisibilityFlags::ReadonlyDoc,
92 ToolbarId::Objectbar_Preview);
93
94 GetStaticInterface()->RegisterPopupMenu("preview");
95 }
96
97 SFX_IMPL_NAMED_VIEWFACTORY( ScPreviewShell, "PrintPreview" )
98 {
99 SFX_VIEW_REGISTRATION(ScDocShell);
100 }
101
Construct(vcl::Window * pParent)102 void ScPreviewShell::Construct( vcl::Window* pParent )
103 {
104 // Find the top-most window, and set the close window handler to intercept
105 // the window close event.
106 vcl::Window* pWin = pParent;
107 while (!pWin->IsSystemWindow())
108 {
109 if (pWin->GetParent())
110 pWin = pWin->GetParent();
111 else
112 break;
113 }
114
115 mpFrameWindow = dynamic_cast<SystemWindow*>(pWin);
116 if (mpFrameWindow)
117 mpFrameWindow->SetCloseHdl(LINK(this, ScPreviewShell, CloseHdl));
118
119 eZoom = SvxZoomType::WHOLEPAGE;
120
121 pCorner = VclPtr<ScrollBarBox>::Create( pParent, WB_SIZEABLE );
122
123 pHorScroll = VclPtr<ScrollBar>::Create(pParent, WB_HSCROLL );
124 pVerScroll = VclPtr<ScrollBar>::Create(pParent, WB_VSCROLL);
125
126 // RTL: no mirroring for horizontal scrollbars
127 pHorScroll->EnableRTL( false );
128
129 pHorScroll->SetEndScrollHdl( LINK( this, ScPreviewShell, ScrollHandler ) );
130 pVerScroll->SetEndScrollHdl( LINK( this, ScPreviewShell, ScrollHandler ) );
131
132 pPreview = VclPtr<ScPreview>::Create( pParent, pDocShell, this );
133
134 SetPool( &SC_MOD()->GetPool() );
135 SetWindow( pPreview );
136 StartListening(*pDocShell, DuplicateHandling::Prevent);
137 StartListening(*SfxGetpApp(), DuplicateHandling::Prevent); // #i62045# #i62046# application is needed for Calc's own hints
138 SfxBroadcaster* pDrawBC = pDocShell->GetDocument().GetDrawBroadcaster();
139 if (pDrawBC)
140 StartListening(*pDrawBC);
141
142 pHorScroll->Show( false );
143 pVerScroll->Show( false );
144 pCorner->Show();
145 SetName("Preview");
146 }
147
ScPreviewShell(SfxViewFrame * pViewFrame,SfxViewShell * pOldSh)148 ScPreviewShell::ScPreviewShell( SfxViewFrame* pViewFrame,
149 SfxViewShell* pOldSh ) :
150 SfxViewShell( pViewFrame, SfxViewShellFlags::HAS_PRINTOPTIONS ),
151 pDocShell( static_cast<ScDocShell*>(pViewFrame->GetObjectShell()) ),
152 mpFrameWindow(nullptr),
153 nSourceDesignMode( TRISTATE_INDET ),
154 nMaxVertPos(0)
155 {
156 Construct( &pViewFrame->GetWindow() );
157
158 try
159 {
160 SfxShell::SetContextBroadcasterEnabled(true);
161 SfxShell::SetContextName(
162 vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Printpreview));
163 SfxShell::BroadcastContextForActivation(true);
164 }
165 catch (const css::uno::RuntimeException& e)
166 {
167 // tdf#130559: allow BackingComp to fail adding listener when opening document
168 css::uno::Reference<css::lang::XServiceInfo> xServiceInfo(e.Context, css::uno::UNO_QUERY);
169 if (!xServiceInfo || !xServiceInfo->supportsService("com.sun.star.frame.StartModule"))
170 throw;
171 SAL_WARN("sc.ui", "Opening file from StartModule straight into print preview");
172 }
173
174 auto& pNotebookBar = pViewFrame->GetWindow().GetSystemWindow()->GetNotebookBar();
175 if (pNotebookBar)
176 pNotebookBar->ControlListenerForCurrentController(false); // stop listening
177
178 if ( auto pTabViewShell = dynamic_cast<ScTabViewShell*>( pOldSh) )
179 {
180 // store view settings, show table from TabView
181 //! store live ScViewData instead, and update on ScTablesHint?
182 //! or completely forget aSourceData on ScTablesHint?
183
184 const ScViewData& rData = pTabViewShell->GetViewData();
185 pPreview->SetSelectedTabs(rData.GetMarkData());
186 InitStartTable( rData.GetTabNo() );
187
188 // also have to store the TabView's DesignMode state
189 // (only if draw view exists)
190 SdrView* pDrawView = pTabViewShell->GetScDrawView();
191 if ( pDrawView )
192 nSourceDesignMode
193 = pDrawView->IsDesignMode() ? TRISTATE_TRUE : TRISTATE_FALSE;
194 }
195
196 new ScPreviewObj(this);
197 }
198
~ScPreviewShell()199 ScPreviewShell::~ScPreviewShell()
200 {
201 if (mpFrameWindow)
202 mpFrameWindow->SetCloseHdl(Link<SystemWindow&,void>()); // Remove close handler.
203
204 if (auto& pBar = GetViewFrame()->GetWindow().GetSystemWindow()->GetNotebookBar())
205 pBar->ControlListenerForCurrentController(true); // let it start listening now
206
207 // #108333#; notify Accessibility that Shell is dying and before destroy all
208 BroadcastAccessibility( SfxHint( SfxHintId::Dying ) );
209 pAccessibilityBroadcaster.reset();
210
211 SfxBroadcaster* pDrawBC = pDocShell->GetDocument().GetDrawBroadcaster();
212 if (pDrawBC)
213 EndListening(*pDrawBC);
214 EndListening(*SfxGetpApp());
215 EndListening(*pDocShell);
216
217 SetWindow(nullptr);
218 pPreview.disposeAndClear();
219 pHorScroll.disposeAndClear();
220 pVerScroll.disposeAndClear();
221 pCorner.disposeAndClear();
222
223 // normal mode of operation is switching back to default view in the same frame,
224 // so there's no need to activate any other window here anymore
225 }
226
InitStartTable(SCTAB nTab)227 void ScPreviewShell::InitStartTable(SCTAB nTab)
228 {
229 pPreview->SetPageNo( pPreview->GetFirstPage(nTab) );
230 }
231
AdjustPosSizePixel(const Point & rPos,const Size & rSize)232 void ScPreviewShell::AdjustPosSizePixel( const Point &rPos, const Size &rSize )
233 {
234 Size aOutSize( rSize );
235 pPreview->SetPosSizePixel( rPos, aOutSize );
236
237 if ( SvxZoomType::WHOLEPAGE == eZoom )
238 pPreview->SetZoom( pPreview->GetOptimalZoom(false) );
239 else if ( SvxZoomType::PAGEWIDTH == eZoom )
240 pPreview->SetZoom( pPreview->GetOptimalZoom(true) );
241
242 UpdateNeededScrollBars(false);
243 }
244
InnerResizePixel(const Point & rOfs,const Size & rSize,bool)245 void ScPreviewShell::InnerResizePixel( const Point &rOfs, const Size &rSize, bool )
246 {
247 AdjustPosSizePixel( rOfs,rSize );
248 }
249
OuterResizePixel(const Point & rOfs,const Size & rSize)250 void ScPreviewShell::OuterResizePixel( const Point &rOfs, const Size &rSize )
251 {
252 AdjustPosSizePixel( rOfs,rSize );
253 }
254
GetPageSize(Size & aPageSize)255 bool ScPreviewShell::GetPageSize( Size& aPageSize )
256 {
257 ScDocument& rDoc = pDocShell->GetDocument();
258 SCTAB nTab = pPreview->GetTab();
259
260 ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
261 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( rDoc.GetPageStyle( nTab ),
262 SfxStyleFamily::Page );
263 OSL_ENSURE(pStyleSheet,"No style sheet");
264 if (!pStyleSheet) return false;
265 const SfxItemSet* pParamSet = &pStyleSheet->GetItemSet();
266
267 aPageSize = pParamSet->Get(ATTR_PAGE_SIZE).GetSize();
268 aPageSize.setWidth(o3tl::convert(aPageSize.Width(), o3tl::Length::twip, o3tl::Length::mm100));
269 aPageSize.setHeight(o3tl::convert(aPageSize.Height(), o3tl::Length::twip, o3tl::Length::mm100));
270 return true;
271 }
272
UpdateNeededScrollBars(bool bFromZoom)273 void ScPreviewShell::UpdateNeededScrollBars( bool bFromZoom )
274 {
275 Size aPageSize;
276 OutputDevice* pDevice = Application::GetDefaultDevice();
277
278 tools::Long nBarW = GetViewFrame()->GetWindow().GetSettings().GetStyleSettings().GetScrollBarSize();
279 tools::Long nBarH = nBarW;
280
281 tools::Long aHeightOffSet = pDevice ? pDevice->PixelToLogic( Size( nBarW, nBarH ), pPreview->GetMapMode() ).Height() : 0;
282 tools::Long aWidthOffSet = aHeightOffSet;
283
284 if (!GetPageSize( aPageSize ))
285 return;
286
287 // for centering, page size without the shadow is used
288 bool bVert = pVerScroll->IsVisible();
289 bool bHori = pHorScroll->IsVisible();
290 Size aWindowSize = pPreview->GetOutDev()->GetOutputSize();
291 Point aPos = pPreview->GetPosPixel();
292 Size aWindowPixelSize = pPreview->GetOutputSizePixel();
293
294 // if we are called from Zoom then we need to compensate for whatever
295 // scrollbars were displayed before the zoom was called
296 if ( bFromZoom )
297 {
298 if ( bVert )
299 {
300 aWindowPixelSize.AdjustWidth(nBarH );
301 aWindowSize.AdjustWidth(aHeightOffSet );
302 }
303 if ( bHori )
304 {
305 aWindowPixelSize.AdjustHeight(nBarW );
306 aWindowSize.AdjustHeight(aWidthOffSet );
307 }
308 }
309
310 // recalculate any needed scrollbars
311 tools::Long nMaxWidthPos = aPageSize.Width() - aWindowSize.Width();
312 bHori = nMaxWidthPos >= 0;
313 tools::Long nMaxHeightPos = aPageSize.Height() - aWindowSize.Height();
314 bVert = nMaxHeightPos >= 0;
315
316 // see if having a scroll bar requires the other
317 if ( bVert != bHori && ( bVert || bHori ) )
318 {
319 if ( bVert && ( (nMaxWidthPos + aWidthOffSet ) > 0 ) )
320 bHori = true;
321 else if ( (nMaxHeightPos + aHeightOffSet ) > 0 )
322 bVert = true;
323 }
324 pHorScroll->Show( bHori );
325 pVerScroll->Show( bVert );
326
327 // make room for needed scrollbars ( and reduce the size
328 // of the preview appropriately )
329 if ( bHori )
330 aWindowPixelSize.AdjustHeight( -nBarW );
331 if ( bVert )
332 aWindowPixelSize.AdjustWidth( -nBarH );
333
334 pPreview->SetSizePixel( aWindowPixelSize );
335 pHorScroll->SetPosSizePixel( Point( aPos.X(), aPos.Y() + aWindowPixelSize.Height() ),
336 Size( aWindowPixelSize.Width(), nBarH ) );
337 pVerScroll->SetPosSizePixel( Point( aPos.X() + aWindowPixelSize.Width(), aPos.Y() ),
338 Size( nBarW, aWindowPixelSize.Height() ) );
339 pCorner->SetPosSizePixel( Point( aPos.X() + aWindowPixelSize.Width(), aPos.Y() + aWindowPixelSize.Height() ),
340 Size( nBarW, nBarH ) );
341 UpdateScrollBars();
342 }
343
UpdateScrollBars()344 void ScPreviewShell::UpdateScrollBars()
345 {
346 Size aPageSize;
347 if ( !GetPageSize( aPageSize ) )
348 return;
349
350 // for centering, page size without the shadow is used
351
352 Size aWindowSize = pPreview->GetOutDev()->GetOutputSize();
353
354 Point aOfs = pPreview->GetOffset();
355
356 if( pHorScroll )
357 {
358 pHorScroll->SetRange( Range( 0, aPageSize.Width() ) );
359 pHorScroll->SetLineSize( aWindowSize.Width() / 16 );
360 pHorScroll->SetPageSize( aWindowSize.Width() );
361 pHorScroll->SetVisibleSize( aWindowSize.Width() );
362 tools::Long nMaxPos = aPageSize.Width() - aWindowSize.Width();
363 if ( nMaxPos<0 )
364 {
365 // page smaller than window -> center (but put scrollbar to 0)
366 aOfs.setX( 0 );
367 pPreview->SetXOffset( nMaxPos / 2 );
368 }
369 else if (aOfs.X() < 0)
370 {
371 // page larger than window -> never use negative offset
372 aOfs.setX( 0 );
373 pPreview->SetXOffset( 0 );
374 }
375 else if (aOfs.X() > nMaxPos)
376 {
377 // limit offset to align with right edge of window
378 aOfs.setX( nMaxPos );
379 pPreview->SetXOffset(nMaxPos);
380 }
381 pHorScroll->SetThumbPos( aOfs.X() );
382 }
383
384 if( !pVerScroll )
385 return;
386
387 tools::Long nPageNo = pPreview->GetPageNo();
388 tools::Long nTotalPages = pPreview->GetTotalPages();
389
390 nMaxVertPos = aPageSize.Height() - aWindowSize.Height();
391 pVerScroll->SetLineSize( aWindowSize.Height() / 16 );
392 pVerScroll->SetPageSize( aWindowSize.Height() );
393 pVerScroll->SetVisibleSize( aWindowSize.Height() );
394 if ( nMaxVertPos < 0 )
395 {
396 // page smaller than window -> center (but put scrollbar to 0)
397 aOfs.setY( 0 );
398 pPreview->SetYOffset( nMaxVertPos / 2 );
399 pVerScroll->SetThumbPos( nPageNo * aWindowSize.Height() );
400 pVerScroll->SetRange( Range( 0, aWindowSize.Height() * nTotalPages ));
401 }
402 else if (aOfs.Y() < 0)
403 {
404 // page larger than window -> never use negative offset
405 pVerScroll->SetRange( Range( 0, aPageSize.Height() ) );
406 aOfs.setY( 0 );
407 pPreview->SetYOffset( 0 );
408 pVerScroll->SetThumbPos( aOfs.Y() );
409 }
410 else if (aOfs.Y() > nMaxVertPos )
411 {
412 // limit offset to align with window bottom
413 pVerScroll->SetRange( Range( 0, aPageSize.Height() ) );
414 aOfs.setY( nMaxVertPos );
415 pPreview->SetYOffset( nMaxVertPos );
416 pVerScroll->SetThumbPos( aOfs.Y() );
417 }
418 }
419
IMPL_LINK(ScPreviewShell,ScrollHandler,ScrollBar *,pScroll,void)420 IMPL_LINK( ScPreviewShell, ScrollHandler, ScrollBar*, pScroll, void )
421 {
422 tools::Long nPos = pScroll->GetThumbPos();
423 tools::Long nDelta = pScroll->GetDelta();
424 tools::Long nMaxRange = pScroll->GetRangeMax();
425 tools::Long nTotalPages = pPreview->GetTotalPages();
426 tools::Long nPageNo = 0;
427 tools::Long nPerPageLength = 0;
428 bool bIsDivide = true;
429
430 if( nTotalPages )
431 nPerPageLength = nMaxRange / nTotalPages;
432
433 if( nPerPageLength )
434 {
435 nPageNo = nPos / nPerPageLength;
436 if( nPos % nPerPageLength )
437 {
438 bIsDivide = false;
439 nPageNo ++;
440 }
441 }
442
443 bool bHoriz = ( pScroll == pHorScroll );
444
445 if( bHoriz )
446 pPreview->SetXOffset( nPos );
447 else
448 {
449 if( nMaxVertPos > 0 )
450 pPreview->SetYOffset( nPos );
451 else
452 {
453 Point aMousePos = pScroll->OutputToNormalizedScreenPixel( pScroll->GetPointerPosPixel() );
454 Point aPos = pScroll->GetParent()->OutputToNormalizedScreenPixel( pScroll->GetPosPixel() );
455 OUString aHelpStr;
456 tools::Rectangle aRect;
457 QuickHelpFlags nAlign;
458
459 if( nDelta < 0 )
460 {
461 if ( nTotalPages && nPageNo > 0 && !bIsDivide )
462 pPreview->SetPageNo( nPageNo-1 );
463 if( bIsDivide )
464 pPreview->SetPageNo( nPageNo );
465
466 aHelpStr = ScResId( STR_PAGE ) +
467 " " + OUString::number( nPageNo ) +
468 " / " + OUString::number( nTotalPages );
469 }
470 else if( nDelta > 0 )
471 {
472 bool bAllTested = pPreview->AllTested();
473 if ( nTotalPages && ( nPageNo < nTotalPages || !bAllTested ) )
474 pPreview->SetPageNo( nPageNo );
475
476 aHelpStr = ScResId( STR_PAGE ) +
477 " " + OUString::number( nPageNo+1 ) +
478 " / " + OUString::number( nTotalPages );
479 }
480
481 aRect.SetLeft( aPos.X() - 8 );
482 aRect.SetTop( aMousePos.Y() );
483 aRect.SetRight( aRect.Left() );
484 aRect.SetBottom( aRect.Top() );
485 nAlign = QuickHelpFlags::Bottom|QuickHelpFlags::Center;
486 Help::ShowQuickHelp( pScroll->GetParent(), aRect, aHelpStr, nAlign );
487 }
488 }
489 }
490
IMPL_LINK_NOARG(ScPreviewShell,CloseHdl,SystemWindow &,void)491 IMPL_LINK_NOARG(ScPreviewShell, CloseHdl, SystemWindow&, void)
492 {
493 ExitPreview();
494 }
495
ScrollCommand(const CommandEvent & rCEvt)496 bool ScPreviewShell::ScrollCommand( const CommandEvent& rCEvt )
497 {
498 bool bDone = false;
499 const CommandWheelData* pData = rCEvt.GetWheelData();
500 if ( pData && pData->GetMode() == CommandWheelMode::ZOOM )
501 {
502 tools::Long nOld = pPreview->GetZoom();
503 tools::Long nNew;
504 if ( pData->GetDelta() < 0 )
505 nNew = std::max( tools::Long(MINZOOM), basegfx::zoomtools::zoomOut( nOld ));
506 else
507 nNew = std::min( tools::Long(MAXZOOM), basegfx::zoomtools::zoomIn( nOld ));
508
509 if ( nNew != nOld )
510 {
511 eZoom = SvxZoomType::PERCENT;
512 pPreview->SetZoom( static_cast<sal_uInt16>(nNew) );
513 }
514
515 bDone = true;
516 }
517 else
518 {
519 bDone = pPreview->HandleScrollCommand( rCEvt, pHorScroll, pVerScroll );
520 }
521
522 return bDone;
523 }
524
GetPrinter(bool bCreate)525 SfxPrinter* ScPreviewShell::GetPrinter( bool bCreate )
526 {
527 return pDocShell->GetPrinter(bCreate);
528 }
529
SetPrinter(SfxPrinter * pNewPrinter,SfxPrinterChangeFlags nDiffFlags)530 sal_uInt16 ScPreviewShell::SetPrinter( SfxPrinter *pNewPrinter, SfxPrinterChangeFlags nDiffFlags )
531 {
532 return pDocShell->SetPrinter( pNewPrinter, nDiffFlags );
533 }
534
HasPrintOptionsPage() const535 bool ScPreviewShell::HasPrintOptionsPage() const
536 {
537 return true;
538 }
539
CreatePrintOptionsPage(weld::Container * pPage,weld::DialogController * pController,const SfxItemSet & rOptions)540 std::unique_ptr<SfxTabPage> ScPreviewShell::CreatePrintOptionsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rOptions)
541 {
542 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
543 ::CreateTabPage ScTpPrintOptionsCreate = pFact->GetTabPageCreatorFunc(RID_SC_TP_PRINT);
544 if ( ScTpPrintOptionsCreate )
545 return ScTpPrintOptionsCreate(pPage, pController, &rOptions);
546 return nullptr;
547 }
548
Activate(bool bMDI)549 void ScPreviewShell::Activate(bool bMDI)
550 {
551 SfxViewShell::Activate(bMDI);
552
553 //! Basic etc. -> outsource to its own file (see tabvwsh4)
554
555 if (bMDI)
556 {
557 // InputHdl is now mostly Null, no more assertion!
558 ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
559 if ( pInputHdl )
560 pInputHdl->NotifyChange( nullptr );
561 }
562 }
563
Execute(SfxRequest & rReq)564 void ScPreviewShell::Execute( SfxRequest& rReq )
565 {
566 sal_uInt16 nSlot = rReq.GetSlot();
567 const SfxItemSet* pReqArgs = rReq.GetArgs();
568
569 switch ( nSlot )
570 {
571 case SID_FORMATPAGE:
572 case SID_STATUS_PAGESTYLE:
573 case SID_HFEDIT:
574 pDocShell->ExecutePageStyle( *this, rReq, pPreview->GetTab() );
575 break;
576 case SID_REPAINT:
577 pPreview->Invalidate();
578 rReq.Done();
579 break;
580 case SID_PREV_TABLE: // Accelerator
581 case SID_PREVIEW_PREVIOUS:
582 {
583 tools::Long nPage = pPreview->GetPageNo();
584 tools::Long nTotal = pPreview->GetTotalPages();
585 if (nTotal && nPage > 0)
586 pPreview->SetPageNo( nPage-1 );
587 }
588 break;
589 case SID_NEXT_TABLE: // Accelerator
590 case SID_PREVIEW_NEXT:
591 {
592 bool bAllTested = pPreview->AllTested();
593 tools::Long nPage = pPreview->GetPageNo();
594 tools::Long nTotal = pPreview->GetTotalPages();
595 if (nTotal && (nPage+1 < nTotal || !bAllTested))
596 pPreview->SetPageNo( nPage+1 );
597 }
598 break;
599 case SID_CURSORTOPOFFILE: // Accelerator
600 case SID_PREVIEW_FIRST:
601 {
602 tools::Long nPage = pPreview->GetPageNo();
603 tools::Long nTotal = pPreview->GetTotalPages();
604 if (nTotal && nPage != 0)
605 pPreview->SetPageNo( 0 );
606 }
607 break;
608 case SID_CURSORENDOFFILE: // Accelerator
609 case SID_PREVIEW_LAST:
610 {
611 if (!pPreview->AllTested())
612 pPreview->CalcAll();
613
614 tools::Long nPage = pPreview->GetPageNo();
615 tools::Long nTotal = pPreview->GetTotalPages();
616 if (nTotal && nPage+1 != nTotal)
617 pPreview->SetPageNo( nTotal-1 );
618 }
619 break;
620 case SID_ATTR_ZOOM:
621 case FID_SCALE:
622 {
623 sal_uInt16 nZoom = 100;
624 bool bCancel = false;
625
626 eZoom = SvxZoomType::PERCENT;
627
628 if ( pReqArgs )
629 {
630
631 const SvxZoomItem& rZoomItem = pReqArgs->Get(SID_ATTR_ZOOM);
632
633 eZoom = rZoomItem.GetType();
634 nZoom = rZoomItem.GetValue();
635 }
636 else
637 {
638 SfxItemSet aSet ( GetPool(), svl::Items<SID_ATTR_ZOOM, SID_ATTR_ZOOM>{} );
639 SvxZoomItem aZoomItem( SvxZoomType::PERCENT, pPreview->GetZoom(), SID_ATTR_ZOOM );
640
641 aSet.Put( aZoomItem );
642 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
643 ScopedVclPtr<AbstractSvxZoomDialog> pDlg(pFact->CreateSvxZoomDialog(nullptr, aSet));
644 pDlg->SetLimits( 20, 400 );
645 pDlg->HideButton( ZoomButtonId::OPTIMAL );
646 bCancel = ( RET_CANCEL == pDlg->Execute() );
647
648 if ( !bCancel )
649 {
650 const SvxZoomItem& rZoomItem = pDlg->GetOutputItemSet()->
651 Get( SID_ATTR_ZOOM );
652
653 eZoom = rZoomItem.GetType();
654 nZoom = rZoomItem.GetValue();
655 }
656 }
657
658 if ( !bCancel )
659 {
660 switch ( eZoom )
661 {
662 case SvxZoomType::OPTIMAL:
663 case SvxZoomType::WHOLEPAGE:
664 nZoom = pPreview->GetOptimalZoom(false);
665 break;
666 case SvxZoomType::PAGEWIDTH:
667 nZoom = pPreview->GetOptimalZoom(true);
668 break;
669 default:
670 {
671 // added to avoid warnings
672 }
673 }
674
675 pPreview->SetZoom( nZoom );
676 rReq.Done();
677 }
678 }
679 break;
680 case SID_ZOOM_IN:
681 {
682 sal_uInt16 nNew = pPreview->GetZoom() + 20 ;
683 nNew -= nNew % 20;
684 pPreview->SetZoom( nNew );
685 eZoom = SvxZoomType::PERCENT;
686 rReq.Done();
687 }
688 break;
689 case SID_ZOOM_OUT:
690 {
691 sal_uInt16 nNew = pPreview->GetZoom() - 1;
692 nNew -= nNew % 20;
693 pPreview->SetZoom( nNew );
694 eZoom = SvxZoomType::PERCENT;
695 rReq.Done();
696 }
697 break;
698 case SID_PREVIEW_MARGIN:
699 {
700 bool bMargin = pPreview->GetPageMargins();
701 pPreview->SetPageMargins( !bMargin );
702 pPreview->Invalidate();
703 rReq.Done();
704 }
705 break;
706 case SID_ATTR_ZOOMSLIDER:
707 {
708 const SfxPoolItem* pItem;
709 eZoom = SvxZoomType::PERCENT;
710 if( pReqArgs && SfxItemState::SET == pReqArgs->GetItemState( SID_ATTR_ZOOMSLIDER, true, &pItem ) )
711 {
712 const sal_uInt16 nCurrentZoom = static_cast<const SvxZoomSliderItem*>(pItem)->GetValue();
713 if( nCurrentZoom )
714 {
715 pPreview->SetZoom( nCurrentZoom );
716 rReq.Done();
717 }
718 }
719 }
720 break;
721 case SID_PREVIEW_SCALINGFACTOR:
722 {
723 const SfxPoolItem* pItem;
724 SCTAB nTab = pPreview->GetTab();
725 OUString aOldName = pDocShell->GetDocument().GetPageStyle( pPreview->GetTab() );
726 ScStyleSheetPool* pStylePool = pDocShell->GetDocument().GetStyleSheetPool();
727 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aOldName, SfxStyleFamily::Page );
728 OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" );
729
730 if ( pReqArgs && pStyleSheet && SfxItemState::SET == pReqArgs->GetItemState( SID_PREVIEW_SCALINGFACTOR, true, &pItem ) )
731 {
732 const sal_uInt16 nCurrentZoom = static_cast<const SvxZoomSliderItem *>(pItem)->GetValue();
733 SfxItemSet& rSet = pStyleSheet->GetItemSet();
734 rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALE, nCurrentZoom ) );
735 ScPrintFunc aPrintFunc( pDocShell, pDocShell->GetPrinter(), nTab );
736 aPrintFunc.UpdatePages();
737 rReq.Done();
738 }
739 GetViewFrame()->GetBindings().Invalidate( nSlot );
740 }
741 break;
742 case SID_PRINTPREVIEW:
743 case SID_PREVIEW_CLOSE:
744 // print preview is now always in the same frame as the tab view
745 // -> always switch this frame back to normal view
746 // (ScTabViewShell ctor reads stored view data)
747
748 ExitPreview();
749 break;
750 case SID_CURSORPAGEUP:
751 case SID_CURSORPAGEDOWN:
752 case SID_CURSORHOME:
753 case SID_CURSOREND:
754 case SID_CURSORUP:
755 case SID_CURSORDOWN:
756 case SID_CURSORLEFT:
757 case SID_CURSORRIGHT:
758 DoScroll( nSlot );
759 break;
760 case SID_CANCEL:
761 if( ScViewUtil::IsFullScreen( *this ) )
762 ScViewUtil::SetFullScreen( *this, false );
763 break;
764
765 default:
766 break;
767 }
768 }
769
GetState(SfxItemSet & rSet)770 void ScPreviewShell::GetState( SfxItemSet& rSet )
771 {
772 pPreview->SetInGetState(true);
773
774 SCTAB nTab = pPreview->GetTab();
775 tools::Long nPage = pPreview->GetPageNo();
776 tools::Long nTotal = pPreview->GetTotalPages();
777 sal_uInt16 nZoom = pPreview->GetZoom();
778 bool bAllTested = pPreview->AllTested();
779
780 SfxWhichIter aIter(rSet);
781 sal_uInt16 nWhich = aIter.FirstWhich();
782 while ( nWhich )
783 {
784 switch (nWhich)
785 {
786 case SID_STATUS_PAGESTYLE:
787 case SID_HFEDIT:
788 pDocShell->GetStatePageStyle( rSet, nTab );
789 break;
790 case SID_UNDO:
791 case SID_REDO:
792 case SID_REPEAT:
793 case SID_SAVEDOC:
794 case SID_SAVEASDOC:
795 case SID_MAIL_SENDDOC:
796 case SID_VIEW_DATA_SOURCE_BROWSER:
797 case SID_QUITAPP:
798 rSet.DisableItem(nWhich);
799 break;
800 case SID_PREVIEW_PREVIOUS:
801 case SID_PREVIEW_FIRST:
802 if (!nTotal || nPage==0)
803 rSet.DisableItem(nWhich);
804 break;
805 case SID_PREVIEW_NEXT:
806 case SID_PREVIEW_LAST:
807 if (bAllTested)
808 if (!nTotal || nPage==nTotal-1)
809 rSet.DisableItem(nWhich);
810 break;
811 case SID_ZOOM_IN:
812 if (nZoom >= 400)
813 rSet.DisableItem(nWhich);
814 break;
815 case SID_ZOOM_OUT:
816 if (nZoom <= 20)
817 rSet.DisableItem(nWhich);
818 break;
819 case SID_ATTR_ZOOM:
820 {
821 SvxZoomItem aZoom( eZoom, nZoom, nWhich );
822 aZoom.SetValueSet( SvxZoomEnableFlags::ALL & ~SvxZoomEnableFlags::OPTIMAL );
823 rSet.Put( aZoom );
824 }
825 break;
826 case SID_ATTR_ZOOMSLIDER:
827 {
828 SvxZoomSliderItem aZoomSliderItem( nZoom, MINZOOM, MAXZOOM, SID_ATTR_ZOOMSLIDER );
829 aZoomSliderItem.AddSnappingPoint( 100 );
830 rSet.Put( aZoomSliderItem );
831 }
832 break;
833 case SID_PREVIEW_SCALINGFACTOR:
834 {
835 if( pDocShell->IsReadOnly() )
836 rSet.DisableItem( nWhich );
837 else
838 {
839 OUString aOldName = pDocShell->GetDocument().GetPageStyle( pPreview->GetTab() );
840 ScStyleSheetPool* pStylePool = pDocShell->GetDocument().GetStyleSheetPool();
841 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aOldName, SfxStyleFamily::Page );
842 OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" );
843
844 if ( pStyleSheet )
845 {
846 SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
847 sal_uInt16 nCurrentZoom = rStyleSet.Get(ATTR_PAGE_SCALE).GetValue();
848 if( nCurrentZoom )
849 {
850 SvxZoomSliderItem aZoomSliderItem( nCurrentZoom, MINZOOM_SLIDER, MAXZOOM_SLIDER, SID_PREVIEW_SCALINGFACTOR );
851 aZoomSliderItem.AddSnappingPoint( 100 );
852 rSet.Put( aZoomSliderItem );
853 }
854 else
855 rSet.DisableItem( nWhich );
856 }
857 }
858 }
859 break;
860 case SID_STATUS_DOCPOS:
861 rSet.Put( SfxStringItem( nWhich, pPreview->GetPosString() ) );
862 break;
863 case SID_PRINTPREVIEW:
864 rSet.Put( SfxBoolItem( nWhich, true ) );
865 break;
866 case SID_FORMATPAGE:
867 case SID_PREVIEW_MARGIN:
868 if( pDocShell->IsReadOnly() )
869 rSet.DisableItem( nWhich );
870 break;
871 }
872
873 nWhich = aIter.NextWhich();
874 }
875
876 pPreview->SetInGetState(false);
877 }
878
FillFieldData(ScHeaderFieldData & rData)879 void ScPreviewShell::FillFieldData( ScHeaderFieldData& rData )
880 {
881 ScDocument& rDoc = pDocShell->GetDocument();
882 SCTAB nTab = pPreview->GetTab();
883 OUString aTmp;
884 rDoc.GetName(nTab, aTmp);
885 rData.aTabName = aTmp;
886
887 if( pDocShell->getDocProperties()->getTitle().getLength() != 0 )
888 rData.aTitle = pDocShell->getDocProperties()->getTitle();
889 else
890 rData.aTitle = pDocShell->GetTitle();
891
892 const INetURLObject& rURLObj = pDocShell->GetMedium()->GetURLObject();
893 rData.aLongDocName = rURLObj.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous );
894 if ( !rData.aLongDocName.isEmpty() )
895 rData.aShortDocName = rURLObj.GetLastName(INetURLObject::DecodeMechanism::Unambiguous);
896 else
897 rData.aShortDocName = rData.aLongDocName = rData.aTitle;
898 rData.nPageNo = pPreview->GetPageNo() + 1;
899
900 bool bAllTested = pPreview->AllTested();
901 if (bAllTested)
902 rData.nTotalPages = pPreview->GetTotalPages();
903 else
904 rData.nTotalPages = 99;
905
906 // the dialog knows eNumType
907 }
908
WriteUserData(OUString & rData,bool)909 void ScPreviewShell::WriteUserData(OUString& rData, bool /* bBrowse */)
910 {
911 // nZoom
912 // nPageNo
913
914 rData = OUString::number(pPreview->GetZoom())
915 + OUStringChar(SC_USERDATA_SEP)
916 + OUString::number(pPreview->GetPageNo());
917 }
918
ReadUserData(const OUString & rData,bool)919 void ScPreviewShell::ReadUserData(const OUString& rData, bool /* bBrowse */)
920 {
921 if (!rData.isEmpty())
922 {
923 sal_Int32 nIndex = 0;
924 pPreview->SetZoom(static_cast<sal_uInt16>(rData.getToken(0, SC_USERDATA_SEP, nIndex).toInt32()));
925 pPreview->SetPageNo(rData.getToken(0, SC_USERDATA_SEP, nIndex).toInt32());
926 eZoom = SvxZoomType::PERCENT;
927 }
928 }
929
WriteUserDataSequence(uno::Sequence<beans::PropertyValue> & rSeq)930 void ScPreviewShell::WriteUserDataSequence(uno::Sequence < beans::PropertyValue >& rSeq)
931 {
932 // tdf#130559: don't export preview view data if active
933 if (comphelper::IsContextFlagActive("NoPreviewData"))
934 return;
935
936 rSeq.realloc(3);
937 beans::PropertyValue* pSeq = rSeq.getArray();
938 sal_uInt16 nViewID(GetViewFrame()->GetCurViewId());
939 pSeq[0].Name = SC_VIEWID;
940 pSeq[0].Value <<= SC_VIEW + OUString::number(nViewID);
941 pSeq[1].Name = SC_ZOOMVALUE;
942 pSeq[1].Value <<= sal_Int32 (pPreview->GetZoom());
943 pSeq[2].Name = "PageNumber";
944 pSeq[2].Value <<= pPreview->GetPageNo();
945
946 // Common SdrModel processing
947 if (ScDrawLayer* pDrawLayer = GetDocument().GetDrawLayer())
948 pDrawLayer->WriteUserDataSequence(rSeq);
949 }
950
ReadUserDataSequence(const uno::Sequence<beans::PropertyValue> & rSeq)951 void ScPreviewShell::ReadUserDataSequence(const uno::Sequence < beans::PropertyValue >& rSeq)
952 {
953 for (const auto& propval : rSeq)
954 {
955 if (propval.Name == SC_ZOOMVALUE)
956 {
957 sal_Int32 nTemp = 0;
958 if (propval.Value >>= nTemp)
959 pPreview->SetZoom(sal_uInt16(nTemp));
960 }
961 else if (propval.Name == "PageNumber")
962 {
963 sal_Int32 nTemp = 0;
964 if (propval.Value >>= nTemp)
965 pPreview->SetPageNo(nTemp);
966 }
967 // Fallback to common SdrModel processing
968 else
969 pDocShell->MakeDrawLayer()->ReadUserDataSequenceValue(&propval);
970 }
971 }
972
DoScroll(sal_uInt16 nMode)973 void ScPreviewShell::DoScroll( sal_uInt16 nMode )
974 {
975 Point aCurPos, aPrevPos;
976
977 tools::Long nHRange = pHorScroll->GetRange().Max();
978 tools::Long nHLine = pHorScroll->GetLineSize();
979 tools::Long nHPage = pHorScroll->GetPageSize();
980 tools::Long nVRange = pVerScroll->GetRange().Max();
981 tools::Long nVLine = pVerScroll->GetLineSize();
982 tools::Long nVPage = pVerScroll->GetPageSize();
983
984 aCurPos.setX( pHorScroll->GetThumbPos() );
985 aCurPos.setY( pVerScroll->GetThumbPos() );
986 aPrevPos = aCurPos;
987
988 tools::Long nThumbPos = pVerScroll->GetThumbPos();
989 tools::Long nRangeMax = pVerScroll->GetRangeMax();
990
991 switch( nMode )
992 {
993 case SID_CURSORUP:
994 if( nMaxVertPos<0 )
995 {
996 tools::Long nPage = pPreview->GetPageNo();
997
998 if( nPage>0 )
999 {
1000 SfxViewFrame* pSfxViewFrame = GetViewFrame();
1001 SfxRequest aSfxRequest( pSfxViewFrame, SID_PREVIEW_PREVIOUS );
1002 Execute( aSfxRequest );
1003 }
1004 }
1005 else
1006 aCurPos.AdjustY( -nVLine );
1007 break;
1008 case SID_CURSORDOWN:
1009 if( nMaxVertPos<0 )
1010 {
1011 tools::Long nPage = pPreview->GetPageNo();
1012 tools::Long nTotal = pPreview->GetTotalPages();
1013
1014 // before testing for last page, make sure all page counts are calculated
1015 if ( nPage+1 == nTotal && !pPreview->AllTested() )
1016 {
1017 pPreview->CalcAll();
1018 nTotal = pPreview->GetTotalPages();
1019 }
1020
1021 if( nPage<nTotal-1 )
1022 {
1023 SfxViewFrame* pSfxViewFrame = GetViewFrame();
1024 SfxRequest aSfxRequest( pSfxViewFrame, SID_PREVIEW_NEXT );
1025 Execute( aSfxRequest );
1026 }
1027 }
1028 else
1029 aCurPos.AdjustY(nVLine );
1030 break;
1031 case SID_CURSORLEFT:
1032 aCurPos.AdjustX( -nHLine );
1033 break;
1034 case SID_CURSORRIGHT:
1035 aCurPos.AdjustX(nHLine );
1036 break;
1037 case SID_CURSORPAGEUP:
1038 if( nThumbPos==0 || nMaxVertPos<0 )
1039 {
1040 tools::Long nPage = pPreview->GetPageNo();
1041
1042 if( nPage>0 )
1043 {
1044 SfxViewFrame* pSfxViewFrame = GetViewFrame();
1045 SfxRequest aSfxRequest( pSfxViewFrame, SID_PREVIEW_PREVIOUS );
1046 Execute( aSfxRequest );
1047 aCurPos.setY( nVRange );
1048 }
1049 }
1050 else
1051 aCurPos.AdjustY( -nVPage );
1052 break;
1053 case SID_CURSORPAGEDOWN:
1054 if( (std::abs(nVPage+nThumbPos-nRangeMax)<10) || nMaxVertPos<0 )
1055 {
1056 tools::Long nPage = pPreview->GetPageNo();
1057 tools::Long nTotal = pPreview->GetTotalPages();
1058
1059 // before testing for last page, make sure all page counts are calculated
1060 if ( nPage+1 == nTotal && !pPreview->AllTested() )
1061 {
1062 pPreview->CalcAll();
1063 nTotal = pPreview->GetTotalPages();
1064 }
1065 if( nPage<nTotal-1 )
1066 {
1067 SfxViewFrame* pSfxViewFrame = GetViewFrame();
1068 SfxRequest aSfxRequest( pSfxViewFrame, SID_PREVIEW_NEXT );
1069 Execute( aSfxRequest );
1070 aCurPos.setY( 0 );
1071 }
1072 }
1073 else
1074 aCurPos.AdjustY(nVPage );
1075 break;
1076 case SID_CURSORHOME:
1077 if( nMaxVertPos<0 )
1078 {
1079 tools::Long nPage = pPreview->GetPageNo();
1080 tools::Long nTotal = pPreview->GetTotalPages();
1081 if( nTotal && nPage != 0 )
1082 {
1083 SfxViewFrame* pSfxViewFrame = GetViewFrame();
1084 SfxRequest aSfxRequest( pSfxViewFrame, SID_PREVIEW_FIRST );
1085 Execute( aSfxRequest );
1086 }
1087 }
1088 else
1089 {
1090 aCurPos.setY( 0 );
1091 aCurPos.setX( 0 );
1092 }
1093 break;
1094 case SID_CURSOREND:
1095 if( nMaxVertPos<0 )
1096 {
1097 if( !pPreview->AllTested() )
1098 pPreview->CalcAll();
1099 tools::Long nPage = pPreview->GetPageNo();
1100 tools::Long nTotal = pPreview->GetTotalPages();
1101 if( nTotal && nPage+1 != nTotal )
1102 {
1103 SfxViewFrame* pSfxViewFrame = GetViewFrame();
1104 SfxRequest aSfxRequest( pSfxViewFrame, SID_PREVIEW_LAST );
1105 Execute( aSfxRequest );
1106 }
1107 }
1108 else
1109 {
1110 aCurPos.setY( nVRange );
1111 aCurPos.setX( nHRange );
1112 }
1113 break;
1114 }
1115
1116 // nHRange-nHPage might be negative, that's why we check for < 0 afterwards
1117
1118 if( aCurPos.Y() > (nVRange-nVPage) )
1119 aCurPos.setY( nVRange-nVPage );
1120 if( aCurPos.Y() < 0 )
1121 aCurPos.setY( 0 );
1122 if( aCurPos.X() > (nHRange-nHPage) )
1123 aCurPos.setX( nHRange-nHPage );
1124 if( aCurPos.X() < 0 )
1125 aCurPos.setX( 0 );
1126
1127 if( nMaxVertPos>=0 )
1128 {
1129 if( aCurPos.Y() != aPrevPos.Y() )
1130 {
1131 pVerScroll->SetThumbPos( aCurPos.Y() );
1132 pPreview->SetYOffset( aCurPos.Y() );
1133 }
1134 }
1135
1136 if( aCurPos.X() != aPrevPos.X() )
1137 {
1138 pHorScroll->SetThumbPos( aCurPos.X() );
1139 pPreview->SetXOffset( aCurPos.X() );
1140 }
1141
1142 }
1143
ExitPreview()1144 void ScPreviewShell::ExitPreview()
1145 {
1146 GetViewFrame()->GetDispatcher()->Execute(SID_VIEWSHELL0, SfxCallMode::ASYNCHRON);
1147 }
1148
AddAccessibilityObject(SfxListener & rObject)1149 void ScPreviewShell::AddAccessibilityObject( SfxListener& rObject )
1150 {
1151 if (!pAccessibilityBroadcaster)
1152 pAccessibilityBroadcaster.reset( new SfxBroadcaster );
1153
1154 rObject.StartListening( *pAccessibilityBroadcaster );
1155 }
1156
RemoveAccessibilityObject(SfxListener & rObject)1157 void ScPreviewShell::RemoveAccessibilityObject( SfxListener& rObject )
1158 {
1159 if (pAccessibilityBroadcaster)
1160 rObject.EndListening( *pAccessibilityBroadcaster );
1161 else
1162 {
1163 OSL_FAIL("no accessibility broadcaster?");
1164 }
1165 }
1166
BroadcastAccessibility(const SfxHint & rHint)1167 void ScPreviewShell::BroadcastAccessibility( const SfxHint &rHint )
1168 {
1169 if (pAccessibilityBroadcaster)
1170 pAccessibilityBroadcaster->Broadcast( rHint );
1171 }
1172
HasAccessibilityObjects() const1173 bool ScPreviewShell::HasAccessibilityObjects() const
1174 {
1175 return pAccessibilityBroadcaster && pAccessibilityBroadcaster->HasListeners();
1176 }
1177
GetLocationData()1178 const ScPreviewLocationData& ScPreviewShell::GetLocationData()
1179 {
1180 return pPreview->GetLocationData();
1181 }
1182
GetDocument()1183 ScDocument& ScPreviewShell::GetDocument()
1184 {
1185 return pDocShell->GetDocument();
1186 }
1187
1188 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1189