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 { 233 if (rEventObject.Source == mxCanvas) 234 { 235 mxCanvas = NULL; 236 } 237 else if (rEventObject.Source == mxWindow) 238 { 239 mxWindow = NULL; 240 dispose(); 241 } 242 } 243 244 245 246 247 //----- XWindowListener ------------------------------------------------------- 248 249 void SAL_CALL PresenterHelpView::windowResized (const awt::WindowEvent& rEvent) 250 { 251 (void)rEvent; 252 ThrowIfDisposed(); 253 Resize(); 254 } 255 256 257 258 259 void SAL_CALL PresenterHelpView::windowMoved (const awt::WindowEvent& rEvent) 260 { 261 (void)rEvent; 262 ThrowIfDisposed(); 263 } 264 265 266 267 268 void SAL_CALL PresenterHelpView::windowShown (const lang::EventObject& rEvent) 269 { 270 (void)rEvent; 271 ThrowIfDisposed(); 272 Resize(); 273 } 274 275 276 277 278 void SAL_CALL PresenterHelpView::windowHidden (const lang::EventObject& rEvent) 279 { 280 (void)rEvent; 281 ThrowIfDisposed(); 282 } 283 284 285 286 287 //----- XPaintListener -------------------------------------------------------- 288 289 void SAL_CALL PresenterHelpView::windowPaint (const css::awt::PaintEvent& rEvent) 290 { 291 Paint(rEvent.UpdateRect); 292 } 293 294 295 296 297 void PresenterHelpView::Paint (const awt::Rectangle& rUpdateBox) 298 { 299 ProvideCanvas(); 300 if ( ! mxCanvas.is()) 301 return; 302 303 // Clear background. 304 const awt::Rectangle aWindowBox (mxWindow->getPosSize()); 305 mpPresenterController->GetCanvasHelper()->Paint( 306 mpPresenterController->GetViewBackground(mxViewId->getResourceURL()), 307 Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY), 308 rUpdateBox, 309 awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height), 310 awt::Rectangle()); 311 312 // Paint vertical divider. 313 314 rendering::ViewState aViewState( 315 geometry::AffineMatrix2D(1,0,0, 0,1,0), 316 PresenterGeometryHelper::CreatePolygon(rUpdateBox, mxCanvas->getDevice())); 317 318 rendering::RenderState aRenderState ( 319 geometry::AffineMatrix2D(1,0,0, 0,1,0), 320 NULL, 321 Sequence<double>(4), 322 rendering::CompositeOperation::SOURCE); 323 PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor); 324 325 mxCanvas->drawLine( 326 geometry::RealPoint2D(aWindowBox.Width/2, gnVerticalBorder), 327 geometry::RealPoint2D(aWindowBox.Width/2, mnSeparatorY - gnVerticalBorder), 328 aViewState, 329 aRenderState); 330 331 // Paint the horizontal separator. 332 mxCanvas->drawLine( 333 geometry::RealPoint2D(0, mnSeparatorY), 334 geometry::RealPoint2D(aWindowBox.Width, mnSeparatorY), 335 aViewState, 336 aRenderState); 337 338 // Paint text. 339 double nY (gnVerticalBorder); 340 TextContainer::const_iterator iBlock (mpTextContainer->begin()); 341 TextContainer::const_iterator iBlockEnd (mpTextContainer->end()); 342 for ( ; iBlock!=iBlockEnd; ++iBlock) 343 { 344 const double nLeftHeight ( 345 (*iBlock)->maLeft.Paint(mxCanvas, 346 geometry::RealRectangle2D( 347 gnHorizontalGap, 348 nY, 349 aWindowBox.Width/2 - gnHorizontalGap, 350 aWindowBox.Height - gnVerticalBorder), 351 false, 352 aViewState, 353 aRenderState, 354 mpFont->mxFont)); 355 const double nRightHeight ( 356 (*iBlock)->maRight.Paint(mxCanvas, 357 geometry::RealRectangle2D( 358 aWindowBox.Width/2 + gnHorizontalGap, 359 nY, 360 aWindowBox.Width - gnHorizontalGap, 361 aWindowBox.Height - gnVerticalBorder), 362 true, 363 aViewState, 364 aRenderState, 365 mpFont->mxFont)); 366 nY += ::std::max(nLeftHeight,nRightHeight); 367 } 368 369 Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); 370 if (xSpriteCanvas.is()) 371 xSpriteCanvas->updateScreen(sal_False); 372 } 373 374 375 376 377 void PresenterHelpView::ReadHelpStrings (void) 378 { 379 mpTextContainer.reset(new TextContainer()); 380 PresenterConfigurationAccess aConfiguration ( 381 mxComponentContext, 382 OUString::createFromAscii("/org.openoffice.Office.PresenterScreen/"), 383 PresenterConfigurationAccess::READ_ONLY); 384 Reference<container::XNameAccess> xStrings ( 385 aConfiguration.GetConfigurationNode(A2S("PresenterScreenSettings/HelpView/HelpStrings")), 386 UNO_QUERY); 387 PresenterConfigurationAccess::ForAll( 388 xStrings, 389 ::boost::bind(&PresenterHelpView::ProcessString, this, _2)); 390 } 391 392 393 394 395 void PresenterHelpView::ProcessString ( 396 const Reference<beans::XPropertySet>& rsProperties) 397 { 398 if ( ! rsProperties.is()) 399 return; 400 401 OUString sLeftText; 402 PresenterConfigurationAccess::GetProperty(rsProperties, A2S("Left")) >>= sLeftText; 403 OUString sRightText; 404 PresenterConfigurationAccess::GetProperty(rsProperties, A2S("Right")) >>= sRightText; 405 406 const awt::Rectangle aWindowBox (mxWindow->getPosSize()); 407 mpTextContainer->push_back( 408 ::boost::shared_ptr<Block>( 409 new Block(sLeftText, sRightText, mpFont->mxFont, mnMaximalWidth))); 410 } 411 412 413 414 415 void PresenterHelpView::CheckFontSize (void) 416 { 417 if (mpFont.get() == NULL) 418 return; 419 420 const awt::Rectangle aWindowBox (mxWindow->getPosSize()); 421 if (aWindowBox.Width<=0 || aWindowBox.Height<=0) 422 return; 423 424 sal_Int32 nBestSize (6); 425 426 // Scaling down and then reformatting can cause the text to be too large 427 // still. So do this again and again until the text size is 428 // small enough. Restrict the number of loops. 429 for (int nLoopCount=0; nLoopCount<5; ++nLoopCount) 430 { 431 double nY (gnVerticalBorder); 432 TextContainer::iterator iBlock (mpTextContainer->begin()); 433 TextContainer::const_iterator iBlockEnd (mpTextContainer->end()); 434 for ( ; iBlock!=iBlockEnd; ++iBlock) 435 nY += ::std::max( 436 (*iBlock)->maLeft.GetHeight(), 437 (*iBlock)->maRight.GetHeight()); 438 439 const double nHeightDifference (nY - (aWindowBox.Height-gnVerticalBorder)); 440 if (nHeightDifference <= 0 && nHeightDifference > -50) 441 { 442 // We have found a good font size that is large and leaves not 443 // too much space below the help text. 444 return; 445 } 446 447 // Font is too large. Make it smaller. 448 449 // Use a simple linear transformation to calculate initial guess of 450 // a size that lets all help text be shown inside the window. 451 const double nScale (double(aWindowBox.Height-gnVerticalBorder) / nY); 452 if (nScale > 0.95 && nScale <1.05) 453 break; 454 455 sal_Int32 nFontSizeGuess (::std::max(sal_Int32(1),sal_Int32(mpFont->mnSize * nScale))); 456 if (nHeightDifference<0 && mpFont->mnSize>nBestSize) 457 nBestSize = mpFont->mnSize; 458 mpFont->mnSize = nFontSizeGuess; 459 mpFont->mxFont = NULL; 460 mpFont->PrepareFont(mxCanvas); 461 462 // Reformat blocks. 463 for (iBlock=mpTextContainer->begin(); iBlock!=iBlockEnd; ++iBlock) 464 (*iBlock)->Update(mpFont->mxFont, mnMaximalWidth); 465 } 466 467 if (nBestSize != mpFont->mnSize) 468 { 469 mpFont->mnSize = nBestSize; 470 mpFont->mxFont = NULL; 471 mpFont->PrepareFont(mxCanvas); 472 473 // Reformat blocks. 474 for (TextContainer::iterator 475 iBlock (mpTextContainer->begin()), 476 iEnd (mpTextContainer->end()); 477 iBlock!=iEnd; 478 ++iBlock) 479 { 480 (*iBlock)->Update(mpFont->mxFont, mnMaximalWidth); 481 } 482 } 483 } 484 485 486 487 488 //----- XResourceId ----------------------------------------------------------- 489 490 Reference<XResourceId> SAL_CALL PresenterHelpView::getResourceId (void) 491 { 492 ThrowIfDisposed(); 493 return mxViewId; 494 } 495 496 497 498 499 sal_Bool SAL_CALL PresenterHelpView::isAnchorOnly (void) 500 { 501 return false; 502 } 503 504 505 506 507 //----------------------------------------------------------------------------- 508 509 void PresenterHelpView::ProvideCanvas (void) 510 { 511 if ( ! mxCanvas.is() && mxPane.is()) 512 { 513 mxCanvas = mxPane->getCanvas(); 514 if ( ! mxCanvas.is()) 515 return; 516 Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY); 517 if (xComponent.is()) 518 xComponent->addEventListener(static_cast<awt::XPaintListener*>(this)); 519 520 if (mpCloseButton.is()) 521 mpCloseButton->SetCanvas(mxCanvas, mxWindow); 522 } 523 } 524 525 526 527 528 void PresenterHelpView::Resize (void) 529 { 530 if (mpCloseButton.get() != NULL && mxWindow.is()) 531 { 532 const awt::Rectangle aWindowBox (mxWindow->getPosSize()); 533 mnMaximalWidth = (mxWindow->getPosSize().Width - 4*gnHorizontalGap) / 2; 534 535 // Place vertical separator. 536 mnSeparatorY = aWindowBox.Height 537 - mpCloseButton->GetSize().Height - gnVerticalButtonPadding; 538 539 mpCloseButton->SetCenter(geometry::RealPoint2D( 540 aWindowBox.Width/2, 541 aWindowBox.Height - mpCloseButton->GetSize().Height/2)); 542 543 CheckFontSize(); 544 } 545 } 546 547 548 549 550 void PresenterHelpView::ThrowIfDisposed (void) 551 { 552 if (rBHelper.bDisposed || rBHelper.bInDispose) 553 { 554 throw lang::DisposedException ( 555 OUString(RTL_CONSTASCII_USTRINGPARAM( 556 "PresenterHelpView has been already disposed")), 557 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); 558 } 559 } 560 561 562 563 564 //===== LineDescritor ========================================================= 565 566 namespace { 567 568 LineDescriptor::LineDescriptor (void) 569 : msLine(), 570 maSize(0,0), 571 mnVerticalOffset(0) 572 { 573 } 574 575 576 577 578 void LineDescriptor::AddPart ( 579 const OUString& rsLine, 580 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) 581 { 582 msLine += rsLine; 583 584 CalculateSize(rxFont); 585 } 586 587 588 589 590 bool LineDescriptor::IsEmpty (void) const 591 { 592 return msLine.getLength()==0; 593 } 594 595 596 597 598 void LineDescriptor::CalculateSize ( 599 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) 600 { 601 OSL_ASSERT(rxFont.is()); 602 603 rendering::StringContext aContext (msLine, 0, msLine.getLength()); 604 Reference<rendering::XTextLayout> xLayout ( 605 rxFont->createTextLayout(aContext, rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 0)); 606 const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds()); 607 maSize = css::geometry::RealSize2D(aTextBBox.X2 - aTextBBox.X1, aTextBBox.Y2 - aTextBBox.Y1); 608 mnVerticalOffset = aTextBBox.Y2; 609 } 610 611 } // end of anonymous namespace 612 613 614 615 616 //===== LineDescriptorList ==================================================== 617 618 namespace { 619 620 LineDescriptorList::LineDescriptorList ( 621 const OUString& rsText, 622 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 623 const sal_Int32 nMaximalWidth) 624 : msText(rsText) 625 { 626 Update(rxFont, nMaximalWidth); 627 } 628 629 630 631 632 double LineDescriptorList::Paint( 633 const Reference<rendering::XCanvas>& rxCanvas, 634 const geometry::RealRectangle2D& rBBox, 635 const bool bFlushLeft, 636 const rendering::ViewState& rViewState, 637 rendering::RenderState& rRenderState, 638 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) const 639 { 640 if ( ! rxCanvas.is()) 641 return 0; 642 643 double nY (rBBox.Y1); 644 vector<LineDescriptor>::const_iterator iLine (mpLineDescriptors->begin()); 645 vector<LineDescriptor>::const_iterator iEnd (mpLineDescriptors->end()); 646 for ( ; iLine!=iEnd; ++iLine) 647 { 648 double nX (rBBox.X1); 649 if ( ! bFlushLeft) 650 nX = rBBox.X2 - iLine->maSize.Width; 651 rRenderState.AffineTransform.m02 = nX; 652 rRenderState.AffineTransform.m12 = nY + iLine->maSize.Height - iLine->mnVerticalOffset; 653 654 const rendering::StringContext aContext (iLine->msLine, 0, iLine->msLine.getLength()); 655 656 rxCanvas->drawText ( 657 aContext, 658 rxFont, 659 rViewState, 660 rRenderState, 661 rendering::TextDirection::WEAK_LEFT_TO_RIGHT); 662 663 nY += iLine->maSize.Height * 1.2; 664 } 665 666 return nY - rBBox.Y1; 667 } 668 669 670 671 672 double LineDescriptorList::GetHeight (void) const 673 { 674 double nHeight (0); 675 vector<LineDescriptor>::const_iterator iLine (mpLineDescriptors->begin()); 676 vector<LineDescriptor>::const_iterator iEnd (mpLineDescriptors->end()); 677 for ( ; iLine!=iEnd; ++iLine) 678 nHeight += iLine->maSize.Height * 1.2; 679 680 return nHeight; 681 } 682 683 684 685 686 void LineDescriptorList::Update ( 687 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 688 const sal_Int32 nMaximalWidth) 689 { 690 vector<OUString> aTextParts; 691 SplitText(msText, aTextParts); 692 FormatText(aTextParts, rxFont, nMaximalWidth); 693 } 694 695 696 697 698 void LineDescriptorList::SplitText ( 699 const OUString& rsText, 700 vector<OUString>& rTextParts) 701 { 702 const sal_Char cQuote ('\''); 703 const sal_Char cSeparator (','); 704 705 sal_Int32 nIndex (0); 706 sal_Int32 nStart (0); 707 sal_Int32 nLength (rsText.getLength()); 708 bool bIsQuoted (false); 709 while (nIndex < nLength) 710 { 711 const sal_Int32 nQuoteIndex (rsText.indexOf(cQuote, nIndex)); 712 const sal_Int32 nSeparatorIndex (rsText.indexOf(cSeparator, nIndex)); 713 if (nQuoteIndex>=0 && (nSeparatorIndex==-1 || nQuoteIndex<nSeparatorIndex)) 714 { 715 bIsQuoted = !bIsQuoted; 716 nIndex = nQuoteIndex+1; 717 continue; 718 } 719 720 const sal_Int32 nNextIndex = nSeparatorIndex; 721 if (nNextIndex < 0) 722 { 723 break; 724 } 725 else if ( ! bIsQuoted) 726 { 727 rTextParts.push_back(rsText.copy(nStart, nNextIndex-nStart)); 728 nStart = nNextIndex + 1; 729 } 730 nIndex = nNextIndex+1; 731 } 732 if (nStart < nLength) 733 rTextParts.push_back(rsText.copy(nStart, nLength-nStart)); 734 } 735 736 737 738 739 void LineDescriptorList::FormatText ( 740 const vector<OUString>& rTextParts, 741 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 742 const sal_Int32 nMaximalWidth) 743 { 744 LineDescriptor aLineDescriptor; 745 746 mpLineDescriptors.reset(new vector<LineDescriptor>()); 747 748 vector<OUString>::const_iterator iPart (rTextParts.begin()); 749 vector<OUString>::const_iterator iEnd (rTextParts.end()); 750 for ( ; iPart!=iEnd; ++iPart) 751 { 752 if (aLineDescriptor.IsEmpty()) 753 { 754 // Avoid empty lines. 755 aLineDescriptor.AddPart(*iPart, rxFont); 756 } 757 else if (PresenterCanvasHelper::GetTextSize( 758 rxFont, aLineDescriptor.msLine+A2S(", ")+*iPart).Width > nMaximalWidth) 759 { 760 aLineDescriptor.AddPart(A2S(","), rxFont); 761 mpLineDescriptors->push_back(aLineDescriptor); 762 aLineDescriptor = LineDescriptor(); 763 aLineDescriptor.AddPart(*iPart, rxFont); 764 } 765 else 766 { 767 aLineDescriptor.AddPart(A2S(", ")+*iPart, rxFont); 768 } 769 } 770 if ( ! aLineDescriptor.IsEmpty()) 771 { 772 mpLineDescriptors->push_back(aLineDescriptor); 773 } 774 } 775 776 777 } // end of anonymous namespace 778 779 780 781 782 //===== Block ================================================================= 783 784 namespace { 785 786 Block::Block ( 787 const OUString& rsLeftText, 788 const OUString& rsRightText, 789 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 790 const sal_Int32 nMaximalWidth) 791 : maLeft(rsLeftText, rxFont, nMaximalWidth), 792 maRight(rsRightText, rxFont, nMaximalWidth) 793 { 794 } 795 796 797 798 void Block::Update ( 799 const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 800 const sal_Int32 nMaximalWidth) 801 { 802 maLeft.Update(rxFont, nMaximalWidth); 803 maRight.Update(rxFont, nMaximalWidth); 804 } 805 806 } // end of anonymous namespace 807 808 } } // end of namespace ::sdext::presenter 809