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>
44 using namespace ::com::sun::star
;
45 using namespace ::com::sun::star::uno
;
46 using namespace ::com::sun::star::drawing::framework
;
48 static const sal_Int32
gnSpaceBelowSeparator (10);
49 static const sal_Int32
gnSpaceAboveSeparator (10);
50 static const double gnLineScrollFactor (1.2);
52 namespace sdext
{ namespace presenter
{
54 //===== PresenterNotesView ====================================================
56 PresenterNotesView::PresenterNotesView (
57 const Reference
<XComponentContext
>& rxComponentContext
,
58 const Reference
<XResourceId
>& rxViewId
,
59 const Reference
<frame::XController
>& rxController
,
60 const ::rtl::Reference
<PresenterController
>& rpPresenterController
)
61 : PresenterNotesViewInterfaceBase(m_aMutex
),
63 mpPresenterController(rpPresenterController
),
71 maSeparatorColor(0xffffff),
72 mnSeparatorYLocation(0),
81 Reference
<XControllerManager
> xCM (rxController
, UNO_QUERY_THROW
);
82 Reference
<XConfigurationController
> xCC (xCM
->getConfigurationController(), UNO_QUERY_THROW
);
83 Reference
<XPane
> xPane (xCC
->getResource(rxViewId
->getAnchor()), UNO_QUERY_THROW
);
85 mxParentWindow
= xPane
->getWindow();
86 mxCanvas
= xPane
->getCanvas();
87 mpTextView
.reset(new PresenterTextView(
90 mpPresenterController
->GetPaintManager()->GetInvalidator(mxParentWindow
)));
92 const OUString
sResourceURL (mxViewId
->getResourceURL());
93 mpFont
.reset(new PresenterTheme::FontDescriptor(
94 rpPresenterController
->GetViewFont(sResourceURL
)));
95 maSeparatorColor
= mpFont
->mnColor
;
96 mpTextView
->SetFont(mpFont
);
98 CreateToolBar(rxComponentContext
, rpPresenterController
);
100 mpCloseButton
= PresenterButton::Create(
102 mpPresenterController
,
103 mpPresenterController
->GetTheme(),
108 if (mxParentWindow
.is())
110 mxParentWindow
->addWindowListener(this);
111 mxParentWindow
->addPaintListener(this);
112 mxParentWindow
->addKeyListener(this);
113 mxParentWindow
->setVisible(true);
116 mpScrollBar
= new PresenterVerticalScrollBar(
119 mpPresenterController
->GetPaintManager(),
120 [this](double f
) { return this->SetTop(f
); });
121 mpScrollBar
->SetBackground(
122 mpPresenterController
->GetViewBackground(mxViewId
->getResourceURL()));
124 mpScrollBar
->SetCanvas(mxCanvas
);
128 catch (RuntimeException
&)
130 PresenterNotesView::disposing();
135 PresenterNotesView::~PresenterNotesView()
139 void SAL_CALL
PresenterNotesView::disposing()
141 if (mxParentWindow
.is())
143 mxParentWindow
->removeWindowListener(this);
144 mxParentWindow
->removePaintListener(this);
145 mxParentWindow
->removeKeyListener(this);
146 mxParentWindow
= nullptr;
151 Reference
<XComponent
> xComponent (static_cast<XWeak
*>(mpToolBar
.get()), UNO_QUERY
);
154 xComponent
->dispose();
157 Reference
<XComponent
> xComponent (mxToolBarCanvas
, UNO_QUERY
);
158 mxToolBarCanvas
= nullptr;
160 xComponent
->dispose();
163 Reference
<XComponent
> xComponent (mxToolBarWindow
, UNO_QUERY
);
164 mxToolBarWindow
= nullptr;
166 xComponent
->dispose();
169 // Dispose close button
171 Reference
<XComponent
> xComponent (static_cast<XWeak
*>(mpCloseButton
.get()), UNO_QUERY
);
172 mpCloseButton
= nullptr;
174 xComponent
->dispose();
177 // Create the tool bar.
179 mpScrollBar
= nullptr;
184 void PresenterNotesView::CreateToolBar (
185 const css::uno::Reference
<css::uno::XComponentContext
>& rxContext
,
186 const ::rtl::Reference
<PresenterController
>& rpPresenterController
)
188 if (rpPresenterController
.get() == nullptr)
191 Reference
<drawing::XPresenterHelper
> xPresenterHelper (
192 rpPresenterController
->GetPresenterHelper());
193 if ( ! xPresenterHelper
.is())
196 // Create a new window as container of the tool bar.
197 mxToolBarWindow
= xPresenterHelper
->createWindow(
203 mxToolBarCanvas
= xPresenterHelper
->createSharedCanvas (
204 Reference
<rendering::XSpriteCanvas
>(mxCanvas
, UNO_QUERY
),
210 // Create the tool bar.
211 mpToolBar
= new PresenterToolBar(
215 rpPresenterController
,
216 PresenterToolBar::Left
);
217 mpToolBar
->Initialize(
218 "PresenterScreenSettings/ToolBars/NotesToolBar");
221 void PresenterNotesView::SetSlide (const Reference
<drawing::XDrawPage
>& rxNotesPage
)
223 static const OUString
sNotesShapeName (
224 "com.sun.star.presentation.NotesShape");
225 static const OUString
sTextShapeName (
226 "com.sun.star.drawing.TextShape");
228 Reference
<container::XIndexAccess
> xIndexAccess (rxNotesPage
, UNO_QUERY
);
229 if (xIndexAccess
.is())
231 // Iterate over all shapes and find the one that holds the text.
232 sal_Int32
nCount (xIndexAccess
->getCount());
233 for (sal_Int32 nIndex
=0; nIndex
<nCount
; ++nIndex
)
236 Reference
<lang::XServiceName
> xServiceName (
237 xIndexAccess
->getByIndex(nIndex
), UNO_QUERY
);
238 if (xServiceName
.is()
239 && xServiceName
->getServiceName() == sNotesShapeName
)
244 Reference
<drawing::XShapeDescriptor
> xShapeDescriptor (
245 xIndexAccess
->getByIndex(nIndex
), UNO_QUERY
);
246 if (xShapeDescriptor
.is())
248 OUString
sType (xShapeDescriptor
->getShapeType());
249 if (sType
== sNotesShapeName
|| sType
== sTextShapeName
)
251 Reference
<text::XTextRange
> xText (
252 xIndexAccess
->getByIndex(nIndex
), UNO_QUERY
);
255 mpTextView
->SetText(Reference
<text::XText
>(xText
, UNO_QUERY
));
264 if (mpScrollBar
.get() != nullptr)
266 mpScrollBar
->SetThumbPosition(0, false);
274 //----- lang::XEventListener -------------------------------------------------
276 void SAL_CALL
PresenterNotesView::disposing (const lang::EventObject
& rEventObject
)
278 if (rEventObject
.Source
== mxParentWindow
)
279 mxParentWindow
= nullptr;
282 //----- XWindowListener -------------------------------------------------------
284 void SAL_CALL
PresenterNotesView::windowResized (const awt::WindowEvent
&)
289 void SAL_CALL
PresenterNotesView::windowMoved (const awt::WindowEvent
&) {}
291 void SAL_CALL
PresenterNotesView::windowShown (const lang::EventObject
&) {}
293 void SAL_CALL
PresenterNotesView::windowHidden (const lang::EventObject
&) {}
295 //----- XPaintListener --------------------------------------------------------
297 void SAL_CALL
PresenterNotesView::windowPaint (const awt::PaintEvent
& rEvent
)
299 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
301 throw lang::DisposedException (
302 "PresenterNotesView object has already been disposed",
303 static_cast<uno::XWeak
*>(this));
306 if ( ! mbIsPresenterViewActive
)
309 ::osl::MutexGuard
aSolarGuard (::osl::Mutex::getGlobalMutex());
310 Paint(rEvent
.UpdateRect
);
313 //----- XResourceId -----------------------------------------------------------
315 Reference
<XResourceId
> SAL_CALL
PresenterNotesView::getResourceId()
320 sal_Bool SAL_CALL
PresenterNotesView::isAnchorOnly()
325 //----- XDrawView -------------------------------------------------------------
327 void SAL_CALL
PresenterNotesView::setCurrentPage (const Reference
<drawing::XDrawPage
>& rxSlide
)
329 // Get the associated notes page.
330 mxCurrentNotesPage
= nullptr;
333 Reference
<presentation::XPresentationPage
> xPresentationPage(rxSlide
, UNO_QUERY
);
334 if (xPresentationPage
.is())
335 mxCurrentNotesPage
= xPresentationPage
->getNotesPage();
337 catch (RuntimeException
&)
341 SetSlide(mxCurrentNotesPage
);
344 Reference
<drawing::XDrawPage
> SAL_CALL
PresenterNotesView::getCurrentPage()
349 //----- XKeyListener ----------------------------------------------------------
351 void SAL_CALL
PresenterNotesView::keyPressed (const awt::KeyEvent
& rEvent
)
353 switch (rEvent
.KeyCode
)
356 Scroll(-gnLineScrollFactor
* mpFont
->mnSize
);
361 Scroll(+gnLineScrollFactor
* mpFont
->mnSize
);
374 mpTextView
->MoveCaret(
376 (rEvent
.Modifiers
== awt::KeyModifier::SHIFT
)
377 ? css::accessibility::AccessibleTextType::CHARACTER
378 : css::accessibility::AccessibleTextType::WORD
);
383 mpTextView
->MoveCaret(
385 (rEvent
.Modifiers
== awt::KeyModifier::SHIFT
)
386 ? css::accessibility::AccessibleTextType::CHARACTER
387 : css::accessibility::AccessibleTextType::WORD
);
392 void SAL_CALL
PresenterNotesView::keyReleased (const awt::KeyEvent
&) {}
395 void PresenterNotesView::Layout()
397 if ( ! mxParentWindow
.is())
399 awt::Rectangle
aWindowBox (mxParentWindow
->getPosSize());
400 geometry::RealRectangle2D
aNewTextBoundingBox (0,0,aWindowBox
.Width
, aWindowBox
.Height
);
401 // Size the tool bar and the horizontal separator above it.
402 if (mxToolBarWindow
.is())
404 const geometry::RealSize2D
aToolBarSize (mpToolBar
->GetMinimalSize());
405 const sal_Int32 nToolBarHeight
= sal_Int32(aToolBarSize
.Height
+ 0.5);
406 mxToolBarWindow
->setPosSize(0, aWindowBox
.Height
- nToolBarHeight
,
407 sal_Int32(aToolBarSize
.Width
+ 0.5), nToolBarHeight
,
408 awt::PosSize::POSSIZE
);
409 aNewTextBoundingBox
.Y2
-= nToolBarHeight
;
410 mnSeparatorYLocation
= aWindowBox
.Height
- nToolBarHeight
- gnSpaceBelowSeparator
;
411 aNewTextBoundingBox
.Y2
= mnSeparatorYLocation
- gnSpaceAboveSeparator
;
412 // Place the close button.
413 if (mpCloseButton
.get() != nullptr)
414 mpCloseButton
->SetCenter(geometry::RealPoint2D(
415 (aWindowBox
.Width
+ aToolBarSize
.Width
) / 2,
416 aWindowBox
.Height
- aToolBarSize
.Height
/2));
418 // Check whether the vertical scroll bar is necessary.
419 if (mpScrollBar
.get() != nullptr)
421 bool bShowVerticalScrollbar (false);
424 const double nTextBoxHeight (aNewTextBoundingBox
.Y2
- aNewTextBoundingBox
.Y1
);
425 const double nHeight (mpTextView
->GetTotalTextHeight());
426 if (nHeight
> nTextBoxHeight
)
428 bShowVerticalScrollbar
= true;
429 if(!AllSettings::GetLayoutRTL())
430 aNewTextBoundingBox
.X2
-= mpScrollBar
->GetSize();
432 aNewTextBoundingBox
.X1
+= mpScrollBar
->GetSize();
434 mpScrollBar
->SetTotalSize(nHeight
);
436 catch(beans::UnknownPropertyException
&)
440 if(AllSettings::GetLayoutRTL())
442 mpScrollBar
->SetVisible(bShowVerticalScrollbar
);
443 mpScrollBar
->SetPosSize(
444 geometry::RealRectangle2D(
445 aNewTextBoundingBox
.X1
- mpScrollBar
->GetSize(),
446 aNewTextBoundingBox
.Y1
,
447 aNewTextBoundingBox
.X1
,
448 aNewTextBoundingBox
.Y2
));
449 if( ! bShowVerticalScrollbar
)
450 mpScrollBar
->SetThumbPosition(0, false);
455 mpScrollBar
->SetVisible(bShowVerticalScrollbar
);
456 mpScrollBar
->SetPosSize(
457 geometry::RealRectangle2D(
458 aWindowBox
.Width
- mpScrollBar
->GetSize(),
459 aNewTextBoundingBox
.Y1
,
460 aNewTextBoundingBox
.X2
+ mpScrollBar
->GetSize(),
461 aNewTextBoundingBox
.Y2
));
462 if( ! bShowVerticalScrollbar
)
463 mpScrollBar
->SetThumbPosition(0, false);
467 // Has the text area has changed it position or size?
468 if (aNewTextBoundingBox
.X1
!= maTextBoundingBox
.X1
469 || aNewTextBoundingBox
.Y1
!= maTextBoundingBox
.Y1
470 || aNewTextBoundingBox
.X2
!= maTextBoundingBox
.X2
471 || aNewTextBoundingBox
.Y2
!= maTextBoundingBox
.Y2
)
473 maTextBoundingBox
= aNewTextBoundingBox
;
474 mpTextView
->SetLocation(
475 geometry::RealPoint2D(
476 aNewTextBoundingBox
.X1
,
477 aNewTextBoundingBox
.Y1
));
479 geometry::RealSize2D(
480 aNewTextBoundingBox
.X2
- aNewTextBoundingBox
.X1
,
481 aNewTextBoundingBox
.Y2
- aNewTextBoundingBox
.Y1
));
485 void PresenterNotesView::Paint (const awt::Rectangle
& rUpdateBox
)
487 if ( ! mxParentWindow
.is())
489 if ( ! mxCanvas
.is())
492 if (mpBackground
.get() == nullptr)
493 mpBackground
= mpPresenterController
->GetViewBackground(mxViewId
->getResourceURL());
495 if (rUpdateBox
.Y
< maTextBoundingBox
.Y2
496 && rUpdateBox
.X
< maTextBoundingBox
.X2
)
498 PaintText(rUpdateBox
);
501 mpTextView
->Paint(rUpdateBox
);
503 if (rUpdateBox
.Y
+ rUpdateBox
.Height
> maTextBoundingBox
.Y2
)
505 PaintToolBar(rUpdateBox
);
509 void PresenterNotesView::PaintToolBar (const awt::Rectangle
& rUpdateBox
)
511 awt::Rectangle
aWindowBox (mxParentWindow
->getPosSize());
513 rendering::ViewState
aViewState (
514 geometry::AffineMatrix2D(1,0,0, 0,1,0),
516 rendering::RenderState
aRenderState(
517 geometry::AffineMatrix2D(1,0,0, 0,1,0),
520 rendering::CompositeOperation::SOURCE
);
522 if (mpBackground
.get() != nullptr)
524 // Paint the background.
525 mpPresenterController
->GetCanvasHelper()->Paint(
529 awt::Rectangle(0,sal_Int32(maTextBoundingBox
.Y2
),aWindowBox
.Width
,aWindowBox
.Height
),
533 // Paint the horizontal separator.
534 OSL_ASSERT(mxViewId
.is());
535 PresenterCanvasHelper::SetDeviceColor(aRenderState
, maSeparatorColor
);
538 geometry::RealPoint2D(0,mnSeparatorYLocation
),
539 geometry::RealPoint2D(aWindowBox
.Width
,mnSeparatorYLocation
),
544 void PresenterNotesView::PaintText (const awt::Rectangle
& rUpdateBox
)
546 const awt::Rectangle
aBox (PresenterGeometryHelper::Intersection(rUpdateBox
,
547 PresenterGeometryHelper::ConvertRectangle(maTextBoundingBox
)));
549 if (aBox
.Width
<= 0 || aBox
.Height
<= 0)
552 rendering::ViewState
aViewState (
553 geometry::AffineMatrix2D(1,0,0, 0,1,0),
554 PresenterGeometryHelper::CreatePolygon(aBox
, mxCanvas
->getDevice()));
555 rendering::RenderState
aRenderState(
556 geometry::AffineMatrix2D(1,0,0, 0,1,0),
559 rendering::CompositeOperation::SOURCE
);
561 if (mpBackground
.get() != nullptr)
563 // Paint the background.
564 mpPresenterController
->GetCanvasHelper()->Paint(
572 Reference
<rendering::XSpriteCanvas
> xSpriteCanvas (mxCanvas
, UNO_QUERY
);
573 if (xSpriteCanvas
.is())
574 xSpriteCanvas
->updateScreen(false);
577 void PresenterNotesView::Invalidate()
579 mpPresenterController
->GetPaintManager()->Invalidate(
581 PresenterGeometryHelper::ConvertRectangle(maTextBoundingBox
));
584 void PresenterNotesView::Scroll (const double rnDistance
)
589 mpTextView
->SetOffset(0, mnTop
);
594 catch (beans::UnknownPropertyException
&)
598 void PresenterNotesView::SetTop (const double nTop
)
603 mpTextView
->SetOffset(0, mnTop
);
608 catch (beans::UnknownPropertyException
&)
612 void PresenterNotesView::ChangeFontSize (const sal_Int32 nSizeChange
)
614 const sal_Int32
nNewSize (mpFont
->mnSize
+ nSizeChange
);
617 mpFont
->mnSize
= nNewSize
;
618 mpFont
->mxFont
= nullptr;
619 mpTextView
->SetFont(mpFont
);
625 // Write the new font size to the configuration to make it persistent.
628 const OUString
sStyleName (mpPresenterController
->GetTheme()->GetStyleName(
629 mxViewId
->getResourceURL()));
630 std::shared_ptr
<PresenterConfigurationAccess
> pConfiguration (
631 mpPresenterController
->GetTheme()->GetNodeForViewStyle(
633 if (pConfiguration
.get()==nullptr || ! pConfiguration
->IsValid())
636 pConfiguration
->GoToChild(OUString("Font"));
637 pConfiguration
->SetProperty("Size", Any(static_cast<sal_Int32
>(nNewSize
+0.5)));
638 pConfiguration
->CommitChanges();
647 const std::shared_ptr
<PresenterTextView
>& PresenterNotesView::GetTextView() const
652 void PresenterNotesView::UpdateScrollBar()
654 if (mpScrollBar
.get() != nullptr)
658 mpScrollBar
->SetTotalSize(mpTextView
->GetTotalTextHeight());
660 catch(beans::UnknownPropertyException
&)
665 mpScrollBar
->SetLineHeight(mpFont
->mnSize
*1.2);
666 mpScrollBar
->SetThumbPosition(mnTop
, false);
668 mpScrollBar
->SetThumbSize(maTextBoundingBox
.Y2
- maTextBoundingBox
.Y1
);
669 mpScrollBar
->CheckValues();
673 } } // end of namespace ::sdext::presenter
675 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */