bump product version to 5.0.4.1
[LibreOffice.git] / sdext / source / presenter / PresenterNotesView.cxx
blob8bb5a0458b7e33f6bf5a9f3a953f31576f51e5fc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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),
63 mxViewId(rxViewId),
64 mpPresenterController(rpPresenterController),
65 mxCanvas(),
66 mxCurrentNotesPage(),
67 mpScrollBar(),
68 mxToolBarWindow(),
69 mxToolBarCanvas(),
70 mpToolBar(),
71 mpCloseButton(),
72 maSeparatorColor(0xffffff),
73 mnSeparatorYLocation(0),
74 maTextBoundingBox(),
75 mpBackground(),
76 mnTop(0),
77 mpFont(),
78 mpTextView()
80 try
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(
89 rxComponentContext,
90 mxCanvas,
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(
102 rxComponentContext,
103 mpPresenterController,
104 mpPresenterController->GetTheme(),
105 mxParentWindow,
106 mxCanvas,
107 "NotesViewCloser");
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(
118 rxComponentContext,
119 mxParentWindow,
120 mpPresenterController->GetPaintManager(),
121 ::boost::bind(&PresenterNotesView::SetTop, this, _1));
122 mpScrollBar->SetBackground(
123 mpPresenterController->GetViewBackground(mxViewId->getResourceURL()));
125 mpScrollBar->SetCanvas(mxCanvas);
127 Layout();
129 catch (RuntimeException&)
131 PresenterNotesView::disposing();
132 throw;
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;
150 // Dispose tool bar.
152 Reference<XComponent> xComponent (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY);
153 mpToolBar = NULL;
154 if (xComponent.is())
155 xComponent->dispose();
158 Reference<XComponent> xComponent (mxToolBarCanvas, UNO_QUERY);
159 mxToolBarCanvas = NULL;
160 if (xComponent.is())
161 xComponent->dispose();
164 Reference<XComponent> xComponent (mxToolBarWindow, UNO_QUERY);
165 mxToolBarWindow = NULL;
166 if (xComponent.is())
167 xComponent->dispose();
170 // Dispose close button
172 Reference<XComponent> xComponent (static_cast<XWeak*>(mpCloseButton.get()), UNO_QUERY);
173 mpCloseButton = NULL;
174 if (xComponent.is())
175 xComponent->dispose();
178 // Create the tool bar.
180 mpScrollBar = NULL;
182 mxViewId = NULL;
185 void PresenterNotesView::CreateToolBar (
186 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
187 const ::rtl::Reference<PresenterController>& rpPresenterController)
189 if (rpPresenterController.get() == NULL)
190 return;
192 Reference<drawing::XPresenterHelper> xPresenterHelper (
193 rpPresenterController->GetPresenterHelper());
194 if ( ! xPresenterHelper.is())
195 return;
197 // Create a new window as container of the tool bar.
198 mxToolBarWindow = xPresenterHelper->createWindow(
199 mxParentWindow,
200 sal_False,
201 sal_True,
202 sal_False,
203 sal_False);
204 mxToolBarCanvas = xPresenterHelper->createSharedCanvas (
205 Reference<rendering::XSpriteCanvas>(mxCanvas, UNO_QUERY),
206 mxParentWindow,
207 mxCanvas,
208 mxParentWindow,
209 mxToolBarWindow);
211 // Create the tool bar.
212 mpToolBar = new PresenterToolBar(
213 rxContext,
214 mxToolBarWindow,
215 mxToolBarCanvas,
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())
232 OUString sText;
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);
245 if (xText.is())
247 sText += xText->getString();
250 else
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);
261 if (xText.is())
263 sText += xText->getString();
264 mpTextView->SetText(Reference<text::XText>(xText, UNO_QUERY));
271 Layout();
273 if (mpScrollBar.get() != NULL)
275 mpScrollBar->SetThumbPosition(0, false);
276 UpdateScrollBar();
279 Invalidate();
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)
297 (void)rEvent;
298 Layout();
301 void SAL_CALL PresenterNotesView::windowMoved (const awt::WindowEvent& rEvent)
302 throw (RuntimeException, std::exception)
304 (void)rEvent;
307 void SAL_CALL PresenterNotesView::windowShown (const lang::EventObject& rEvent)
308 throw (RuntimeException, std::exception)
310 (void)rEvent;
313 void SAL_CALL PresenterNotesView::windowHidden (const lang::EventObject& rEvent)
314 throw (RuntimeException, std::exception)
316 (void)rEvent;
319 //----- XPaintListener --------------------------------------------------------
321 void SAL_CALL PresenterNotesView::windowPaint (const awt::PaintEvent& rEvent)
322 throw (RuntimeException, std::exception)
324 ThrowIfDisposed();
326 if ( ! mbIsPresenterViewActive)
327 return;
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)
338 return mxViewId;
341 sal_Bool SAL_CALL PresenterNotesView::isAnchorOnly()
342 throw (RuntimeException, std::exception)
344 return false;
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)
370 return NULL;
373 //----- XKeyListener ----------------------------------------------------------
375 void SAL_CALL PresenterNotesView::keyPressed (const awt::KeyEvent& rEvent)
376 throw (RuntimeException, std::exception)
378 switch (rEvent.KeyCode)
380 case awt::Key::A:
381 Scroll(-gnLineScrollFactor * mpFont->mnSize);
382 break;
384 case awt::Key::Y:
385 case awt::Key::Z:
386 Scroll(+gnLineScrollFactor * mpFont->mnSize);
387 break;
389 case awt::Key::S:
390 ChangeFontSize(-1);
391 break;
393 case awt::Key::G:
394 ChangeFontSize(+1);
395 break;
397 case awt::Key::H:
398 if (mpTextView)
399 mpTextView->MoveCaret(
401 (rEvent.Modifiers == awt::KeyModifier::SHIFT)
402 ? css::accessibility::AccessibleTextType::CHARACTER
403 : css::accessibility::AccessibleTextType::WORD);
404 break;
406 case awt::Key::L:
407 if (mpTextView)
408 mpTextView->MoveCaret(
410 (rEvent.Modifiers == awt::KeyModifier::SHIFT)
411 ? css::accessibility::AccessibleTextType::CHARACTER
412 : css::accessibility::AccessibleTextType::WORD);
413 break;
417 void SAL_CALL PresenterNotesView::keyReleased (const awt::KeyEvent& rEvent)
418 throw (RuntimeException, std::exception)
420 (void)rEvent;
425 void PresenterNotesView::Layout()
427 if ( ! mxParentWindow.is())
428 return;
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();
461 else
462 aNewTextBoundingBox.X1 += mpScrollBar->GetSize();
464 mpScrollBar->SetTotalSize(nHeight);
466 catch(beans::UnknownPropertyException&)
468 OSL_ASSERT(false);
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);
481 UpdateScrollBar();
483 else
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);
494 UpdateScrollBar();
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));
508 mpTextView->SetSize(
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())
518 return;
519 if ( ! mxCanvas.is())
520 return;
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),
545 NULL);
546 rendering::RenderState aRenderState(
547 geometry::AffineMatrix2D(1,0,0, 0,1,0),
548 NULL,
549 Sequence<double>(4),
550 rendering::CompositeOperation::SOURCE);
552 if (mpBackground.get() != NULL)
554 // Paint the background.
555 mpPresenterController->GetCanvasHelper()->Paint(
556 mpBackground,
557 mxCanvas,
558 rUpdateBox,
559 awt::Rectangle(0,sal_Int32(maTextBoundingBox.Y2),aWindowBox.Width,aWindowBox.Height),
560 awt::Rectangle());
563 // Paint the horizontal separator.
564 OSL_ASSERT(mxViewId.is());
565 PresenterCanvasHelper::SetDeviceColor(aRenderState, maSeparatorColor);
567 mxCanvas->drawLine(
568 geometry::RealPoint2D(0,mnSeparatorYLocation),
569 geometry::RealPoint2D(aWindowBox.Width,mnSeparatorYLocation),
570 aViewState,
571 aRenderState);
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)
580 return;
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),
587 NULL,
588 Sequence<double>(3),
589 rendering::CompositeOperation::SOURCE);
591 if (mpBackground.get() != NULL)
593 // Paint the background.
594 mpPresenterController->GetCanvasHelper()->Paint(
595 mpBackground,
596 mxCanvas,
597 rUpdateBox,
598 aBox,
599 awt::Rectangle());
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(
610 mxParentWindow,
611 PresenterGeometryHelper::ConvertRectangle(maTextBoundingBox));
614 void PresenterNotesView::Scroll (const double rnDistance)
618 mnTop += rnDistance;
619 mpTextView->SetOffset(0, mnTop);
621 UpdateScrollBar();
622 Invalidate();
624 catch (beans::UnknownPropertyException&)
628 void PresenterNotesView::SetTop (const double nTop)
632 mnTop = nTop;
633 mpTextView->SetOffset(0, mnTop);
635 UpdateScrollBar();
636 Invalidate();
638 catch (beans::UnknownPropertyException&)
642 void PresenterNotesView::ChangeFontSize (const sal_Int32 nSizeChange)
644 const sal_Int32 nNewSize (mpFont->mnSize + nSizeChange);
645 if (nNewSize > 5)
647 mpFont->mnSize = nNewSize;
648 mpFont->mxFont = NULL;
649 mpTextView->SetFont(mpFont);
651 Layout();
652 UpdateScrollBar();
653 Invalidate();
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(
662 sStyleName));
663 if (pConfiguration.get()==NULL || ! pConfiguration->IsValid())
664 return;
666 pConfiguration->GoToChild(OUString("Font"));
667 pConfiguration->SetProperty("Size", Any((sal_Int32)(nNewSize+0.5)));
668 pConfiguration->CommitChanges();
670 catch (Exception&)
672 OSL_ASSERT(false);
677 ::boost::shared_ptr<PresenterTextView> PresenterNotesView::GetTextView() const
679 return mpTextView;
682 void PresenterNotesView::UpdateScrollBar()
684 if (mpScrollBar.get() != NULL)
688 mpScrollBar->SetTotalSize(mpTextView->GetTotalTextHeight());
690 catch(beans::UnknownPropertyException&)
692 OSL_ASSERT(false);
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: */