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: PresenterNotesView.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 "PresenterNotesView.hxx"
36 #include "PresenterButton.hxx"
37 #include "PresenterCanvasHelper.hxx"
38 #include "PresenterGeometryHelper.hxx"
39 #include "PresenterPaintManager.hxx"
40 #include "PresenterScrollBar.hxx"
41 #include "PresenterTextView.hxx"
42 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
43 #include <com/sun/star/awt/Key.hpp>
44 #include <com/sun/star/awt/KeyModifier.hpp>
45 #include <com/sun/star/awt/PosSize.hpp>
46 #include <com/sun/star/beans/XPropertySet.hpp>
47 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
48 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
49 #include <com/sun/star/drawing/framework/XPane.hpp>
50 #include <com/sun/star/lang/XServiceName.hpp>
51 #include <com/sun/star/presentation/XPresentationPage.hpp>
52 #include <com/sun/star/rendering/CompositeOperation.hpp>
53 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
54 #include <com/sun/star/text/XTextRange.hpp>
55 #include <com/sun/star/util/XChangesBatch.hpp>
56 #include <com/sun/star/container/XChild.hpp>
57 #include <boost/bind.hpp>
60 using namespace ::com::sun::star
;
61 using namespace ::com::sun::star::uno
;
62 using namespace ::com::sun::star::drawing::framework
;
63 using ::rtl::OUString
;
65 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
67 static const sal_Int32
gnSpaceBelowSeparator (10);
68 static const sal_Int32
gnSpaceAboveSeparator (10);
69 static const sal_Int32
gnPartHeight (128);
70 /** Maximal size of memory used for bitmaps which show the notes text.
72 static const sal_Int32
gnMaximalCacheSize (8*1024*1024);
73 static const double gnLineScrollFactor (1.2);
75 namespace sdext
{ namespace presenter
{
77 //===== PresenterNotesView ====================================================
79 PresenterNotesView::PresenterNotesView (
80 const Reference
<XComponentContext
>& rxComponentContext
,
81 const Reference
<XResourceId
>& rxViewId
,
82 const Reference
<frame::XController
>& rxController
,
83 const ::rtl::Reference
<PresenterController
>& rpPresenterController
)
84 : PresenterNotesViewInterfaceBase(m_aMutex
),
86 mpPresenterController(rpPresenterController
),
94 maSeparatorColor(0xffffff),
95 mnSeparatorYLocation(0),
104 Reference
<XControllerManager
> xCM (rxController
, UNO_QUERY_THROW
);
105 Reference
<XConfigurationController
> xCC (xCM
->getConfigurationController(), UNO_QUERY_THROW
);
106 Reference
<XPane
> xPane (xCC
->getResource(rxViewId
->getAnchor()), UNO_QUERY_THROW
);
108 mxParentWindow
= xPane
->getWindow();
109 mxCanvas
= xPane
->getCanvas();
110 mpTextView
.reset(new PresenterTextView(
113 mpPresenterController
->GetPaintManager()->GetInvalidator(mxParentWindow
)));
115 const OUString
sResourceURL (mxViewId
->getResourceURL());
116 mpFont
.reset(new PresenterTheme::FontDescriptor(
117 rpPresenterController
->GetViewFont(sResourceURL
)));
118 maSeparatorColor
= mpFont
->mnColor
;
119 mpTextView
->SetFont(mpFont
);
121 CreateToolBar(rxComponentContext
, rpPresenterController
);
123 mpCloseButton
= PresenterButton::Create(
125 mpPresenterController
,
126 mpPresenterController
->GetTheme(),
129 A2S("NotesViewCloser"));
131 if (mxParentWindow
.is())
133 mxParentWindow
->addWindowListener(this);
134 mxParentWindow
->addPaintListener(this);
135 mxParentWindow
->addKeyListener(this);
136 mxParentWindow
->setVisible(sal_True
);
139 mpScrollBar
= new PresenterVerticalScrollBar(
142 mpPresenterController
->GetPaintManager(),
143 ::boost::bind(&PresenterNotesView::SetTop
, this, _1
));
144 mpScrollBar
->SetBackground(
145 mpPresenterController
->GetViewBackground(mxViewId
->getResourceURL()));
147 mpScrollBar
->SetCanvas(mxCanvas
);
151 catch (RuntimeException
&)
153 PresenterNotesView::disposing();
161 PresenterNotesView::~PresenterNotesView (void)
168 void SAL_CALL
PresenterNotesView::disposing (void)
170 if (mxParentWindow
.is())
172 mxParentWindow
->removeWindowListener(this);
173 mxParentWindow
->removePaintListener(this);
174 mxParentWindow
->removeKeyListener(this);
175 mxParentWindow
= NULL
;
180 Reference
<XComponent
> xComponent (static_cast<XWeak
*>(mpToolBar
.get()), UNO_QUERY
);
183 xComponent
->dispose();
186 Reference
<XComponent
> xComponent (mxToolBarCanvas
, UNO_QUERY
);
187 mxToolBarCanvas
= NULL
;
189 xComponent
->dispose();
192 Reference
<XComponent
> xComponent (mxToolBarWindow
, UNO_QUERY
);
193 mxToolBarWindow
= NULL
;
195 xComponent
->dispose();
198 // Dispose close button
200 Reference
<XComponent
> xComponent (static_cast<XWeak
*>(mpCloseButton
.get()), UNO_QUERY
);
201 mpCloseButton
= NULL
;
203 xComponent
->dispose();
206 // Create the tool bar.
216 void PresenterNotesView::CreateToolBar (
217 const css::uno::Reference
<css::uno::XComponentContext
>& rxContext
,
218 const ::rtl::Reference
<PresenterController
>& rpPresenterController
)
220 if (rpPresenterController
.get() == NULL
)
223 Reference
<drawing::XPresenterHelper
> xPresenterHelper (
224 rpPresenterController
->GetPresenterHelper());
225 if ( ! xPresenterHelper
.is())
228 // Create a new window as container of the tool bar.
229 mxToolBarWindow
= xPresenterHelper
->createWindow(
235 mxToolBarCanvas
= xPresenterHelper
->createSharedCanvas (
236 Reference
<rendering::XSpriteCanvas
>(mxCanvas
, UNO_QUERY
),
242 // Create the tool bar.
243 mpToolBar
= new PresenterToolBar(
247 rpPresenterController
,
248 PresenterToolBar::Left
);
249 mpToolBar
->Initialize(
250 A2S("PresenterScreenSettings/ToolBars/NotesToolBar"));
256 void PresenterNotesView::SetSlide (const Reference
<drawing::XDrawPage
>& rxNotesPage
)
258 static const ::rtl::OUString
sNotesShapeName (
259 A2S("com.sun.star.presentation.NotesShape"));
260 static const ::rtl::OUString
sTextShapeName (
261 A2S("com.sun.star.drawing.TextShape"));
263 Reference
<container::XIndexAccess
> xIndexAccess (rxNotesPage
, UNO_QUERY
);
264 if (xIndexAccess
.is())
266 ::rtl::OUString sText
;
268 // Iterate over all shapes and find the one that holds the text.
269 sal_Int32
nCount (xIndexAccess
->getCount());
270 for (sal_Int32 nIndex
=0; nIndex
<nCount
; ++nIndex
)
273 Reference
<lang::XServiceName
> xServiceName (
274 xIndexAccess
->getByIndex(nIndex
), UNO_QUERY
);
275 if (xServiceName
.is()
276 && xServiceName
->getServiceName().equals(sNotesShapeName
))
278 Reference
<text::XTextRange
> xText (xServiceName
, UNO_QUERY
);
281 sText
+= xText
->getString();
286 Reference
<drawing::XShapeDescriptor
> xShapeDescriptor (
287 xIndexAccess
->getByIndex(nIndex
), UNO_QUERY
);
288 if (xShapeDescriptor
.is())
290 ::rtl::OUString
sType (xShapeDescriptor
->getShapeType());
291 if (sType
.equals(sNotesShapeName
) || sType
.equals(sTextShapeName
))
293 Reference
<text::XTextRange
> xText (
294 xIndexAccess
->getByIndex(nIndex
), UNO_QUERY
);
297 sText
+= xText
->getString();
298 mpTextView
->SetText(Reference
<text::XText
>(xText
, UNO_QUERY
));
307 if (mpScrollBar
.get() != NULL
)
309 mpScrollBar
->SetThumbPosition(0, false);
320 //----- lang::XEventListener -------------------------------------------------
322 void SAL_CALL
PresenterNotesView::disposing (const lang::EventObject
& rEventObject
)
323 throw (RuntimeException
)
325 if (rEventObject
.Source
== mxParentWindow
)
326 mxParentWindow
= NULL
;
332 //----- XWindowListener -------------------------------------------------------
334 void SAL_CALL
PresenterNotesView::windowResized (const awt::WindowEvent
& rEvent
)
335 throw (RuntimeException
)
344 void SAL_CALL
PresenterNotesView::windowMoved (const awt::WindowEvent
& rEvent
)
345 throw (RuntimeException
)
353 void SAL_CALL
PresenterNotesView::windowShown (const lang::EventObject
& rEvent
)
354 throw (RuntimeException
)
362 void SAL_CALL
PresenterNotesView::windowHidden (const lang::EventObject
& rEvent
)
363 throw (RuntimeException
)
371 //----- XPaintListener --------------------------------------------------------
373 void SAL_CALL
PresenterNotesView::windowPaint (const awt::PaintEvent
& rEvent
)
374 throw (RuntimeException
)
378 if ( ! mbIsPresenterViewActive
)
381 ::osl::MutexGuard
aSolarGuard (::osl::Mutex::getGlobalMutex());
382 Paint(rEvent
.UpdateRect
);
388 //----- XResourceId -----------------------------------------------------------
390 Reference
<XResourceId
> SAL_CALL
PresenterNotesView::getResourceId (void)
391 throw (RuntimeException
)
399 sal_Bool SAL_CALL
PresenterNotesView::isAnchorOnly (void)
400 throw (RuntimeException
)
408 //----- XDrawView -------------------------------------------------------------
410 void SAL_CALL
PresenterNotesView::setCurrentPage (const Reference
<drawing::XDrawPage
>& rxSlide
)
411 throw (RuntimeException
)
413 // Get the associated notes page.
414 mxCurrentNotesPage
= NULL
;
417 Reference
<presentation::XPresentationPage
> xPresentationPage(rxSlide
, UNO_QUERY
);
418 if (xPresentationPage
.is())
419 mxCurrentNotesPage
= xPresentationPage
->getNotesPage();
421 catch (RuntimeException
&)
425 SetSlide(mxCurrentNotesPage
);
431 Reference
<drawing::XDrawPage
> SAL_CALL
PresenterNotesView::getCurrentPage (void)
432 throw (RuntimeException
)
440 //----- XKeyListener ----------------------------------------------------------
442 void SAL_CALL
PresenterNotesView::keyPressed (const awt::KeyEvent
& rEvent
)
443 throw (RuntimeException
)
445 switch (rEvent
.KeyCode
)
448 Scroll(-gnLineScrollFactor
* mpFont
->mnSize
);
453 Scroll(+gnLineScrollFactor
* mpFont
->mnSize
);
466 mpTextView
->MoveCaret(
468 (rEvent
.Modifiers
== awt::KeyModifier::SHIFT
)
469 ? cssa::AccessibleTextType::CHARACTER
470 : cssa::AccessibleTextType::WORD
);
475 mpTextView
->MoveCaret(
477 (rEvent
.Modifiers
== awt::KeyModifier::SHIFT
)
478 ? cssa::AccessibleTextType::CHARACTER
479 : cssa::AccessibleTextType::WORD
);
487 void SAL_CALL
PresenterNotesView::keyReleased (const awt::KeyEvent
& rEvent
)
488 throw (RuntimeException
)
496 //-----------------------------------------------------------------------------
498 void PresenterNotesView::Layout (void)
500 if ( ! mxParentWindow
.is())
503 awt::Rectangle
aWindowBox (mxParentWindow
->getPosSize());
504 geometry::RealRectangle2D
aNewTextBoundingBox (0,0,aWindowBox
.Width
, aWindowBox
.Height
);
506 // Size the tool bar and the horizontal separator above it.
507 if (mxToolBarWindow
.is())
509 const geometry::RealSize2D
aToolBarSize (mpToolBar
->GetMinimalSize());
510 const sal_Int32 nToolBarHeight
= sal_Int32(aToolBarSize
.Height
+ 0.5);
511 mxToolBarWindow
->setPosSize(0, aWindowBox
.Height
- nToolBarHeight
,
512 sal_Int32(aToolBarSize
.Width
+ 0.5), nToolBarHeight
,
513 awt::PosSize::POSSIZE
);
514 aNewTextBoundingBox
.Y2
-= nToolBarHeight
;
516 mnSeparatorYLocation
= aWindowBox
.Height
- nToolBarHeight
- gnSpaceBelowSeparator
;
517 aNewTextBoundingBox
.Y2
= mnSeparatorYLocation
- gnSpaceAboveSeparator
;
519 // Place the close button.
520 if (mpCloseButton
.get() != NULL
)
521 mpCloseButton
->SetCenter(geometry::RealPoint2D(
522 (aWindowBox
.Width
+ aToolBarSize
.Width
) / 2,
523 aWindowBox
.Height
- aToolBarSize
.Height
/2));
526 // Check whether the vertical scroll bar is necessary.
527 if (mpScrollBar
.get() != NULL
)
529 bool bShowVerticalScrollbar (false);
532 const double nTextBoxHeight (aNewTextBoundingBox
.Y2
- aNewTextBoundingBox
.Y1
);
533 const double nHeight (mpTextView
->GetTotalTextHeight());
534 if (nHeight
> nTextBoxHeight
)
536 bShowVerticalScrollbar
= true;
537 aNewTextBoundingBox
.X2
-= mpScrollBar
->GetSize();
539 mpScrollBar
->SetTotalSize(nHeight
);
541 catch(beans::UnknownPropertyException
&)
546 mpScrollBar
->SetVisible(bShowVerticalScrollbar
);
547 mpScrollBar
->SetPosSize(
548 geometry::RealRectangle2D(
549 aNewTextBoundingBox
.X2
,
550 aNewTextBoundingBox
.X1
,
551 aNewTextBoundingBox
.X2
+ mpScrollBar
->GetSize(),
552 aNewTextBoundingBox
.Y2
));
553 if ( ! bShowVerticalScrollbar
)
554 mpScrollBar
->SetThumbPosition(0, false);
559 // Has the text area has changed it position or size?
560 if (aNewTextBoundingBox
.X1
!= maTextBoundingBox
.X1
561 || aNewTextBoundingBox
.Y1
!= maTextBoundingBox
.Y1
562 || aNewTextBoundingBox
.X2
!= maTextBoundingBox
.X2
563 || aNewTextBoundingBox
.Y2
!= maTextBoundingBox
.Y2
)
565 maTextBoundingBox
= aNewTextBoundingBox
;
567 mpTextView
->SetLocation(
568 geometry::RealPoint2D(
569 aNewTextBoundingBox
.X1
,
570 aNewTextBoundingBox
.Y1
));
572 geometry::RealSize2D(
573 aNewTextBoundingBox
.X2
- aNewTextBoundingBox
.X1
,
574 aNewTextBoundingBox
.Y2
- aNewTextBoundingBox
.Y1
));
581 void PresenterNotesView::Paint (const awt::Rectangle
& rUpdateBox
)
583 if ( ! mxParentWindow
.is())
585 if ( ! mxCanvas
.is())
588 if (mpBackground
.get() == NULL
)
589 mpBackground
= mpPresenterController
->GetViewBackground(mxViewId
->getResourceURL());
591 if (rUpdateBox
.Y
< maTextBoundingBox
.Y2
592 && rUpdateBox
.X
< maTextBoundingBox
.X2
)
594 PaintText(rUpdateBox
);
597 mpTextView
->Paint(rUpdateBox
);
599 if (rUpdateBox
.Y
+ rUpdateBox
.Height
> maTextBoundingBox
.Y2
)
601 PaintToolBar(rUpdateBox
);
608 void PresenterNotesView::PaintToolBar (const awt::Rectangle
& rUpdateBox
)
610 awt::Rectangle
aWindowBox (mxParentWindow
->getPosSize());
612 rendering::ViewState
aViewState (
613 geometry::AffineMatrix2D(1,0,0, 0,1,0),
615 rendering::RenderState
aRenderState(
616 geometry::AffineMatrix2D(1,0,0, 0,1,0),
619 rendering::CompositeOperation::SOURCE
);
621 if (mpBackground
.get() != NULL
)
623 // Paint the background.
624 mpPresenterController
->GetCanvasHelper()->Paint(
628 awt::Rectangle(0,sal_Int32(maTextBoundingBox
.Y2
),aWindowBox
.Width
,aWindowBox
.Height
),
632 // Paint the horizontal separator.
633 OSL_ASSERT(mxViewId
.is());
634 PresenterCanvasHelper::SetDeviceColor(aRenderState
, maSeparatorColor
);
637 geometry::RealPoint2D(0,mnSeparatorYLocation
),
638 geometry::RealPoint2D(aWindowBox
.Width
,mnSeparatorYLocation
),
646 void PresenterNotesView::PaintText (const awt::Rectangle
& rUpdateBox
)
648 const awt::Rectangle
aBox (PresenterGeometryHelper::Intersection(rUpdateBox
,
649 PresenterGeometryHelper::ConvertRectangle(maTextBoundingBox
)));
651 if (aBox
.Width
<= 0 || aBox
.Height
<= 0)
654 rendering::ViewState
aViewState (
655 geometry::AffineMatrix2D(1,0,0, 0,1,0),
656 PresenterGeometryHelper::CreatePolygon(aBox
, mxCanvas
->getDevice()));
657 rendering::RenderState
aRenderState(
658 geometry::AffineMatrix2D(1,0,0, 0,1,0),
661 rendering::CompositeOperation::SOURCE
);
663 if (mpBackground
.get() != NULL
)
665 // Paint the background.
666 mpPresenterController
->GetCanvasHelper()->Paint(
674 Reference
<rendering::XSpriteCanvas
> xSpriteCanvas (mxCanvas
, UNO_QUERY
);
675 if (xSpriteCanvas
.is())
676 xSpriteCanvas
->updateScreen(sal_False
);
682 void PresenterNotesView::Invalidate (void)
684 mpPresenterController
->GetPaintManager()->Invalidate(
686 PresenterGeometryHelper::ConvertRectangle(maTextBoundingBox
));
692 void PresenterNotesView::Scroll (const double rnDistance
)
697 mpTextView
->SetOffset(0, mnTop
);
702 catch (beans::UnknownPropertyException
&)
709 void PresenterNotesView::SetTop (const double nTop
)
714 mpTextView
->SetOffset(0, mnTop
);
719 catch (beans::UnknownPropertyException
&)
726 void PresenterNotesView::ChangeFontSize (const sal_Int32 nSizeChange
)
728 const sal_Int32
nNewSize (mpFont
->mnSize
+ nSizeChange
);
731 mpFont
->mnSize
= nNewSize
;
732 mpFont
->mxFont
= NULL
;
733 mpTextView
->SetFont(mpFont
);
739 // Write the new font size to the configuration to make it persistent.
742 const OUString
sStyleName (mpPresenterController
->GetTheme()->GetStyleName(
743 mxViewId
->getResourceURL()));
744 ::boost::shared_ptr
<PresenterConfigurationAccess
> pConfiguration (
745 mpPresenterController
->GetTheme()->GetNodeForViewStyle(
747 PresenterConfigurationAccess::READ_WRITE
));
748 if (pConfiguration
.get()==NULL
|| ! pConfiguration
->IsValid())
751 pConfiguration
->GoToChild(A2S("Font"));
752 pConfiguration
->SetProperty(A2S("Size"), Any((sal_Int32
)(nNewSize
+0.5)));
753 pConfiguration
->CommitChanges();
765 ::boost::shared_ptr
<PresenterTextView
> PresenterNotesView::GetTextView (void) const
773 void PresenterNotesView::UpdateScrollBar (void)
775 if (mpScrollBar
.get() != NULL
)
779 mpScrollBar
->SetTotalSize(mpTextView
->GetTotalTextHeight());
781 catch(beans::UnknownPropertyException
&)
786 mpScrollBar
->SetLineHeight(mpFont
->mnSize
*1.2);
787 mpScrollBar
->SetThumbPosition(mnTop
, false);
789 mpScrollBar
->SetThumbSize(maTextBoundingBox
.Y2
- maTextBoundingBox
.Y1
);
790 mpScrollBar
->CheckValues();
797 void PresenterNotesView::ThrowIfDisposed (void)
798 throw (::com::sun::star::lang::DisposedException
)
800 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
802 throw lang::DisposedException (
803 A2S("PresenterNotesView object has already been disposed"),
804 static_cast<uno::XWeak
*>(this));
811 } } // end of namespace ::sdext::presenter