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
