summaryrefslogtreecommitdiff
path: root/sdext/source/presenter/PresenterPaneBorderManager.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sdext/source/presenter/PresenterPaneBorderManager.cxx')
-rw-r--r--sdext/source/presenter/PresenterPaneBorderManager.cxx585
1 files changed, 585 insertions, 0 deletions
diff --git a/sdext/source/presenter/PresenterPaneBorderManager.cxx b/sdext/source/presenter/PresenterPaneBorderManager.cxx
new file mode 100644
index 000000000000..6150d0ce8914
--- /dev/null
+++ b/sdext/source/presenter/PresenterPaneBorderManager.cxx
@@ -0,0 +1,585 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sdext.hxx"
+
+// The body of this file is only used when PresenterWindowManager defines
+// the preprocessor symbol ENABLE_PANE_RESIZING, which by default is not the
+// case.
+#ifdef ENABLE_PANE_RESIZING
+
+#include "PresenterPaneBorderManager.hxx"
+#include "PresenterController.hxx"
+#include "PresenterPaintManager.hxx"
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/awt/SystemPointer.hpp>
+#include <com/sun/star/awt/WindowAttribute.hpp>
+#include <com/sun/star/awt/WindowDescriptor.hpp>
+#include <com/sun/star/awt/WindowClass.hpp>
+#include <com/sun/star/awt/XWindow2.hpp>
+#include <com/sun/star/awt/XWindowPeer.hpp>
+#include <com/sun/star/lang/XMultiComponentFactory.hpp>
+#include <cppuhelper/compbase1.hxx>
+#include <osl/mutex.hxx>
+#include <boost/weak_ptr.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using ::rtl::OUString;
+
+namespace sdext { namespace presenter {
+
+//===== Service ===============================================================
+
+
+OUString PresenterPaneBorderManager::getImplementationName_static (void)
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.PresenterPaneBorderManager"));
+}
+
+
+
+
+Sequence<OUString> PresenterPaneBorderManager::getSupportedServiceNames_static (void)
+{
+ static const ::rtl::OUString sServiceName(
+ RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.PresenterPaneBorderManager"));
+ return Sequence<rtl::OUString>(&sServiceName, 1);
+}
+
+
+
+
+Reference<XInterface> PresenterPaneBorderManager::Create (const Reference<uno::XComponentContext>& rxContext)
+ SAL_THROW((css::uno::Exception))
+{
+ return Reference<XInterface>(static_cast<XWeak*>(
+ new PresenterPaneBorderManager(rxContext, NULL)));
+}
+
+
+
+
+//===== PresenterPaneBorderManager ============================================
+
+PresenterPaneBorderManager::PresenterPaneBorderManager (
+ const Reference<XComponentContext>& rxContext,
+ const ::rtl::Reference<PresenterController>& rpPresenterController)
+ : PresenterPaneBorderManagerInterfaceBase(m_aMutex),
+ mpPresenterController(rpPresenterController),
+ mxComponentContext(rxContext),
+ mxPresenterHelper(),
+ maWindowList(),
+ mnPointerType(),
+ maDragAnchor(),
+ meDragType(Outside),
+ mxOuterDragWindow(),
+ mxInnerDragWindow(),
+ mxPointer()
+{
+ Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager());
+ if (xFactory.is())
+ {
+ mxPointer = Reference<awt::XPointer>(
+ xFactory->createInstanceWithContext(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.Pointer")),
+ rxContext),
+ UNO_QUERY_THROW);
+
+ mxPresenterHelper = Reference<drawing::XPresenterHelper>(
+ xFactory->createInstanceWithContext(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.PresenterHelper")),
+ rxContext),
+ UNO_QUERY_THROW);
+ }
+}
+
+
+
+
+PresenterPaneBorderManager::~PresenterPaneBorderManager (void)
+{
+}
+
+
+
+
+void PresenterPaneBorderManager::disposing (void)
+{
+ WindowList::const_iterator iDescriptor;
+ for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
+ {
+ iDescriptor->first->removeMouseListener(this);
+ iDescriptor->first->removeMouseMotionListener(this);
+ }
+ maWindowList.clear();
+}
+
+
+
+
+namespace {
+const static sal_Int32 mnOutside = 0;
+const static sal_Int32 mnLeft = 0x01;
+const static sal_Int32 mnHorizontalCenter = 0x02;
+const static sal_Int32 mnRight = 0x04;
+const static sal_Int32 mnTop = 0x10;
+const static sal_Int32 mnVerticalCenter = 0x20;
+const static sal_Int32 mnBottom = 0x40;
+}
+
+PresenterPaneBorderManager::BorderElement
+ PresenterPaneBorderManager::ClassifyBorderElementUnderMouse (
+ const Reference<awt::XWindow>& rxOuterWindow,
+ const Reference<awt::XWindow>& rxInnerWindow,
+ const awt::Point aPosition) const
+{
+ OSL_ASSERT(rxOuterWindow.is());
+ OSL_ASSERT(rxInnerWindow.is());
+
+ awt::Rectangle aOuterBox (rxOuterWindow->getPosSize());
+ const awt::Rectangle aInnerBox (rxInnerWindow->getPosSize());
+
+ // Coordinates of the pointer position are given in the window
+ // coordinate system. Therefore the upper left corner of the outer box
+ // is the origin.
+ aOuterBox.X = 0;
+ aOuterBox.Y = 0;
+
+ sal_Int32 nCode = 0;
+
+ // Add horizontal classification to nCode.
+ if (aPosition.X < aInnerBox.X)
+ if (aPosition.X < aOuterBox.X)
+ nCode = mnOutside;
+ else
+ nCode = mnLeft;
+ else if (aPosition.X >= aInnerBox.X+aInnerBox.Width)
+ if (aPosition.X >= aOuterBox.X+aOuterBox.Width)
+ nCode = mnOutside;
+ else
+ nCode = mnRight;
+ else
+ nCode = mnHorizontalCenter;
+
+ // Add vertical classification to nCode.
+ if (aPosition.Y < aInnerBox.Y)
+ if (aPosition.Y < aOuterBox.Y)
+ nCode |= mnOutside;
+ else
+ nCode |= mnTop;
+ else if (aPosition.Y >= aInnerBox.Y+aInnerBox.Height)
+ if (aPosition.Y >= aOuterBox.Y+aOuterBox.Height)
+ nCode |= mnOutside;
+ else
+ nCode |= mnBottom;
+ else
+ nCode |= mnVerticalCenter;
+
+ // Translate bits in nCode into BorderElement value.
+ switch (nCode)
+ {
+ case mnOutside | mnOutside:
+ case mnOutside | mnLeft:
+ case mnOutside | mnRight:
+ case mnOutside | mnHorizontalCenter:
+ case mnTop | mnOutside:
+ case mnBottom | mnOutside:
+ case mnVerticalCenter | mnOutside:
+ default:
+ return Outside;
+
+ case mnVerticalCenter | mnHorizontalCenter:
+ return Content;
+
+ case mnTop | mnLeft:
+ return TopLeft;
+
+ case mnTop | mnRight:
+ return TopRight;
+
+ case mnTop | mnHorizontalCenter:
+ return Top;
+
+ case mnBottom | mnLeft:
+ return BottomLeft;
+
+ case mnBottom | mnRight:
+ return BottomRight;
+
+ case mnBottom | mnHorizontalCenter:
+ return Bottom;
+
+ case mnVerticalCenter | mnLeft:
+ return Left;
+
+ case mnVerticalCenter | mnRight:
+ return Right;
+ }
+}
+
+
+
+
+//----- XInitialization -------------------------------------------------------
+
+void SAL_CALL PresenterPaneBorderManager::initialize (const Sequence<Any>& rArguments)
+ throw (Exception, RuntimeException)
+{
+ ThrowIfDisposed();
+
+ if (rArguments.getLength()%2 == 1 && mxComponentContext.is())
+ {
+ try
+ {
+ mxParentWindow = Reference<awt::XWindow>(rArguments[0], UNO_QUERY_THROW);
+
+ // Get the outer and inner windows from the argument list and
+ // build a window list of it.
+ for (sal_Int32 nIndex=1; nIndex<rArguments.getLength(); nIndex+=2)
+ {
+ Reference<awt::XWindow> xOuterWindow (rArguments[nIndex], UNO_QUERY_THROW);
+ Reference<awt::XWindow> xInnerWindow (rArguments[nIndex+1], UNO_QUERY_THROW);
+
+ maWindowList.push_back(WindowDescriptor(xOuterWindow,xInnerWindow));
+
+ xOuterWindow->addMouseListener(this);
+ xOuterWindow->addMouseMotionListener(this);
+ }
+ }
+ catch (RuntimeException&)
+ {
+ PresenterPaneBorderManager::disposing();
+ throw;
+ }
+ }
+ else
+ {
+ throw RuntimeException(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("PresenterPane: invalid number of arguments")),
+ static_cast<XWeak*>(this));
+ }
+}
+
+
+
+
+//----- XMouseListener --------------------------------------------------------
+
+void SAL_CALL PresenterPaneBorderManager::mousePressed (const css::awt::MouseEvent& rEvent)
+ throw (css::uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
+
+ // Find window descriptor of the window that has been clicked.
+ WindowList::const_iterator iDescriptor;
+ for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
+ if (iDescriptor->first == rEvent.Source)
+ break;
+
+ if (iDescriptor != maWindowList.end())
+ {
+ // Prepare dragging.
+ mxOuterDragWindow = iDescriptor->first;
+ mxInnerDragWindow = iDescriptor->second;
+ OSL_ASSERT(mxOuterDragWindow.is() && mxInnerDragWindow.is());
+ const awt::Rectangle aOuterBox (mxOuterDragWindow->getPosSize());
+ maDragAnchor.X = rEvent.X + aOuterBox.X;
+ maDragAnchor.Y = rEvent.Y + aOuterBox.Y;
+ meDragType = ClassifyBorderElementUnderMouse(
+ mxOuterDragWindow,
+ mxInnerDragWindow,
+ awt::Point(rEvent.X, rEvent.Y));
+ }
+}
+
+
+
+
+void SAL_CALL PresenterPaneBorderManager::mouseReleased (const css::awt::MouseEvent& rEvent)
+ throw (css::uno::RuntimeException)
+{
+ (void)rEvent;
+ ThrowIfDisposed();
+ ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
+
+ ReleaseMouse(mxOuterDragWindow);
+ meDragType = PresenterPaneBorderManager::Outside;
+ mxOuterDragWindow = NULL;
+ mxInnerDragWindow = NULL;
+}
+
+
+
+
+void SAL_CALL PresenterPaneBorderManager::mouseEntered (const css::awt::MouseEvent& rEvent)
+ throw (css::uno::RuntimeException)
+{
+ (void)rEvent;
+}
+
+
+
+
+void SAL_CALL PresenterPaneBorderManager::mouseExited (const css::awt::MouseEvent& rEvent)
+ throw (css::uno::RuntimeException)
+{
+ (void)rEvent;
+ ThrowIfDisposed();
+ ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
+
+ ReleaseMouse(mxOuterDragWindow);
+ meDragType = PresenterPaneBorderManager::Outside;
+ mxOuterDragWindow = NULL;
+ mxInnerDragWindow = NULL;
+}
+
+
+
+
+//----- XMouseMotionListener --------------------------------------------------
+
+void SAL_CALL PresenterPaneBorderManager::mouseMoved (const css::awt::MouseEvent& rEvent)
+ throw (css::uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
+
+ WindowList::const_iterator iDescriptor;
+ for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
+ if (iDescriptor->first == rEvent.Source)
+ break;
+ if (iDescriptor != maWindowList.end())
+ {
+ // Choose pointer shape according to position in the window border.
+ switch (ClassifyBorderElementUnderMouse(
+ iDescriptor->first,
+ iDescriptor->second,
+ awt::Point(rEvent.X,rEvent.Y)))
+ {
+ case PresenterPaneBorderManager::Top:
+ mnPointerType = awt::SystemPointer::MOVE;
+ break;
+ case PresenterPaneBorderManager::TopLeft:
+ mnPointerType = awt::SystemPointer::WINDOW_NWSIZE;
+ break;
+ case PresenterPaneBorderManager::TopRight:
+ mnPointerType = awt::SystemPointer::WINDOW_NESIZE;
+ break;
+ case PresenterPaneBorderManager::Left:
+ mnPointerType = awt::SystemPointer::WINDOW_WSIZE;
+ break;
+ case PresenterPaneBorderManager::Right:
+ mnPointerType = awt::SystemPointer::WINDOW_ESIZE;
+ break;
+ case PresenterPaneBorderManager::BottomLeft:
+ mnPointerType = awt::SystemPointer::WINDOW_SWSIZE;
+ break;
+ case PresenterPaneBorderManager::BottomRight:
+ mnPointerType = awt::SystemPointer::WINDOW_SESIZE;
+ break;
+ case PresenterPaneBorderManager::Bottom:
+ mnPointerType = awt::SystemPointer::WINDOW_SSIZE;
+ break;
+
+ case PresenterPaneBorderManager::Content:
+ case PresenterPaneBorderManager::Outside:
+ default:
+ mnPointerType = awt::SystemPointer::ARROW;
+ break;
+ }
+
+ // Make the pointer shape visible.
+ Reference<awt::XWindowPeer> xPeer (iDescriptor->first, UNO_QUERY);
+ if (xPeer.is())
+ {
+ if (mxPointer.is())
+ mxPointer->setType(mnPointerType);
+ xPeer->setPointer(mxPointer);
+ }
+ }
+}
+
+
+
+
+void SAL_CALL PresenterPaneBorderManager::mouseDragged (const css::awt::MouseEvent& rEvent)
+ throw (css::uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
+
+ if ( ! mxOuterDragWindow.is())
+ return;
+
+ CaptureMouse(mxOuterDragWindow);
+
+ const awt::Rectangle aOldBox (mxOuterDragWindow->getPosSize());
+ const sal_Int32 nX = rEvent.X + aOldBox.X;
+ const sal_Int32 nY = rEvent.Y + aOldBox.Y;
+ const sal_Int32 nDiffX = nX - maDragAnchor.X;
+ const sal_Int32 nDiffY = nY - maDragAnchor.Y;
+ maDragAnchor.X = nX;
+ maDragAnchor.Y = nY;
+
+ const sal_Int32 nOldRight = aOldBox.X + aOldBox.Width;
+ const sal_Int32 nOldBottom = aOldBox.Y + aOldBox.Height;
+
+ awt::Rectangle aBox (aOldBox);
+ sal_Int32 nRight = aBox.X + aBox.Width;
+ sal_Int32 nBottom = aBox.Y + aBox.Height;
+
+ // Update position and/or size according to initial pointer position
+ // inside the window border.
+ switch (meDragType)
+ {
+ case PresenterPaneBorderManager::Top:
+ aBox.X += nDiffX; aBox.Y += nDiffY;
+ nRight += nDiffX; nBottom += nDiffY;
+ break;
+ case PresenterPaneBorderManager::TopLeft:
+ aBox.X += nDiffX; aBox.Y += nDiffY;
+ break;
+ case PresenterPaneBorderManager::TopRight:
+ nRight += nDiffX; aBox.Y += nDiffY;
+ break;
+ case PresenterPaneBorderManager::Left:
+ aBox.X += nDiffX;
+ break;
+ case PresenterPaneBorderManager::Right:
+ nRight += nDiffX;
+ break;
+ case PresenterPaneBorderManager::BottomLeft:
+ aBox.X += nDiffX; nBottom += nDiffY;
+ break;
+ case PresenterPaneBorderManager::BottomRight:
+ nRight += nDiffX; nBottom += nDiffY;
+ break;
+ case PresenterPaneBorderManager::Bottom:
+ nBottom += nDiffY;
+ break;
+ default: break;
+ }
+
+ aBox.Width = nRight - aBox.X;
+ aBox.Height = nBottom - aBox.Y;
+ if (aBox.Width > 20
+ && aBox.Height > 20)
+ {
+ // Set position and/or size of the border window to the new values.
+ sal_Int16 nFlags (0);
+ if (aBox.X != aOldBox.X)
+ nFlags |= awt::PosSize::X;
+ if (aBox.Y != aOldBox.Y)
+ nFlags |= awt::PosSize::Y;
+ if (aBox.Width != aOldBox.Width)
+ nFlags |= awt::PosSize::WIDTH;
+ if (aBox.Height != aOldBox.Height)
+ nFlags |= awt::PosSize::HEIGHT;
+ mxOuterDragWindow->setPosSize(aBox.X, aBox.Y, aBox.Width, aBox.Height, nFlags);
+
+ // Invalidate that is or was covered by the border window before and
+ // after the move/resize.
+ if (mpPresenterController.get() != NULL)
+ {
+ const sal_Int32 nLeft = ::std::min(aOldBox.X,aBox.X);
+ const sal_Int32 nTop = ::std::min(aOldBox.Y,aBox.Y);
+ const sal_Int32 nWidth = ::std::max(nOldRight,nRight) - nLeft;
+ const sal_Int32 nHeight = ::std::max(nOldBottom,nBottom) - nTop;
+
+ OSL_ASSERT(mpPresenterController->GetPaintManager().get()!=NULL);
+ mpPresenterController->GetPaintManager()->Invalidate(
+ mxParentWindow,
+ ::awt::Rectangle(nLeft,nTop,nWidth-1,nHeight-1));
+ }
+ }
+}
+
+
+
+
+//----- lang::XEventListener --------------------------------------------------
+
+void SAL_CALL PresenterPaneBorderManager::disposing (const lang::EventObject& rEvent)
+ throw (RuntimeException)
+{
+ WindowList::iterator iDescriptor;
+ for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
+ if (iDescriptor->first == rEvent.Source)
+ {
+ maWindowList.erase(iDescriptor);
+ break;
+ }
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+
+
+void PresenterPaneBorderManager::CaptureMouse (const Reference<awt::XWindow>& rxWindow)
+{
+ if (mxPresenterHelper.is())
+ mxPresenterHelper->captureMouse(rxWindow);
+}
+
+
+
+
+void PresenterPaneBorderManager::ReleaseMouse (const Reference<awt::XWindow>& rxWindow)
+{
+ if (mxPresenterHelper.is())
+ mxPresenterHelper->releaseMouse(rxWindow);
+}
+
+
+
+
+void PresenterPaneBorderManager::ThrowIfDisposed (void)
+ throw (::com::sun::star::lang::DisposedException)
+{
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ {
+ throw lang::DisposedException (
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "PresenterPaneBorderManager object has already been disposed")),
+ static_cast<uno::XWeak*>(this));
+ }
+}
+
+
+
+
+} } // end of namespace ::sd::presenter
+
+#endif // ENABLE_PANE_RESIZING
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */