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 {
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
windowResized(const awt::WindowEvent & rEvent)249 void SAL_CALL PresenterHelpView::windowResized (const awt::WindowEvent& rEvent)
250 {
251 (void)rEvent;
252 ThrowIfDisposed();
253 Resize();
254 }
255
256
257
258
windowMoved(const awt::WindowEvent & rEvent)259 void SAL_CALL PresenterHelpView::windowMoved (const awt::WindowEvent& rEvent)
260 {
261 (void)rEvent;
262 ThrowIfDisposed();
263 }
264
265
266
267
windowShown(const lang::EventObject & rEvent)268 void SAL_CALL PresenterHelpView::windowShown (const lang::EventObject& rEvent)
269 {
270 (void)rEvent;
271 ThrowIfDisposed();
272 Resize();
273 }
274
275
276
277
windowHidden(const lang::EventObject & rEvent)278 void SAL_CALL PresenterHelpView::windowHidden (const lang::EventObject& rEvent)
279 {
280 (void)rEvent;
281 ThrowIfDisposed();
282 }
283
284
285
286
287 //----- XPaintListener --------------------------------------------------------
288
windowPaint(const css::awt::PaintEvent & rEvent)289 void SAL_CALL PresenterHelpView::windowPaint (const css::awt::PaintEvent& rEvent)
290 {
291 Paint(rEvent.UpdateRect);
292 }
293
294
295
296
Paint(const awt::Rectangle & rUpdateBox)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
ReadHelpStrings(void)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
ProcessString(const Reference<beans::XPropertySet> & rsProperties)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
CheckFontSize(void)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
getResourceId(void)490 Reference<XResourceId> SAL_CALL PresenterHelpView::getResourceId (void)
491 {
492 ThrowIfDisposed();
493 return mxViewId;
494 }
495
496
497
498
isAnchorOnly(void)499 sal_Bool SAL_CALL PresenterHelpView::isAnchorOnly (void)
500 {
501 return false;
502 }
503
504
505
506
507 //-----------------------------------------------------------------------------
508
ProvideCanvas(void)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
Resize(void)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
ThrowIfDisposed(void)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
LineDescriptor(void)568 LineDescriptor::LineDescriptor (void)
569 : msLine(),
570 maSize(0,0),
571 mnVerticalOffset(0)
572 {
573 }
574
575
576
577
AddPart(const OUString & rsLine,const css::uno::Reference<css::rendering::XCanvasFont> & rxFont)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
IsEmpty(void) const590 bool LineDescriptor::IsEmpty (void) const
591 {
592 return msLine.getLength()==0;
593 }
594
595
596
597
CalculateSize(const css::uno::Reference<css::rendering::XCanvasFont> & rxFont)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
LineDescriptorList(const OUString & rsText,const css::uno::Reference<css::rendering::XCanvasFont> & rxFont,const sal_Int32 nMaximalWidth)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
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) const632 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
GetHeight(void) const672 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
Update(const css::uno::Reference<css::rendering::XCanvasFont> & rxFont,const sal_Int32 nMaximalWidth)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
SplitText(const OUString & rsText,vector<OUString> & rTextParts)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
FormatText(const vector<OUString> & rTextParts,const css::uno::Reference<css::rendering::XCanvasFont> & rxFont,const sal_Int32 nMaximalWidth)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
Block(const OUString & rsLeftText,const OUString & rsRightText,const css::uno::Reference<css::rendering::XCanvasFont> & rxFont,const sal_Int32 nMaximalWidth)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
Update(const css::uno::Reference<css::rendering::XCanvasFont> & rxFont,const sal_Int32 nMaximalWidth)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