1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sdext.hxx"
26
27 // The body of this file is only used when PresenterWindowManager defines
28 // the preprocessor symbol ENABLE_PANE_RESIZING, which by default is not the
29 // case.
30 #ifdef ENABLE_PANE_RESIZING
31
32 #include "PresenterPaneBorderManager.hxx"
33 #include "PresenterController.hxx"
34 #include "PresenterPaintManager.hxx"
35 #include <com/sun/star/awt/PosSize.hpp>
36 #include <com/sun/star/awt/SystemPointer.hpp>
37 #include <com/sun/star/awt/WindowAttribute.hpp>
38 #include <com/sun/star/awt/WindowDescriptor.hpp>
39 #include <com/sun/star/awt/WindowClass.hpp>
40 #include <com/sun/star/awt/XWindow2.hpp>
41 #include <com/sun/star/awt/XWindowPeer.hpp>
42 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
43 #include <cppuhelper/compbase1.hxx>
44 #include <osl/mutex.hxx>
45 #include <boost/weak_ptr.hpp>
46
47 using namespace ::com::sun::star;
48 using namespace ::com::sun::star::uno;
49 using ::rtl::OUString;
50
51 namespace sdext { namespace presenter {
52
53 //===== Service ===============================================================
54
55
getImplementationName_static(void)56 OUString PresenterPaneBorderManager::getImplementationName_static (void)
57 {
58 return OUString::createFromAscii("com.sun.star.comp.Draw.PresenterPaneBorderManager");
59 }
60
61
62
63
getSupportedServiceNames_static(void)64 Sequence<OUString> PresenterPaneBorderManager::getSupportedServiceNames_static (void)
65 {
66 static const ::rtl::OUString sServiceName(
67 ::rtl::OUString::createFromAscii("com.sun.star.drawing.PresenterPaneBorderManager"));
68 return Sequence<rtl::OUString>(&sServiceName, 1);
69 }
70
71
72
73
Create(const Reference<uno::XComponentContext> & rxContext)74 Reference<XInterface> PresenterPaneBorderManager::Create (const Reference<uno::XComponentContext>& rxContext)
75 {
76 return Reference<XInterface>(static_cast<XWeak*>(
77 new PresenterPaneBorderManager(rxContext, NULL)));
78 }
79
80
81
82
83 //===== PresenterPaneBorderManager ============================================
84
PresenterPaneBorderManager(const Reference<XComponentContext> & rxContext,const::rtl::Reference<PresenterController> & rpPresenterController)85 PresenterPaneBorderManager::PresenterPaneBorderManager (
86 const Reference<XComponentContext>& rxContext,
87 const ::rtl::Reference<PresenterController>& rpPresenterController)
88 : PresenterPaneBorderManagerInterfaceBase(m_aMutex),
89 mpPresenterController(rpPresenterController),
90 mxComponentContext(rxContext),
91 mxPresenterHelper(),
92 maWindowList(),
93 mnPointerType(),
94 maDragAnchor(),
95 meDragType(Outside),
96 mxOuterDragWindow(),
97 mxInnerDragWindow(),
98 mxPointer()
99 {
100 Reference<lang::XMultiComponentFactory> xFactory (rxContext->getServiceManager());
101 if (xFactory.is())
102 {
103 mxPointer = Reference<awt::XPointer>(
104 xFactory->createInstanceWithContext(
105 OUString::createFromAscii("com.sun.star.awt.Pointer"),
106 rxContext),
107 UNO_QUERY_THROW);
108
109 mxPresenterHelper = Reference<drawing::XPresenterHelper>(
110 xFactory->createInstanceWithContext(
111 OUString::createFromAscii("com.sun.star.comp.Draw.PresenterHelper"),
112 rxContext),
113 UNO_QUERY_THROW);
114 }
115 }
116
117
118
119
~PresenterPaneBorderManager(void)120 PresenterPaneBorderManager::~PresenterPaneBorderManager (void)
121 {
122 }
123
124
125
126
disposing(void)127 void PresenterPaneBorderManager::disposing (void)
128 {
129 WindowList::const_iterator iDescriptor;
130 for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
131 {
132 iDescriptor->first->removeMouseListener(this);
133 iDescriptor->first->removeMouseMotionListener(this);
134 }
135 maWindowList.clear();
136 }
137
138
139
140
141 namespace {
142 const static sal_Int32 mnOutside = 0;
143 const static sal_Int32 mnLeft = 0x01;
144 const static sal_Int32 mnHorizontalCenter = 0x02;
145 const static sal_Int32 mnRight = 0x04;
146 const static sal_Int32 mnTop = 0x10;
147 const static sal_Int32 mnVerticalCenter = 0x20;
148 const static sal_Int32 mnBottom = 0x40;
149 }
150
151 PresenterPaneBorderManager::BorderElement
ClassifyBorderElementUnderMouse(const Reference<awt::XWindow> & rxOuterWindow,const Reference<awt::XWindow> & rxInnerWindow,const awt::Point aPosition) const152 PresenterPaneBorderManager::ClassifyBorderElementUnderMouse (
153 const Reference<awt::XWindow>& rxOuterWindow,
154 const Reference<awt::XWindow>& rxInnerWindow,
155 const awt::Point aPosition) const
156 {
157 OSL_ASSERT(rxOuterWindow.is());
158 OSL_ASSERT(rxInnerWindow.is());
159
160 awt::Rectangle aOuterBox (rxOuterWindow->getPosSize());
161 const awt::Rectangle aInnerBox (rxInnerWindow->getPosSize());
162
163 // Coordinates of the pointer position are given in the window
164 // coordinate system. Therefore the upper left corner of the outer box
165 // is the origin.
166 aOuterBox.X = 0;
167 aOuterBox.Y = 0;
168
169 sal_Int32 nCode = 0;
170
171 // Add horizontal classification to nCode.
172 if (aPosition.X < aInnerBox.X)
173 if (aPosition.X < aOuterBox.X)
174 nCode = mnOutside;
175 else
176 nCode = mnLeft;
177 else if (aPosition.X >= aInnerBox.X+aInnerBox.Width)
178 if (aPosition.X >= aOuterBox.X+aOuterBox.Width)
179 nCode = mnOutside;
180 else
181 nCode = mnRight;
182 else
183 nCode = mnHorizontalCenter;
184
185 // Add vertical classification to nCode.
186 if (aPosition.Y < aInnerBox.Y)
187 if (aPosition.Y < aOuterBox.Y)
188 nCode |= mnOutside;
189 else
190 nCode |= mnTop;
191 else if (aPosition.Y >= aInnerBox.Y+aInnerBox.Height)
192 if (aPosition.Y >= aOuterBox.Y+aOuterBox.Height)
193 nCode |= mnOutside;
194 else
195 nCode |= mnBottom;
196 else
197 nCode |= mnVerticalCenter;
198
199 // Translate bits in nCode into BorderElement value.
200 switch (nCode)
201 {
202 case mnOutside | mnOutside:
203 case mnOutside | mnLeft:
204 case mnOutside | mnRight:
205 case mnOutside | mnHorizontalCenter:
206 case mnTop | mnOutside:
207 case mnBottom | mnOutside:
208 case mnVerticalCenter | mnOutside:
209 default:
210 return Outside;
211
212 case mnVerticalCenter | mnHorizontalCenter:
213 return Content;
214
215 case mnTop | mnLeft:
216 return TopLeft;
217
218 case mnTop | mnRight:
219 return TopRight;
220
221 case mnTop | mnHorizontalCenter:
222 return Top;
223
224 case mnBottom | mnLeft:
225 return BottomLeft;
226
227 case mnBottom | mnRight:
228 return BottomRight;
229
230 case mnBottom | mnHorizontalCenter:
231 return Bottom;
232
233 case mnVerticalCenter | mnLeft:
234 return Left;
235
236 case mnVerticalCenter | mnRight:
237 return Right;
238 }
239 }
240
241
242
243
244 //----- XInitialization -------------------------------------------------------
245
initialize(const Sequence<Any> & rArguments)246 void SAL_CALL PresenterPaneBorderManager::initialize (const Sequence<Any>& rArguments)
247 {
248 ThrowIfDisposed();
249
250 if (rArguments.getLength()%2 == 1 && mxComponentContext.is())
251 {
252 try
253 {
254 mxParentWindow = Reference<awt::XWindow>(rArguments[0], UNO_QUERY_THROW);
255
256 // Get the outer and inner windows from the argument list and
257 // build a window list of it.
258 for (sal_Int32 nIndex=1; nIndex<rArguments.getLength(); nIndex+=2)
259 {
260 Reference<awt::XWindow> xOuterWindow (rArguments[nIndex], UNO_QUERY_THROW);
261 Reference<awt::XWindow> xInnerWindow (rArguments[nIndex+1], UNO_QUERY_THROW);
262
263 maWindowList.push_back(WindowDescriptor(xOuterWindow,xInnerWindow));
264
265 xOuterWindow->addMouseListener(this);
266 xOuterWindow->addMouseMotionListener(this);
267 }
268 }
269 catch (RuntimeException&)
270 {
271 PresenterPaneBorderManager::disposing();
272 throw;
273 }
274 }
275 else
276 {
277 throw RuntimeException(
278 OUString::createFromAscii("PresenterPane: invalid number of arguments"),
279 static_cast<XWeak*>(this));
280 }
281 }
282
283
284
285
286 //----- XMouseListener --------------------------------------------------------
287
mousePressed(const css::awt::MouseEvent & rEvent)288 void SAL_CALL PresenterPaneBorderManager::mousePressed (const css::awt::MouseEvent& rEvent)
289 {
290 ThrowIfDisposed();
291 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
292
293 // Find window descriptor of the window that has been clicked.
294 WindowList::const_iterator iDescriptor;
295 for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
296 if (iDescriptor->first == rEvent.Source)
297 break;
298
299 if (iDescriptor != maWindowList.end())
300 {
301 // Prepare dragging.
302 mxOuterDragWindow = iDescriptor->first;
303 mxInnerDragWindow = iDescriptor->second;
304 OSL_ASSERT(mxOuterDragWindow.is() && mxInnerDragWindow.is());
305 const awt::Rectangle aOuterBox (mxOuterDragWindow->getPosSize());
306 maDragAnchor.X = rEvent.X + aOuterBox.X;
307 maDragAnchor.Y = rEvent.Y + aOuterBox.Y;
308 meDragType = ClassifyBorderElementUnderMouse(
309 mxOuterDragWindow,
310 mxInnerDragWindow,
311 awt::Point(rEvent.X, rEvent.Y));
312 }
313 }
314
315
316
317
mouseReleased(const css::awt::MouseEvent & rEvent)318 void SAL_CALL PresenterPaneBorderManager::mouseReleased (const css::awt::MouseEvent& rEvent)
319 {
320 (void)rEvent;
321 ThrowIfDisposed();
322 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
323
324 ReleaseMouse(mxOuterDragWindow);
325 meDragType = PresenterPaneBorderManager::Outside;
326 mxOuterDragWindow = NULL;
327 mxInnerDragWindow = NULL;
328 }
329
330
331
332
mouseEntered(const css::awt::MouseEvent & rEvent)333 void SAL_CALL PresenterPaneBorderManager::mouseEntered (const css::awt::MouseEvent& rEvent)
334 {
335 (void)rEvent;
336 }
337
338
339
340
mouseExited(const css::awt::MouseEvent & rEvent)341 void SAL_CALL PresenterPaneBorderManager::mouseExited (const css::awt::MouseEvent& rEvent)
342 {
343 (void)rEvent;
344 ThrowIfDisposed();
345 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
346
347 ReleaseMouse(mxOuterDragWindow);
348 meDragType = PresenterPaneBorderManager::Outside;
349 mxOuterDragWindow = NULL;
350 mxInnerDragWindow = NULL;
351 }
352
353
354
355
356 //----- XMouseMotionListener --------------------------------------------------
357
mouseMoved(const css::awt::MouseEvent & rEvent)358 void SAL_CALL PresenterPaneBorderManager::mouseMoved (const css::awt::MouseEvent& rEvent)
359 {
360 ThrowIfDisposed();
361 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
362
363 WindowList::const_iterator iDescriptor;
364 for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
365 if (iDescriptor->first == rEvent.Source)
366 break;
367 if (iDescriptor != maWindowList.end())
368 {
369 // Choose pointer shape according to position in the window border.
370 switch (ClassifyBorderElementUnderMouse(
371 iDescriptor->first,
372 iDescriptor->second,
373 awt::Point(rEvent.X,rEvent.Y)))
374 {
375 case PresenterPaneBorderManager::Top:
376 mnPointerType = awt::SystemPointer::MOVE;
377 break;
378 case PresenterPaneBorderManager::TopLeft:
379 mnPointerType = awt::SystemPointer::WINDOW_NWSIZE;
380 break;
381 case PresenterPaneBorderManager::TopRight:
382 mnPointerType = awt::SystemPointer::WINDOW_NESIZE;
383 break;
384 case PresenterPaneBorderManager::Left:
385 mnPointerType = awt::SystemPointer::WINDOW_WSIZE;
386 break;
387 case PresenterPaneBorderManager::Right:
388 mnPointerType = awt::SystemPointer::WINDOW_ESIZE;
389 break;
390 case PresenterPaneBorderManager::BottomLeft:
391 mnPointerType = awt::SystemPointer::WINDOW_SWSIZE;
392 break;
393 case PresenterPaneBorderManager::BottomRight:
394 mnPointerType = awt::SystemPointer::WINDOW_SESIZE;
395 break;
396 case PresenterPaneBorderManager::Bottom:
397 mnPointerType = awt::SystemPointer::WINDOW_SSIZE;
398 break;
399
400 case PresenterPaneBorderManager::Content:
401 case PresenterPaneBorderManager::Outside:
402 default:
403 mnPointerType = awt::SystemPointer::ARROW;
404 break;
405 }
406
407 // Make the pointer shape visible.
408 Reference<awt::XWindowPeer> xPeer (iDescriptor->first, UNO_QUERY);
409 if (xPeer.is())
410 {
411 if (mxPointer.is())
412 mxPointer->setType(mnPointerType);
413 xPeer->setPointer(mxPointer);
414 }
415 }
416 }
417
418
419
420
mouseDragged(const css::awt::MouseEvent & rEvent)421 void SAL_CALL PresenterPaneBorderManager::mouseDragged (const css::awt::MouseEvent& rEvent)
422 {
423 ThrowIfDisposed();
424 ::osl::MutexGuard aGuard (::osl::Mutex::getGlobalMutex());
425
426 if ( ! mxOuterDragWindow.is())
427 return;
428
429 CaptureMouse(mxOuterDragWindow);
430
431 const awt::Rectangle aOldBox (mxOuterDragWindow->getPosSize());
432 const sal_Int32 nX = rEvent.X + aOldBox.X;
433 const sal_Int32 nY = rEvent.Y + aOldBox.Y;
434 const sal_Int32 nDiffX = nX - maDragAnchor.X;
435 const sal_Int32 nDiffY = nY - maDragAnchor.Y;
436 maDragAnchor.X = nX;
437 maDragAnchor.Y = nY;
438
439 const sal_Int32 nOldRight = aOldBox.X + aOldBox.Width;
440 const sal_Int32 nOldBottom = aOldBox.Y + aOldBox.Height;
441
442 awt::Rectangle aBox (aOldBox);
443 sal_Int32 nRight = aBox.X + aBox.Width;
444 sal_Int32 nBottom = aBox.Y + aBox.Height;
445
446 // Update position and/or size according to initial pointer position
447 // inside the window border.
448 switch (meDragType)
449 {
450 case PresenterPaneBorderManager::Top:
451 aBox.X += nDiffX; aBox.Y += nDiffY;
452 nRight += nDiffX; nBottom += nDiffY;
453 break;
454 case PresenterPaneBorderManager::TopLeft:
455 aBox.X += nDiffX; aBox.Y += nDiffY;
456 break;
457 case PresenterPaneBorderManager::TopRight:
458 nRight += nDiffX; aBox.Y += nDiffY;
459 break;
460 case PresenterPaneBorderManager::Left:
461 aBox.X += nDiffX;
462 break;
463 case PresenterPaneBorderManager::Right:
464 nRight += nDiffX;
465 break;
466 case PresenterPaneBorderManager::BottomLeft:
467 aBox.X += nDiffX; nBottom += nDiffY;
468 break;
469 case PresenterPaneBorderManager::BottomRight:
470 nRight += nDiffX; nBottom += nDiffY;
471 break;
472 case PresenterPaneBorderManager::Bottom:
473 nBottom += nDiffY;
474 break;
475 default: break;
476 }
477
478 aBox.Width = nRight - aBox.X;
479 aBox.Height = nBottom - aBox.Y;
480 if (aBox.Width > 20
481 && aBox.Height > 20)
482 {
483 // Set position and/or size of the border window to the new values.
484 sal_Int16 nFlags (0);
485 if (aBox.X != aOldBox.X)
486 nFlags |= awt::PosSize::X;
487 if (aBox.Y != aOldBox.Y)
488 nFlags |= awt::PosSize::Y;
489 if (aBox.Width != aOldBox.Width)
490 nFlags |= awt::PosSize::WIDTH;
491 if (aBox.Height != aOldBox.Height)
492 nFlags |= awt::PosSize::HEIGHT;
493 mxOuterDragWindow->setPosSize(aBox.X, aBox.Y, aBox.Width, aBox.Height, nFlags);
494
495 // Invalidate that is or was covered by the border window before and
496 // after the move/resize.
497 if (mpPresenterController.get() != NULL)
498 {
499 const sal_Int32 nLeft = ::std::min(aOldBox.X,aBox.X);
500 const sal_Int32 nTop = ::std::min(aOldBox.Y,aBox.Y);
501 const sal_Int32 nWidth = ::std::max(nOldRight,nRight) - nLeft;
502 const sal_Int32 nHeight = ::std::max(nOldBottom,nBottom) - nTop;
503
504 OSL_ASSERT(mpPresenterController->GetPaintManager().get()!=NULL);
505 mpPresenterController->GetPaintManager()->Invalidate(
506 mxParentWindow,
507 ::awt::Rectangle(nLeft,nTop,nWidth-1,nHeight-1));
508 }
509 }
510 }
511
512
513
514
515 //----- lang::XEventListener --------------------------------------------------
516
disposing(const lang::EventObject & rEvent)517 void SAL_CALL PresenterPaneBorderManager::disposing (const lang::EventObject& rEvent)
518 {
519 WindowList::iterator iDescriptor;
520 for (iDescriptor=maWindowList.begin(); iDescriptor!=maWindowList.end(); ++iDescriptor)
521 if (iDescriptor->first == rEvent.Source)
522 {
523 maWindowList.erase(iDescriptor);
524 break;
525 }
526 }
527
528
529
530
531 //-----------------------------------------------------------------------------
532
533
CaptureMouse(const Reference<awt::XWindow> & rxWindow)534 void PresenterPaneBorderManager::CaptureMouse (const Reference<awt::XWindow>& rxWindow)
535 {
536 if (mxPresenterHelper.is())
537 mxPresenterHelper->captureMouse(rxWindow);
538 }
539
540
541
542
ReleaseMouse(const Reference<awt::XWindow> & rxWindow)543 void PresenterPaneBorderManager::ReleaseMouse (const Reference<awt::XWindow>& rxWindow)
544 {
545 if (mxPresenterHelper.is())
546 mxPresenterHelper->releaseMouse(rxWindow);
547 }
548
549
550
551
ThrowIfDisposed(void)552 void PresenterPaneBorderManager::ThrowIfDisposed (void)
553 {
554 if (rBHelper.bDisposed || rBHelper.bInDispose)
555 {
556 throw lang::DisposedException (
557 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
558 "PresenterPaneBorderManager object has already been disposed")),
559 static_cast<uno::XWeak*>(this));
560 }
561 }
562
563
564
565
566 } } // end of namespace ::sd::presenter
567
568 #endif // ENABLE_PANE_RESIZING
569