merge the formfield patch from ooo-build
[ooovba.git] / sdext / source / presenter / PresenterPaneBorderManager.cxx
blob066d2bbd01eb66deb5cc9e4dfa1ff5f1207fec26
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: PresenterPaneBorderManager.cxx,v $
11 * $Revision: 1.5 $
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 // The body of this file is only used when PresenterWindowManager defines
36 // the preprocessor symbol ENABLE_PANE_RESIZING, which by default is not the
37 // case.
38 #ifdef ENABLE_PANE_RESIZING
40 #include "PresenterPaneBorderManager.hxx"
41 #include "PresenterController.hxx"
42 #include "PresenterPaintManager.hxx"
43 #include <com/sun/star/awt/PosSize.hpp>
44 #include <com/sun/star/awt/SystemPointer.hpp>
45 #include <com/sun/star/awt/WindowAttribute.hpp>
46 #include <com/sun/star/awt/WindowDescriptor.hpp>
47 #include <com/sun/star/awt/WindowClass.hpp>
48 #include <com/sun/star/awt/XWindow2.hpp>
49 #include <com/sun/star/awt/XWindowPeer.hpp>
50 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
51 #include <cppuhelper/compbase1.hxx>
52 #include <osl/mutex.hxx>
53 #include <boost/weak_ptr.hpp>
55 using namespace ::com::sun::star;
56 using namespace ::com::sun::star::uno;
57 using ::rtl::OUString;
59 namespace sdext { namespace presenter {
61 //===== Service ===============================================================
64 OUString PresenterPaneBorderManager::getImplementationName_static (void)
66 return OUString::createFromAscii("com.sun.star.comp.Draw.PresenterPaneBorderManager");
72 Sequence<OUString> PresenterPaneBorderManager::getSupportedServiceNames_static (void)
74 static const ::rtl::OUString sServiceName(
75 ::rtl::OUString::createFromAscii("com.sun.star.drawing.PresenterPaneBorderManager"));
76 return Sequence<rtl::OUString>(&sServiceName, 1);
82 Reference<XInterface> PresenterPaneBorderManager::Create (const Reference<uno::XComponentContext>& rxContext)
83 SAL_THROW((css::uno::Exception))
85 return Reference<XInterface>(static_cast<XWeak*>(
86 new PresenterPaneBorderManager(rxContext, NULL)));
92 //===== PresenterPaneBorderManager ============================================
94 PresenterPaneBorderManager::PresenterPaneBorderManager (
95 const Reference<XComponentContext>& rxContext,
96 const ::rtl::Reference<PresenterController>& rpPresenterController)
97 : PresenterPaneBorderManagerInterfaceBase(m_aMutex),
98 mpPresenterController(rpPresenterController),
99 mxComponentContext(rxContext),
100 mxPresenterHelper(),
101 maWindowList(),
102 mnPointerType(),
103 maDragAnchor(),
104 meDragType(Outside),
105 mxOuterDragWindow(),
106 mxInnerDragWindow(),
107 mxPointer()
109 Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager());
110 if (xFactory.is())
112 mxPointer = Reference<awt::XPointer>(
113 xFactory->createInstanceWithContext(
114 OUString::createFromAscii("com.sun.star.awt.Pointer"),
115 rxContext),
116 UNO_QUERY_THROW);
118 mxPresenterHelper = Reference<drawing::XPresenterHelper>(
119 xFactory->createInstanceWithContext(
120 OUString::createFromAscii("com.sun.star.comp.Draw.PresenterHelper"),
121 rxContext),
122 UNO_QUERY_THROW);
129 PresenterPaneBorderManager::~PresenterPaneBorderManager (void)
136 void PresenterPaneBorderManager::disposing (void)
138 WindowList::const_iterator iDescriptor;
139 for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
141 iDescriptor->first->removeMouseListener(this);
142 iDescriptor->first->removeMouseMotionListener(this);
144 maWindowList.clear();
150 namespace {
151 const static sal_Int32 mnOutside = 0;
152 const static sal_Int32 mnLeft = 0x01;
153 const static sal_Int32 mnHorizontalCenter = 0x02;
154 const static sal_Int32 mnRight = 0x04;
155 const static sal_Int32 mnTop = 0x10;
156 const static sal_Int32 mnVerticalCenter = 0x20;
157 const static sal_Int32 mnBottom = 0x40;
160 PresenterPaneBorderManager::BorderElement
161 PresenterPaneBorderManager::ClassifyBorderElementUnderMouse (
162 const Reference<awt::XWindow>& rxOuterWindow,
163 const Reference<awt::XWindow>& rxInnerWindow,
164 const awt::Point aPosition) const
166 OSL_ASSERT(rxOuterWindow.is());
167 OSL_ASSERT(rxInnerWindow.is());
169 awt::Rectangle aOuterBox (rxOuterWindow->getPosSize());
170 const awt::Rectangle aInnerBox (rxInnerWindow->getPosSize());
172 // Coordinates of the pointer position are given in the window
173 // coordinate system. Therefore the upper left corner of the outer box
174 // is the origin.
175 aOuterBox.X = 0;
176 aOuterBox.Y = 0;
178 sal_Int32 nCode = 0;
180 // Add horizontal classification to nCode.
181 if (aPosition.X < aInnerBox.X)
182 if (aPosition.X < aOuterBox.X)
183 nCode = mnOutside;
184 else
185 nCode = mnLeft;
186 else if (aPosition.X >= aInnerBox.X+aInnerBox.Width)
187 if (aPosition.X >= aOuterBox.X+aOuterBox.Width)
188 nCode = mnOutside;
189 else
190 nCode = mnRight;
191 else
192 nCode = mnHorizontalCenter;
194 // Add vertical classification to nCode.
195 if (aPosition.Y < aInnerBox.Y)
196 if (aPosition.Y < aOuterBox.Y)
197 nCode |= mnOutside;
198 else
199 nCode |= mnTop;
200 else if (aPosition.Y >= aInnerBox.Y+aInnerBox.Height)
201 if (aPosition.Y >= aOuterBox.Y+aOuterBox.Height)
202 nCode |= mnOutside;
203 else
204 nCode |= mnBottom;
205 else
206 nCode |= mnVerticalCenter;
208 // Translate bits in nCode into BorderElement value.
209 switch (nCode)
211 case mnOutside | mnOutside:
212 case mnOutside | mnLeft:
213 case mnOutside | mnRight:
214 case mnOutside | mnHorizontalCenter:
215 case mnTop | mnOutside:
216 case mnBottom | mnOutside:
217 case mnVerticalCenter | mnOutside:
218 default:
219 return Outside;
221 case mnVerticalCenter | mnHorizontalCenter:
222 return Content;
224 case mnTop | mnLeft:
225 return TopLeft;
227 case mnTop | mnRight:
228 return TopRight;
230 case mnTop | mnHorizontalCenter:
231 return Top;
233 case mnBottom | mnLeft:
234 return BottomLeft;
236 case mnBottom | mnRight:
237 return BottomRight;
239 case mnBottom | mnHorizontalCenter:
240 return Bottom;
242 case mnVerticalCenter | mnLeft:
243 return Left;
245 case mnVerticalCenter | mnRight:
246 return Right;
253 //----- XInitialization -------------------------------------------------------
255 void SAL_CALL PresenterPaneBorderManager::initialize (const Sequence<Any>& rArguments)
256 throw (Exception, RuntimeException)
258 ThrowIfDisposed();
260 if (rArguments.getLength()%2 == 1 && mxComponentContext.is())
264 mxParentWindow = Reference<awt::XWindow>(rArguments[0], UNO_QUERY_THROW);
266 // Get the outer and inner windows from the argument list and
267 // build a window list of it.
268 for (sal_Int32 nIndex=1; nIndex<rArguments.getLength(); nIndex+=2)
270 Reference<awt::XWindow> xOuterWindow (rArguments[nIndex], UNO_QUERY_THROW);
271 Reference<awt::XWindow> xInnerWindow (rArguments[nIndex+1], UNO_QUERY_THROW);
273 maWindowList.push_back(WindowDescriptor(xOuterWindow,xInnerWindow));
275 xOuterWindow->addMouseListener(this);
276 xOuterWindow->addMouseMotionListener(this);
279 catch (RuntimeException&)
281 PresenterPaneBorderManager::disposing();
282 throw;
285 else
287 throw RuntimeException(
288 OUString::createFromAscii("PresenterPane: invalid number of arguments"),
289 static_cast<XWeak*>(this));
296 //----- XMouseListener --------------------------------------------------------
298 void SAL_CALL PresenterPaneBorderManager::mousePressed (const css::awt::MouseEvent& rEvent)
299 throw (css::uno::RuntimeException)
301 ThrowIfDisposed();
302 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
304 // Find window descriptor of the window that has been clicked.
305 WindowList::const_iterator iDescriptor;
306 for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
307 if (iDescriptor->first == rEvent.Source)
308 break;
310 if (iDescriptor != maWindowList.end())
312 // Prepare dragging.
313 mxOuterDragWindow = iDescriptor->first;
314 mxInnerDragWindow = iDescriptor->second;
315 OSL_ASSERT(mxOuterDragWindow.is() && mxInnerDragWindow.is());
316 const awt::Rectangle aOuterBox (mxOuterDragWindow->getPosSize());
317 maDragAnchor.X = rEvent.X + aOuterBox.X;
318 maDragAnchor.Y = rEvent.Y + aOuterBox.Y;
319 meDragType = ClassifyBorderElementUnderMouse(
320 mxOuterDragWindow,
321 mxInnerDragWindow,
322 awt::Point(rEvent.X, rEvent.Y));
329 void SAL_CALL PresenterPaneBorderManager::mouseReleased (const css::awt::MouseEvent& rEvent)
330 throw (css::uno::RuntimeException)
332 (void)rEvent;
333 ThrowIfDisposed();
334 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
336 ReleaseMouse(mxOuterDragWindow);
337 meDragType = PresenterPaneBorderManager::Outside;
338 mxOuterDragWindow = NULL;
339 mxInnerDragWindow = NULL;
345 void SAL_CALL PresenterPaneBorderManager::mouseEntered (const css::awt::MouseEvent& rEvent)
346 throw (css::uno::RuntimeException)
348 (void)rEvent;
354 void SAL_CALL PresenterPaneBorderManager::mouseExited (const css::awt::MouseEvent& rEvent)
355 throw (css::uno::RuntimeException)
357 (void)rEvent;
358 ThrowIfDisposed();
359 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
361 ReleaseMouse(mxOuterDragWindow);
362 meDragType = PresenterPaneBorderManager::Outside;
363 mxOuterDragWindow = NULL;
364 mxInnerDragWindow = NULL;
370 //----- XMouseMotionListener --------------------------------------------------
372 void SAL_CALL PresenterPaneBorderManager::mouseMoved (const css::awt::MouseEvent& rEvent)
373 throw (css::uno::RuntimeException)
375 ThrowIfDisposed();
376 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
378 WindowList::const_iterator iDescriptor;
379 for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
380 if (iDescriptor->first == rEvent.Source)
381 break;
382 if (iDescriptor != maWindowList.end())
384 // Choose pointer shape according to position in the window border.
385 switch (ClassifyBorderElementUnderMouse(
386 iDescriptor->first,
387 iDescriptor->second,
388 awt::Point(rEvent.X,rEvent.Y)))
390 case PresenterPaneBorderManager::Top:
391 mnPointerType = awt::SystemPointer::MOVE;
392 break;
393 case PresenterPaneBorderManager::TopLeft:
394 mnPointerType = awt::SystemPointer::WINDOW_NWSIZE;
395 break;
396 case PresenterPaneBorderManager::TopRight:
397 mnPointerType = awt::SystemPointer::WINDOW_NESIZE;
398 break;
399 case PresenterPaneBorderManager::Left:
400 mnPointerType = awt::SystemPointer::WINDOW_WSIZE;
401 break;
402 case PresenterPaneBorderManager::Right:
403 mnPointerType = awt::SystemPointer::WINDOW_ESIZE;
404 break;
405 case PresenterPaneBorderManager::BottomLeft:
406 mnPointerType = awt::SystemPointer::WINDOW_SWSIZE;
407 break;
408 case PresenterPaneBorderManager::BottomRight:
409 mnPointerType = awt::SystemPointer::WINDOW_SESIZE;
410 break;
411 case PresenterPaneBorderManager::Bottom:
412 mnPointerType = awt::SystemPointer::WINDOW_SSIZE;
413 break;
415 case PresenterPaneBorderManager::Content:
416 case PresenterPaneBorderManager::Outside:
417 default:
418 mnPointerType = awt::SystemPointer::ARROW;
419 break;
422 // Make the pointer shape visible.
423 Reference<awt::XWindowPeer> xPeer (iDescriptor->first, UNO_QUERY);
424 if (xPeer.is())
426 if (mxPointer.is())
427 mxPointer->setType(mnPointerType);
428 xPeer->setPointer(mxPointer);
436 void SAL_CALL PresenterPaneBorderManager::mouseDragged (const css::awt::MouseEvent& rEvent)
437 throw (css::uno::RuntimeException)
439 ThrowIfDisposed();
440 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
442 if ( ! mxOuterDragWindow.is())
443 return;
445 CaptureMouse(mxOuterDragWindow);
447 const awt::Rectangle aOldBox (mxOuterDragWindow->getPosSize());
448 const sal_Int32 nX = rEvent.X + aOldBox.X;
449 const sal_Int32 nY = rEvent.Y + aOldBox.Y;
450 const sal_Int32 nDiffX = nX - maDragAnchor.X;
451 const sal_Int32 nDiffY = nY - maDragAnchor.Y;
452 maDragAnchor.X = nX;
453 maDragAnchor.Y = nY;
455 const sal_Int32 nOldRight = aOldBox.X + aOldBox.Width;
456 const sal_Int32 nOldBottom = aOldBox.Y + aOldBox.Height;
458 awt::Rectangle aBox (aOldBox);
459 sal_Int32 nRight = aBox.X + aBox.Width;
460 sal_Int32 nBottom = aBox.Y + aBox.Height;
462 // Update position and/or size according to initial pointer position
463 // inside the window border.
464 switch (meDragType)
466 case PresenterPaneBorderManager::Top:
467 aBox.X += nDiffX; aBox.Y += nDiffY;
468 nRight += nDiffX; nBottom += nDiffY;
469 break;
470 case PresenterPaneBorderManager::TopLeft:
471 aBox.X += nDiffX; aBox.Y += nDiffY;
472 break;
473 case PresenterPaneBorderManager::TopRight:
474 nRight += nDiffX; aBox.Y += nDiffY;
475 break;
476 case PresenterPaneBorderManager::Left:
477 aBox.X += nDiffX;
478 break;
479 case PresenterPaneBorderManager::Right:
480 nRight += nDiffX;
481 break;
482 case PresenterPaneBorderManager::BottomLeft:
483 aBox.X += nDiffX; nBottom += nDiffY;
484 break;
485 case PresenterPaneBorderManager::BottomRight:
486 nRight += nDiffX; nBottom += nDiffY;
487 break;
488 case PresenterPaneBorderManager::Bottom:
489 nBottom += nDiffY;
490 break;
491 default: break;
494 aBox.Width = nRight - aBox.X;
495 aBox.Height = nBottom - aBox.Y;
496 if (aBox.Width > 20
497 && aBox.Height > 20)
499 // Set position and/or size of the border window to the new values.
500 sal_Int16 nFlags (0);
501 if (aBox.X != aOldBox.X)
502 nFlags |= awt::PosSize::X;
503 if (aBox.Y != aOldBox.Y)
504 nFlags |= awt::PosSize::Y;
505 if (aBox.Width != aOldBox.Width)
506 nFlags |= awt::PosSize::WIDTH;
507 if (aBox.Height != aOldBox.Height)
508 nFlags |= awt::PosSize::HEIGHT;
509 mxOuterDragWindow->setPosSize(aBox.X, aBox.Y, aBox.Width, aBox.Height, nFlags);
511 // Invalidate that is or was covered by the border window before and
512 // after the move/resize.
513 if (mpPresenterController.get() != NULL)
515 const sal_Int32 nLeft = ::std::min(aOldBox.X,aBox.X);
516 const sal_Int32 nTop = ::std::min(aOldBox.Y,aBox.Y);
517 const sal_Int32 nWidth = ::std::max(nOldRight,nRight) - nLeft;
518 const sal_Int32 nHeight = ::std::max(nOldBottom,nBottom) - nTop;
520 OSL_ASSERT(mpPresenterController->GetPaintManager().get()!=NULL);
521 mpPresenterController->GetPaintManager()->Invalidate(
522 mxParentWindow,
523 ::awt::Rectangle(nLeft,nTop,nWidth-1,nHeight-1));
531 //----- lang::XEventListener --------------------------------------------------
533 void SAL_CALL PresenterPaneBorderManager::disposing (const lang::EventObject& rEvent)
534 throw (RuntimeException)
536 WindowList::iterator iDescriptor;
537 for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
538 if (iDescriptor->first == rEvent.Source)
540 maWindowList.erase(iDescriptor);
541 break;
548 //-----------------------------------------------------------------------------
551 void PresenterPaneBorderManager::CaptureMouse (const Reference<awt::XWindow>& rxWindow)
553 if (mxPresenterHelper.is())
554 mxPresenterHelper->captureMouse(rxWindow);
560 void PresenterPaneBorderManager::ReleaseMouse (const Reference<awt::XWindow>& rxWindow)
562 if (mxPresenterHelper.is())
563 mxPresenterHelper->releaseMouse(rxWindow);
569 void PresenterPaneBorderManager::ThrowIfDisposed (void)
570 throw (::com::sun::star::lang::DisposedException)
572 if (rBHelper.bDisposed || rBHelper.bInDispose)
574 throw lang::DisposedException (
575 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
576 "PresenterPaneBorderManager object has already been disposed")),
577 static_cast<uno::XWeak*>(this));
584 } } // end of namespace ::sd::presenter
586 #endif // ENABLE_PANE_RESIZING