1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #include "vcl/svapp.hxx"
20 #include "PresenterNotesView.hxx"
21 #include "PresenterButton.hxx"
22 #include "PresenterCanvasHelper.hxx"
23 #include "PresenterGeometryHelper.hxx"
24 #include "PresenterPaintManager.hxx"
25 #include "PresenterScrollBar.hxx"
26 #include "PresenterTextView.hxx"
27 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
28 #include <com/sun/star/awt/Key.hpp>
29 #include <com/sun/star/awt/KeyModifier.hpp>
30 #include <com/sun/star/awt/PosSize.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
33 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
34 #include <com/sun/star/drawing/framework/XPane.hpp>
35 #include <com/sun/star/lang/XServiceName.hpp>
36 #include <com/sun/star/presentation/XPresentationPage.hpp>
37 #include <com/sun/star/rendering/CompositeOperation.hpp>
38 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
39 #include <com/sun/star/text/XTextRange.hpp>
40 #include <com/sun/star/util/XChangesBatch.hpp>
41 #include <com/sun/star/container/XChild.hpp>
42 #include <boost/bind.hpp>
45 using namespace ::com::sun::star
;
46 using namespace ::com::sun::star::uno
;
47 using namespace ::com::sun::star::drawing::framework
;
49 static const sal_Int32
gnSpaceBelowSeparator (10);
50 static const sal_Int32
gnSpaceAboveSeparator (10);
51 static const sal_Int32
gnPartHeight (128);
52 /** Maximal size of memory used for bitmaps which show the notes text.
54 static const sal_Int32
gnMaximalCacheSize (8*1024*1024);
55 static const double gnLineScrollFactor (1.2);
57 namespace sdext
{ namespace presenter
{
59 //===== PresenterNotesView ====================================================
61 PresenterNotesView::PresenterNotesView (
62 const Reference
<XComponentContext
>& rxComponentContext
,
63 const Reference
<XResourceId
>& rxViewId
,
64 const Reference
<frame::XController
>& rxController
,
65 const ::rtl::Reference
<PresenterController
>& rpPresenterController
)
66 : PresenterNotesViewInterfaceBase(m_aMutex
),
68 mpPresenterController(rpPresenterController
),
76 maSeparatorColor(0xffffff),
77 mnSeparatorYLocation(0),
86 Reference
<XControllerManager
> xCM (rxController
, UNO_QUERY_THROW
);
87 Reference
<XConfigurationController
> xCC (xCM
->getConfigurationController(), UNO_QUERY_THROW
);
88 Reference
<XPane
> xPane (xCC
->getResource(rxViewId
->getAnchor()), UNO_QUERY_THROW
);
90 mxParentWindow
= xPane
->getWindow();
91 mxCanvas
= xPane
->getCanvas();
92 mpTextView
.reset(new PresenterTextView(
95 mpPresenterController
->GetPaintManager()->GetInvalidator(mxParentWindow
)));
97 const OUString
sResourceURL (mxViewId
->getResourceURL());
98 mpFont
.reset(new PresenterTheme::FontDescriptor(
99 rpPresenterController
->GetViewFont(sResourceURL
)));
100 maSeparatorColor
= mpFont
->mnColor
;
101 mpTextView
->SetFont(mpFont
);
103 CreateToolBar(rxComponentContext
, rpPresenterController
);
105 mpCloseButton
= PresenterButton::Create(
107 mpPresenterController
,
108 mpPresenterController
->GetTheme(),
113 if (mxParentWindow
.is())
115 mxParentWindow
->addWindowListener(this);
116 mxParentWindow
->addPaintListener(this);
117 mxParentWindow
->addKeyListener(this);
118 mxParentWindow
->setVisible(sal_True
);
121 mpScrollBar
= new PresenterVerticalScrollBar(
124 mpPresenterController
->GetPaintManager(),
125 ::boost::bind(&PresenterNotesView::SetTop
, this, _1
));
126 mpScrollBar
->SetBackground(
127 mpPresenterController
->GetViewBackground(mxViewId
->getResourceURL()));
129 mpScrollBar
->SetCanvas(mxCanvas
);
133 catch (RuntimeException
&)
135 PresenterNotesView::disposing();
140 PresenterNotesView::~PresenterNotesView (void)
144 void SAL_CALL
PresenterNotesView::disposing (void)
146 if (mxParentWindow
.is())
148 mxParentWindow
->removeWindowListener(this);
149 mxParentWindow
->removePaintListener(this);
150 mxParentWindow
->removeKeyListener(this);
151 mxParentWindow
= NULL
;
156 Reference
<XComponent
> xComponent (static_cast<XWeak
*>(mpToolBar
.get()), UNO_QUERY
);
159 xComponent
->dispose();
162 Reference
<XComponent
> xComponent (mxToolBarCanvas
, UNO_QUERY
);
163 mxToolBarCanvas
= NULL
;
165 xComponent
->dispose();
168 Reference
<XComponent
> xComponent (mxToolBarWindow
, UNO_QUERY
);
169 mxToolBarWindow
= NULL
;
171 xComponent
->dispose();
174 // Dispose close button
176 Reference
<XComponent
> xComponent (static_cast<XWeak
*>(mpCloseButton
.get()), UNO_QUERY
);
177 mpCloseButton
= NULL
;
179 xComponent
->dispose();
182 // Create the tool bar.
189 void PresenterNotesView::CreateToolBar (
190 const css::uno::Reference
<css::uno::XComponentContext
>& rxContext
,
191 const ::rtl::Reference
<PresenterController
>& rpPresenterController
)
193 if (rpPresenterController
.get() == NULL
)
196 Reference
<drawing::XPresenterHelper
> xPresenterHelper (
197 rpPresenterController
->GetPresenterHelper());
198 if ( ! xPresenterHelper
.is())
201 // Create a new window as container of the tool bar.
202 mxToolBarWindow
= xPresenterHelper
->createWindow(
208 mxToolBarCanvas
= xPresenterHelper
->createSharedCanvas (
209 Reference
<rendering::XSpriteCanvas
>(mxCanvas
, UNO_QUERY
),
215 // Create the tool bar.
216 mpToolBar
= new PresenterToolBar(
220 rpPresenterController
,
221 PresenterToolBar::Left
);
222 mpToolBar
->Initialize(
223 "PresenterScreenSettings/ToolBars/NotesToolBar");
226 void PresenterNotesView::SetSlide (const Reference
<drawing::XDrawPage
>& rxNotesPage
)
228 static const OUString
sNotesShapeName (
229 "com.sun.star.presentation.NotesShape");
230 static const OUString
sTextShapeName (
231 "com.sun.star.drawing.TextShape");
233 Reference
<container::XIndexAccess
> xIndexAccess (rxNotesPage
, UNO_QUERY
);
234 if (xIndexAccess
.is())
238 // Iterate over all shapes and find the one that holds the text.
239 sal_Int32
nCount (xIndexAccess
->getCount());
240 for (sal_Int32 nIndex
=0; nIndex
<nCount
; ++nIndex
)
243 Reference
<lang::XServiceName
> xServiceName (
244 xIndexAccess
->getByIndex(nIndex
), UNO_QUERY
);
245 if (xServiceName
.is()
246 && xServiceName
->getServiceName().equals(sNotesShapeName
))
248 Reference
<text::XTextRange
> xText (xServiceName
, UNO_QUERY
);
251 sText
+= xText
->getString();
256 Reference
<drawing::XShapeDescriptor
> xShapeDescriptor (
257 xIndexAccess
->getByIndex(nIndex
), UNO_QUERY
);
258 if (xShapeDescriptor
.is())
260 OUString
sType (xShapeDescriptor
->getShapeType());
261 if (sType
.equals(sNotesShapeName
) || sType
.equals(sTextShapeName
))
263 Reference
<text::XTextRange
> xText (
264 xIndexAccess
->getByIndex(nIndex
), UNO_QUERY
);
267 sText
+= xText
->getString();
268 mpTextView
->SetText(Reference
<text::XText
>(xText
, UNO_QUERY
));
277 if (mpScrollBar
.get() != NULL
)
279 mpScrollBar
->SetThumbPosition(0, false);
287 //----- lang::XEventListener -------------------------------------------------
289 void SAL_CALL
PresenterNotesView::disposing (const lang::EventObject
& rEventObject
)
290 throw (RuntimeException
)
292 if (rEventObject
.Source
== mxParentWindow
)
293 mxParentWindow
= NULL
;
296 //----- XWindowListener -------------------------------------------------------
298 void SAL_CALL
PresenterNotesView::windowResized (const awt::WindowEvent
& rEvent
)
299 throw (RuntimeException
)
305 void SAL_CALL
PresenterNotesView::windowMoved (const awt::WindowEvent
& rEvent
)
306 throw (RuntimeException
)
311 void SAL_CALL
PresenterNotesView::windowShown (const lang::EventObject
& rEvent
)
312 throw (RuntimeException
)
317 void SAL_CALL
PresenterNotesView::windowHidden (const lang::EventObject
& rEvent
)
318 throw (RuntimeException
)
323 //----- XPaintListener --------------------------------------------------------
325 void SAL_CALL
PresenterNotesView::windowPaint (const awt::PaintEvent
& rEvent
)
326 throw (RuntimeException
)
330 if ( ! mbIsPresenterViewActive
)
333 ::osl::MutexGuard
aSolarGuard (::osl::Mutex::getGlobalMutex());
334 Paint(rEvent
.UpdateRect
);
337 //----- XResourceId -----------------------------------------------------------
339 Reference
<XResourceId
> SAL_CALL
PresenterNotesView::getResourceId (void)
340 throw (RuntimeException
)
345 sal_Bool SAL_CALL
PresenterNotesView::isAnchorOnly (void)
346 throw (RuntimeException
)
351 //----- XDrawView -------------------------------------------------------------
353 void SAL_CALL
PresenterNotesView::setCurrentPage (const Reference
<drawing::XDrawPage
>& rxSlide
)
354 throw (RuntimeException
)
356 // Get the associated notes page.
357 mxCurrentNotesPage
= NULL
;
360 Reference
<presentation::XPresentationPage
> xPresentationPage(rxSlide
, UNO_QUERY
);
361 if (xPresentationPage
.is())
362 mxCurrentNotesPage
= xPresentationPage
->getNotesPage();
364 catch (RuntimeException
&)
368 SetSlide(mxCurrentNotesPage
);
371 Reference
<drawing::XDrawPage
> SAL_CALL
PresenterNotesView::getCurrentPage (void)
372 throw (RuntimeException
)
377 //----- XKeyListener ----------------------------------------------------------
379 void SAL_CALL
PresenterNotesView::keyPressed (const awt::KeyEvent
& rEvent
)
380 throw (RuntimeException
)
382 switch (rEvent
.KeyCode
)
385 Scroll(-gnLineScrollFactor
* mpFont
->mnSize
);
390 Scroll(+gnLineScrollFactor
* mpFont
->mnSize
);
403 mpTextView
->MoveCaret(
405 (rEvent
.Modifiers
== awt::KeyModifier::SHIFT
)
406 ? cssa::AccessibleTextType::CHARACTER
407 : cssa::AccessibleTextType::WORD
);
412 mpTextView
->MoveCaret(
414 (rEvent
.Modifiers
== awt::KeyModifier::SHIFT
)
415 ? cssa::AccessibleTextType::CHARACTER
416 : cssa::AccessibleTextType::WORD
);
421 void SAL_CALL
PresenterNotesView::keyReleased (const awt::KeyEvent
& rEvent
)
422 throw (RuntimeException
)
427 //-----------------------------------------------------------------------------
429 void PresenterNotesView::Layout (void)
431 if ( ! mxParentWindow
.is())
433 awt::Rectangle
aWindowBox (mxParentWindow
->getPosSize());
434 geometry::RealRectangle2D
aNewTextBoundingBox (0,0,aWindowBox
.Width
, aWindowBox
.Height
);
435 // Size the tool bar and the horizontal separator above it.
436 if (mxToolBarWindow
.is())
438 const geometry::RealSize2D
aToolBarSize (mpToolBar
->GetMinimalSize());
439 const sal_Int32 nToolBarHeight
= sal_Int32(aToolBarSize
.Height
+ 0.5);
440 mxToolBarWindow
->setPosSize(0, aWindowBox
.Height
- nToolBarHeight
,
441 sal_Int32(aToolBarSize
.Width
+ 0.5), nToolBarHeight
,
442 awt::PosSize::POSSIZE
);
443 aNewTextBoundingBox
.Y2
-= nToolBarHeight
;
444 mnSeparatorYLocation
= aWindowBox
.Height
- nToolBarHeight
- gnSpaceBelowSeparator
;
445 aNewTextBoundingBox
.Y2
= mnSeparatorYLocation
- gnSpaceAboveSeparator
;
446 // Place the close button.
447 if (mpCloseButton
.get() != NULL
)
448 mpCloseButton
->SetCenter(geometry::RealPoint2D(
449 (aWindowBox
.Width
+ aToolBarSize
.Width
) / 2,
450 aWindowBox
.Height
- aToolBarSize
.Height
/2));
452 // Check whether the vertical scroll bar is necessary.
453 if (mpScrollBar
.get() != NULL
)
455 bool bShowVerticalScrollbar (false);
458 const double nTextBoxHeight (aNewTextBoundingBox
.Y2
- aNewTextBoundingBox
.Y1
);
459 const double nHeight (mpTextView
->GetTotalTextHeight());
460 if (nHeight
> nTextBoxHeight
)
462 bShowVerticalScrollbar
= true;
463 if(!Application::GetSettings().GetLayoutRTL())
464 aNewTextBoundingBox
.X2
-= mpScrollBar
->GetSize();
466 aNewTextBoundingBox
.X1
+= mpScrollBar
->GetSize();
468 mpScrollBar
->SetTotalSize(nHeight
);
470 catch(beans::UnknownPropertyException
&)
474 if(Application::GetSettings().GetLayoutRTL())
476 mpScrollBar
->SetVisible(bShowVerticalScrollbar
);
477 mpScrollBar
->SetPosSize(
478 geometry::RealRectangle2D(
479 aNewTextBoundingBox
.X1
- mpScrollBar
->GetSize(),
480 aNewTextBoundingBox
.Y1
,
481 aNewTextBoundingBox
.X1
,
482 aNewTextBoundingBox
.Y2
));
483 if( ! bShowVerticalScrollbar
)
484 mpScrollBar
->SetThumbPosition(0, false);
489 mpScrollBar
->SetVisible(bShowVerticalScrollbar
);
490 mpScrollBar
->SetPosSize(
491 geometry::RealRectangle2D(
492 aWindowBox
.Width
- mpScrollBar
->GetSize(),
493 aNewTextBoundingBox
.Y1
,
494 aNewTextBoundingBox
.X2
+ mpScrollBar
->GetSize(),
495 aNewTextBoundingBox
.Y2
));
496 if( ! bShowVerticalScrollbar
)
497 mpScrollBar
->SetThumbPosition(0, false);
501 // Has the text area has changed it position or size?
502 if (aNewTextBoundingBox
.X1
!= maTextBoundingBox
.X1
503 || aNewTextBoundingBox
.Y1
!= maTextBoundingBox
.Y1
504 || aNewTextBoundingBox
.X2
!= maTextBoundingBox
.X2
505 || aNewTextBoundingBox
.Y2
!= maTextBoundingBox
.Y2
)
507 maTextBoundingBox
= aNewTextBoundingBox
;
508 mpTextView
->SetLocation(
509 geometry::RealPoint2D(
510 aNewTextBoundingBox
.X1
,
511 aNewTextBoundingBox
.Y1
));
513 geometry::RealSize2D(
514 aNewTextBoundingBox
.X2
- aNewTextBoundingBox
.X1
,
515 aNewTextBoundingBox
.Y2
- aNewTextBoundingBox
.Y1
));
519 void PresenterNotesView::Paint (const awt::Rectangle
& rUpdateBox
)
521 if ( ! mxParentWindow
.is())
523 if ( ! mxCanvas
.is())
526 if (mpBackground
.get() == NULL
)
527 mpBackground
= mpPresenterController
->GetViewBackground(mxViewId
->getResourceURL());
529 if (rUpdateBox
.Y
< maTextBoundingBox
.Y2
530 && rUpdateBox
.X
< maTextBoundingBox
.X2
)
532 PaintText(rUpdateBox
);
535 mpTextView
->Paint(rUpdateBox
);
537 if (rUpdateBox
.Y
+ rUpdateBox
.Height
> maTextBoundingBox
.Y2
)
539 PaintToolBar(rUpdateBox
);
543 void PresenterNotesView::PaintToolBar (const awt::Rectangle
& rUpdateBox
)
545 awt::Rectangle
aWindowBox (mxParentWindow
->getPosSize());
547 rendering::ViewState
aViewState (
548 geometry::AffineMatrix2D(1,0,0, 0,1,0),
550 rendering::RenderState
aRenderState(
551 geometry::AffineMatrix2D(1,0,0, 0,1,0),
554 rendering::CompositeOperation::SOURCE
);
556 if (mpBackground
.get() != NULL
)
558 // Paint the background.
559 mpPresenterController
->GetCanvasHelper()->Paint(
563 awt::Rectangle(0,sal_Int32(maTextBoundingBox
.Y2
),aWindowBox
.Width
,aWindowBox
.Height
),
567 // Paint the horizontal separator.
568 OSL_ASSERT(mxViewId
.is());
569 PresenterCanvasHelper::SetDeviceColor(aRenderState
, maSeparatorColor
);
572 geometry::RealPoint2D(0,mnSeparatorYLocation
),
573 geometry::RealPoint2D(aWindowBox
.Width
,mnSeparatorYLocation
),
578 void PresenterNotesView::PaintText (const awt::Rectangle
& rUpdateBox
)
580 const awt::Rectangle
aBox (PresenterGeometryHelper::Intersection(rUpdateBox
,
581 PresenterGeometryHelper::ConvertRectangle(maTextBoundingBox
)));
583 if (aBox
.Width
<= 0 || aBox
.Height
<= 0)
586 rendering::ViewState
aViewState (
587 geometry::AffineMatrix2D(1,0,0, 0,1,0),
588 PresenterGeometryHelper::CreatePolygon(aBox
, mxCanvas
->getDevice()));
589 rendering::RenderState
aRenderState(
590 geometry::AffineMatrix2D(1,0,0, 0,1,0),
593 rendering::CompositeOperation::SOURCE
);
595 if (mpBackground
.get() != NULL
)
597 // Paint the background.
598 mpPresenterController
->GetCanvasHelper()->Paint(
606 Reference
<rendering::XSpriteCanvas
> xSpriteCanvas (mxCanvas
, UNO_QUERY
);
607 if (xSpriteCanvas
.is())
608 xSpriteCanvas
->updateScreen(sal_False
);
611 void PresenterNotesView::Invalidate (void)
613 mpPresenterController
->GetPaintManager()->Invalidate(
615 PresenterGeometryHelper::ConvertRectangle(maTextBoundingBox
));
618 void PresenterNotesView::Scroll (const double rnDistance
)
623 mpTextView
->SetOffset(0, mnTop
);
628 catch (beans::UnknownPropertyException
&)
632 void PresenterNotesView::SetTop (const double nTop
)
637 mpTextView
->SetOffset(0, mnTop
);
642 catch (beans::UnknownPropertyException
&)
646 void PresenterNotesView::ChangeFontSize (const sal_Int32 nSizeChange
)
648 const sal_Int32
nNewSize (mpFont
->mnSize
+ nSizeChange
);
651 mpFont
->mnSize
= nNewSize
;
652 mpFont
->mxFont
= NULL
;
653 mpTextView
->SetFont(mpFont
);
659 // Write the new font size to the configuration to make it persistent.
662 const OUString
sStyleName (mpPresenterController
->GetTheme()->GetStyleName(
663 mxViewId
->getResourceURL()));
664 ::boost::shared_ptr
<PresenterConfigurationAccess
> pConfiguration (
665 mpPresenterController
->GetTheme()->GetNodeForViewStyle(
667 if (pConfiguration
.get()==NULL
|| ! pConfiguration
->IsValid())
670 pConfiguration
->GoToChild(OUString("Font"));
671 pConfiguration
->SetProperty("Size", Any((sal_Int32
)(nNewSize
+0.5)));
672 pConfiguration
->CommitChanges();
681 ::boost::shared_ptr
<PresenterTextView
> PresenterNotesView::GetTextView (void) const
686 void PresenterNotesView::UpdateScrollBar (void)
688 if (mpScrollBar
.get() != NULL
)
692 mpScrollBar
->SetTotalSize(mpTextView
->GetTotalTextHeight());
694 catch(beans::UnknownPropertyException
&)
699 mpScrollBar
->SetLineHeight(mpFont
->mnSize
*1.2);
700 mpScrollBar
->SetThumbPosition(mnTop
, false);
702 mpScrollBar
->SetThumbSize(maTextBoundingBox
.Y2
- maTextBoundingBox
.Y1
);
703 mpScrollBar
->CheckValues();
707 void PresenterNotesView::ThrowIfDisposed (void)
708 throw (::com::sun::star::lang::DisposedException
)
710 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
712 throw lang::DisposedException (
713 "PresenterNotesView object has already been disposed",
714 static_cast<uno::XWeak
*>(this));
718 } } // end of namespace ::sdext::presenter
720 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */