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