/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the 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 #include #include #include #include #include #include #include #include #include #include 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::createFromAscii("com.sun.star.comp.Draw.PresenterPaneBorderManager"); } Sequence PresenterPaneBorderManager::getSupportedServiceNames_static (void) { static const ::rtl::OUString sServiceName( ::rtl::OUString::createFromAscii("com.sun.star.drawing.PresenterPaneBorderManager")); return Sequence(&sServiceName, 1); } Reference PresenterPaneBorderManager::Create (const Reference& rxContext) SAL_THROW((css::uno::Exception)) { return Reference(static_cast( new PresenterPaneBorderManager(rxContext, NULL))); } //===== PresenterPaneBorderManager ============================================ PresenterPaneBorderManager::PresenterPaneBorderManager ( const Reference& rxContext, const ::rtl::Reference& rpPresenterController) : PresenterPaneBorderManagerInterfaceBase(m_aMutex), mpPresenterController(rpPresenterController), mxComponentContext(rxContext), mxPresenterHelper(), maWindowList(), mnPointerType(), maDragAnchor(), meDragType(Outside), mxOuterDragWindow(), mxInnerDragWindow(), mxPointer() { Reference xFactory (rxContext->getServiceManager()); if (xFactory.is()) { mxPointer = Reference( xFactory->createInstanceWithContext( OUString::createFromAscii("com.sun.star.awt.Pointer"), rxContext), UNO_QUERY_THROW); mxPresenterHelper = Reference( xFactory->createInstanceWithContext( OUString::createFromAscii("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& rxOuterWindow, const Reference& 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& rArguments) throw (Exception, RuntimeException) { ThrowIfDisposed(); if (rArguments.getLength()%2 == 1 && mxComponentContext.is()) { try { mxParentWindow = Reference(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 xOuterWindow (rArguments[nIndex], UNO_QUERY_THROW); Reference 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::createFromAscii("PresenterPane: invalid number of arguments"), static_cast(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 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& rxWindow) { if (mxPresenterHelper.is()) mxPresenterHelper->captureMouse(rxWindow); } void PresenterPaneBorderManager::ReleaseMouse (const Reference& 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(this)); } } } } // end of namespace ::sd::presenter #endif // ENABLE_PANE_RESIZING