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