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 56 OUString PresenterPaneBorderManager::getImplementationName_static (void) 57 { 58 return OUString::createFromAscii("com.sun.star.comp.Draw.PresenterPaneBorderManager"); 59 } 60 61 62 63 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 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 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 121 PresenterPaneBorderManager::~PresenterPaneBorderManager (void) 122 { 123 } 124 125 126 127 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 153 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 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 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 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 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 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 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 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 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 543 void PresenterPaneBorderManager::CaptureMouse (const Reference<awt::XWindow>& rxWindow) 544 { 545 if (mxPresenterHelper.is()) 546 mxPresenterHelper->captureMouse(rxWindow); 547 } 548 549 550 551 552 void PresenterPaneBorderManager::ReleaseMouse (const Reference<awt::XWindow>& rxWindow) 553 { 554 if (mxPresenterHelper.is()) 555 mxPresenterHelper->releaseMouse(rxWindow); 556 } 557 558 559 560 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