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