1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: PresenterHelpView.cxx,v $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_sdext.hxx"
35 #include "PresenterHelpView.hxx"
36 #include "PresenterButton.hxx"
37 #include "PresenterCanvasHelper.hxx"
38 #include "PresenterGeometryHelper.hxx"
39 #include "PresenterHelper.hxx"
40 #include "PresenterWindowManager.hxx"
41 #include <com/sun/star/awt/XWindowPeer.hpp>
42 #include <com/sun/star/container/XNameAccess.hpp>
43 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
44 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
45 #include <com/sun/star/rendering/CompositeOperation.hpp>
46 #include <com/sun/star/rendering/TextDirection.hpp>
47 #include <com/sun/star/util/Color.hpp>
50 #include <boost/bind.hpp>
52 using namespace ::com::sun::star
;
53 using namespace ::com::sun::star::uno
;
54 using namespace ::com::sun::star::drawing::framework
;
55 using ::rtl::OUString
;
58 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
61 namespace sdext
{ namespace presenter
{
64 const static sal_Int32
gnHorizontalGap (20);
65 const static sal_Int32
gnVerticalBorder (30);
66 const static sal_Int32
gnVerticalButtonPadding (12);
73 const OUString
& rsLine
,
74 const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
);
75 bool IsEmpty (void) const;
78 geometry::RealSize2D maSize
;
79 double mnVerticalOffset
;
81 void CalculateSize (const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
);
84 class LineDescriptorList
88 const OUString
& rsText
,
89 const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
,
90 const sal_Int32 nMaximalWidth
);
93 const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
,
94 const sal_Int32 nMaximalWidth
);
97 const Reference
<rendering::XCanvas
>& rxCanvas
,
98 const geometry::RealRectangle2D
& rBBox
,
99 const bool bFlushLeft
,
100 const rendering::ViewState
& rViewState
,
101 rendering::RenderState
& rRenderState
,
102 const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
) const;
103 double GetHeight (void) const;
106 const OUString msText
;
107 ::boost::shared_ptr
<vector
<LineDescriptor
> > mpLineDescriptors
;
109 void SplitText (const ::rtl::OUString
& rsText
, vector
<rtl::OUString
>& rTextParts
);
111 const vector
<rtl::OUString
>& rTextParts
,
112 const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
,
113 const sal_Int32 nMaximalWidth
);
119 Block (const Block
& rBlock
);
121 const OUString
& rsLeftText
,
122 const OUString
& rsRightText
,
123 const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
,
124 const sal_Int32 nMaximalWidth
);
126 const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
,
127 const sal_Int32 nMaximalWidth
);
129 LineDescriptorList maLeft
;
130 LineDescriptorList maRight
;
132 } // end of anonymous namespace
134 class PresenterHelpView::TextContainer
: public vector
<boost::shared_ptr
<Block
> >
139 PresenterHelpView::PresenterHelpView (
140 const Reference
<uno::XComponentContext
>& rxContext
,
141 const Reference
<XResourceId
>& rxViewId
,
142 const Reference
<frame::XController
>& rxController
,
143 const ::rtl::Reference
<PresenterController
>& rpPresenterController
)
144 : PresenterHelpViewInterfaceBase(m_aMutex
),
145 mxComponentContext(rxContext
),
150 mpPresenterController(rpPresenterController
),
159 // Get the content window via the pane anchor.
160 Reference
<XControllerManager
> xCM (rxController
, UNO_QUERY_THROW
);
161 Reference
<XConfigurationController
> xCC (
162 xCM
->getConfigurationController(), UNO_QUERY_THROW
);
163 mxPane
= Reference
<XPane
>(xCC
->getResource(rxViewId
->getAnchor()), UNO_QUERY_THROW
);
165 mxWindow
= mxPane
->getWindow();
168 mxWindow
->addWindowListener(this);
169 mxWindow
->addPaintListener(this);
170 Reference
<awt::XWindowPeer
> xPeer (mxWindow
, UNO_QUERY
);
172 xPeer
->setBackground(util::Color(0xff000000));
173 mxWindow
->setVisible(sal_True
);
175 if (mpPresenterController
.is())
177 mpFont
= mpPresenterController
->GetViewFont(mxViewId
->getResourceURL());
178 if (mpFont
.get() != NULL
)
180 mpFont
->PrepareFont(mxCanvas
);
184 // Create the close button.
185 mpCloseButton
= PresenterButton::Create(
187 mpPresenterController
,
188 mpPresenterController
->GetTheme(),
191 A2S("HelpViewCloser"));
193 mnMaximalWidth
= (mxWindow
->getPosSize().Width
- 4*gnHorizontalGap
) / 2;
198 catch (RuntimeException
&)
209 PresenterHelpView::~PresenterHelpView (void)
216 void SAL_CALL
PresenterHelpView::disposing (void)
220 if (mpCloseButton
.is())
222 Reference
<lang::XComponent
> xComponent (
223 static_cast<XWeak
*>(mpCloseButton
.get()), UNO_QUERY
);
224 mpCloseButton
= NULL
;
226 xComponent
->dispose();
231 mxWindow
->removeWindowListener(this);
232 mxWindow
->removePaintListener(this);
239 //----- lang::XEventListener --------------------------------------------------
241 void SAL_CALL
PresenterHelpView::disposing (const lang::EventObject
& rEventObject
)
242 throw (RuntimeException
)
244 if (rEventObject
.Source
== mxCanvas
)
248 else if (rEventObject
.Source
== mxWindow
)
258 //----- XWindowListener -------------------------------------------------------
260 void SAL_CALL
PresenterHelpView::windowResized (const awt::WindowEvent
& rEvent
)
261 throw (uno::RuntimeException
)
271 void SAL_CALL
PresenterHelpView::windowMoved (const awt::WindowEvent
& rEvent
)
272 throw (uno::RuntimeException
)
281 void SAL_CALL
PresenterHelpView::windowShown (const lang::EventObject
& rEvent
)
282 throw (uno::RuntimeException
)
292 void SAL_CALL
PresenterHelpView::windowHidden (const lang::EventObject
& rEvent
)
293 throw (uno::RuntimeException
)
302 //----- XPaintListener --------------------------------------------------------
304 void SAL_CALL
PresenterHelpView::windowPaint (const css::awt::PaintEvent
& rEvent
)
305 throw (RuntimeException
)
307 Paint(rEvent
.UpdateRect
);
313 void PresenterHelpView::Paint (const awt::Rectangle
& rUpdateBox
)
316 if ( ! mxCanvas
.is())
320 const awt::Rectangle
aWindowBox (mxWindow
->getPosSize());
321 mpPresenterController
->GetCanvasHelper()->Paint(
322 mpPresenterController
->GetViewBackground(mxViewId
->getResourceURL()),
323 Reference
<rendering::XCanvas
>(mxCanvas
, UNO_QUERY
),
325 awt::Rectangle(0,0,aWindowBox
.Width
,aWindowBox
.Height
),
328 // Paint vertical divider.
330 rendering::ViewState
aViewState(
331 geometry::AffineMatrix2D(1,0,0, 0,1,0),
332 PresenterGeometryHelper::CreatePolygon(rUpdateBox
, mxCanvas
->getDevice()));
334 rendering::RenderState
aRenderState (
335 geometry::AffineMatrix2D(1,0,0, 0,1,0),
338 rendering::CompositeOperation::SOURCE
);
339 PresenterCanvasHelper::SetDeviceColor(aRenderState
, mpFont
->mnColor
);
342 geometry::RealPoint2D(aWindowBox
.Width
/2, gnVerticalBorder
),
343 geometry::RealPoint2D(aWindowBox
.Width
/2, mnSeparatorY
- gnVerticalBorder
),
347 // Paint the horizontal separator.
349 geometry::RealPoint2D(0, mnSeparatorY
),
350 geometry::RealPoint2D(aWindowBox
.Width
, mnSeparatorY
),
355 double nY (gnVerticalBorder
);
356 TextContainer::const_iterator
iBlock (mpTextContainer
->begin());
357 TextContainer::const_iterator
iBlockEnd (mpTextContainer
->end());
358 for ( ; iBlock
!=iBlockEnd
; ++iBlock
)
360 const double nLeftHeight (
361 (*iBlock
)->maLeft
.Paint(mxCanvas
,
362 geometry::RealRectangle2D(
365 aWindowBox
.Width
/2 - gnHorizontalGap
,
366 aWindowBox
.Height
- gnVerticalBorder
),
371 const double nRightHeight (
372 (*iBlock
)->maRight
.Paint(mxCanvas
,
373 geometry::RealRectangle2D(
374 aWindowBox
.Width
/2 + gnHorizontalGap
,
376 aWindowBox
.Width
- gnHorizontalGap
,
377 aWindowBox
.Height
- gnVerticalBorder
),
382 nY
+= ::std::max(nLeftHeight
,nRightHeight
);
385 Reference
<rendering::XSpriteCanvas
> xSpriteCanvas (mxCanvas
, UNO_QUERY
);
386 if (xSpriteCanvas
.is())
387 xSpriteCanvas
->updateScreen(sal_False
);
393 void PresenterHelpView::ReadHelpStrings (void)
395 mpTextContainer
.reset(new TextContainer());
396 PresenterConfigurationAccess
aConfiguration (
398 OUString::createFromAscii("/org.openoffice.Office.extension.PresenterScreen/"),
399 PresenterConfigurationAccess::READ_ONLY
);
400 Reference
<container::XNameAccess
> xStrings (
401 aConfiguration
.GetConfigurationNode(A2S("PresenterScreenSettings/HelpView/HelpStrings")),
403 PresenterConfigurationAccess::ForAll(
405 ::boost::bind(&PresenterHelpView::ProcessString
, this, _2
));
411 void PresenterHelpView::ProcessString (
412 const Reference
<beans::XPropertySet
>& rsProperties
)
414 if ( ! rsProperties
.is())
418 PresenterConfigurationAccess::GetProperty(rsProperties
, A2S("Left")) >>= sLeftText
;
420 PresenterConfigurationAccess::GetProperty(rsProperties
, A2S("Right")) >>= sRightText
;
422 const awt::Rectangle
aWindowBox (mxWindow
->getPosSize());
423 mpTextContainer
->push_back(
424 ::boost::shared_ptr
<Block
>(
425 new Block(sLeftText
, sRightText
, mpFont
->mxFont
, mnMaximalWidth
)));
431 void PresenterHelpView::CheckFontSize (void)
433 if (mpFont
.get() == NULL
)
436 const awt::Rectangle
aWindowBox (mxWindow
->getPosSize());
438 // Scaling down and then reformatting can cause the text to be too large
439 // still. So do this again and again until the text size is
440 // small enough. Restrict the number of loops.
441 for (int nLoopCount
=0; nLoopCount
<5; ++nLoopCount
)
443 double nY (gnVerticalBorder
);
444 TextContainer::iterator
iBlock (mpTextContainer
->begin());
445 TextContainer::const_iterator
iBlockEnd (mpTextContainer
->end());
446 for ( ; iBlock
!=iBlockEnd
; ++iBlock
)
448 (*iBlock
)->maLeft
.GetHeight(),
449 (*iBlock
)->maRight
.GetHeight());
451 if (nY
<= aWindowBox
.Height
-gnVerticalBorder
)
454 // Font is too large. Make it smaller.
456 // Use a simple linear transformation to calculate initial guess of
457 // a size that lets all help text be shown inside the window.
458 const double nScale (::std::min(0.95,double(aWindowBox
.Height
-gnVerticalBorder
) / nY
));
459 sal_Int32
nFontSizeGuess (::std::max(sal_Int32(1),sal_Int32(mpFont
->mnSize
* nScale
)));
460 mpFont
->mnSize
= nFontSizeGuess
;
461 mpFont
->mxFont
= NULL
;
462 mpFont
->PrepareFont(mxCanvas
);
465 for (iBlock
=mpTextContainer
->begin(); iBlock
!=iBlockEnd
; ++iBlock
)
466 (*iBlock
)->Update(mpFont
->mxFont
, mnMaximalWidth
);
473 //----- XResourceId -----------------------------------------------------------
475 Reference
<XResourceId
> SAL_CALL
PresenterHelpView::getResourceId (void)
476 throw (RuntimeException
)
485 sal_Bool SAL_CALL
PresenterHelpView::isAnchorOnly (void)
486 throw (RuntimeException
)
494 //-----------------------------------------------------------------------------
496 void PresenterHelpView::ProvideCanvas (void)
498 if ( ! mxCanvas
.is() && mxPane
.is())
500 mxCanvas
= mxPane
->getCanvas();
501 if ( ! mxCanvas
.is())
503 Reference
<lang::XComponent
> xComponent (mxCanvas
, UNO_QUERY
);
505 xComponent
->addEventListener(static_cast<awt::XPaintListener
*>(this));
507 if (mpCloseButton
.is())
508 mpCloseButton
->SetCanvas(mxCanvas
, mxWindow
);
515 void PresenterHelpView::Resize (void)
517 if (mpCloseButton
.get() != NULL
&& mxWindow
.is())
519 const awt::Rectangle
aWindowBox (mxWindow
->getPosSize());
521 // Place vertical separator.
522 mnSeparatorY
= aWindowBox
.Height
523 - mpCloseButton
->GetSize().Height
- gnVerticalButtonPadding
;
525 mpCloseButton
->SetCenter(geometry::RealPoint2D(
527 aWindowBox
.Height
- mpCloseButton
->GetSize().Height
/2));
534 void PresenterHelpView::ThrowIfDisposed (void)
535 throw (lang::DisposedException
)
537 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
539 throw lang::DisposedException (
540 OUString(RTL_CONSTASCII_USTRINGPARAM(
541 "PresenterHelpView has been already disposed")),
542 const_cast<uno::XWeak
*>(static_cast<const uno::XWeak
*>(this)));
549 //===== LineDescritor =========================================================
553 LineDescriptor::LineDescriptor (void)
563 void LineDescriptor::AddPart (
564 const OUString
& rsLine
,
565 const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
)
569 CalculateSize(rxFont
);
575 bool LineDescriptor::IsEmpty (void) const
577 return msLine
.getLength()==0;
583 void LineDescriptor::CalculateSize (
584 const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
)
586 OSL_ASSERT(rxFont
.is());
588 rendering::StringContext
aContext (msLine
, 0, msLine
.getLength());
589 Reference
<rendering::XTextLayout
> xLayout (
590 rxFont
->createTextLayout(aContext
, rendering::TextDirection::WEAK_LEFT_TO_RIGHT
, 0));
591 const geometry::RealRectangle2D
aTextBBox (xLayout
->queryTextBounds());
592 maSize
= css::geometry::RealSize2D(aTextBBox
.X2
- aTextBBox
.X1
, aTextBBox
.Y2
- aTextBBox
.Y1
);
593 mnVerticalOffset
= aTextBBox
.Y2
;
596 } // end of anonymous namespace
601 //===== LineDescriptorList ====================================================
605 LineDescriptorList::LineDescriptorList (
606 const OUString
& rsText
,
607 const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
,
608 const sal_Int32 nMaximalWidth
)
611 Update(rxFont
, nMaximalWidth
);
617 double LineDescriptorList::Paint(
618 const Reference
<rendering::XCanvas
>& rxCanvas
,
619 const geometry::RealRectangle2D
& rBBox
,
620 const bool bFlushLeft
,
621 const rendering::ViewState
& rViewState
,
622 rendering::RenderState
& rRenderState
,
623 const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
) const
625 if ( ! rxCanvas
.is())
628 double nY (rBBox
.Y1
);
629 vector
<LineDescriptor
>::const_iterator
iLine (mpLineDescriptors
->begin());
630 vector
<LineDescriptor
>::const_iterator
iEnd (mpLineDescriptors
->end());
631 for ( ; iLine
!=iEnd
; ++iLine
)
633 double nX (rBBox
.X1
);
635 nX
= rBBox
.X2
- iLine
->maSize
.Width
;
636 rRenderState
.AffineTransform
.m02
= nX
;
637 rRenderState
.AffineTransform
.m12
= nY
+ iLine
->maSize
.Height
- iLine
->mnVerticalOffset
;
639 const rendering::StringContext
aContext (iLine
->msLine
, 0, iLine
->msLine
.getLength());
646 rendering::TextDirection::WEAK_LEFT_TO_RIGHT
);
648 nY
+= iLine
->maSize
.Height
* 1.2;
651 return nY
- rBBox
.Y1
;
657 double LineDescriptorList::GetHeight (void) const
660 vector
<LineDescriptor
>::const_iterator
iLine (mpLineDescriptors
->begin());
661 vector
<LineDescriptor
>::const_iterator
iEnd (mpLineDescriptors
->end());
662 for ( ; iLine
!=iEnd
; ++iLine
)
663 nHeight
+= iLine
->maSize
.Height
* 1.2;
671 void LineDescriptorList::Update (
672 const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
,
673 const sal_Int32 nMaximalWidth
)
675 vector
<OUString
> aTextParts
;
676 SplitText(msText
, aTextParts
);
677 FormatText(aTextParts
, rxFont
, nMaximalWidth
);
683 void LineDescriptorList::SplitText (
684 const OUString
& rsText
,
685 vector
<OUString
>& rTextParts
)
687 const sal_Char
cQuote ('\'');
688 const sal_Char
cSeparator (',');
690 sal_Int32
nIndex (0);
691 sal_Int32
nStart (0);
692 sal_Int32
nLength (rsText
.getLength());
693 bool bIsQuoted (false);
694 while (nIndex
< nLength
)
696 const sal_Int32
nQuoteIndex (rsText
.indexOf(cQuote
, nIndex
));
697 const sal_Int32
nSeparatorIndex (rsText
.indexOf(cSeparator
, nIndex
));
698 if (nQuoteIndex
>=0 && (nSeparatorIndex
==-1 || nQuoteIndex
<nSeparatorIndex
))
700 bIsQuoted
= !bIsQuoted
;
701 nIndex
= nQuoteIndex
+1;
705 const sal_Int32 nNextIndex
= nSeparatorIndex
;
710 else if ( ! bIsQuoted
)
712 rTextParts
.push_back(rsText
.copy(nStart
, nNextIndex
-nStart
));
713 nStart
= nNextIndex
+ 1;
715 nIndex
= nNextIndex
+1;
717 if (nStart
< nLength
)
718 rTextParts
.push_back(rsText
.copy(nStart
, nLength
-nStart
));
724 void LineDescriptorList::FormatText (
725 const vector
<OUString
>& rTextParts
,
726 const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
,
727 const sal_Int32 nMaximalWidth
)
729 LineDescriptor aLineDescriptor
;
731 mpLineDescriptors
.reset(new vector
<LineDescriptor
>());
733 vector
<OUString
>::const_iterator
iPart (rTextParts
.begin());
734 vector
<OUString
>::const_iterator
iEnd (rTextParts
.end());
735 for ( ; iPart
!=iEnd
; ++iPart
)
737 if (aLineDescriptor
.IsEmpty())
739 // Avoid empty lines.
740 aLineDescriptor
.AddPart(*iPart
, rxFont
);
742 else if (PresenterCanvasHelper::GetTextSize(
743 rxFont
, aLineDescriptor
.msLine
+A2S(", ")+*iPart
).Width
> nMaximalWidth
)
745 aLineDescriptor
.AddPart(A2S(","), rxFont
);
746 mpLineDescriptors
->push_back(aLineDescriptor
);
747 aLineDescriptor
= LineDescriptor();
748 aLineDescriptor
.AddPart(*iPart
, rxFont
);
752 aLineDescriptor
.AddPart(A2S(", ")+*iPart
, rxFont
);
755 if ( ! aLineDescriptor
.IsEmpty())
756 mpLineDescriptors
->push_back(aLineDescriptor
);
760 } // end of anonymous namespace
765 //===== Block =================================================================
770 const OUString
& rsLeftText
,
771 const OUString
& rsRightText
,
772 const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
,
773 const sal_Int32 nMaximalWidth
)
774 : maLeft(rsLeftText
, rxFont
, nMaximalWidth
),
775 maRight(rsRightText
, rxFont
, nMaximalWidth
)
782 const css::uno::Reference
<css::rendering::XCanvasFont
>& rxFont
,
783 const sal_Int32 nMaximalWidth
)
785 maLeft
.Update(rxFont
, nMaximalWidth
);
786 maRight
.Update(rxFont
, nMaximalWidth
);
789 } // end of anonymous namespace
791 } } // end of namespace ::sdext::presenter