Update ooo320-m1
[ooovba.git] / sdext / source / presenter / PresenterNotesView.cxx
blob244de6dcc644dd59a075471b1e2b8a027a527d6d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: PresenterNotesView.cxx,v $
11 * $Revision: 1.8 $
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>
58 #include <set>
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),
85 mxViewId(rxViewId),
86 mpPresenterController(rpPresenterController),
87 mxCanvas(),
88 mxCurrentNotesPage(),
89 mpScrollBar(),
90 mxToolBarWindow(),
91 mxToolBarCanvas(),
92 mpToolBar(),
93 mpCloseButton(),
94 maSeparatorColor(0xffffff),
95 mnSeparatorYLocation(0),
96 maTextBoundingBox(),
97 mpBackground(),
98 mnTop(0),
99 mpFont(),
100 mpTextView()
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(
111 rxComponentContext,
112 mxCanvas,
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(
124 rxComponentContext,
125 mpPresenterController,
126 mpPresenterController->GetTheme(),
127 mxParentWindow,
128 mxCanvas,
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(
140 rxComponentContext,
141 mxParentWindow,
142 mpPresenterController->GetPaintManager(),
143 ::boost::bind(&PresenterNotesView::SetTop, this, _1));
144 mpScrollBar->SetBackground(
145 mpPresenterController->GetViewBackground(mxViewId->getResourceURL()));
147 mpScrollBar->SetCanvas(mxCanvas);
149 Layout();
151 catch (RuntimeException&)
153 PresenterNotesView::disposing();
154 throw;
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;
178 // Dispose tool bar.
180 Reference<XComponent> xComponent (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY);
181 mpToolBar = NULL;
182 if (xComponent.is())
183 xComponent->dispose();
186 Reference<XComponent> xComponent (mxToolBarCanvas, UNO_QUERY);
187 mxToolBarCanvas = NULL;
188 if (xComponent.is())
189 xComponent->dispose();
192 Reference<XComponent> xComponent (mxToolBarWindow, UNO_QUERY);
193 mxToolBarWindow = NULL;
194 if (xComponent.is())
195 xComponent->dispose();
198 // Dispose close button
200 Reference<XComponent> xComponent (static_cast<XWeak*>(mpCloseButton.get()), UNO_QUERY);
201 mpCloseButton = NULL;
202 if (xComponent.is())
203 xComponent->dispose();
206 // Create the tool bar.
208 mpScrollBar = NULL;
210 mxViewId = NULL;
216 void PresenterNotesView::CreateToolBar (
217 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
218 const ::rtl::Reference<PresenterController>& rpPresenterController)
220 if (rpPresenterController.get() == NULL)
221 return;
223 Reference<drawing::XPresenterHelper> xPresenterHelper (
224 rpPresenterController->GetPresenterHelper());
225 if ( ! xPresenterHelper.is())
226 return;
228 // Create a new window as container of the tool bar.
229 mxToolBarWindow = xPresenterHelper->createWindow(
230 mxParentWindow,
231 sal_False,
232 sal_True,
233 sal_False,
234 sal_False);
235 mxToolBarCanvas = xPresenterHelper->createSharedCanvas (
236 Reference<rendering::XSpriteCanvas>(mxCanvas, UNO_QUERY),
237 mxParentWindow,
238 mxCanvas,
239 mxParentWindow,
240 mxToolBarWindow);
242 // Create the tool bar.
243 mpToolBar = new PresenterToolBar(
244 rxContext,
245 mxToolBarWindow,
246 mxToolBarCanvas,
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);
279 if (xText.is())
281 sText += xText->getString();
284 else
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);
295 if (xText.is())
297 sText += xText->getString();
298 mpTextView->SetText(Reference<text::XText>(xText, UNO_QUERY));
305 Layout();
307 if (mpScrollBar.get() != NULL)
309 mpScrollBar->SetThumbPosition(0, false);
310 UpdateScrollBar();
313 Invalidate();
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)
337 (void)rEvent;
338 Layout();
344 void SAL_CALL PresenterNotesView::windowMoved (const awt::WindowEvent& rEvent)
345 throw (RuntimeException)
347 (void)rEvent;
353 void SAL_CALL PresenterNotesView::windowShown (const lang::EventObject& rEvent)
354 throw (RuntimeException)
356 (void)rEvent;
362 void SAL_CALL PresenterNotesView::windowHidden (const lang::EventObject& rEvent)
363 throw (RuntimeException)
365 (void)rEvent;
371 //----- XPaintListener --------------------------------------------------------
373 void SAL_CALL PresenterNotesView::windowPaint (const awt::PaintEvent& rEvent)
374 throw (RuntimeException)
376 ThrowIfDisposed();
378 if ( ! mbIsPresenterViewActive)
379 return;
381 ::osl::MutexGuard aSolarGuard (::osl::Mutex::getGlobalMutex());
382 Paint(rEvent.UpdateRect);
388 //----- XResourceId -----------------------------------------------------------
390 Reference<XResourceId> SAL_CALL PresenterNotesView::getResourceId (void)
391 throw (RuntimeException)
393 return mxViewId;
399 sal_Bool SAL_CALL PresenterNotesView::isAnchorOnly (void)
400 throw (RuntimeException)
402 return false;
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)
434 return NULL;
440 //----- XKeyListener ----------------------------------------------------------
442 void SAL_CALL PresenterNotesView::keyPressed (const awt::KeyEvent& rEvent)
443 throw (RuntimeException)
445 switch (rEvent.KeyCode)
447 case awt::Key::A:
448 Scroll(-gnLineScrollFactor * mpFont->mnSize);
449 break;
451 case awt::Key::Y:
452 case awt::Key::Z:
453 Scroll(+gnLineScrollFactor * mpFont->mnSize);
454 break;
456 case awt::Key::S:
457 ChangeFontSize(-1);
458 break;
460 case awt::Key::G:
461 ChangeFontSize(+1);
462 break;
464 case awt::Key::H:
465 if (mpTextView)
466 mpTextView->MoveCaret(
468 (rEvent.Modifiers == awt::KeyModifier::SHIFT)
469 ? cssa::AccessibleTextType::CHARACTER
470 : cssa::AccessibleTextType::WORD);
471 break;
473 case awt::Key::L:
474 if (mpTextView)
475 mpTextView->MoveCaret(
477 (rEvent.Modifiers == awt::KeyModifier::SHIFT)
478 ? cssa::AccessibleTextType::CHARACTER
479 : cssa::AccessibleTextType::WORD);
480 break;
487 void SAL_CALL PresenterNotesView::keyReleased (const awt::KeyEvent& rEvent)
488 throw (RuntimeException)
490 (void)rEvent;
496 //-----------------------------------------------------------------------------
498 void PresenterNotesView::Layout (void)
500 if ( ! mxParentWindow.is())
501 return;
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&)
543 OSL_ASSERT(false);
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);
556 UpdateScrollBar();
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));
571 mpTextView->SetSize(
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())
584 return;
585 if ( ! mxCanvas.is())
586 return;
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),
614 NULL);
615 rendering::RenderState aRenderState(
616 geometry::AffineMatrix2D(1,0,0, 0,1,0),
617 NULL,
618 Sequence<double>(4),
619 rendering::CompositeOperation::SOURCE);
621 if (mpBackground.get() != NULL)
623 // Paint the background.
624 mpPresenterController->GetCanvasHelper()->Paint(
625 mpBackground,
626 mxCanvas,
627 rUpdateBox,
628 awt::Rectangle(0,sal_Int32(maTextBoundingBox.Y2),aWindowBox.Width,aWindowBox.Height),
629 awt::Rectangle());
632 // Paint the horizontal separator.
633 OSL_ASSERT(mxViewId.is());
634 PresenterCanvasHelper::SetDeviceColor(aRenderState, maSeparatorColor);
636 mxCanvas->drawLine(
637 geometry::RealPoint2D(0,mnSeparatorYLocation),
638 geometry::RealPoint2D(aWindowBox.Width,mnSeparatorYLocation),
639 aViewState,
640 aRenderState);
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)
652 return;
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),
659 NULL,
660 Sequence<double>(3),
661 rendering::CompositeOperation::SOURCE);
663 if (mpBackground.get() != NULL)
665 // Paint the background.
666 mpPresenterController->GetCanvasHelper()->Paint(
667 mpBackground,
668 mxCanvas,
669 rUpdateBox,
670 aBox,
671 awt::Rectangle());
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(
685 mxParentWindow,
686 PresenterGeometryHelper::ConvertRectangle(maTextBoundingBox));
692 void PresenterNotesView::Scroll (const double rnDistance)
696 mnTop += rnDistance;
697 mpTextView->SetOffset(0, mnTop);
699 UpdateScrollBar();
700 Invalidate();
702 catch (beans::UnknownPropertyException&)
709 void PresenterNotesView::SetTop (const double nTop)
713 mnTop = nTop;
714 mpTextView->SetOffset(0, mnTop);
716 UpdateScrollBar();
717 Invalidate();
719 catch (beans::UnknownPropertyException&)
726 void PresenterNotesView::ChangeFontSize (const sal_Int32 nSizeChange)
728 const sal_Int32 nNewSize (mpFont->mnSize + nSizeChange);
729 if (nNewSize > 5)
731 mpFont->mnSize = nNewSize;
732 mpFont->mxFont = NULL;
733 mpTextView->SetFont(mpFont);
735 Layout();
736 UpdateScrollBar();
737 Invalidate();
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(
746 sStyleName,
747 PresenterConfigurationAccess::READ_WRITE));
748 if (pConfiguration.get()==NULL || ! pConfiguration->IsValid())
749 return;
751 pConfiguration->GoToChild(A2S("Font"));
752 pConfiguration->SetProperty(A2S("Size"), Any((sal_Int32)(nNewSize+0.5)));
753 pConfiguration->CommitChanges();
755 catch (Exception&)
757 OSL_ASSERT(false);
765 ::boost::shared_ptr<PresenterTextView> PresenterNotesView::GetTextView (void) const
767 return mpTextView;
773 void PresenterNotesView::UpdateScrollBar (void)
775 if (mpScrollBar.get() != NULL)
779 mpScrollBar->SetTotalSize(mpTextView->GetTotalTextHeight());
781 catch(beans::UnknownPropertyException&)
783 OSL_ASSERT(false);
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