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
PresenterHelpView(const Reference<uno::XComponentContext> & rxContext,const Reference<XResourceId> & rxViewId,const Reference<frame::XController> & rxController,const::rtl::Reference<PresenterController> & rpPresenterController)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
~PresenterHelpView(void)199 PresenterHelpView::~PresenterHelpView (void)
200 {
201 }
202
203
204
205
disposing(void)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
disposing(const lang::EventObject & rEventObject)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
windowResized(const awt::WindowEvent & rEvent)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
windowMoved(const awt::WindowEvent & rEvent)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
windowShown(const lang::EventObject & rEvent)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
windowHidden(const lang::EventObject & rEvent)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
windowPaint(const css::awt::PaintEvent & rEvent)294 void SAL_CALL PresenterHelpView::windowPaint (const css::awt::PaintEvent& rEvent)
295 throw (RuntimeException)
296 {
297 Paint(rEvent.UpdateRect);
298 }
299
300
301
302
Paint(const awt::Rectangle & rUpdateBox)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
ReadHelpStrings(void)383 void PresenterHelpView::ReadHelpStrings (void)
384 {
385 mpTextContainer.reset(new TextContainer());
386 PresenterConfigurationAccess aConfiguration (
387 mxComponentContext,
388 OUString::createFromAscii("/org.openoffice.Office.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
ProcessString(const Reference<beans::XPropertySet> & rsProperties)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
CheckFontSize(void)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
getResourceId(void)496 Reference<XResourceId> SAL_CALL PresenterHelpView::getResourceId (void)
497 throw (RuntimeException)
498 {
499 ThrowIfDisposed();
500 return mxViewId;
501 }
502
503
504
505
isAnchorOnly(void)506 sal_Bool SAL_CALL PresenterHelpView::isAnchorOnly (void)
507 throw (RuntimeException)
508 {
509 return false;
510 }
511
512
513
514
515 //-----------------------------------------------------------------------------
516
ProvideCanvas(void)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
Resize(void)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
ThrowIfDisposed(void)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
LineDescriptor(void)577 LineDescriptor::LineDescriptor (void)
578 : msLine(),
579 maSize(0,0),
580 mnVerticalOffset(0)
581 {
582 }
583
584
585
586
AddPart(const OUString & rsLine,const css::uno::Reference<css::rendering::XCanvasFont> & rxFont)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
IsEmpty(void) const599 bool LineDescriptor::IsEmpty (void) const
600 {
601 return msLine.getLength()==0;
602 }
603
604
605
606
CalculateSize(const css::uno::Reference<css::rendering::XCanvasFont> & rxFont)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
LineDescriptorList(const OUString & rsText,const css::uno::Reference<css::rendering::XCanvasFont> & rxFont,const sal_Int32 nMaximalWidth)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
Paint(const Reference<rendering::XCanvas> & rxCanvas,const geometry::RealRectangle2D & rBBox,const bool bFlushLeft,const rendering::ViewState & rViewState,rendering::RenderState & rRenderState,const css::uno::Reference<css::rendering::XCanvasFont> & rxFont) const641 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
GetHeight(void) const681 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
Update(const css::uno::Reference<css::rendering::XCanvasFont> & rxFont,const sal_Int32 nMaximalWidth)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
SplitText(const OUString & rsText,vector<OUString> & rTextParts)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
FormatText(const vector<OUString> & rTextParts,const css::uno::Reference<css::rendering::XCanvasFont> & rxFont,const sal_Int32 nMaximalWidth)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
Block(const OUString & rsLeftText,const OUString & rsRightText,const css::uno::Reference<css::rendering::XCanvasFont> & rxFont,const sal_Int32 nMaximalWidth)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
Update(const css::uno::Reference<css::rendering::XCanvasFont> & rxFont,const sal_Int32 nMaximalWidth)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