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