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 "vcl/settings.hxx"
21 #include "PresenterNotesView.hxx"
22 #include "PresenterButton.hxx"
23 #include "PresenterCanvasHelper.hxx"
24 #include "PresenterGeometryHelper.hxx"
25 #include "PresenterPaintManager.hxx"
26 #include "PresenterScrollBar.hxx"
27 #include "PresenterTextView.hxx"
28 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
29 #include <com/sun/star/awt/Key.hpp>
30 #include <com/sun/star/awt/KeyModifier.hpp>
31 #include <com/sun/star/awt/PosSize.hpp>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
34 #include <com/sun/star/drawing/framework/XConfigurationController.hpp>
35 #include <com/sun/star/drawing/framework/XPane.hpp>
36 #include <com/sun/star/lang/XServiceName.hpp>
37 #include <com/sun/star/presentation/XPresentationPage.hpp>
38 #include <com/sun/star/rendering/CompositeOperation.hpp>
39 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
40 #include <com/sun/star/text/XTextRange.hpp>
41 #include <com/sun/star/util/XChangesBatch.hpp>
42 #include <com/sun/star/container/XChild.hpp>
43 #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 double gnLineScrollFactor (1.2);
53 namespace sdext
{ namespace presenter
{
55 //===== PresenterNotesView ====================================================
57 PresenterNotesView::PresenterNotesView (
58 const Reference
<XComponentContext
>& rxComponentContext
,
59 const Reference
<XResourceId
>& rxViewId
,
60 const Reference
<frame::XController
>& rxController
,
61 const ::rtl::Reference
<PresenterController
>& rpPresenterController
)
62 : PresenterNotesViewInterfaceBase(m_aMutex
),
64 mpPresenterController(rpPresenterController
),
72 maSeparatorColor(0xffffff),
73 mnSeparatorYLocation(0),
82 Reference
<XControllerManager
> xCM (rxController
, UNO_QUERY_THROW
);
83 Reference
<XConfigurationController
> xCC (xCM
->getConfigurationController(), UNO_QUERY_THROW
);
84 Reference
<XPane
> xPane (xCC
->getResource(rxViewId
->getAnchor()), UNO_QUERY_THROW
);
86 mxParentWindow
= xPane
->getWindow();
87 mxCanvas
= xPane
->getCanvas();
88 mpTextView
.reset(new PresenterTextView(
91 mpPresenterController
->GetPaintManager()->GetInvalidator(mxParentWindow
)));
93 const OUString
sResourceURL (mxViewId
->getResourceURL());
94 mpFont
.reset(new PresenterTheme::FontDescriptor(
95 rpPresenterController
->GetViewFont(sResourceURL
)));
96 maSeparatorColor
= mpFont
->mnColor
;
97 mpTextView
->SetFont(mpFont
);
99 CreateToolBar(rxComponentContext
, rpPresenterController
);
101 mpCloseButton
= PresenterButton::Create(
103 mpPresenterController
,
104 mpPresenterController
->GetTheme(),
109 if (mxParentWindow
.is())
111 mxParentWindow
->addWindowListener(this);
112 mxParentWindow
->addPaintListener(this);
113 mxParentWindow
->addKeyListener(this);
114 mxParentWindow
->setVisible(sal_True
);
117 mpScrollBar
= new PresenterVerticalScrollBar(
120 mpPresenterController
->GetPaintManager(),
121 ::boost::bind(&PresenterNotesView::SetTop
, this, _1
));
122 mpScrollBar
->SetBackground(
123 mpPresenterController
->GetViewBackground(mxViewId
->getResourceURL()));
125 mpScrollBar
->SetCanvas(mxCanvas
);
129 catch (RuntimeException
&)
131 PresenterNotesView::disposing();
136 PresenterNotesView::~PresenterNotesView()
140 void SAL_CALL
PresenterNotesView::disposing()
142 if (mxParentWindow
.is())
144 mxParentWindow
->removeWindowListener(this);
145 mxParentWindow
->removePaintListener(this);
146 mxParentWindow
->removeKeyListener(this);
147 mxParentWindow
= NULL
;
152 Reference
<XComponent
> xComponent (static_cast<XWeak
*>(mpToolBar
.get()), UNO_QUERY
);
155 xComponent
->dispose();
158 Reference
<XComponent
> xComponent (mxToolBarCanvas
, UNO_QUERY
);
159 mxToolBarCanvas
= NULL
;
161 xComponent
->dispose();
164 Reference
<XComponent
> xComponent (mxToolBarWindow
, UNO_QUERY
);
165 mxToolBarWindow
= NULL
;
167 xComponent
->dispose();
170 // Dispose close button
172 Reference
<XComponent
> xComponent (static_cast<XWeak
*>(mpCloseButton
.get()), UNO_QUERY
);
173 mpCloseButton
= NULL
;
175 xComponent
->dispose();
178 // Create the tool bar.
185 void PresenterNotesView::CreateToolBar (
186 const css::uno::Reference
<css::uno::XComponentContext
>& rxContext
,
187 const ::rtl::Reference
<PresenterController
>& rpPresenterController
)
189 if (rpPresenterController
.get() == NULL
)
192 Reference
<drawing::XPresenterHelper
> xPresenterHelper (
193 rpPresenterController
->GetPresenterHelper());
194 if ( ! xPresenterHelper
.is())
197 // Create a new window as container of the tool bar.
198 mxToolBarWindow
= xPresenterHelper
->createWindow(
204 mxToolBarCanvas
= xPresenterHelper
->createSharedCanvas (
205 Reference
<rendering::XSpriteCanvas
>(mxCanvas
, UNO_QUERY
),
211 // Create the tool bar.
212 mpToolBar
= new PresenterToolBar(
216 rpPresenterController
,
217 PresenterToolBar::Left
);
218 mpToolBar
->Initialize(
219 "PresenterScreenSettings/ToolBars/NotesToolBar");
222 void PresenterNotesView::SetSlide (const Reference
<drawing::XDrawPage
>& rxNotesPage
)
224 static const OUString
sNotesShapeName (
225 "com.sun.star.presentation.NotesShape");
226 static const OUString
sTextShapeName (
227 "com.sun.star.drawing.TextShape");
229 Reference
<container::XIndexAccess
> xIndexAccess (rxNotesPage
, UNO_QUERY
);
230 if (xIndexAccess
.is())
234 // Iterate over all shapes and find the one that holds the text.
235 sal_Int32
nCount (xIndexAccess
->getCount());
236 for (sal_Int32 nIndex
=0; nIndex
<nCount
; ++nIndex
)
239 Reference
<lang::XServiceName
> xServiceName (
240 xIndexAccess
->getByIndex(nIndex
), UNO_QUERY
);
241 if (xServiceName
.is()
242 && xServiceName
->getServiceName().equals(sNotesShapeName
))
244 Reference
<text::XTextRange
> xText (xServiceName
, UNO_QUERY
);
247 sText
+= xText
->getString();
252 Reference
<drawing::XShapeDescriptor
> xShapeDescriptor (
253 xIndexAccess
->getByIndex(nIndex
), UNO_QUERY
);
254 if (xShapeDescriptor
.is())
256 OUString
sType (xShapeDescriptor
->getShapeType());
257 if (sType
.equals(sNotesShapeName
) || sType
.equals(sTextShapeName
))
259 Reference
<text::XTextRange
> xText (
260 xIndexAccess
->getByIndex(nIndex
), UNO_QUERY
);
263 sText
+= xText
->getString();
264 mpTextView
->SetText(Reference
<text::XText
>(xText
, UNO_QUERY
));
273 if (mpScrollBar
.get() != NULL
)
275 mpScrollBar
->SetThumbPosition(0, false);
283 //----- lang::XEventListener -------------------------------------------------
285 void SAL_CALL
PresenterNotesView::disposing (const lang::EventObject
& rEventObject
)
286 throw (RuntimeException
, std::exception
)
288 if (rEventObject
.Source
== mxParentWindow
)
289 mxParentWindow
= NULL
;
292 //----- XWindowListener -------------------------------------------------------
294 void SAL_CALL
PresenterNotesView::windowResized (const awt::WindowEvent
& rEvent
)
295 throw (RuntimeException
, std::exception
)
301 void SAL_CALL
PresenterNotesView::windowMoved (const awt::WindowEvent
& rEvent
)
302 throw (RuntimeException
, std::exception
)
307 void SAL_CALL
PresenterNotesView::windowShown (const lang::EventObject
& rEvent
)
308 throw (RuntimeException
, std::exception
)
313 void SAL_CALL
PresenterNotesView::windowHidden (const lang::EventObject
& rEvent
)
314 throw (RuntimeException
, std::exception
)
319 //----- XPaintListener --------------------------------------------------------
321 void SAL_CALL
PresenterNotesView::windowPaint (const awt::PaintEvent
& rEvent
)
322 throw (RuntimeException
, std::exception
)
326 if ( ! mbIsPresenterViewActive
)
329 ::osl::MutexGuard
aSolarGuard (::osl::Mutex::getGlobalMutex());
330 Paint(rEvent
.UpdateRect
);
333 //----- XResourceId -----------------------------------------------------------
335 Reference
<XResourceId
> SAL_CALL
PresenterNotesView::getResourceId()
336 throw (RuntimeException
, std::exception
)
341 sal_Bool SAL_CALL
PresenterNotesView::isAnchorOnly()
342 throw (RuntimeException
, std::exception
)
347 //----- XDrawView -------------------------------------------------------------
349 void SAL_CALL
PresenterNotesView::setCurrentPage (const Reference
<drawing::XDrawPage
>& rxSlide
)
350 throw (RuntimeException
, std::exception
)
352 // Get the associated notes page.
353 mxCurrentNotesPage
= NULL
;
356 Reference
<presentation::XPresentationPage
> xPresentationPage(rxSlide
, UNO_QUERY
);
357 if (xPresentationPage
.is())
358 mxCurrentNotesPage
= xPresentationPage
->getNotesPage();
360 catch (RuntimeException
&)
364 SetSlide(mxCurrentNotesPage
);
367 Reference
<drawing::XDrawPage
> SAL_CALL
PresenterNotesView::getCurrentPage()
368 throw (RuntimeException
, std::exception
)
373 //----- XKeyListener ----------------------------------------------------------
375 void SAL_CALL
PresenterNotesView::keyPressed (const awt::KeyEvent
& rEvent
)
376 throw (RuntimeException
, std::exception
)
378 switch (rEvent
.KeyCode
)
381 Scroll(-gnLineScrollFactor
* mpFont
->mnSize
);
386 Scroll(+gnLineScrollFactor
* mpFont
->mnSize
);
399 mpTextView
->MoveCaret(
401 (rEvent
.Modifiers
== awt::KeyModifier::SHIFT
)
402 ? css::accessibility::AccessibleTextType::CHARACTER
403 : css::accessibility::AccessibleTextType::WORD
);
408 mpTextView
->MoveCaret(
410 (rEvent
.Modifiers
== awt::KeyModifier::SHIFT
)
411 ? css::accessibility::AccessibleTextType::CHARACTER
412 : css::accessibility::AccessibleTextType::WORD
);
417 void SAL_CALL
PresenterNotesView::keyReleased (const awt::KeyEvent
& rEvent
)
418 throw (RuntimeException
, std::exception
)
425 void PresenterNotesView::Layout()
427 if ( ! mxParentWindow
.is())
429 awt::Rectangle
aWindowBox (mxParentWindow
->getPosSize());
430 geometry::RealRectangle2D
aNewTextBoundingBox (0,0,aWindowBox
.Width
, aWindowBox
.Height
);
431 // Size the tool bar and the horizontal separator above it.
432 if (mxToolBarWindow
.is())
434 const geometry::RealSize2D
aToolBarSize (mpToolBar
->GetMinimalSize());
435 const sal_Int32 nToolBarHeight
= sal_Int32(aToolBarSize
.Height
+ 0.5);
436 mxToolBarWindow
->setPosSize(0, aWindowBox
.Height
- nToolBarHeight
,
437 sal_Int32(aToolBarSize
.Width
+ 0.5), nToolBarHeight
,
438 awt::PosSize::POSSIZE
);
439 aNewTextBoundingBox
.Y2
-= nToolBarHeight
;
440 mnSeparatorYLocation
= aWindowBox
.Height
- nToolBarHeight
- gnSpaceBelowSeparator
;
441 aNewTextBoundingBox
.Y2
= mnSeparatorYLocation
- gnSpaceAboveSeparator
;
442 // Place the close button.
443 if (mpCloseButton
.get() != NULL
)
444 mpCloseButton
->SetCenter(geometry::RealPoint2D(
445 (aWindowBox
.Width
+ aToolBarSize
.Width
) / 2,
446 aWindowBox
.Height
- aToolBarSize
.Height
/2));
448 // Check whether the vertical scroll bar is necessary.
449 if (mpScrollBar
.get() != NULL
)
451 bool bShowVerticalScrollbar (false);
454 const double nTextBoxHeight (aNewTextBoundingBox
.Y2
- aNewTextBoundingBox
.Y1
);
455 const double nHeight (mpTextView
->GetTotalTextHeight());
456 if (nHeight
> nTextBoxHeight
)
458 bShowVerticalScrollbar
= true;
459 if(!AllSettings::GetLayoutRTL())
460 aNewTextBoundingBox
.X2
-= mpScrollBar
->GetSize();
462 aNewTextBoundingBox
.X1
+= mpScrollBar
->GetSize();
464 mpScrollBar
->SetTotalSize(nHeight
);
466 catch(beans::UnknownPropertyException
&)
470 if(AllSettings::GetLayoutRTL())
472 mpScrollBar
->SetVisible(bShowVerticalScrollbar
);
473 mpScrollBar
->SetPosSize(
474 geometry::RealRectangle2D(
475 aNewTextBoundingBox
.X1
- mpScrollBar
->GetSize(),
476 aNewTextBoundingBox
.Y1
,
477 aNewTextBoundingBox
.X1
,
478 aNewTextBoundingBox
.Y2
));
479 if( ! bShowVerticalScrollbar
)
480 mpScrollBar
->SetThumbPosition(0, false);
485 mpScrollBar
->SetVisible(bShowVerticalScrollbar
);
486 mpScrollBar
->SetPosSize(
487 geometry::RealRectangle2D(
488 aWindowBox
.Width
- mpScrollBar
->GetSize(),
489 aNewTextBoundingBox
.Y1
,
490 aNewTextBoundingBox
.X2
+ mpScrollBar
->GetSize(),
491 aNewTextBoundingBox
.Y2
));
492 if( ! bShowVerticalScrollbar
)
493 mpScrollBar
->SetThumbPosition(0, false);
497 // Has the text area has changed it position or size?
498 if (aNewTextBoundingBox
.X1
!= maTextBoundingBox
.X1
499 || aNewTextBoundingBox
.Y1
!= maTextBoundingBox
.Y1
500 || aNewTextBoundingBox
.X2
!= maTextBoundingBox
.X2
501 || aNewTextBoundingBox
.Y2
!= maTextBoundingBox
.Y2
)
503 maTextBoundingBox
= aNewTextBoundingBox
;
504 mpTextView
->SetLocation(
505 geometry::RealPoint2D(
506 aNewTextBoundingBox
.X1
,
507 aNewTextBoundingBox
.Y1
));
509 geometry::RealSize2D(
510 aNewTextBoundingBox
.X2
- aNewTextBoundingBox
.X1
,
511 aNewTextBoundingBox
.Y2
- aNewTextBoundingBox
.Y1
));
515 void PresenterNotesView::Paint (const awt::Rectangle
& rUpdateBox
)
517 if ( ! mxParentWindow
.is())
519 if ( ! mxCanvas
.is())
522 if (mpBackground
.get() == NULL
)
523 mpBackground
= mpPresenterController
->GetViewBackground(mxViewId
->getResourceURL());
525 if (rUpdateBox
.Y
< maTextBoundingBox
.Y2
526 && rUpdateBox
.X
< maTextBoundingBox
.X2
)
528 PaintText(rUpdateBox
);
531 mpTextView
->Paint(rUpdateBox
);
533 if (rUpdateBox
.Y
+ rUpdateBox
.Height
> maTextBoundingBox
.Y2
)
535 PaintToolBar(rUpdateBox
);
539 void PresenterNotesView::PaintToolBar (const awt::Rectangle
& rUpdateBox
)
541 awt::Rectangle
aWindowBox (mxParentWindow
->getPosSize());
543 rendering::ViewState
aViewState (
544 geometry::AffineMatrix2D(1,0,0, 0,1,0),
546 rendering::RenderState
aRenderState(
547 geometry::AffineMatrix2D(1,0,0, 0,1,0),
550 rendering::CompositeOperation::SOURCE
);
552 if (mpBackground
.get() != NULL
)
554 // Paint the background.
555 mpPresenterController
->GetCanvasHelper()->Paint(
559 awt::Rectangle(0,sal_Int32(maTextBoundingBox
.Y2
),aWindowBox
.Width
,aWindowBox
.Height
),
563 // Paint the horizontal separator.
564 OSL_ASSERT(mxViewId
.is());
565 PresenterCanvasHelper::SetDeviceColor(aRenderState
, maSeparatorColor
);
568 geometry::RealPoint2D(0,mnSeparatorYLocation
),
569 geometry::RealPoint2D(aWindowBox
.Width
,mnSeparatorYLocation
),
574 void PresenterNotesView::PaintText (const awt::Rectangle
& rUpdateBox
)
576 const awt::Rectangle
aBox (PresenterGeometryHelper::Intersection(rUpdateBox
,
577 PresenterGeometryHelper::ConvertRectangle(maTextBoundingBox
)));
579 if (aBox
.Width
<= 0 || aBox
.Height
<= 0)
582 rendering::ViewState
aViewState (
583 geometry::AffineMatrix2D(1,0,0, 0,1,0),
584 PresenterGeometryHelper::CreatePolygon(aBox
, mxCanvas
->getDevice()));
585 rendering::RenderState
aRenderState(
586 geometry::AffineMatrix2D(1,0,0, 0,1,0),
589 rendering::CompositeOperation::SOURCE
);
591 if (mpBackground
.get() != NULL
)
593 // Paint the background.
594 mpPresenterController
->GetCanvasHelper()->Paint(
602 Reference
<rendering::XSpriteCanvas
> xSpriteCanvas (mxCanvas
, UNO_QUERY
);
603 if (xSpriteCanvas
.is())
604 xSpriteCanvas
->updateScreen(sal_False
);
607 void PresenterNotesView::Invalidate()
609 mpPresenterController
->GetPaintManager()->Invalidate(
611 PresenterGeometryHelper::ConvertRectangle(maTextBoundingBox
));
614 void PresenterNotesView::Scroll (const double rnDistance
)
619 mpTextView
->SetOffset(0, mnTop
);
624 catch (beans::UnknownPropertyException
&)
628 void PresenterNotesView::SetTop (const double nTop
)
633 mpTextView
->SetOffset(0, mnTop
);
638 catch (beans::UnknownPropertyException
&)
642 void PresenterNotesView::ChangeFontSize (const sal_Int32 nSizeChange
)
644 const sal_Int32
nNewSize (mpFont
->mnSize
+ nSizeChange
);
647 mpFont
->mnSize
= nNewSize
;
648 mpFont
->mxFont
= NULL
;
649 mpTextView
->SetFont(mpFont
);
655 // Write the new font size to the configuration to make it persistent.
658 const OUString
sStyleName (mpPresenterController
->GetTheme()->GetStyleName(
659 mxViewId
->getResourceURL()));
660 ::boost::shared_ptr
<PresenterConfigurationAccess
> pConfiguration (
661 mpPresenterController
->GetTheme()->GetNodeForViewStyle(
663 if (pConfiguration
.get()==NULL
|| ! pConfiguration
->IsValid())
666 pConfiguration
->GoToChild(OUString("Font"));
667 pConfiguration
->SetProperty("Size", Any((sal_Int32
)(nNewSize
+0.5)));
668 pConfiguration
->CommitChanges();
677 ::boost::shared_ptr
<PresenterTextView
> PresenterNotesView::GetTextView() const
682 void PresenterNotesView::UpdateScrollBar()
684 if (mpScrollBar
.get() != NULL
)
688 mpScrollBar
->SetTotalSize(mpTextView
->GetTotalTextHeight());
690 catch(beans::UnknownPropertyException
&)
695 mpScrollBar
->SetLineHeight(mpFont
->mnSize
*1.2);
696 mpScrollBar
->SetThumbPosition(mnTop
, false);
698 mpScrollBar
->SetThumbSize(maTextBoundingBox
.Y2
- maTextBoundingBox
.Y1
);
699 mpScrollBar
->CheckValues();
703 void PresenterNotesView::ThrowIfDisposed()
704 throw (::com::sun::star::lang::DisposedException
)
706 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
708 throw lang::DisposedException (
709 "PresenterNotesView object has already been disposed",
710 static_cast<uno::XWeak
*>(this));
714 } } // end of namespace ::sdext::presenter
716 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */