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 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sdext.hxx" 30 31 #include "PresenterHelpView.hxx" 32 #include "PresenterButton.hxx" 33 #include "PresenterCanvasHelper.hxx" 34 #include "PresenterGeometryHelper.hxx" 35 #include "PresenterHelper.hxx" 36 #include "PresenterWindowManager.hxx" 37 #include <com/sun/star/awt/XWindowPeer.hpp> 38 #include <com/sun/star/container/XNameAccess.hpp> 39 #include <com/sun/star/drawing/framework/XConfigurationController.hpp> 40 #include <com/sun/star/drawing/framework/XControllerManager.hpp> 41 #include <com/sun/star/rendering/CompositeOperation.hpp> 42 #include <com/sun/star/rendering/TextDirection.hpp> 43 #include <com/sun/star/util/Color.hpp> 44 #include <algorithm> 45 #include <vector> 46 #include <boost/bind.hpp> 47 48 using namespace ::com::sun::star; 49 using namespace ::com::sun::star::uno; 50 using namespace ::com::sun::star::drawing::framework; 51 using ::rtl::OUString; 52 using ::std::vector; 53 54 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) 55 56 57 namespace sdext { namespace presenter { 58 59 namespace { 60 const static sal_Int32 gnHorizontalGap (20); 61 const static sal_Int32 gnVerticalBorder (30); 62 const static sal_Int32 gnVerticalButtonPadding (12); 63 64 class LineDescriptor 65 { 66 public: 67 LineDescriptor(void); 68 void AddPart ( 69 const OUString& rsLine, 70 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont); 71 bool IsEmpty (void) const; 72 73 OUString msLine; 74 geometry::RealSize2D maSize; 75 double mnVerticalOffset; 76 77 void CalculateSize (const css::uno::Reference<css::rendering::XCanvasFont>& rxFont); 78 }; 79 80 class LineDescriptorList 81 { 82 public: 83 LineDescriptorList ( 84 const OUString& rsText, 85 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 86 const sal_Int32 nMaximalWidth); 87 88 void Update ( 89 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 90 const sal_Int32 nMaximalWidth); 91 92 double Paint( 93 const Reference<rendering::XCanvas>& rxCanvas, 94 const geometry::RealRectangle2D& rBBox, 95 const bool bFlushLeft, 96 const rendering::ViewState& rViewState, 97 rendering::RenderState& rRenderState, 98 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) const; 99 double GetHeight (void) const; 100 101 private: 102 const OUString msText; 103 ::boost::shared_ptr<vector<LineDescriptor> > mpLineDescriptors; 104 105 void SplitText (const ::rtl::OUString& rsText, vector<rtl::OUString>& rTextParts); 106 void FormatText ( 107 const vector<rtl::OUString>& rTextParts, 108 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 109 const sal_Int32 nMaximalWidth); 110 }; 111 112 class Block 113 { 114 public: 115 Block (const Block& rBlock); 116 Block ( 117 const OUString& rsLeftText, 118 const OUString& rsRightText, 119 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 120 const sal_Int32 nMaximalWidth); 121 void Update ( 122 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 123 const sal_Int32 nMaximalWidth); 124 125 LineDescriptorList maLeft; 126 LineDescriptorList maRight; 127 }; 128 } // end of anonymous namespace 129 130 class PresenterHelpView::TextContainer : public vector<boost::shared_ptr<Block> > 131 { 132 }; 133 134 135 PresenterHelpView::PresenterHelpView ( 136 const Reference<uno::XComponentContext>& rxContext, 137 const Reference<XResourceId>& rxViewId, 138 const Reference<frame::XController>& rxController, 139 const ::rtl::Reference<PresenterController>& rpPresenterController) 140 : PresenterHelpViewInterfaceBase(m_aMutex), 141 mxComponentContext(rxContext), 142 mxViewId(rxViewId), 143 mxPane(), 144 mxWindow(), 145 mxCanvas(), 146 mpPresenterController(rpPresenterController), 147 mpFont(), 148 mpTextContainer(), 149 mpCloseButton(), 150 mnSeparatorY(0), 151 mnMaximalWidth(0) 152 { 153 try 154 { 155 // Get the content window via the pane anchor. 156 Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW); 157 Reference<XConfigurationController> xCC ( 158 xCM->getConfigurationController(), UNO_QUERY_THROW); 159 mxPane = Reference<XPane>(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW); 160 161 mxWindow = mxPane->getWindow(); 162 ProvideCanvas(); 163 164 mxWindow->addWindowListener(this); 165 mxWindow->addPaintListener(this); 166 Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY); 167 if (xPeer.is()) 168 xPeer->setBackground(util::Color(0xff000000)); 169 mxWindow->setVisible(sal_True); 170 171 if (mpPresenterController.is()) 172 { 173 mpFont = mpPresenterController->GetViewFont(mxViewId->getResourceURL()); 174 if (mpFont.get() != NULL) 175 { 176 mpFont->PrepareFont(mxCanvas); 177 } 178 } 179 180 // Create the close button. 181 mpCloseButton = PresenterButton::Create( 182 mxComponentContext, 183 mpPresenterController, 184 mpPresenterController->GetTheme(), 185 mxWindow, 186 mxCanvas, 187 A2S("HelpViewCloser")); 188 189 ReadHelpStrings(); 190 Resize(); 191 } 192 catch (RuntimeException&) 193 { 194 mxViewId = NULL; 195 mxWindow = NULL; 196 throw; 197 } 198 } 199 200 201 202 203 PresenterHelpView::~PresenterHelpView (void) 204 { 205 } 206 207 208 209 210 void SAL_CALL PresenterHelpView::disposing (void) 211 { 212 mxViewId = NULL; 213 214 if (mpCloseButton.is()) 215 { 216 Reference<lang::XComponent> xComponent ( 217 static_cast<XWeak*>(mpCloseButton.get()), UNO_QUERY); 218 mpCloseButton = NULL; 219 if (xComponent.is()) 220 xComponent->dispose(); 221 } 222 223 if (mxWindow.is()) 224 { 225 mxWindow->removeWindowListener(this); 226 mxWindow->removePaintListener(this); 227 } 228 } 229 230 231 232 233 //----- lang::XEventListener -------------------------------------------------- 234 235 void SAL_CALL PresenterHelpView::disposing (const lang::EventObject& rEventObject) 236 throw (RuntimeException) 237 { 238 if (rEventObject.Source == mxCanvas) 239 { 240 mxCanvas = NULL; 241 } 242 else if (rEventObject.Source == mxWindow) 243 { 244 mxWindow = NULL; 245 dispose(); 246 } 247 } 248 249 250 251 252 //----- XWindowListener ------------------------------------------------------- 253 254 void SAL_CALL PresenterHelpView::windowResized (const awt::WindowEvent& rEvent) 255 throw (uno::RuntimeException) 256 { 257 (void)rEvent; 258 ThrowIfDisposed(); 259 Resize(); 260 } 261 262 263 264 265 void SAL_CALL PresenterHelpView::windowMoved (const awt::WindowEvent& rEvent) 266 throw (uno::RuntimeException) 267 { 268 (void)rEvent; 269 ThrowIfDisposed(); 270 } 271 272 273 274 275 void SAL_CALL PresenterHelpView::windowShown (const lang::EventObject& rEvent) 276 throw (uno::RuntimeException) 277 { 278 (void)rEvent; 279 ThrowIfDisposed(); 280 Resize(); 281 } 282 283 284 285 286 void SAL_CALL PresenterHelpView::windowHidden (const lang::EventObject& rEvent) 287 throw (uno::RuntimeException) 288 { 289 (void)rEvent; 290 ThrowIfDisposed(); 291 } 292 293 294 295 296 //----- XPaintListener -------------------------------------------------------- 297 298 void SAL_CALL PresenterHelpView::windowPaint (const css::awt::PaintEvent& rEvent) 299 throw (RuntimeException) 300 { 301 Paint(rEvent.UpdateRect); 302 } 303 304 305 306 307 void PresenterHelpView::Paint (const awt::Rectangle& rUpdateBox) 308 { 309 ProvideCanvas(); 310 if ( ! mxCanvas.is()) 311 return; 312 313 // Clear background. 314 const awt::Rectangle aWindowBox (mxWindow->getPosSize()); 315 mpPresenterController->GetCanvasHelper()->Paint( 316 mpPresenterController->GetViewBackground(mxViewId->getResourceURL()), 317 Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY), 318 rUpdateBox, 319 awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height), 320 awt::Rectangle()); 321 322 // Paint vertical divider. 323 324 rendering::ViewState aViewState( 325 geometry::AffineMatrix2D(1,0,0, 0,1,0), 326 PresenterGeometryHelper::CreatePolygon(rUpdateBox, mxCanvas->getDevice())); 327 328 rendering::RenderState aRenderState ( 329 geometry::AffineMatrix2D(1,0,0, 0,1,0), 330 NULL, 331 Sequence<double>(4), 332 rendering::CompositeOperation::SOURCE); 333 PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor); 334 335 mxCanvas->drawLine( 336 geometry::RealPoint2D(aWindowBox.Width/2, gnVerticalBorder), 337 geometry::RealPoint2D(aWindowBox.Width/2, mnSeparatorY - gnVerticalBorder), 338 aViewState, 339 aRenderState); 340 341 // Paint the horizontal separator. 342 mxCanvas->drawLine( 343 geometry::RealPoint2D(0, mnSeparatorY), 344 geometry::RealPoint2D(aWindowBox.Width, mnSeparatorY), 345 aViewState, 346 aRenderState); 347 348 // Paint text. 349 double nY (gnVerticalBorder); 350 TextContainer::const_iterator iBlock (mpTextContainer->begin()); 351 TextContainer::const_iterator iBlockEnd (mpTextContainer->end()); 352 for ( ; iBlock!=iBlockEnd; ++iBlock) 353 { 354 const double nLeftHeight ( 355 (*iBlock)->maLeft.Paint(mxCanvas, 356 geometry::RealRectangle2D( 357 gnHorizontalGap, 358 nY, 359 aWindowBox.Width/2 - gnHorizontalGap, 360 aWindowBox.Height - gnVerticalBorder), 361 false, 362 aViewState, 363 aRenderState, 364 mpFont->mxFont)); 365 const double nRightHeight ( 366 (*iBlock)->maRight.Paint(mxCanvas, 367 geometry::RealRectangle2D( 368 aWindowBox.Width/2 + gnHorizontalGap, 369 nY, 370 aWindowBox.Width - gnHorizontalGap, 371 aWindowBox.Height - gnVerticalBorder), 372 true, 373 aViewState, 374 aRenderState, 375 mpFont->mxFont)); 376 nY += ::std::max(nLeftHeight,nRightHeight); 377 } 378 379 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); 380 if (xSpriteCanvas.is()) 381 xSpriteCanvas->updateScreen(sal_False); 382 } 383 384 385 386 387 void PresenterHelpView::ReadHelpStrings (void) 388 { 389 mpTextContainer.reset(new TextContainer()); 390 PresenterConfigurationAccess aConfiguration ( 391 mxComponentContext, 392 OUString::createFromAscii("/org.openoffice.Office.extension.PresenterScreen/"), 393 PresenterConfigurationAccess::READ_ONLY); 394 Reference<container::XNameAccess> xStrings ( 395 aConfiguration.GetConfigurationNode(A2S("PresenterScreenSettings/HelpView/HelpStrings")), 396 UNO_QUERY); 397 PresenterConfigurationAccess::ForAll( 398 xStrings, 399 ::boost::bind(&PresenterHelpView::ProcessString, this, _2)); 400 } 401 402 403 404 405 void PresenterHelpView::ProcessString ( 406 const Reference<beans::XPropertySet>& rsProperties) 407 { 408 if ( ! rsProperties.is()) 409 return; 410 411 OUString sLeftText; 412 PresenterConfigurationAccess::GetProperty(rsProperties, A2S("Left")) >>= sLeftText; 413 OUString sRightText; 414 PresenterConfigurationAccess::GetProperty(rsProperties, A2S("Right")) >>= sRightText; 415 416 const awt::Rectangle aWindowBox (mxWindow->getPosSize()); 417 mpTextContainer->push_back( 418 ::boost::shared_ptr<Block>( 419 new Block(sLeftText, sRightText, mpFont->mxFont, mnMaximalWidth))); 420 } 421 422 423 424 425 void PresenterHelpView::CheckFontSize (void) 426 { 427 if (mpFont.get() == NULL) 428 return; 429 430 const awt::Rectangle aWindowBox (mxWindow->getPosSize()); 431 if (aWindowBox.Width<=0 || aWindowBox.Height<=0) 432 return; 433 434 sal_Int32 nBestSize (6); 435 436 // Scaling down and then reformatting can cause the text to be too large 437 // still. So do this again and again until the text size is 438 // small enough. Restrict the number of loops. 439 for (int nLoopCount=0; nLoopCount<5; ++nLoopCount) 440 { 441 double nY (gnVerticalBorder); 442 TextContainer::iterator iBlock (mpTextContainer->begin()); 443 TextContainer::const_iterator iBlockEnd (mpTextContainer->end()); 444 for ( ; iBlock!=iBlockEnd; ++iBlock) 445 nY += ::std::max( 446 (*iBlock)->maLeft.GetHeight(), 447 (*iBlock)->maRight.GetHeight()); 448 449 const double nHeightDifference (nY - (aWindowBox.Height-gnVerticalBorder)); 450 if (nHeightDifference <= 0 && nHeightDifference > -50) 451 { 452 // We have found a good font size that is large and leaves not 453 // too much space below the help text. 454 return; 455 } 456 457 // Font is too large. Make it smaller. 458 459 // Use a simple linear transformation to calculate initial guess of 460 // a size that lets all help text be shown inside the window. 461 const double nScale (double(aWindowBox.Height-gnVerticalBorder) / nY); 462 if (nScale > 0.95 && nScale <1.05) 463 break; 464 465 sal_Int32 nFontSizeGuess (::std::max(sal_Int32(1),sal_Int32(mpFont->mnSize * nScale))); 466 if (nHeightDifference<0 && mpFont->mnSize>nBestSize) 467 nBestSize = mpFont->mnSize; 468 mpFont->mnSize = nFontSizeGuess; 469 mpFont->mxFont = NULL; 470 mpFont->PrepareFont(mxCanvas); 471 472 // Reformat blocks. 473 for (iBlock=mpTextContainer->begin(); iBlock!=iBlockEnd; ++iBlock) 474 (*iBlock)->Update(mpFont->mxFont, mnMaximalWidth); 475 } 476 477 if (nBestSize != mpFont->mnSize) 478 { 479 mpFont->mnSize = nBestSize; 480 mpFont->mxFont = NULL; 481 mpFont->PrepareFont(mxCanvas); 482 483 // Reformat blocks. 484 for (TextContainer::iterator 485 iBlock (mpTextContainer->begin()), 486 iEnd (mpTextContainer->end()); 487 iBlock!=iEnd; 488 ++iBlock) 489 { 490 (*iBlock)->Update(mpFont->mxFont, mnMaximalWidth); 491 } 492 } 493 } 494 495 496 497 498 //----- XResourceId ----------------------------------------------------------- 499 500 Reference<XResourceId> SAL_CALL PresenterHelpView::getResourceId (void) 501 throw (RuntimeException) 502 { 503 ThrowIfDisposed(); 504 return mxViewId; 505 } 506 507 508 509 510 sal_Bool SAL_CALL PresenterHelpView::isAnchorOnly (void) 511 throw (RuntimeException) 512 { 513 return false; 514 } 515 516 517 518 519 //----------------------------------------------------------------------------- 520 521 void PresenterHelpView::ProvideCanvas (void) 522 { 523 if ( ! mxCanvas.is() && mxPane.is()) 524 { 525 mxCanvas = mxPane->getCanvas(); 526 if ( ! mxCanvas.is()) 527 return; 528 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY); 529 if (xComponent.is()) 530 xComponent->addEventListener(static_cast<awt::XPaintListener*>(this)); 531 532 if (mpCloseButton.is()) 533 mpCloseButton->SetCanvas(mxCanvas, mxWindow); 534 } 535 } 536 537 538 539 540 void PresenterHelpView::Resize (void) 541 { 542 if (mpCloseButton.get() != NULL && mxWindow.is()) 543 { 544 const awt::Rectangle aWindowBox (mxWindow->getPosSize()); 545 mnMaximalWidth = (mxWindow->getPosSize().Width - 4*gnHorizontalGap) / 2; 546 547 // Place vertical separator. 548 mnSeparatorY = aWindowBox.Height 549 - mpCloseButton->GetSize().Height - gnVerticalButtonPadding; 550 551 mpCloseButton->SetCenter(geometry::RealPoint2D( 552 aWindowBox.Width/2, 553 aWindowBox.Height - mpCloseButton->GetSize().Height/2)); 554 555 CheckFontSize(); 556 } 557 } 558 559 560 561 562 void PresenterHelpView::ThrowIfDisposed (void) 563 throw (lang::DisposedException) 564 { 565 if (rBHelper.bDisposed || rBHelper.bInDispose) 566 { 567 throw lang::DisposedException ( 568 OUString(RTL_CONSTASCII_USTRINGPARAM( 569 "PresenterHelpView has been already disposed")), 570 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); 571 } 572 } 573 574 575 576 577 //===== LineDescritor ========================================================= 578 579 namespace { 580 581 LineDescriptor::LineDescriptor (void) 582 : msLine(), 583 maSize(0,0), 584 mnVerticalOffset(0) 585 { 586 } 587 588 589 590 591 void LineDescriptor::AddPart ( 592 const OUString& rsLine, 593 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) 594 { 595 msLine += rsLine; 596 597 CalculateSize(rxFont); 598 } 599 600 601 602 603 bool LineDescriptor::IsEmpty (void) const 604 { 605 return msLine.getLength()==0; 606 } 607 608 609 610 611 void LineDescriptor::CalculateSize ( 612 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) 613 { 614 OSL_ASSERT(rxFont.is()); 615 616 rendering::StringContext aContext (msLine, 0, msLine.getLength()); 617 Reference<rendering::XTextLayout> xLayout ( 618 rxFont->createTextLayout(aContext, rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 0)); 619 const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds()); 620 maSize = css::geometry::RealSize2D(aTextBBox.X2 - aTextBBox.X1, aTextBBox.Y2 - aTextBBox.Y1); 621 mnVerticalOffset = aTextBBox.Y2; 622 } 623 624 } // end of anonymous namespace 625 626 627 628 629 //===== LineDescriptorList ==================================================== 630 631 namespace { 632 633 LineDescriptorList::LineDescriptorList ( 634 const OUString& rsText, 635 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 636 const sal_Int32 nMaximalWidth) 637 : msText(rsText) 638 { 639 Update(rxFont, nMaximalWidth); 640 } 641 642 643 644 645 double LineDescriptorList::Paint( 646 const Reference<rendering::XCanvas>& rxCanvas, 647 const geometry::RealRectangle2D& rBBox, 648 const bool bFlushLeft, 649 const rendering::ViewState& rViewState, 650 rendering::RenderState& rRenderState, 651 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) const 652 { 653 if ( ! rxCanvas.is()) 654 return 0; 655 656 double nY (rBBox.Y1); 657 vector<LineDescriptor>::const_iterator iLine (mpLineDescriptors->begin()); 658 vector<LineDescriptor>::const_iterator iEnd (mpLineDescriptors->end()); 659 for ( ; iLine!=iEnd; ++iLine) 660 { 661 double nX (rBBox.X1); 662 if ( ! bFlushLeft) 663 nX = rBBox.X2 - iLine->maSize.Width; 664 rRenderState.AffineTransform.m02 = nX; 665 rRenderState.AffineTransform.m12 = nY + iLine->maSize.Height - iLine->mnVerticalOffset; 666 667 const rendering::StringContext aContext (iLine->msLine, 0, iLine->msLine.getLength()); 668 669 rxCanvas->drawText ( 670 aContext, 671 rxFont, 672 rViewState, 673 rRenderState, 674 rendering::TextDirection::WEAK_LEFT_TO_RIGHT); 675 676 nY += iLine->maSize.Height * 1.2; 677 } 678 679 return nY - rBBox.Y1; 680 } 681 682 683 684 685 double LineDescriptorList::GetHeight (void) const 686 { 687 double nHeight (0); 688 vector<LineDescriptor>::const_iterator iLine (mpLineDescriptors->begin()); 689 vector<LineDescriptor>::const_iterator iEnd (mpLineDescriptors->end()); 690 for ( ; iLine!=iEnd; ++iLine) 691 nHeight += iLine->maSize.Height * 1.2; 692 693 return nHeight; 694 } 695 696 697 698 699 void LineDescriptorList::Update ( 700 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 701 const sal_Int32 nMaximalWidth) 702 { 703 vector<OUString> aTextParts; 704 SplitText(msText, aTextParts); 705 FormatText(aTextParts, rxFont, nMaximalWidth); 706 } 707 708 709 710 711 void LineDescriptorList::SplitText ( 712 const OUString& rsText, 713 vector<OUString>& rTextParts) 714 { 715 const sal_Char cQuote ('\''); 716 const sal_Char cSeparator (','); 717 718 sal_Int32 nIndex (0); 719 sal_Int32 nStart (0); 720 sal_Int32 nLength (rsText.getLength()); 721 bool bIsQuoted (false); 722 while (nIndex < nLength) 723 { 724 const sal_Int32 nQuoteIndex (rsText.indexOf(cQuote, nIndex)); 725 const sal_Int32 nSeparatorIndex (rsText.indexOf(cSeparator, nIndex)); 726 if (nQuoteIndex>=0 && (nSeparatorIndex==-1 || nQuoteIndex<nSeparatorIndex)) 727 { 728 bIsQuoted = !bIsQuoted; 729 nIndex = nQuoteIndex+1; 730 continue; 731 } 732 733 const sal_Int32 nNextIndex = nSeparatorIndex; 734 if (nNextIndex < 0) 735 { 736 break; 737 } 738 else if ( ! bIsQuoted) 739 { 740 rTextParts.push_back(rsText.copy(nStart, nNextIndex-nStart)); 741 nStart = nNextIndex + 1; 742 } 743 nIndex = nNextIndex+1; 744 } 745 if (nStart < nLength) 746 rTextParts.push_back(rsText.copy(nStart, nLength-nStart)); 747 } 748 749 750 751 752 void LineDescriptorList::FormatText ( 753 const vector<OUString>& rTextParts, 754 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 755 const sal_Int32 nMaximalWidth) 756 { 757 LineDescriptor aLineDescriptor; 758 759 mpLineDescriptors.reset(new vector<LineDescriptor>()); 760 761 vector<OUString>::const_iterator iPart (rTextParts.begin()); 762 vector<OUString>::const_iterator iEnd (rTextParts.end()); 763 for ( ; iPart!=iEnd; ++iPart) 764 { 765 if (aLineDescriptor.IsEmpty()) 766 { 767 // Avoid empty lines. 768 aLineDescriptor.AddPart(*iPart, rxFont); 769 } 770 else if (PresenterCanvasHelper::GetTextSize( 771 rxFont, aLineDescriptor.msLine+A2S(", ")+*iPart).Width > nMaximalWidth) 772 { 773 aLineDescriptor.AddPart(A2S(","), rxFont); 774 mpLineDescriptors->push_back(aLineDescriptor); 775 aLineDescriptor = LineDescriptor(); 776 aLineDescriptor.AddPart(*iPart, rxFont); 777 } 778 else 779 { 780 aLineDescriptor.AddPart(A2S(", ")+*iPart, rxFont); 781 } 782 } 783 if ( ! aLineDescriptor.IsEmpty()) 784 { 785 mpLineDescriptors->push_back(aLineDescriptor); 786 } 787 } 788 789 790 } // end of anonymous namespace 791 792 793 794 795 //===== Block ================================================================= 796 797 namespace { 798 799 Block::Block ( 800 const OUString& rsLeftText, 801 const OUString& rsRightText, 802 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 803 const sal_Int32 nMaximalWidth) 804 : maLeft(rsLeftText, rxFont, nMaximalWidth), 805 maRight(rsRightText, rxFont, nMaximalWidth) 806 { 807 } 808 809 810 811 void Block::Update ( 812 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 813 const sal_Int32 nMaximalWidth) 814 { 815 maLeft.Update(rxFont, nMaximalWidth); 816 maRight.Update(rxFont, nMaximalWidth); 817 } 818 819 } // end of anonymous namespace 820 821 } } // end of namespace ::sdext::presenter 822 823 824