Bump version to 5.0-14
[LibreOffice.git] / sdext / source / presenter / PresenterPaneBorderManager.cxx
blobb5a09797f2788828a4fd0e99b4b544c1f2edf86a
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 .
20 // The body of this file is only used when PresenterWindowManager defines
21 // the preprocessor symbol ENABLE_PANE_RESIZING, which by default is not the
22 // case.
23 #ifdef ENABLE_PANE_RESIZING
25 #include "PresenterPaneBorderManager.hxx"
26 #include "PresenterController.hxx"
27 #include "PresenterPaintManager.hxx"
28 #include <com/sun/star/awt/PosSize.hpp>
29 #include <com/sun/star/awt/SystemPointer.hpp>
30 #include <com/sun/star/awt/WindowAttribute.hpp>
31 #include <com/sun/star/awt/WindowDescriptor.hpp>
32 #include <com/sun/star/awt/WindowClass.hpp>
33 #include <com/sun/star/awt/XWindow2.hpp>
34 #include <com/sun/star/awt/XWindowPeer.hpp>
35 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
36 #include <cppuhelper/compbase1.hxx>
37 #include <osl/mutex.hxx>
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::uno;
42 namespace sdext { namespace presenter {
44 //===== Service ===============================================================
46 OUString PresenterPaneBorderManager::getImplementationName_static()
48 return OUString("com.sun.star.comp.Draw.PresenterPaneBorderManager");
51 Sequence<OUString> PresenterPaneBorderManager::getSupportedServiceNames_static()
53 static const OUString sServiceName(
54 "com.sun.star.drawing.PresenterPaneBorderManager");
55 return Sequence<OUString>(&sServiceName, 1);
58 Reference<XInterface> PresenterPaneBorderManager::Create (const Reference<uno::XComponentContext>& rxContext)
60 return Reference<XInterface>(static_cast<XWeak*>(
61 new PresenterPaneBorderManager(rxContext, NULL)));
64 //===== PresenterPaneBorderManager ============================================
66 PresenterPaneBorderManager::PresenterPaneBorderManager (
67 const Reference<XComponentContext>& rxContext,
68 const ::rtl::Reference<PresenterController>& rpPresenterController)
69 : PresenterPaneBorderManagerInterfaceBase(m_aMutex),
70 mpPresenterController(rpPresenterController),
71 mxComponentContext(rxContext),
72 mxPresenterHelper(),
73 maWindowList(),
74 mnPointerType(),
75 maDragAnchor(),
76 meDragType(Outside),
77 mxOuterDragWindow(),
78 mxInnerDragWindow(),
79 mxPointer()
81 Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager());
82 if (xFactory.is())
84 mxPointer = awt::Pointer::create(rxContext);
86 mxPresenterHelper = Reference<drawing::XPresenterHelper>(
87 xFactory->createInstanceWithContext(
88 OUString("com.sun.star.comp.Draw.PresenterHelper"),
89 rxContext),
90 UNO_QUERY_THROW);
94 PresenterPaneBorderManager::~PresenterPaneBorderManager()
98 void PresenterPaneBorderManager::disposing()
100 WindowList::const_iterator iDescriptor;
101 for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
103 iDescriptor->first->removeMouseListener(this);
104 iDescriptor->first->removeMouseMotionListener(this);
106 maWindowList.clear();
109 namespace {
110 const static sal_Int32 mnOutside = 0;
111 const static sal_Int32 mnLeft = 0x01;
112 const static sal_Int32 mnHorizontalCenter = 0x02;
113 const static sal_Int32 mnRight = 0x04;
114 const static sal_Int32 mnTop = 0x10;
115 const static sal_Int32 mnVerticalCenter = 0x20;
116 const static sal_Int32 mnBottom = 0x40;
119 PresenterPaneBorderManager::BorderElement
120 PresenterPaneBorderManager::ClassifyBorderElementUnderMouse (
121 const Reference<awt::XWindow>& rxOuterWindow,
122 const Reference<awt::XWindow>& rxInnerWindow,
123 const awt::Point aPosition) const
125 OSL_ASSERT(rxOuterWindow.is());
126 OSL_ASSERT(rxInnerWindow.is());
128 awt::Rectangle aOuterBox (rxOuterWindow->getPosSize());
129 const awt::Rectangle aInnerBox (rxInnerWindow->getPosSize());
131 // Coordinates of the pointer position are given in the window
132 // coordinate system. Therefore the upper left corner of the outer box
133 // is the origin.
134 aOuterBox.X = 0;
135 aOuterBox.Y = 0;
137 sal_Int32 nCode = 0;
139 // Add horizontal classification to nCode.
140 if (aPosition.X < aInnerBox.X)
141 if (aPosition.X < aOuterBox.X)
142 nCode = mnOutside;
143 else
144 nCode = mnLeft;
145 else if (aPosition.X >= aInnerBox.X+aInnerBox.Width)
146 if (aPosition.X >= aOuterBox.X+aOuterBox.Width)
147 nCode = mnOutside;
148 else
149 nCode = mnRight;
150 else
151 nCode = mnHorizontalCenter;
153 // Add vertical classification to nCode.
154 if (aPosition.Y < aInnerBox.Y)
155 if (aPosition.Y < aOuterBox.Y)
156 nCode |= mnOutside;
157 else
158 nCode |= mnTop;
159 else if (aPosition.Y >= aInnerBox.Y+aInnerBox.Height)
160 if (aPosition.Y >= aOuterBox.Y+aOuterBox.Height)
161 nCode |= mnOutside;
162 else
163 nCode |= mnBottom;
164 else
165 nCode |= mnVerticalCenter;
167 // Translate bits in nCode into BorderElement value.
168 switch (nCode)
170 case mnOutside:
171 case mnOutside | mnLeft:
172 case mnOutside | mnRight:
173 case mnOutside | mnHorizontalCenter:
174 case mnTop | mnOutside:
175 case mnBottom | mnOutside:
176 case mnVerticalCenter | mnOutside:
177 default:
178 return Outside;
180 case mnVerticalCenter | mnHorizontalCenter:
181 return Content;
183 case mnTop | mnLeft:
184 return TopLeft;
186 case mnTop | mnRight:
187 return TopRight;
189 case mnTop | mnHorizontalCenter:
190 return Top;
192 case mnBottom | mnLeft:
193 return BottomLeft;
195 case mnBottom | mnRight:
196 return BottomRight;
198 case mnBottom | mnHorizontalCenter:
199 return Bottom;
201 case mnVerticalCenter | mnLeft:
202 return Left;
204 case mnVerticalCenter | mnRight:
205 return Right;
209 //----- XInitialization -------------------------------------------------------
211 void SAL_CALL PresenterPaneBorderManager::initialize (const Sequence<Any>& rArguments)
212 throw (Exception, RuntimeException)
214 ThrowIfDisposed();
216 if (rArguments.getLength()%2 == 1 && mxComponentContext.is())
220 mxParentWindow = Reference<awt::XWindow>(rArguments[0], UNO_QUERY_THROW);
222 // Get the outer and inner windows from the argument list and
223 // build a window list of it.
224 for (sal_Int32 nIndex=1; nIndex<rArguments.getLength(); nIndex+=2)
226 Reference<awt::XWindow> xOuterWindow (rArguments[nIndex], UNO_QUERY_THROW);
227 Reference<awt::XWindow> xInnerWindow (rArguments[nIndex+1], UNO_QUERY_THROW);
229 maWindowList.push_back(WindowDescriptor(xOuterWindow,xInnerWindow));
231 xOuterWindow->addMouseListener(this);
232 xOuterWindow->addMouseMotionListener(this);
235 catch (RuntimeException&)
237 PresenterPaneBorderManager::disposing();
238 throw;
241 else
243 throw RuntimeException(
244 "PresenterPane: invalid number of arguments",
245 static_cast<XWeak*>(this));
249 //----- XMouseListener --------------------------------------------------------
251 void SAL_CALL PresenterPaneBorderManager::mousePressed (const css::awt::MouseEvent& rEvent)
252 throw (css::uno::RuntimeException)
254 ThrowIfDisposed();
255 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
257 // Find window descriptor of the window that has been clicked.
258 WindowList::const_iterator iDescriptor;
259 for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
260 if (iDescriptor->first == rEvent.Source)
261 break;
263 if (iDescriptor != maWindowList.end())
265 // Prepare dragging.
266 mxOuterDragWindow = iDescriptor->first;
267 mxInnerDragWindow = iDescriptor->second;
268 OSL_ASSERT(mxOuterDragWindow.is() && mxInnerDragWindow.is());
269 const awt::Rectangle aOuterBox (mxOuterDragWindow->getPosSize());
270 maDragAnchor.X = rEvent.X + aOuterBox.X;
271 maDragAnchor.Y = rEvent.Y + aOuterBox.Y;
272 meDragType = ClassifyBorderElementUnderMouse(
273 mxOuterDragWindow,
274 mxInnerDragWindow,
275 awt::Point(rEvent.X, rEvent.Y));
279 void SAL_CALL PresenterPaneBorderManager::mouseReleased (const css::awt::MouseEvent& rEvent)
280 throw (css::uno::RuntimeException)
282 (void)rEvent;
283 ThrowIfDisposed();
284 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
286 ReleaseMouse(mxOuterDragWindow);
287 meDragType = PresenterPaneBorderManager::Outside;
288 mxOuterDragWindow = NULL;
289 mxInnerDragWindow = NULL;
292 void SAL_CALL PresenterPaneBorderManager::mouseEntered (const css::awt::MouseEvent& rEvent)
293 throw (css::uno::RuntimeException)
295 (void)rEvent;
298 void SAL_CALL PresenterPaneBorderManager::mouseExited (const css::awt::MouseEvent& rEvent)
299 throw (css::uno::RuntimeException)
301 (void)rEvent;
302 ThrowIfDisposed();
303 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
305 ReleaseMouse(mxOuterDragWindow);
306 meDragType = PresenterPaneBorderManager::Outside;
307 mxOuterDragWindow = NULL;
308 mxInnerDragWindow = NULL;
311 //----- XMouseMotionListener --------------------------------------------------
313 void SAL_CALL PresenterPaneBorderManager::mouseMoved (const css::awt::MouseEvent& rEvent)
314 throw (css::uno::RuntimeException)
316 ThrowIfDisposed();
317 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
319 WindowList::const_iterator iDescriptor;
320 for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
321 if (iDescriptor->first == rEvent.Source)
322 break;
323 if (iDescriptor != maWindowList.end())
325 // Choose pointer shape according to position in the window border.
326 switch (ClassifyBorderElementUnderMouse(
327 iDescriptor->first,
328 iDescriptor->second,
329 awt::Point(rEvent.X,rEvent.Y)))
331 case PresenterPaneBorderManager::Top:
332 mnPointerType = awt::SystemPointer::MOVE;
333 break;
334 case PresenterPaneBorderManager::TopLeft:
335 mnPointerType = awt::SystemPointer::WINDOW_NWSIZE;
336 break;
337 case PresenterPaneBorderManager::TopRight:
338 mnPointerType = awt::SystemPointer::WINDOW_NESIZE;
339 break;
340 case PresenterPaneBorderManager::Left:
341 mnPointerType = awt::SystemPointer::WINDOW_WSIZE;
342 break;
343 case PresenterPaneBorderManager::Right:
344 mnPointerType = awt::SystemPointer::WINDOW_ESIZE;
345 break;
346 case PresenterPaneBorderManager::BottomLeft:
347 mnPointerType = awt::SystemPointer::WINDOW_SWSIZE;
348 break;
349 case PresenterPaneBorderManager::BottomRight:
350 mnPointerType = awt::SystemPointer::WINDOW_SESIZE;
351 break;
352 case PresenterPaneBorderManager::Bottom:
353 mnPointerType = awt::SystemPointer::WINDOW_SSIZE;
354 break;
356 case PresenterPaneBorderManager::Content:
357 case PresenterPaneBorderManager::Outside:
358 default:
359 mnPointerType = awt::SystemPointer::ARROW;
360 break;
363 // Make the pointer shape visible.
364 Reference<awt::XWindowPeer> xPeer (iDescriptor->first, UNO_QUERY);
365 if (xPeer.is())
367 if (mxPointer.is())
368 mxPointer->setType(mnPointerType);
369 xPeer->setPointer(mxPointer);
374 void SAL_CALL PresenterPaneBorderManager::mouseDragged (const css::awt::MouseEvent& rEvent)
375 throw (css::uno::RuntimeException)
377 ThrowIfDisposed();
378 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
380 if ( ! mxOuterDragWindow.is())
381 return;
383 CaptureMouse(mxOuterDragWindow);
385 const awt::Rectangle aOldBox (mxOuterDragWindow->getPosSize());
386 const sal_Int32 nX = rEvent.X + aOldBox.X;
387 const sal_Int32 nY = rEvent.Y + aOldBox.Y;
388 const sal_Int32 nDiffX = nX - maDragAnchor.X;
389 const sal_Int32 nDiffY = nY - maDragAnchor.Y;
390 maDragAnchor.X = nX;
391 maDragAnchor.Y = nY;
393 const sal_Int32 nOldRight = aOldBox.X + aOldBox.Width;
394 const sal_Int32 nOldBottom = aOldBox.Y + aOldBox.Height;
396 awt::Rectangle aBox (aOldBox);
397 sal_Int32 nRight = aBox.X + aBox.Width;
398 sal_Int32 nBottom = aBox.Y + aBox.Height;
400 // Update position and/or size according to initial pointer position
401 // inside the window border.
402 switch (meDragType)
404 case PresenterPaneBorderManager::Top:
405 aBox.X += nDiffX; aBox.Y += nDiffY;
406 nRight += nDiffX; nBottom += nDiffY;
407 break;
408 case PresenterPaneBorderManager::TopLeft:
409 aBox.X += nDiffX; aBox.Y += nDiffY;
410 break;
411 case PresenterPaneBorderManager::TopRight:
412 nRight += nDiffX; aBox.Y += nDiffY;
413 break;
414 case PresenterPaneBorderManager::Left:
415 aBox.X += nDiffX;
416 break;
417 case PresenterPaneBorderManager::Right:
418 nRight += nDiffX;
419 break;
420 case PresenterPaneBorderManager::BottomLeft:
421 aBox.X += nDiffX; nBottom += nDiffY;
422 break;
423 case PresenterPaneBorderManager::BottomRight:
424 nRight += nDiffX; nBottom += nDiffY;
425 break;
426 case PresenterPaneBorderManager::Bottom:
427 nBottom += nDiffY;
428 break;
429 default: break;
432 aBox.Width = nRight - aBox.X;
433 aBox.Height = nBottom - aBox.Y;
434 if (aBox.Width > 20
435 && aBox.Height > 20)
437 // Set position and/or size of the border window to the new values.
438 sal_Int16 nFlags (0);
439 if (aBox.X != aOldBox.X)
440 nFlags |= awt::PosSize::X;
441 if (aBox.Y != aOldBox.Y)
442 nFlags |= awt::PosSize::Y;
443 if (aBox.Width != aOldBox.Width)
444 nFlags |= awt::PosSize::WIDTH;
445 if (aBox.Height != aOldBox.Height)
446 nFlags |= awt::PosSize::HEIGHT;
447 mxOuterDragWindow->setPosSize(aBox.X, aBox.Y, aBox.Width, aBox.Height, nFlags);
449 // Invalidate that is or was covered by the border window before and
450 // after the move/resize.
451 if (mpPresenterController.get() != NULL)
453 const sal_Int32 nLeft = ::std::min(aOldBox.X,aBox.X);
454 const sal_Int32 nTop = ::std::min(aOldBox.Y,aBox.Y);
455 const sal_Int32 nWidth = ::std::max(nOldRight,nRight) - nLeft;
456 const sal_Int32 nHeight = ::std::max(nOldBottom,nBottom) - nTop;
458 OSL_ASSERT(mpPresenterController->GetPaintManager().get()!=NULL);
459 mpPresenterController->GetPaintManager()->Invalidate(
460 mxParentWindow,
461 ::awt::Rectangle(nLeft,nTop,nWidth-1,nHeight-1));
466 //----- lang::XEventListener --------------------------------------------------
468 void SAL_CALL PresenterPaneBorderManager::disposing (const lang::EventObject& rEvent)
469 throw (RuntimeException)
471 WindowList::iterator iDescriptor;
472 for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
473 if (iDescriptor->first == rEvent.Source)
475 maWindowList.erase(iDescriptor);
476 break;
482 void PresenterPaneBorderManager::CaptureMouse (const Reference<awt::XWindow>& rxWindow)
484 if (mxPresenterHelper.is())
485 mxPresenterHelper->captureMouse(rxWindow);
488 void PresenterPaneBorderManager::ReleaseMouse (const Reference<awt::XWindow>& rxWindow)
490 if (mxPresenterHelper.is())
491 mxPresenterHelper->releaseMouse(rxWindow);
494 void PresenterPaneBorderManager::ThrowIfDisposed()
495 throw (::com::sun::star::lang::DisposedException)
497 if (rBHelper.bDisposed || rBHelper.bInDispose)
499 throw lang::DisposedException (
500 "PresenterPaneBorderManager object has already been disposed",
501 static_cast<uno::XWeak*>(this));
505 } } // end of namespace ::sd::presenter
507 #endif // ENABLE_PANE_RESIZING
509 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */