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