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