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