1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "precompiled_sd.hxx" 29 30 #include "view/SlsButtonBar.hxx" 31 32 #include "SlideSorter.hxx" 33 #include "model/SlsPageDescriptor.hxx" 34 #include "model/SlideSorterModel.hxx" 35 #include "view/SlsTheme.hxx" 36 #include "view/SlideSorterView.hxx" 37 #include "view/SlsToolTip.hxx" 38 #include "controller/SlideSorterController.hxx" 39 #include "controller/SlsSlotManager.hxx" 40 #include "controller/SlsCurrentSlideManager.hxx" 41 #include "controller/SlsPageSelector.hxx" 42 #include "controller/SlsAnimator.hxx" 43 #include "controller/SlsAnimationFunction.hxx" 44 #include "app.hrc" 45 #include "drawdoc.hxx" 46 #include "sddll.hxx" 47 #include "optsitem.hxx" 48 #include <svx/svxids.hrc> 49 #include <sfx2/dispatch.hxx> 50 #include <vcl/bmpacc.hxx> 51 #include <vcl/virdev.hxx> 52 #include <basegfx/polygon/b2dpolygontools.hxx> 53 #include <basegfx/polygon/b2dpolygon.hxx> 54 #include <basegfx/numeric/ftools.hxx> 55 #include <com/sun/star/presentation/XPresentation2.hpp> 56 #include <boost/bind.hpp> 57 58 using ::com::sun::star::uno::Any; 59 using ::com::sun::star::uno::Reference; 60 using ::com::sun::star::uno::Sequence; 61 using ::com::sun::star::beans::PropertyValue; 62 using ::com::sun::star::presentation::XPresentation2; 63 64 namespace sd { namespace slidesorter { namespace view { 65 66 /** Base class for the painter of the background bar onto which the buttons 67 are painted. It also provides some size information. 68 */ 69 class ButtonBar::BackgroundTheme 70 { 71 public: 72 BackgroundTheme( 73 const ::boost::shared_ptr<Theme>& rpTheme, 74 const ::std::vector<SharedButton>& rButtons); 75 /** Set the preview bounding box, the maximal area in which to display 76 buttons. A call to this method triggers a call to Layout(). 77 */ 78 void SetPreviewBoundingBox (const Rectangle& rPreviewBoundingBox); 79 Button::IconSize GetIconSize (void) const; 80 81 virtual BitmapEx CreateBackground ( 82 const OutputDevice& rTemplateDevice, 83 const bool bIsButtonDown) const = 0; 84 virtual Point GetBackgroundLocation (void) = 0; 85 virtual Rectangle GetButtonArea (void) = 0; 86 87 protected: 88 ::boost::shared_ptr<Theme> mpTheme; 89 Rectangle maPreviewBoundingBox; 90 Size maMinimumLargeButtonAreaSize; 91 Size maMinimumMediumButtonAreaSize; 92 Size maMinimumSmallButtonAreaSize; 93 Button::IconSize meIconSize; 94 95 virtual void Layout (void) = 0; 96 97 private: 98 void UpdateMinimumIconSizes(const ::std::vector<SharedButton>& rButtons); 99 }; 100 101 102 namespace { 103 /** Rectangular button bar that covers the whole width of the preview. 104 */ 105 class RectangleBackgroundTheme : public ButtonBar::BackgroundTheme 106 { 107 public: 108 RectangleBackgroundTheme( 109 const ::boost::shared_ptr<Theme>& rpTheme, 110 const ::std::vector<SharedButton>& rButtons); 111 virtual BitmapEx CreateBackground ( 112 const OutputDevice& rTemplateDevice, 113 const bool bIsButtonDown) const; 114 virtual Point GetBackgroundLocation (void); 115 virtual Rectangle GetButtonArea (void); 116 protected: 117 virtual void Layout (void); 118 private: 119 sal_Int32 mnBarHeight; 120 }; 121 122 /** Button bar is composed of three images, the left and right end of 123 the bar and the center image. Buttons are only placed over the 124 center image. The center image is painted as is, it is not scaled. 125 */ 126 class BitmapBackgroundTheme : public ButtonBar::BackgroundTheme 127 { 128 public: 129 BitmapBackgroundTheme( 130 const ::boost::shared_ptr<Theme>& rpTheme, 131 const ::std::vector<SharedButton>& rButtons); 132 virtual BitmapEx CreateBackground ( 133 const OutputDevice& rTemplateDevice, 134 const bool bIsButtonDown) const; 135 virtual Point GetBackgroundLocation (void); 136 virtual Rectangle GetButtonArea (void); 137 protected: 138 virtual void Layout (void); 139 private: 140 Rectangle maButtonArea; 141 Point maBackgroundLocation; 142 }; 143 144 /** The source mask is essentially multiplied with the given alpha value. 145 The result is writen to the result mask. 146 */ 147 void AdaptTransparency (AlphaMask& rMask, const AlphaMask& rSourceMask, const double nAlpha) 148 { 149 BitmapWriteAccess* pBitmap = rMask.AcquireWriteAccess(); 150 const BitmapReadAccess* pSourceBitmap = const_cast<AlphaMask&>(rSourceMask).AcquireReadAccess(); 151 152 if (pBitmap!=NULL && pSourceBitmap!=NULL) 153 { 154 const sal_Int32 nWidth (pBitmap->Width()); 155 const sal_Int32 nHeight (pBitmap->Height()); 156 157 for (sal_Int32 nY = 0; nY<nHeight; ++nY) 158 for (sal_Int32 nX = 0; nX<nWidth; ++nX) 159 { 160 const sal_uInt8 nValue (255 - pSourceBitmap->GetPixel(nY, nX).GetBlueOrIndex()); 161 const sal_Int32 nNewValue (::basegfx::clamp<sal_Int32>( 162 static_cast<sal_Int32>(nValue * (1-nAlpha)), 163 0, 164 255)); 165 pBitmap->SetPixel(nY, nX, 255-sal_uInt8(nNewValue)); 166 } 167 } 168 } 169 170 } // end of anonymous namespace 171 172 173 //===== ButtonBar::Lock ======================================================= 174 175 ButtonBar::Lock::Lock (SlideSorter& rSlideSorter) 176 : mrButtonBar(rSlideSorter.GetView().GetButtonBar()) 177 { 178 mrButtonBar.AcquireLock(); 179 } 180 181 182 183 184 ButtonBar::Lock::~Lock (void) 185 { 186 mrButtonBar.ReleaseLock(); 187 } 188 189 190 191 192 //===== ButtonBar ============================================================= 193 194 ButtonBar::ButtonBar (SlideSorter& rSlideSorter) 195 : mrSlideSorter(rSlideSorter), 196 maPageObjectSize(0,0), 197 maButtonBoundingBox(), 198 maBackgroundLocation(), 199 mpDescriptor(), 200 mbIsExcluded(false), 201 mpButtonUnderMouse(), 202 mpDownButton(), 203 maRegularButtons(), 204 maExcludedButtons(), 205 maNormalBackground(), 206 maButtonDownBackground(), 207 mbIsMouseOverBar(false), 208 mpBackgroundTheme(), 209 mnLockCount(0) 210 { 211 HandleDataChangeEvent(); 212 } 213 214 215 216 217 ButtonBar::~ButtonBar (void) 218 { 219 } 220 221 222 223 224 void ButtonBar::ProcessButtonDownEvent ( 225 const model::SharedPageDescriptor& rpDescriptor, 226 const Point aMouseModelLocation) 227 { 228 SetButtonUnderMouse(GetButtonAt(aMouseModelLocation)); 229 if (mpButtonUnderMouse) 230 mpButtonUnderMouse->SetState(Button::State_Down); 231 mpDownButton = mpButtonUnderMouse; 232 233 mrSlideSorter.GetView().RequestRepaint(rpDescriptor); 234 } 235 236 237 238 239 void ButtonBar::ProcessButtonUpEvent ( 240 const model::SharedPageDescriptor& rpDescriptor, 241 const Point aMouseModelLocation) 242 { 243 SetButtonUnderMouse(GetButtonAt(aMouseModelLocation)); 244 if (mpButtonUnderMouse) 245 { 246 mpButtonUnderMouse->SetState(Button::State_Hover); 247 if (mpButtonUnderMouse == mpDownButton) 248 { 249 // This is done only when the buttons are sufficiently visible. 250 if (mpDescriptor->GetVisualState().GetButtonAlpha()<0.7) 251 { 252 mpButtonUnderMouse->ProcessClick(mpDescriptor); 253 mbIsExcluded = mpDescriptor->HasState(model::PageDescriptor::ST_Excluded); 254 ProcessMouseMotionEvent (rpDescriptor, aMouseModelLocation, false); 255 } 256 } 257 } 258 mpDownButton.reset(); 259 mrSlideSorter.GetView().RequestRepaint(rpDescriptor); 260 } 261 262 263 264 265 void ButtonBar::ProcessMouseMotionEvent ( 266 const model::SharedPageDescriptor& rpDescriptor, 267 const Point aMouseModelLocation, 268 const bool bIsMouseButtonDown) 269 { 270 model::SharedPageDescriptor pOldDescriptor (mpDescriptor); 271 bool bPageHasChanged (false); 272 bool bButtonHasChanged (false); 273 bool bButtonStateHasChanged (false); 274 275 // Update the page object for which to manage the buttons. 276 bPageHasChanged = SetPage(rpDescriptor); 277 mbIsMouseOverBar = IsMouseOverBar(aMouseModelLocation); 278 279 // Update button under mouse. 280 if (rpDescriptor) 281 { 282 bButtonHasChanged = SetButtonUnderMouse(GetButtonAt(aMouseModelLocation)); 283 284 if (mpButtonUnderMouse) 285 { 286 // When the mouse button is down, mark the button under the 287 // mouse only as pressed when it is the same button the mouse 288 // button was pressed over, and where the button release would 289 // lead to a click action. 290 if (bIsMouseButtonDown) 291 { 292 if (mpButtonUnderMouse==mpDownButton) 293 bButtonStateHasChanged = mpButtonUnderMouse->SetState(Button::State_Down); 294 } 295 else 296 bButtonStateHasChanged = mpButtonUnderMouse->SetState(Button::State_Hover); 297 } 298 } 299 300 // Show a quick help text when the mouse is over a button. 301 if (bButtonHasChanged) 302 { 303 SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); 304 if (pWindow) 305 { 306 if (mpButtonUnderMouse) 307 mrSlideSorter.GetView().GetToolTip().ShowHelpText(mpButtonUnderMouse->GetHelpText()); 308 else 309 mrSlideSorter.GetView().GetToolTip().ShowDefaultHelpText(); 310 } 311 } 312 313 if (bPageHasChanged || bButtonHasChanged || bButtonStateHasChanged) 314 { 315 if (pOldDescriptor) 316 mrSlideSorter.GetView().RequestRepaint(pOldDescriptor); 317 if (mpDescriptor && pOldDescriptor!=mpDescriptor) 318 mrSlideSorter.GetView().RequestRepaint(mpDescriptor); 319 } 320 } 321 322 323 324 325 void ButtonBar::ResetPage (void) 326 { 327 SetPage(model::SharedPageDescriptor()); 328 } 329 330 331 332 333 bool ButtonBar::SetPage (const model::SharedPageDescriptor& rpDescriptor) 334 { 335 if (mpDescriptor != rpDescriptor) 336 { 337 mpDescriptor = rpDescriptor; 338 339 if (mpDescriptor) 340 mbIsExcluded = mpDescriptor->HasState(model::PageDescriptor::ST_Excluded); 341 else 342 mbIsExcluded = false; 343 SetButtonUnderMouse(); 344 mpDownButton.reset(); 345 346 return true; 347 } 348 else 349 return false; 350 } 351 352 353 354 355 sal_Int32 ButtonBar::GetButtonCount (const bool bIsExcluded) const 356 { 357 if (bIsExcluded) 358 return maExcludedButtons.size(); 359 else 360 return maRegularButtons.size(); 361 } 362 363 364 365 366 ::boost::shared_ptr<Button> ButtonBar::GetButton ( 367 const bool bIsExcluded, 368 const sal_Int32 nIndex) const 369 { 370 const ::std::vector<boost::shared_ptr<Button> >& rButtons (bIsExcluded 371 ? maExcludedButtons 372 : maRegularButtons); 373 374 if (nIndex<0 || sal_uInt32(nIndex)>=rButtons.size()) 375 { 376 OSL_ASSERT(nIndex<0 || sal_uInt32(nIndex)>=rButtons.size()); 377 return ::boost::shared_ptr<Button>(); 378 } 379 else 380 return rButtons[sal_uInt32(nIndex)]; 381 } 382 383 384 385 386 SharedButton ButtonBar::GetButtonAt (const Point aModelLocation) 387 { 388 if (IsMouseOverBar(aModelLocation)) 389 { 390 const Point aLocalLocation (aModelLocation - mpDescriptor->GetBoundingBox().TopLeft()); 391 ::std::vector<SharedButton>& rButtons ( 392 mbIsExcluded ? maExcludedButtons : maRegularButtons); 393 for (sal_uInt32 nIndex=0; nIndex<rButtons.size(); ++nIndex) 394 { 395 if (rButtons[sal_uInt32(nIndex)]->GetBoundingBox().IsInside(aLocalLocation)) 396 { 397 if (rButtons[sal_uInt32(nIndex)]->IsEnabled()) 398 return rButtons[sal_uInt32(nIndex)]; 399 else 400 return SharedButton(); 401 } 402 } 403 } 404 405 return SharedButton(); 406 } 407 408 409 410 411 bool ButtonBar::IsMouseOverBar (void) const 412 { 413 return mbIsMouseOverBar; 414 } 415 416 417 418 419 bool ButtonBar::SetButtonUnderMouse (const SharedButton& rButton) 420 { 421 if (mpButtonUnderMouse != rButton) 422 { 423 if (mpButtonUnderMouse) 424 mpButtonUnderMouse->SetState(Button::State_Normal); 425 426 mpButtonUnderMouse = rButton; 427 428 return true; 429 } 430 else 431 return false; 432 } 433 434 435 436 437 void ButtonBar::Paint ( 438 OutputDevice& rDevice, 439 const model::SharedPageDescriptor& rpDescriptor) 440 { 441 if ( ! rpDescriptor) 442 return; 443 444 const double nButtonBarAlpha (rpDescriptor->GetVisualState().GetButtonBarAlpha()); 445 if (nButtonBarAlpha >= 1) 446 return; 447 448 LayoutButtons(rpDescriptor->GetBoundingBox().GetSize()); 449 450 const Point aOffset (rpDescriptor->GetBoundingBox().TopLeft()); 451 452 // Paint the background. 453 PaintButtonBackground(rDevice, rpDescriptor, aOffset); 454 455 // Paint the buttons. 456 const ::std::vector<SharedButton>& rButtons ( 457 rpDescriptor->HasState(model::PageDescriptor::ST_Excluded) 458 ? maExcludedButtons 459 : maRegularButtons); 460 461 462 const double nButtonAlpha (rpDescriptor->GetVisualState().GetButtonAlpha()); 463 for (sal_uInt32 nIndex=0; nIndex<rButtons.size(); ++nIndex) 464 rButtons[nIndex]->Paint( 465 rDevice, 466 aOffset, 467 nButtonAlpha, 468 mrSlideSorter.GetTheme()); 469 } 470 471 472 473 474 bool ButtonBar::IsMouseOverButton (void) const 475 { 476 return mpButtonUnderMouse; 477 } 478 479 480 481 482 void ButtonBar::PaintButtonBackground ( 483 OutputDevice& rDevice, 484 const model::SharedPageDescriptor& rpDescriptor, 485 const Point aOffset) 486 { 487 BitmapEx* pBitmap = NULL; 488 if (maButtonDownBackground.IsEmpty() || maNormalBackground.IsEmpty()) 489 { 490 if (mpBackgroundTheme) 491 { 492 maButtonDownBackground = mpBackgroundTheme->CreateBackground(rDevice, true); 493 maNormalBackground = mpBackgroundTheme->CreateBackground(rDevice, false); 494 } 495 } 496 if (mpButtonUnderMouse && mpButtonUnderMouse->IsDown()) 497 pBitmap = &maButtonDownBackground; 498 else 499 pBitmap = &maNormalBackground; 500 if (pBitmap != NULL) 501 { 502 AlphaMask aMask (pBitmap->GetSizePixel()); 503 AdaptTransparency( 504 aMask, 505 pBitmap->GetAlpha(), 506 rpDescriptor->GetVisualState().GetButtonBarAlpha()); 507 rDevice.DrawBitmapEx(maBackgroundLocation+aOffset, BitmapEx(pBitmap->GetBitmap(), aMask)); 508 } 509 } 510 511 512 513 514 bool ButtonBar::IsMouseOverBar (const Point aModelLocation) const 515 { 516 if ( ! mpDescriptor || ! mpDescriptor->GetBoundingBox().IsInside(aModelLocation)) 517 return false; 518 519 if ( ! maButtonBoundingBox.IsInside(aModelLocation - mpDescriptor->GetBoundingBox().TopLeft())) 520 return false; 521 522 return true; 523 } 524 525 526 527 528 void ButtonBar::RequestLayout (void) 529 { 530 maPageObjectSize = Size(0,0); 531 } 532 533 534 535 536 void ButtonBar::LayoutButtons (const Size aPageObjectSize) 537 { 538 if (maPageObjectSize != aPageObjectSize) 539 { 540 maPageObjectSize = aPageObjectSize; 541 542 if (mpBackgroundTheme) 543 { 544 mpBackgroundTheme->SetPreviewBoundingBox( 545 mrSlideSorter.GetView().GetLayouter().GetPageObjectLayouter()->GetBoundingBox( 546 Point(0,0), 547 PageObjectLayouter::Preview, 548 PageObjectLayouter::ModelCoordinateSystem)); 549 LayoutButtons(); 550 } 551 552 // Release the background bitmaps so that on the next paint 553 // they are created anew in the right size. 554 maNormalBackground.SetEmpty(); 555 maButtonDownBackground.SetEmpty(); 556 } 557 } 558 559 560 561 562 bool ButtonBar::LayoutButtons (void) 563 { 564 const sal_Int32 nGap (mrSlideSorter.GetTheme()->GetIntegerValue(Theme::Integer_ButtonGap)); 565 const sal_Int32 nBorder (mrSlideSorter.GetTheme()->GetIntegerValue(Theme::Integer_ButtonBorder)); 566 567 const Button::IconSize eIconSize (mpBackgroundTheme->GetIconSize()); 568 569 // Tell buttons which size they are. 570 for (sal_uInt32 nIndex=0; nIndex<maExcludedButtons.size(); ++nIndex) 571 maExcludedButtons[nIndex]->SetIconSize(eIconSize); 572 for (sal_uInt32 nIndex=0; nIndex<maRegularButtons.size(); ++nIndex) 573 maRegularButtons[nIndex]->SetIconSize(eIconSize); 574 575 // Determine maximal height and total width of the buttons. 576 // Start with the buttons used for the excluded state. 577 sal_Int32 nMaximumHeight (0); 578 sal_Int32 nExcludedTotalWidth ((maExcludedButtons.size()-1) * nGap + 2*nBorder); 579 for (sal_uInt32 nIndex=0; nIndex<maExcludedButtons.size(); ++nIndex) 580 { 581 const Size aSize (maExcludedButtons[nIndex]->GetSize()); 582 if (aSize.Height() > nMaximumHeight) 583 nMaximumHeight = aSize.Height(); 584 nExcludedTotalWidth += aSize.Width(); 585 } 586 587 // Do the same for the regular buttons. 588 sal_Int32 nRegularTotalWidth ((maRegularButtons.size()-1) * nGap + 2*nBorder); 589 for (sal_uInt32 nIndex=0; nIndex<maRegularButtons.size(); ++nIndex) 590 { 591 const Size aSize (maRegularButtons[nIndex]->GetSize()); 592 if (aSize.Height() > nMaximumHeight) 593 nMaximumHeight = aSize.Height(); 594 nRegularTotalWidth += aSize.Width(); 595 } 596 nMaximumHeight += 2*nBorder; 597 598 // Set up the bounding box of the button bar. 599 maButtonBoundingBox = mpBackgroundTheme->GetButtonArea(); 600 maBackgroundLocation = mpBackgroundTheme->GetBackgroundLocation(); 601 if (mrSlideSorter.GetTheme()->GetIntegerValue(Theme::Integer_ButtonPaintType) == 1) 602 { 603 // Center the buttons. 604 maButtonBoundingBox.Left() += (maButtonBoundingBox.GetWidth() - nRegularTotalWidth)/2; 605 maButtonBoundingBox.Right() = maButtonBoundingBox.Left() + nRegularTotalWidth - 1; 606 } 607 608 // Place the buttons. 609 Rectangle aBox (maButtonBoundingBox); 610 aBox.Right() -= nBorder; 611 for (sal_Int32 nIndex=maRegularButtons.size()-1; nIndex>=0; --nIndex) 612 { 613 maRegularButtons[nIndex]->Place(aBox); 614 aBox.Right() = maRegularButtons[nIndex]->GetBoundingBox().Left() - nGap; 615 } 616 617 // For slides excluded from the show there is only one icon placed 618 // exactly like the second of the regular icons. 619 if (maRegularButtons.size()>=2 && maExcludedButtons.size()>=1) 620 { 621 aBox = maRegularButtons[1]->GetBoundingBox(); 622 maExcludedButtons[0]->Place(aBox); 623 } 624 625 // We return true only when there is no inactive button. 626 for (sal_uInt32 nIndex=0; nIndex<maExcludedButtons.size(); ++nIndex) 627 if ( ! maExcludedButtons[nIndex]->IsActive()) 628 return false; 629 for (sal_uInt32 nIndex=0; nIndex<maRegularButtons.size(); ++nIndex) 630 if ( ! maRegularButtons[nIndex]->IsActive()) 631 return false; 632 633 return true; 634 } 635 636 637 638 639 void ButtonBar::RequestFadeIn ( 640 const model::SharedPageDescriptor& rpDescriptor, 641 const bool bAnimate) 642 { 643 if ( ! rpDescriptor) 644 return; 645 if (mnLockCount > 0) 646 return; 647 648 const double nMinAlpha (0); 649 if ( ! bAnimate) 650 { 651 rpDescriptor->GetVisualState().SetButtonAlpha(nMinAlpha); 652 rpDescriptor->GetVisualState().SetButtonBarAlpha(nMinAlpha); 653 } 654 else 655 StartFadeAnimation(rpDescriptor, nMinAlpha, true); 656 } 657 658 659 660 661 void ButtonBar::RequestFadeOut ( 662 const model::SharedPageDescriptor& rpDescriptor, 663 const bool bAnimate) 664 { 665 if ( ! rpDescriptor) 666 return; 667 if (mnLockCount > 0) 668 return; 669 670 const double nMaxAlpha (1); 671 if ( ! bAnimate) 672 { 673 rpDescriptor->GetVisualState().SetButtonAlpha(nMaxAlpha); 674 rpDescriptor->GetVisualState().SetButtonBarAlpha(nMaxAlpha); 675 } 676 else 677 StartFadeAnimation(rpDescriptor, nMaxAlpha, false); 678 } 679 680 681 682 683 bool ButtonBar::IsVisible (const model::SharedPageDescriptor& rpDescriptor) 684 { 685 const double nMaxAlpha (1); 686 return rpDescriptor && rpDescriptor->GetVisualState().GetButtonBarAlpha() < nMaxAlpha; 687 } 688 689 690 691 692 void ButtonBar::HandleDataChangeEvent (void) 693 { 694 maExcludedButtons.clear(); 695 maExcludedButtons.push_back(::boost::shared_ptr<Button>(new UnhideButton(mrSlideSorter))); 696 697 maRegularButtons.clear(); 698 maRegularButtons.push_back(::boost::shared_ptr<Button>(new StartShowButton(mrSlideSorter))); 699 maRegularButtons.push_back(::boost::shared_ptr<Button>(new HideButton(mrSlideSorter))); 700 maRegularButtons.push_back(::boost::shared_ptr<Button>(new DuplicateButton(mrSlideSorter))); 701 702 mpBackgroundTheme.reset( 703 new BitmapBackgroundTheme( 704 mrSlideSorter.GetTheme(), 705 maRegularButtons)); 706 707 // Force layout on next Paint(). 708 maPageObjectSize = Size(0,0); 709 } 710 711 712 713 714 void ButtonBar::StartFadeAnimation ( 715 const model::SharedPageDescriptor& rpDescriptor, 716 const double nTargetAlpha, 717 const bool bFadeIn) 718 { 719 model::SharedPageDescriptor pDescriptor (rpDescriptor); 720 721 const double nCurrentButtonAlpha (pDescriptor->GetVisualState().GetButtonAlpha()); 722 const double nCurrentButtonBarAlpha (pDescriptor->GetVisualState().GetButtonBarAlpha()); 723 724 // Stop a running animation. 725 const controller::Animator::AnimationId nId ( 726 pDescriptor->GetVisualState().GetButtonAlphaAnimationId()); 727 if (nId != controller::Animator::NotAnAnimationId) 728 mrSlideSorter.GetController().GetAnimator()->RemoveAnimation(nId); 729 730 // Prepare the blending functors that translate [0,1] animation 731 // times into alpha values of buttons and button bar. 732 const ::boost::function<double(double)> aButtonBlendFunctor ( 733 ::boost::bind( 734 controller::AnimationFunction::Blend, 735 nCurrentButtonAlpha, 736 nTargetAlpha, 737 ::boost::bind(controller::AnimationFunction::Linear, _1))); 738 const ::boost::function<double(double)> aButtonBarBlendFunctor ( 739 ::boost::bind( 740 controller::AnimationFunction::Blend, 741 nCurrentButtonBarAlpha, 742 nTargetAlpha, 743 ::boost::bind(controller::AnimationFunction::Linear, _1))); 744 745 // Delay the fade in a little bit when the buttons are not visible at 746 // all so that we do not leave a trail of half-visible buttons when the 747 // mouse is moved across the screen. No delay on fade out or when the 748 // buttons are already showing. Fade out is faster than fade in. 749 const sal_Int32 nDelay (nCurrentButtonBarAlpha>0 && nCurrentButtonBarAlpha<1 750 ? 0 751 : (mrSlideSorter.GetTheme()->GetIntegerValue(bFadeIn 752 ? Theme::Integer_ButtonFadeInDelay 753 : Theme::Integer_ButtonFadeOutDelay))); 754 const sal_Int32 nDuration (mrSlideSorter.GetTheme()->GetIntegerValue(bFadeIn 755 ? Theme::Integer_ButtonFadeInDuration 756 : Theme::Integer_ButtonFadeOutDuration)); 757 pDescriptor->GetVisualState().SetButtonAlphaAnimationId( 758 mrSlideSorter.GetController().GetAnimator()->AddAnimation( 759 ::boost::bind( 760 controller::AnimationFunction::ApplyButtonAlphaChange, 761 pDescriptor, 762 ::boost::ref(mrSlideSorter.GetView()), 763 ::boost::bind(aButtonBlendFunctor, _1), 764 ::boost::bind(aButtonBarBlendFunctor, _1)), 765 nDelay, 766 nDuration, 767 ::boost::bind( 768 &model::VisualState::SetButtonAlphaAnimationId, 769 ::boost::ref(pDescriptor->GetVisualState()), 770 controller::Animator::NotAnAnimationId) 771 )); 772 } 773 774 775 776 777 void ButtonBar::AcquireLock (void) 778 { 779 if (mnLockCount == 0 && mpDescriptor) 780 RequestFadeOut(mpDescriptor, true); 781 782 ++mnLockCount; 783 } 784 785 786 787 788 void ButtonBar::ReleaseLock (void) 789 { 790 --mnLockCount; 791 792 if (mnLockCount == 0 && mpDescriptor) 793 RequestFadeIn(mpDescriptor, true); 794 } 795 796 797 798 799 //===== BackgroundTheme ===================================================== 800 801 ButtonBar::BackgroundTheme::BackgroundTheme ( 802 const ::boost::shared_ptr<Theme>& rpTheme, 803 const ::std::vector<SharedButton>& rButtons) 804 : mpTheme(rpTheme) 805 { 806 UpdateMinimumIconSizes(rButtons); 807 } 808 809 810 811 812 void ButtonBar::BackgroundTheme::SetPreviewBoundingBox (const Rectangle& rPreviewBoundingBox) 813 { 814 maPreviewBoundingBox = rPreviewBoundingBox; 815 Layout(); 816 } 817 818 819 820 821 void ButtonBar::BackgroundTheme::UpdateMinimumIconSizes ( 822 const ::std::vector<SharedButton>& rButtons) 823 { 824 OSL_ASSERT(mpTheme); 825 826 sal_Int32 nMaximumHeightLarge (0); 827 sal_Int32 nMaximumHeightMedium (0); 828 sal_Int32 nMaximumHeightSmall (0); 829 const sal_Int32 nGap (mpTheme->GetIntegerValue(Theme::Integer_ButtonGap)); 830 const sal_Int32 nBorder (mpTheme->GetIntegerValue(Theme::Integer_ButtonBorder)); 831 sal_Int32 nTotalWidthLarge ((rButtons.size()-1) * nGap + 2*nBorder); 832 sal_Int32 nTotalWidthMedium ((rButtons.size()-1) * nGap + 2*nBorder); 833 sal_Int32 nTotalWidthSmall ((rButtons.size()-1) * nGap + 2*nBorder); 834 for (sal_uInt32 nIndex=0; nIndex<rButtons.size(); ++nIndex) 835 { 836 // Update large size. 837 Size aSize = rButtons[nIndex]->GetSize(Button::IconSize_Large); 838 if (aSize.Height() > nMaximumHeightLarge) 839 nMaximumHeightLarge = aSize.Height(); 840 nTotalWidthLarge += aSize.Width(); 841 842 // Update medium size. 843 aSize = rButtons[nIndex]->GetSize(Button::IconSize_Medium); 844 if (aSize.Height() > nMaximumHeightMedium) 845 nMaximumHeightMedium = aSize.Height(); 846 nTotalWidthMedium += aSize.Width(); 847 848 // Update small size. 849 aSize = rButtons[nIndex]->GetSize(Button::IconSize_Small); 850 if (aSize.Height() > nMaximumHeightSmall) 851 nMaximumHeightSmall = aSize.Height(); 852 nTotalWidthSmall += aSize.Width(); 853 } 854 maMinimumLargeButtonAreaSize = Size(nTotalWidthLarge, nMaximumHeightLarge+2*nBorder); 855 maMinimumMediumButtonAreaSize = Size(nTotalWidthMedium, nMaximumHeightMedium+2*nBorder); 856 maMinimumSmallButtonAreaSize = Size(nTotalWidthSmall, nMaximumHeightSmall+2*nBorder); 857 } 858 859 860 861 862 Button::IconSize ButtonBar::BackgroundTheme::GetIconSize (void) const 863 { 864 return meIconSize; 865 } 866 867 868 869 870 //===== RectangleBackgroundTheme ============================================ 871 872 RectangleBackgroundTheme::RectangleBackgroundTheme ( 873 const ::boost::shared_ptr<Theme>& rpTheme, 874 const ::std::vector<SharedButton>& rButtons) 875 : BackgroundTheme(rpTheme, rButtons), 876 mnBarHeight(0) 877 { 878 } 879 880 881 882 883 BitmapEx RectangleBackgroundTheme::CreateBackground ( 884 const OutputDevice& rTemplateDevice, 885 const bool bIsButtonDown) const 886 { 887 OSL_ASSERT(mpTheme); 888 889 // Setup background color. 890 Color aTopFillColor (mpTheme->GetGradientColor( 891 Theme::Gradient_ButtonBackground, 892 Theme::Fill1)); 893 Color aTopBorderColor (mpTheme->GetGradientColor( 894 Theme::Gradient_ButtonBackground, 895 Theme::Border1)); 896 Color aBottomFillColor (mpTheme->GetGradientColor( 897 Theme::Gradient_ButtonBackground, 898 Theme::Fill2)); 899 Color aBottomBorderColor (mpTheme->GetGradientColor( 900 Theme::Gradient_ButtonBackground, 901 Theme::Border2)); 902 if (bIsButtonDown) 903 { 904 aTopFillColor.DecreaseLuminance(50); 905 aTopBorderColor.DecreaseLuminance(50); 906 aBottomFillColor.DecreaseLuminance(50); 907 aBottomBorderColor.DecreaseLuminance(50); 908 } 909 910 const int nWidth (maPreviewBoundingBox.GetWidth()+2); 911 const int nHeight (mnBarHeight); 912 const int nCenter (nHeight / 2); 913 914 VirtualDevice aDevice (rTemplateDevice, 0, 8); 915 aDevice.SetOutputSizePixel(Size(nWidth,nHeight)); 916 917 // Fill upper and lower half. 918 aDevice.SetLineColor(); 919 aDevice.SetFillColor(aTopFillColor); 920 aDevice.DrawRect(Rectangle(0,0,nWidth-1,nCenter)); 921 aDevice.SetFillColor(aBottomFillColor); 922 aDevice.DrawRect(Rectangle(0,nCenter,nWidth-1,nHeight-1)); 923 924 // Draw border. 925 aDevice.SetFillColor(); 926 aDevice.SetLineColor(aTopBorderColor); 927 aDevice.DrawLine(Point(0,nCenter),Point(0,0)); 928 aDevice.DrawLine(Point(0,0), Point(nWidth-1,0)); 929 aDevice.DrawLine(Point(nWidth-1,0),Point(nWidth-1,nCenter)); 930 aDevice.SetLineColor(aBottomBorderColor); 931 aDevice.DrawLine(Point(0,nCenter),Point(0,nHeight-1)); 932 aDevice.DrawLine(Point(0,nHeight-1), Point(nWidth-1,nHeight-1)); 933 aDevice.DrawLine(Point(nWidth-1,nHeight-1),Point(nWidth-1,nCenter)); 934 935 return aDevice.GetBitmapEx(Point(0,0), Size(nWidth,nHeight)); 936 } 937 938 939 940 941 Point RectangleBackgroundTheme::GetBackgroundLocation (void) 942 { 943 return Point( 944 maPreviewBoundingBox.Left()-1, 945 maPreviewBoundingBox.Bottom() - mnBarHeight + 2); 946 } 947 948 949 950 951 Rectangle RectangleBackgroundTheme::GetButtonArea (void) 952 { 953 return Rectangle( 954 maPreviewBoundingBox.Left(), 955 maPreviewBoundingBox.Bottom() - mnBarHeight + 2, 956 maPreviewBoundingBox.Right(), 957 maPreviewBoundingBox.Bottom()); 958 } 959 960 961 962 963 void RectangleBackgroundTheme::Layout (void) 964 { 965 if (maPreviewBoundingBox.GetWidth() < maMinimumLargeButtonAreaSize.Width()) 966 if (maPreviewBoundingBox.GetWidth() < maMinimumMediumButtonAreaSize.Width()) 967 { 968 meIconSize = Button::IconSize_Small; 969 mnBarHeight = maMinimumSmallButtonAreaSize.Height(); 970 } 971 else 972 { 973 meIconSize = Button::IconSize_Medium; 974 mnBarHeight = maMinimumMediumButtonAreaSize.Height(); 975 } 976 else 977 { 978 meIconSize = Button::IconSize_Large; 979 mnBarHeight = maMinimumLargeButtonAreaSize.Height(); 980 } 981 } 982 983 984 985 986 //===== BitmapBackgroundTheme ================================================= 987 988 BitmapBackgroundTheme::BitmapBackgroundTheme ( 989 const ::boost::shared_ptr<Theme>& rpTheme, 990 const ::std::vector<SharedButton>& rButtons) 991 : BackgroundTheme(rpTheme, rButtons), 992 maButtonArea(), 993 maBackgroundLocation() 994 { 995 } 996 997 998 999 1000 BitmapEx BitmapBackgroundTheme::CreateBackground ( 1001 const OutputDevice& rTemplateDevice, 1002 const bool bIsButtonDown) const 1003 { 1004 (void)rTemplateDevice; 1005 (void)bIsButtonDown; 1006 1007 OSL_ASSERT(mpTheme); 1008 1009 // Get images. 1010 switch (meIconSize) 1011 { 1012 case Button::IconSize_Large: 1013 default: 1014 return mpTheme->GetIcon(Theme::Icon_ButtonBarLarge); 1015 1016 case Button::IconSize_Medium: 1017 return mpTheme->GetIcon(Theme::Icon_ButtonBarMedium); 1018 1019 case Button::IconSize_Small: 1020 return mpTheme->GetIcon(Theme::Icon_ButtonBarSmall); 1021 } 1022 } 1023 1024 1025 1026 1027 Point BitmapBackgroundTheme::GetBackgroundLocation (void) 1028 { 1029 return maBackgroundLocation; 1030 } 1031 1032 1033 1034 1035 Rectangle BitmapBackgroundTheme::GetButtonArea (void) 1036 { 1037 return maButtonArea; 1038 } 1039 1040 1041 1042 1043 void BitmapBackgroundTheme::Layout (void) 1044 { 1045 Size aImageSize (mpTheme->GetIcon(Theme::Icon_ButtonBarLarge).GetSizePixel()); 1046 if (aImageSize.Width() >= maPreviewBoundingBox.GetWidth()) 1047 { 1048 aImageSize = mpTheme->GetIcon(Theme::Icon_ButtonBarMedium).GetSizePixel(); 1049 if (aImageSize.Width() >= maPreviewBoundingBox.GetWidth()) 1050 { 1051 meIconSize = Button::IconSize_Small; 1052 aImageSize = mpTheme->GetIcon(Theme::Icon_ButtonBarSmall).GetSizePixel(); 1053 } 1054 else 1055 meIconSize = Button::IconSize_Medium; 1056 } 1057 else 1058 { 1059 meIconSize = Button::IconSize_Large; 1060 } 1061 1062 maBackgroundLocation = Point( 1063 maPreviewBoundingBox.Left() 1064 + (maPreviewBoundingBox.GetWidth()-aImageSize.Width())/2, 1065 maPreviewBoundingBox.Bottom() - aImageSize.Height()); 1066 maButtonArea = Rectangle(maBackgroundLocation, aImageSize); 1067 } 1068 1069 1070 1071 1072 //===== Button ================================================================ 1073 1074 Button::Button ( 1075 SlideSorter& rSlideSorter, 1076 const ::rtl::OUString& rsHelpText) 1077 : mrSlideSorter(rSlideSorter), 1078 meState(State_Normal), 1079 maBoundingBox(), 1080 msHelpText(rsHelpText), 1081 mbIsActive(false), 1082 meIconSize(IconSize_Large) 1083 { 1084 } 1085 1086 1087 1088 1089 Button::~Button (void) 1090 { 1091 } 1092 1093 1094 1095 1096 bool Button::SetState (const State eState) 1097 { 1098 if (meState != eState) 1099 { 1100 meState = eState; 1101 return true; 1102 } 1103 else 1104 return false; 1105 } 1106 1107 1108 1109 1110 Button::State Button::GetState (void) const 1111 { 1112 return meState; 1113 } 1114 1115 1116 1117 1118 Rectangle Button::GetBoundingBox (void) const 1119 { 1120 if (mbIsActive) 1121 return maBoundingBox; 1122 else 1123 return Rectangle(); 1124 } 1125 1126 1127 1128 1129 ::rtl::OUString Button::GetHelpText (void) const 1130 { 1131 if (mbIsActive) 1132 return msHelpText; 1133 else 1134 return ::rtl::OUString(); 1135 } 1136 1137 1138 1139 1140 bool Button::IsDown (void) const 1141 { 1142 return mbIsActive && meState==State_Down; 1143 } 1144 1145 1146 1147 1148 void Button::SetActiveState (const bool bIsActive) 1149 { 1150 mbIsActive = bIsActive; 1151 } 1152 1153 1154 1155 1156 bool Button::IsActive (void) const 1157 { 1158 return mbIsActive; 1159 } 1160 1161 1162 1163 1164 void Button::SetIconSize (const IconSize eIconSize) 1165 { 1166 meIconSize = eIconSize; 1167 } 1168 1169 1170 1171 1172 Button::IconSize Button::GetIconSize (void) const 1173 { 1174 return meIconSize; 1175 } 1176 1177 1178 1179 1180 bool Button::IsEnabled (void) const 1181 { 1182 return true; 1183 } 1184 1185 1186 1187 1188 //===== TextButton ============================================================ 1189 1190 TextButton::TextButton ( 1191 SlideSorter& rSlideSorter, 1192 const ::rtl::OUString& rsText, 1193 const ::rtl::OUString& rsHelpText) 1194 : Button(rSlideSorter, rsHelpText), 1195 msText(rsText) 1196 { 1197 } 1198 1199 1200 1201 1202 void TextButton::Place (const Rectangle aButtonBarBox) 1203 { 1204 maBoundingBox = aButtonBarBox; 1205 SetActiveState(true); 1206 } 1207 1208 1209 1210 1211 void TextButton::Paint ( 1212 OutputDevice& rDevice, 1213 const Point aOffset, 1214 const double nAlpha, 1215 const ::boost::shared_ptr<Theme>& rpTheme) const 1216 { 1217 (void)nAlpha; 1218 1219 if (mbIsActive) 1220 { 1221 // Paint text over the button background. 1222 if (meState == State_Normal) 1223 rDevice.SetTextColor(rpTheme->GetColor(Theme::Color_ButtonText)); 1224 else 1225 rDevice.SetTextColor(rpTheme->GetColor(Theme::Color_ButtonTextHover)); 1226 Rectangle aBox (maBoundingBox); 1227 aBox += aOffset; 1228 rDevice.DrawText(aBox, msText, TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER); 1229 } 1230 } 1231 1232 1233 1234 1235 Size TextButton::GetSize (void) const 1236 { 1237 return Size(); 1238 } 1239 1240 1241 1242 1243 Size TextButton::GetSize (const Button::IconSize) const 1244 { 1245 return Size(); 1246 } 1247 1248 1249 1250 1251 //===== ImageButon ============================================================ 1252 1253 ImageButton::ImageButton ( 1254 SlideSorter& rSlideSorter, 1255 const BitmapEx& rLargeIcon, 1256 const BitmapEx& rLargeHoverIcon, 1257 const BitmapEx& rMediumIcon, 1258 const BitmapEx& rMediumHoverIcon, 1259 const BitmapEx& rSmallIcon, 1260 const BitmapEx& rSmallHoverIcon, 1261 const ::rtl::OUString& rsHelpText) 1262 : Button(rSlideSorter, rsHelpText), 1263 maLargeIcon(rLargeIcon), 1264 maLargeHoverIcon(rLargeHoverIcon.IsEmpty() ? rLargeIcon : rLargeHoverIcon), 1265 maMediumIcon(rMediumIcon), 1266 maMediumHoverIcon(rMediumHoverIcon.IsEmpty() ? rMediumIcon : rMediumHoverIcon), 1267 maSmallIcon(rSmallIcon), 1268 maSmallHoverIcon(rSmallHoverIcon.IsEmpty() ? rSmallIcon : rSmallHoverIcon) 1269 { 1270 } 1271 1272 1273 1274 1275 void ImageButton::Place (const Rectangle aButtonBarBox) 1276 { 1277 const sal_Int32 nWidth (GetSize().Width()); 1278 maBoundingBox = Rectangle( 1279 aButtonBarBox.Right() - nWidth, 1280 aButtonBarBox.Top(), 1281 aButtonBarBox.Right(), 1282 aButtonBarBox.Bottom()); 1283 SetActiveState(aButtonBarBox.IsInside(maBoundingBox)); 1284 } 1285 1286 1287 1288 1289 void ImageButton::Paint ( 1290 OutputDevice& rDevice, 1291 const Point aOffset, 1292 const double nAlpha, 1293 const ::boost::shared_ptr<Theme>& rpTheme) const 1294 { 1295 (void)rpTheme; 1296 1297 if ( ! mbIsActive) 1298 return; 1299 1300 const sal_uInt16 nSavedAntialiasingMode (rDevice.GetAntialiasing()); 1301 rDevice.SetAntialiasing(nSavedAntialiasingMode | ANTIALIASING_ENABLE_B2DDRAW); 1302 1303 rDevice.SetLineColor(); 1304 1305 // Choose icon. 1306 BitmapEx aIcon; 1307 switch (meIconSize) 1308 { 1309 case IconSize_Large: 1310 default: 1311 if (meState == State_Normal) 1312 aIcon = maLargeIcon; 1313 else 1314 aIcon = maLargeHoverIcon; 1315 break; 1316 1317 case IconSize_Medium: 1318 if (meState == State_Normal) 1319 aIcon = maMediumIcon; 1320 else 1321 aIcon = maMediumHoverIcon; 1322 break; 1323 1324 case IconSize_Small: 1325 if (meState == State_Normal) 1326 aIcon = maSmallIcon; 1327 else 1328 aIcon = maSmallHoverIcon; 1329 break; 1330 } 1331 1332 // Paint icon. 1333 if ( ! aIcon.IsEmpty()) 1334 { 1335 AlphaMask aMask (aIcon.GetSizePixel()); 1336 AdaptTransparency(aMask, aIcon.GetAlpha(), nAlpha); 1337 rDevice.DrawBitmapEx( 1338 Point( 1339 maBoundingBox.Left() 1340 + aOffset.X() 1341 + (maBoundingBox.GetWidth()-aIcon.GetSizePixel().Width())/2, 1342 maBoundingBox.Top() 1343 + aOffset.Y() 1344 + (maBoundingBox.GetHeight()-aIcon.GetSizePixel().Height())/2), 1345 BitmapEx(aIcon.GetBitmap(), aMask)); 1346 } 1347 1348 rDevice.SetAntialiasing(nSavedAntialiasingMode); 1349 } 1350 1351 1352 1353 1354 Size ImageButton::GetSize (void) const 1355 { 1356 return GetSize(meIconSize); 1357 } 1358 1359 1360 1361 1362 Size ImageButton::GetSize (const Button::IconSize eIconSize) const 1363 { 1364 switch (eIconSize) 1365 { 1366 case IconSize_Large: 1367 default: 1368 return maLargeIcon.GetSizePixel(); 1369 1370 case IconSize_Medium: 1371 return maMediumIcon.GetSizePixel(); 1372 1373 case IconSize_Small: 1374 return maSmallIcon.GetSizePixel(); 1375 } 1376 } 1377 1378 1379 1380 1381 //===== UnhideButton ========================================================== 1382 1383 UnhideButton::UnhideButton (SlideSorter& rSlideSorter) 1384 : ImageButton( 1385 rSlideSorter, 1386 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BLarge), 1387 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BLargeHover), 1388 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BMedium), 1389 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BMediumHover), 1390 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BSmall), 1391 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BSmallHover), 1392 rSlideSorter.GetTheme()->GetString(Theme::String_Command2B)) 1393 { 1394 } 1395 1396 1397 1398 1399 void UnhideButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor) 1400 { 1401 if ( ! rpDescriptor) 1402 return; 1403 mrSlideSorter.GetController().GetSlotManager()->ChangeSlideExclusionState( 1404 (rpDescriptor->HasState(model::PageDescriptor::ST_Selected) 1405 ? model::SharedPageDescriptor() 1406 : rpDescriptor), 1407 false); 1408 } 1409 1410 1411 1412 1413 //===== StartSlideShowButton ================================================== 1414 1415 StartShowButton::StartShowButton (SlideSorter& rSlideSorter) 1416 : ImageButton( 1417 rSlideSorter, 1418 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1Large), 1419 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1LargeHover), 1420 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1Medium), 1421 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1MediumHover), 1422 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1Small), 1423 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1SmallHover), 1424 rSlideSorter.GetTheme()->GetString(Theme::String_Command1)) 1425 { 1426 } 1427 1428 1429 1430 1431 bool StartShowButton::IsEnabled (void) const 1432 { 1433 ViewShell* pViewShell = mrSlideSorter.GetViewShell(); 1434 if (pViewShell == NULL) 1435 return false; 1436 SfxDispatcher* pDispatcher = pViewShell->GetDispatcher(); 1437 if (pDispatcher == NULL) 1438 return false; 1439 1440 const SfxPoolItem* pState = NULL; 1441 const SfxItemState eState (pDispatcher->QueryState(SID_PRESENTATION, pState)); 1442 return (eState & SFX_ITEM_DISABLED) == 0; 1443 } 1444 1445 1446 1447 1448 void StartShowButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor) 1449 { 1450 // Hide the tool tip early, while the slide show still intializes. 1451 mrSlideSorter.GetView().GetToolTip().SetPage(model::SharedPageDescriptor()); 1452 1453 Reference< XPresentation2 > xPresentation( 1454 mrSlideSorter.GetModel().GetDocument()->getPresentation()); 1455 if (xPresentation.is()) 1456 { 1457 Sequence<PropertyValue> aProperties (1); 1458 aProperties[0].Name = ::rtl::OUString::createFromAscii("FirstPage"); 1459 const ::rtl::OUString sName (rpDescriptor->GetPage()->GetName()); 1460 aProperties[0].Value = Any(sName); 1461 1462 // We have to temporarily change the options value 1463 // StartWithActualPage to make the slide show use the 1464 // specified first page. 1465 const DocumentType eType (mrSlideSorter.GetModel().GetDocument()->GetDocumentType()); 1466 const sal_Bool bSavedState (SD_MOD()->GetSdOptions(eType)->IsStartWithActualPage()); 1467 SD_MOD()->GetSdOptions(eType)->SetStartWithActualPage(sal_False); 1468 1469 xPresentation->startWithArguments(aProperties); 1470 1471 // Restore previous StartWithActualPage value. 1472 SD_MOD()->GetSdOptions(eType)->SetStartWithActualPage(bSavedState); 1473 } 1474 } 1475 1476 1477 1478 1479 //===== HideButton ============================================================ 1480 1481 HideButton::HideButton (SlideSorter& rSlideSorter) 1482 : ImageButton( 1483 rSlideSorter, 1484 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2Large), 1485 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2LargeHover), 1486 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2Medium), 1487 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2MediumHover), 1488 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2Small), 1489 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2SmallHover), 1490 rSlideSorter.GetTheme()->GetString(Theme::String_Command2)) 1491 { 1492 } 1493 1494 1495 1496 1497 void HideButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor) 1498 { 1499 if ( ! rpDescriptor) 1500 return; 1501 mrSlideSorter.GetController().GetSlotManager()->ChangeSlideExclusionState( 1502 (rpDescriptor->HasState(model::PageDescriptor::ST_Selected) 1503 ? model::SharedPageDescriptor() 1504 : rpDescriptor), 1505 true); 1506 } 1507 1508 1509 1510 1511 //===== DuplicateButton ======================================================= 1512 1513 DuplicateButton::DuplicateButton (SlideSorter& rSlideSorter) 1514 : ImageButton( 1515 rSlideSorter, 1516 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3Large), 1517 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3LargeHover), 1518 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3Medium), 1519 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3MediumHover), 1520 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3Small), 1521 rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3SmallHover), 1522 rSlideSorter.GetTheme()->GetString(Theme::String_Command3)) 1523 { 1524 } 1525 1526 1527 1528 1529 bool DuplicateButton::IsEnabled (void) const 1530 { 1531 ViewShell* pViewShell = mrSlideSorter.GetViewShell(); 1532 if (pViewShell == NULL) 1533 return false; 1534 SfxDispatcher* pDispatcher = pViewShell->GetDispatcher(); 1535 if (pDispatcher == NULL) 1536 return false; 1537 1538 const SfxPoolItem* pState = NULL; 1539 const SfxItemState eState (pDispatcher->QueryState( 1540 SID_DUPLICATE_PAGE, 1541 pState)); 1542 return (eState & SFX_ITEM_DISABLED) == 0; 1543 } 1544 1545 1546 1547 1548 void DuplicateButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor) 1549 { 1550 if ( ! rpDescriptor) 1551 return; 1552 1553 mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor(),false); 1554 1555 // When the page under the button is not selected then set the 1556 // selection to just this page. 1557 if ( ! rpDescriptor->HasState(model::PageDescriptor::ST_Selected)) 1558 { 1559 mrSlideSorter.GetController().GetPageSelector().DeselectAllPages(); 1560 mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor); 1561 } 1562 // Duplicate the selected pages. Insert the new pages right 1563 // after the current selection and select them 1564 if (mrSlideSorter.GetViewShell() != NULL 1565 && mrSlideSorter.GetViewShell()->GetDispatcher() != NULL) 1566 { 1567 mrSlideSorter.GetViewShell()->GetDispatcher()->Execute( 1568 SID_DUPLICATE_PAGE, 1569 SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD); 1570 } 1571 } 1572 1573 1574 1575 } } } // end of namespace ::sd::slidesorter::view 1576