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_vcl.hxx" 30 31 #include "tools/debug.hxx" 32 #include "tools/diagnose_ex.h" 33 #include "tools/time.hxx" 34 35 #include "vcl/window.hxx" 36 #include "vcl/event.hxx" 37 #include "vcl/svapp.hxx" 38 #include "vcl/wrkwin.hxx" 39 #include "vcl/help.hxx" 40 41 #include "helpwin.hxx" 42 #include "svdata.hxx" 43 44 // ======================================================================= 45 46 #define HELPWINSTYLE_QUICK 0 47 #define HELPWINSTYLE_BALLOON 1 48 49 #define HELPTEXTMARGIN_QUICK 3 50 #define HELPTEXTMARGIN_BALLOON 6 51 52 #define HELPDELAY_NORMAL 1 53 #define HELPDELAY_SHORT 2 54 #define HELPDELAY_NONE 3 55 56 // ======================================================================= 57 58 Help::Help() 59 { 60 } 61 62 Help::~Help() 63 { 64 } 65 66 // ----------------------------------------------------------------------- 67 68 void Help::OpenHelpAgent( const rtl::OString& ) 69 { 70 } 71 72 // ----------------------------------------------------------------------- 73 74 sal_Bool Help::Start( const XubString&, const Window* ) 75 { 76 return sal_False; 77 } 78 79 sal_Bool Help::SearchKeyword( const XubString& ) 80 { 81 return sal_False; 82 } 83 84 // ----------------------------------------------------------------------- 85 86 XubString Help::GetHelpText( const String&, const Window* ) 87 { 88 return ImplGetSVEmptyStr(); 89 } 90 91 // ----------------------------------------------------------------------- 92 93 void Help::EnableContextHelp() 94 { 95 ImplGetSVData()->maHelpData.mbContextHelp = sal_True; 96 } 97 98 // ----------------------------------------------------------------------- 99 100 void Help::DisableContextHelp() 101 { 102 ImplGetSVData()->maHelpData.mbContextHelp = sal_False; 103 } 104 105 // ----------------------------------------------------------------------- 106 107 sal_Bool Help::IsContextHelpEnabled() 108 { 109 return ImplGetSVData()->maHelpData.mbContextHelp; 110 } 111 112 // ----------------------------------------------------------------------- 113 114 sal_Bool Help::StartContextHelp() 115 { 116 ImplSVData* pSVData = ImplGetSVData(); 117 118 if ( pSVData->maHelpData.mbContextHelp ) 119 { 120 Window* pWindow = pSVData->maWinData.mpFocusWin; 121 if ( pWindow ) 122 { 123 Point aMousePos = pWindow->OutputToScreenPixel( pWindow->GetPointerPosPixel() ); 124 HelpEvent aHelpEvent( aMousePos, HELPMODE_CONTEXT ); 125 pWindow->RequestHelp( aHelpEvent ); 126 return sal_True; 127 } 128 } 129 130 return sal_False; 131 } 132 133 // ----------------------------------------------------------------------- 134 135 void Help::EnableExtHelp() 136 { 137 ImplGetSVData()->maHelpData.mbExtHelp = sal_True; 138 } 139 140 // ----------------------------------------------------------------------- 141 142 void Help::DisableExtHelp() 143 { 144 ImplGetSVData()->maHelpData.mbExtHelp = sal_False; 145 } 146 147 // ----------------------------------------------------------------------- 148 149 sal_Bool Help::IsExtHelpEnabled() 150 { 151 return ImplGetSVData()->maHelpData.mbExtHelp; 152 } 153 154 // ----------------------------------------------------------------------- 155 156 sal_Bool Help::StartExtHelp() 157 { 158 ImplSVData* pSVData = ImplGetSVData(); 159 160 if ( pSVData->maHelpData.mbExtHelp && !pSVData->maHelpData.mbExtHelpMode ) 161 { 162 pSVData->maHelpData.mbExtHelpMode = sal_True; 163 pSVData->maHelpData.mbOldBalloonMode = pSVData->maHelpData.mbBalloonHelp; 164 pSVData->maHelpData.mbBalloonHelp = sal_True; 165 if ( pSVData->maWinData.mpAppWin ) 166 pSVData->maWinData.mpAppWin->ImplGenerateMouseMove(); 167 return sal_True; 168 } 169 170 return sal_False; 171 } 172 173 // ----------------------------------------------------------------------- 174 175 sal_Bool Help::EndExtHelp() 176 { 177 ImplSVData* pSVData = ImplGetSVData(); 178 179 if ( pSVData->maHelpData.mbExtHelp && pSVData->maHelpData.mbExtHelpMode ) 180 { 181 pSVData->maHelpData.mbExtHelpMode = sal_False; 182 pSVData->maHelpData.mbBalloonHelp = pSVData->maHelpData.mbOldBalloonMode; 183 if ( pSVData->maWinData.mpAppWin ) 184 pSVData->maWinData.mpAppWin->ImplGenerateMouseMove(); 185 return sal_True; 186 } 187 188 return sal_False; 189 } 190 191 // ----------------------------------------------------------------------- 192 193 sal_Bool Help::IsExtHelpActive() 194 { 195 return ImplGetSVData()->maHelpData.mbExtHelpMode; 196 } 197 198 // ----------------------------------------------------------------------- 199 200 void Help::EnableBalloonHelp() 201 { 202 ImplGetSVData()->maHelpData.mbBalloonHelp = sal_True; 203 } 204 205 // ----------------------------------------------------------------------- 206 207 void Help::DisableBalloonHelp() 208 { 209 ImplGetSVData()->maHelpData.mbBalloonHelp = sal_False; 210 } 211 212 // ----------------------------------------------------------------------- 213 214 sal_Bool Help::IsBalloonHelpEnabled() 215 { 216 return ImplGetSVData()->maHelpData.mbBalloonHelp; 217 } 218 219 // ----------------------------------------------------------------------- 220 221 sal_Bool Help::ShowBalloon( Window* pParent, 222 const Point& rScreenPos, 223 const XubString& rHelpText ) 224 { 225 ImplShowHelpWindow( pParent, HELPWINSTYLE_BALLOON, 0, 226 rHelpText, ImplGetSVEmptyStr(), rScreenPos ); 227 228 return sal_True; 229 } 230 231 // ----------------------------------------------------------------------- 232 233 sal_Bool Help::ShowBalloon( Window* pParent, 234 const Point& rScreenPos, const Rectangle& rRect, 235 const XubString& rHelpText ) 236 { 237 ImplShowHelpWindow( pParent, HELPWINSTYLE_BALLOON, 0, 238 rHelpText, ImplGetSVEmptyStr(), rScreenPos, &rRect ); 239 240 return sal_True; 241 } 242 243 // ----------------------------------------------------------------------- 244 245 void Help::EnableQuickHelp() 246 { 247 ImplGetSVData()->maHelpData.mbQuickHelp = sal_True; 248 } 249 250 // ----------------------------------------------------------------------- 251 252 void Help::DisableQuickHelp() 253 { 254 ImplGetSVData()->maHelpData.mbQuickHelp = sal_False; 255 } 256 257 // ----------------------------------------------------------------------- 258 259 sal_Bool Help::IsQuickHelpEnabled() 260 { 261 return ImplGetSVData()->maHelpData.mbQuickHelp; 262 } 263 264 // ----------------------------------------------------------------------- 265 266 sal_Bool Help::ShowQuickHelp( Window* pParent, 267 const Rectangle& rScreenRect, 268 const XubString& rHelpText, 269 const XubString& rLongHelpText, 270 sal_uInt16 nStyle ) 271 { 272 ImplShowHelpWindow( pParent, HELPWINSTYLE_QUICK, nStyle, 273 rHelpText, rLongHelpText, 274 pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), &rScreenRect ); 275 return sal_True; 276 } 277 278 // ----------------------------------------------------------------------- 279 280 void Help::HideBalloonAndQuickHelp() 281 { 282 HelpTextWindow const * pHelpWin = ImplGetSVData()->maHelpData.mpHelpWin; 283 bool const bIsVisible = ( pHelpWin != NULL ) && pHelpWin->IsVisible(); 284 ImplDestroyHelpWindow( bIsVisible ); 285 } 286 287 // ----------------------------------------------------------------------- 288 289 sal_uIntPtr Help::ShowTip( Window* pParent, const Rectangle& rScreenRect, 290 const XubString& rText, sal_uInt16 nStyle ) 291 { 292 sal_uInt16 nHelpWinStyle = ( ( nStyle & QUICKHELP_TIP_STYLE_BALLOON ) != 0 ) ? HELPWINSTYLE_BALLOON : HELPWINSTYLE_QUICK; 293 HelpTextWindow* pHelpWin = new HelpTextWindow( pParent, rText, nHelpWinStyle, nStyle ); 294 295 sal_uIntPtr nId = reinterpret_cast< sal_uIntPtr >( pHelpWin ); 296 UpdateTip( nId, pParent, rScreenRect, rText ); 297 298 pHelpWin->ShowHelp( HELPDELAY_NONE ); 299 return nId; 300 } 301 302 // ----------------------------------------------------------------------- 303 304 void Help::UpdateTip( sal_uIntPtr nId, Window* pParent, const Rectangle& rScreenRect, const XubString& rText ) 305 { 306 HelpTextWindow* pHelpWin = reinterpret_cast< HelpTextWindow* >( nId ); 307 ENSURE_OR_RETURN_VOID( pHelpWin != NULL, "Help::UpdateTip: invalid ID!" ); 308 309 Size aSz = pHelpWin->CalcOutSize(); 310 pHelpWin->SetOutputSizePixel( aSz ); 311 ImplSetHelpWindowPos( pHelpWin, pHelpWin->GetWinStyle(), pHelpWin->GetStyle(), 312 pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), &rScreenRect ); 313 314 pHelpWin->SetHelpText( rText ); 315 pHelpWin->Invalidate(); 316 } 317 318 // ----------------------------------------------------------------------- 319 320 void Help::HideTip( sal_uLong nId ) 321 { 322 HelpTextWindow* pHelpWin = (HelpTextWindow*)nId; 323 Window* pFrameWindow = pHelpWin->ImplGetFrameWindow(); 324 pHelpWin->Hide(); 325 // Update ausloesen, damit ein Paint sofort ausgeloest wird, da 326 // wir den Hintergrund nicht sichern 327 pFrameWindow->ImplUpdateAll(); 328 delete pHelpWin; 329 ImplGetSVData()->maHelpData.mnLastHelpHideTime = Time::GetSystemTicks(); 330 } 331 332 // ======================================================================= 333 334 HelpTextWindow::HelpTextWindow( Window* pParent, const XubString& rText, sal_uInt16 nHelpWinStyle, sal_uInt16 nStyle ) : 335 //FloatingWindow( pParent->ImplGetFrameWindow(), WB_SYSTEMWINDOW ), 336 FloatingWindow( pParent, WB_SYSTEMWINDOW|WB_TOOLTIPWIN ), // #105827# if we change the parent, mirroring will not work correctly when positioning this window 337 maHelpText( rText ) 338 { 339 SetType( WINDOW_HELPTEXTWINDOW ); 340 ImplSetMouseTransparent( sal_True ); 341 mnHelpWinStyle = nHelpWinStyle; 342 mnStyle = nStyle; 343 // on windows this will raise the application window, because help windows are system windows now 344 // EnableAlwaysOnTop(); 345 EnableSaveBackground(); 346 347 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); 348 SetPointFont( rStyleSettings.GetHelpFont() ); 349 SetTextColor( rStyleSettings.GetHelpTextColor() ); 350 SetTextAlign( ALIGN_TOP ); 351 if ( IsNativeControlSupported( CTRL_TOOLTIP, PART_ENTIRE_CONTROL ) ) 352 { 353 EnableChildTransparentMode( sal_True ); 354 SetParentClipMode( PARENTCLIPMODE_NOCLIP ); 355 SetPaintTransparent( sal_True ); 356 SetBackground(); 357 } 358 else 359 SetBackground( Wallpaper( rStyleSettings.GetHelpColor() ) ); 360 if( rStyleSettings.GetHelpColor().IsDark() ) 361 SetLineColor( COL_WHITE ); 362 else 363 SetLineColor( COL_BLACK ); 364 SetFillColor(); 365 366 if( mnStyle & QUICKHELP_BIDI_RTL ) 367 { 368 sal_uLong nLayoutMode = GetLayoutMode(); 369 nLayoutMode |= TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT; 370 SetLayoutMode( nLayoutMode ); 371 } 372 SetHelpText( rText ); 373 Window::SetHelpText( rText ); 374 375 ImplSVData* pSVData = ImplGetSVData(); 376 if ( pSVData->maHelpData.mbSetKeyboardHelp ) 377 pSVData->maHelpData.mbKeyboardHelp = sal_True; 378 379 const HelpSettings& rHelpSettings = pParent->GetSettings().GetHelpSettings(); 380 maShowTimer.SetTimeoutHdl( LINK( this, HelpTextWindow, TimerHdl ) ); 381 maHideTimer.SetTimeoutHdl( LINK( this, HelpTextWindow, TimerHdl ) ); 382 maHideTimer.SetTimeout( rHelpSettings.GetTipTimeout() ); 383 } 384 385 // ----------------------------------------------------------------------- 386 387 HelpTextWindow::~HelpTextWindow() 388 { 389 maShowTimer.Stop(); 390 maHideTimer.Stop(); 391 392 if( this == ImplGetSVData()->maHelpData.mpHelpWin ) 393 ImplGetSVData()->maHelpData.mpHelpWin = NULL; 394 395 if ( maStatusText.Len() ) 396 { 397 ImplSVData* pSVData = ImplGetSVData(); 398 pSVData->mpApp->HideHelpStatusText(); 399 } 400 } 401 402 // ----------------------------------------------------------------------- 403 404 void HelpTextWindow::SetHelpText( const String& rHelpText ) 405 { 406 maHelpText = rHelpText; 407 if ( mnHelpWinStyle == HELPWINSTYLE_QUICK ) 408 { 409 Size aSize; 410 aSize.Height() = GetTextHeight(); 411 if ( mnStyle & QUICKHELP_CTRLTEXT ) 412 aSize.Width() = GetCtrlTextWidth( maHelpText ); 413 else 414 aSize.Width() = GetTextWidth( maHelpText ); 415 maTextRect = Rectangle( Point( HELPTEXTMARGIN_QUICK, HELPTEXTMARGIN_QUICK ), aSize ); 416 } 417 else // HELPWINSTYLE_BALLOON 418 { 419 Point aTmpPoint; 420 sal_uInt16 nCharsInLine = 35 + ((maHelpText.Len()/100)*5); 421 XubString aXXX; 422 aXXX.Fill( nCharsInLine, 'x' ); // Durchschnittliche Breite, damit nicht jedes Fenster anders. 423 long nWidth = GetTextWidth( aXXX ); 424 Size aTmpSize( nWidth, 0x7FFFFFFF ); 425 Rectangle aTry1( aTmpPoint, aTmpSize ); 426 sal_uInt16 nDrawFlags = TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK | 427 TEXT_DRAW_LEFT | TEXT_DRAW_TOP; 428 if ( mnStyle & QUICKHELP_CTRLTEXT ) 429 nDrawFlags |= TEXT_DRAW_MNEMONIC; 430 Rectangle aTextRect = GetTextRect( aTry1, maHelpText, nDrawFlags ); 431 432 // Spaeter mal eine geeignete Breite ermitteln... 433 maTextRect = aTextRect; 434 435 // Sicherheitsabstand... 436 maTextRect.SetPos( Point( HELPTEXTMARGIN_BALLOON, HELPTEXTMARGIN_BALLOON ) ); 437 } 438 439 Size aSize( CalcOutSize() ); 440 SetOutputSizePixel( aSize ); 441 } 442 443 // ----------------------------------------------------------------------- 444 445 void HelpTextWindow::ImplShow() 446 { 447 ImplDelData aDogTag( this ); 448 if ( maStatusText.Len() ) 449 { 450 ImplSVData* pSVData = ImplGetSVData(); 451 pSVData->mpApp->ShowHelpStatusText( maStatusText ); 452 } 453 Show( sal_True, SHOW_NOACTIVATE ); 454 if( !aDogTag.IsDelete() ) 455 Update(); 456 } 457 458 // ----------------------------------------------------------------------- 459 460 void HelpTextWindow::Paint( const Rectangle& ) 461 { 462 // paint native background 463 bool bNativeOK = false; 464 if ( IsNativeControlSupported( CTRL_TOOLTIP, PART_ENTIRE_CONTROL ) ) 465 { 466 // #i46472# workaround gcc3.3 temporary problem 467 Rectangle aCtrlRegion( Point( 0, 0 ), GetOutputSizePixel() ); 468 ImplControlValue aControlValue; 469 bNativeOK = DrawNativeControl( CTRL_TOOLTIP, PART_ENTIRE_CONTROL, aCtrlRegion, 470 0, aControlValue, rtl::OUString() ); 471 } 472 473 // paint text 474 if ( mnHelpWinStyle == HELPWINSTYLE_QUICK ) 475 { 476 if ( mnStyle & QUICKHELP_CTRLTEXT ) 477 DrawCtrlText( maTextRect.TopLeft(), maHelpText ); 478 else 479 DrawText( maTextRect.TopLeft(), maHelpText ); 480 } 481 else // HELPWINSTYLE_BALLOON 482 { 483 sal_uInt16 nDrawFlags = TEXT_DRAW_MULTILINE|TEXT_DRAW_WORDBREAK| 484 TEXT_DRAW_LEFT|TEXT_DRAW_TOP; 485 if ( mnStyle & QUICKHELP_CTRLTEXT ) 486 nDrawFlags |= TEXT_DRAW_MNEMONIC; 487 DrawText( maTextRect, maHelpText, nDrawFlags ); 488 } 489 490 // border 491 if( ! bNativeOK ) 492 { 493 Size aSz = GetOutputSizePixel(); 494 DrawRect( Rectangle( Point(), aSz ) ); 495 if ( mnHelpWinStyle == HELPWINSTYLE_BALLOON ) 496 { 497 aSz.Width() -= 2; 498 aSz.Height() -= 2; 499 Color aColor( GetLineColor() ); 500 SetLineColor( ( COL_GRAY ) ); 501 DrawRect( Rectangle( Point( 1, 1 ), aSz ) ); 502 SetLineColor( aColor ); 503 } 504 } 505 } 506 507 // ----------------------------------------------------------------------- 508 509 void HelpTextWindow::ShowHelp( sal_uInt16 nDelayMode ) 510 { 511 sal_uLong nTimeout = 0; 512 if ( nDelayMode != HELPDELAY_NONE ) 513 { 514 // Im ExtendedHelp-Fall die Hilfe schneller anzeigen 515 if ( ImplGetSVData()->maHelpData.mbExtHelpMode ) 516 nTimeout = 15; 517 else 518 { 519 const HelpSettings& rHelpSettings = GetSettings().GetHelpSettings(); 520 if ( mnHelpWinStyle == HELPWINSTYLE_QUICK ) 521 nTimeout = rHelpSettings.GetTipDelay(); 522 else 523 nTimeout = rHelpSettings.GetBalloonDelay(); 524 } 525 526 if ( nDelayMode == HELPDELAY_SHORT ) 527 nTimeout /= 3; 528 } 529 530 maShowTimer.SetTimeout( nTimeout ); 531 maShowTimer.Start(); 532 } 533 534 // ----------------------------------------------------------------------- 535 536 IMPL_LINK( HelpTextWindow, TimerHdl, Timer*, pTimer) 537 { 538 if ( pTimer == &maShowTimer ) 539 { 540 if ( mnHelpWinStyle == HELPWINSTYLE_QUICK ) 541 { 542 // start auto-hide-timer for non-ShowTip windows 543 ImplSVData* pSVData = ImplGetSVData(); 544 if ( this == pSVData->maHelpData.mpHelpWin ) 545 maHideTimer.Start(); 546 } 547 ImplShow(); 548 } 549 else 550 { 551 DBG_ASSERT( pTimer == &maHideTimer, "HelpTextWindow::TimerHdl with bad Timer" ); 552 ImplDestroyHelpWindow( true ); 553 } 554 555 return 1; 556 } 557 558 // ----------------------------------------------------------------------- 559 560 Size HelpTextWindow::CalcOutSize() const 561 { 562 Size aSz = maTextRect.GetSize(); 563 aSz.Width() += 2*maTextRect.Left(); 564 aSz.Height() += 2*maTextRect.Top(); 565 return aSz; 566 } 567 568 // ----------------------------------------------------------------------- 569 570 void HelpTextWindow::RequestHelp( const HelpEvent& /*rHEvt*/ ) 571 { 572 // Nur damit nicht von Window::RequestHelp() ein 573 // ShowQuickHelp/ShowBalloonHelp am HelpTextWindow aufgerufen wird. 574 } 575 576 // ----------------------------------------------------------------------- 577 578 String HelpTextWindow::GetText() const 579 { 580 return maHelpText; 581 } 582 583 // ----------------------------------------------------------------------- 584 585 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > HelpTextWindow::CreateAccessible() 586 { 587 return FloatingWindow::CreateAccessible(); 588 } 589 590 // ----------------------------------------------------------------------- 591 592 sal_Bool HelpTextWindow::RegisterAccessibleParent() 593 { 594 return sal_False; 595 } 596 597 // ----------------------------------------------------------------------- 598 599 void HelpTextWindow::RevokeAccessibleParent() 600 { 601 } 602 603 // ======================================================================= 604 605 void ImplShowHelpWindow( Window* pParent, sal_uInt16 nHelpWinStyle, sal_uInt16 nStyle, 606 const XubString& rHelpText, const XubString& rStatusText, 607 const Point& rScreenPos, const Rectangle* pHelpArea ) 608 { 609 ImplSVData* pSVData = ImplGetSVData(); 610 611 if( !rHelpText.Len() && !pSVData->maHelpData.mbRequestingHelp ) 612 return; 613 614 HelpTextWindow* pHelpWin = pSVData->maHelpData.mpHelpWin; 615 sal_uInt16 nDelayMode = HELPDELAY_NORMAL; 616 if ( pHelpWin ) 617 { 618 DBG_ASSERT( pHelpWin != pParent, "HelpInHelp ?!" ); 619 620 if ( ( ( pHelpWin->GetHelpText() != rHelpText ) 621 || ( pHelpWin->GetWinStyle() != nHelpWinStyle ) 622 || ( pHelpArea 623 && ( pHelpWin->GetHelpArea() != *pHelpArea ) 624 ) 625 ) 626 && pSVData->maHelpData.mbRequestingHelp 627 ) 628 { 629 // remove help window if no HelpText or other HelpText or 630 // other help mode. but keep it if we are scrolling, ie not requesting help 631 bool bWasVisible = pHelpWin->IsVisible(); 632 if ( bWasVisible ) 633 nDelayMode = HELPDELAY_NONE; // display it quickly if we were already in quick help mode 634 pHelpWin = NULL; 635 ImplDestroyHelpWindow( bWasVisible ); 636 } 637 else 638 { 639 bool const bTextChanged = rHelpText != pHelpWin->GetHelpText(); 640 if ( bTextChanged || ( ( nStyle & QUICKHELP_FORCE_REPOSITION ) != 0 ) ) 641 { 642 Window * pWindow = pHelpWin->GetParent()->ImplGetFrameWindow(); 643 Rectangle aInvRect( pHelpWin->GetWindowExtentsRelative( pWindow ) ); 644 if( pHelpWin->IsVisible() ) 645 pWindow->Invalidate( aInvRect ); 646 647 pHelpWin->SetHelpText( rHelpText ); 648 // approach mouse position 649 ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, pHelpArea ); 650 if( pHelpWin->IsVisible() ) 651 pHelpWin->Invalidate(); 652 } 653 } 654 } 655 656 if ( !pHelpWin && rHelpText.Len() ) 657 { 658 sal_uLong nCurTime = Time::GetSystemTicks(); 659 if ( ( ( nCurTime - pSVData->maHelpData.mnLastHelpHideTime ) < pParent->GetSettings().GetHelpSettings().GetTipDelay() ) 660 || ( ( nStyle & QUICKHELP_NO_DELAY ) != 0 ) 661 ) 662 nDelayMode = HELPDELAY_NONE; 663 664 DBG_ASSERT( !pHelpWin, "Noch ein HelpWin ?!" ); 665 pHelpWin = new HelpTextWindow( pParent, rHelpText, nHelpWinStyle, nStyle ); 666 pSVData->maHelpData.mpHelpWin = pHelpWin; 667 pHelpWin->SetStatusText( rStatusText ); 668 if ( pHelpArea ) 669 pHelpWin->SetHelpArea( *pHelpArea ); 670 671 // positioning 672 Size aSz = pHelpWin->CalcOutSize(); 673 pHelpWin->SetOutputSizePixel( aSz ); 674 ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, pHelpArea ); 675 // if not called from Window::RequestHelp, then without delay... 676 if ( !pSVData->maHelpData.mbRequestingHelp ) 677 nDelayMode = HELPDELAY_NONE; 678 pHelpWin->ShowHelp( nDelayMode ); 679 } 680 } 681 682 // ----------------------------------------------------------------------- 683 684 void ImplDestroyHelpWindow( bool bUpdateHideTime ) 685 { 686 ImplSVData* pSVData = ImplGetSVData(); 687 HelpTextWindow* pHelpWin = pSVData->maHelpData.mpHelpWin; 688 if ( pHelpWin ) 689 { 690 Window * pWindow = pHelpWin->GetParent()->ImplGetFrameWindow(); 691 // find out screen area covered by system help window 692 Rectangle aInvRect( pHelpWin->GetWindowExtentsRelative( pWindow ) ); 693 if( pHelpWin->IsVisible() ) 694 pWindow->Invalidate( aInvRect ); 695 pSVData->maHelpData.mpHelpWin = NULL; 696 pSVData->maHelpData.mbKeyboardHelp = sal_False; 697 pHelpWin->Hide(); 698 delete pHelpWin; 699 if( bUpdateHideTime ) 700 pSVData->maHelpData.mnLastHelpHideTime = Time::GetSystemTicks(); 701 } 702 } 703 704 // ----------------------------------------------------------------------- 705 706 void ImplSetHelpWindowPos( Window* pHelpWin, sal_uInt16 nHelpWinStyle, sal_uInt16 nStyle, 707 const Point& rPos, const Rectangle* pHelpArea ) 708 { 709 Point aPos = rPos; 710 Size aSz = pHelpWin->GetSizePixel(); 711 Rectangle aScreenRect = pHelpWin->ImplGetFrameWindow()->GetDesktopRectPixel(); 712 aPos = pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( aPos ); 713 // get mouse screen coords 714 Point mPos( pHelpWin->GetParent()->ImplGetFrameWindow()->GetPointerPosPixel() ); 715 mPos = pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( mPos ); 716 717 if ( nHelpWinStyle == HELPWINSTYLE_QUICK ) 718 { 719 if ( !(nStyle & QUICKHELP_NOAUTOPOS) ) 720 { 721 long nScreenHeight = aScreenRect.GetHeight(); 722 aPos.X() -= 4; 723 if ( aPos.Y() > aScreenRect.Top()+nScreenHeight-(nScreenHeight/4) ) 724 aPos.Y() -= aSz.Height()+4; 725 else 726 aPos.Y() += 21; 727 } 728 } 729 else 730 { 731 // If it's the mouse position, move the window slightly 732 // so the mouse pointer does not cover it 733 if ( aPos == mPos ) 734 { 735 aPos.X() += 12; 736 aPos.Y() += 16; 737 } 738 } 739 740 if ( nStyle & QUICKHELP_NOAUTOPOS ) 741 { 742 if ( pHelpArea ) 743 { 744 // convert help area to screen coords 745 Rectangle devHelpArea( 746 pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( pHelpArea->TopLeft() ), 747 pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( pHelpArea->BottomRight() ) ); 748 749 // Welche Position vom Rechteck? 750 aPos = devHelpArea.Center(); 751 752 if ( nStyle & QUICKHELP_LEFT ) 753 aPos.X() = devHelpArea.Left(); 754 else if ( nStyle & QUICKHELP_RIGHT ) 755 aPos.X() = devHelpArea.Right(); 756 757 if ( nStyle & QUICKHELP_TOP ) 758 aPos.Y() = devHelpArea.Top(); 759 else if ( nStyle & QUICKHELP_BOTTOM ) 760 aPos.Y() = devHelpArea.Bottom(); 761 } 762 763 // Welche Richtung? 764 if ( nStyle & QUICKHELP_LEFT ) 765 ; 766 else if ( nStyle & QUICKHELP_RIGHT ) 767 aPos.X() -= aSz.Width(); 768 else 769 aPos.X() -= aSz.Width()/2; 770 771 if ( nStyle & QUICKHELP_TOP ) 772 ; 773 else if ( nStyle & QUICKHELP_BOTTOM ) 774 aPos.Y() -= aSz.Height(); 775 else 776 aPos.Y() -= aSz.Height()/2; 777 } 778 779 if ( aPos.X() < aScreenRect.Left() ) 780 aPos.X() = aScreenRect.Left(); 781 else if ( ( aPos.X() + aSz.Width() ) > aScreenRect.Right() ) 782 aPos.X() = aScreenRect.Right() - aSz.Width(); 783 if ( aPos.Y() < aScreenRect.Top() ) 784 aPos.Y() = aScreenRect.Top(); 785 else if ( ( aPos.Y() + aSz.Height() ) > aScreenRect.Bottom() ) 786 aPos.Y() = aScreenRect.Bottom() - aSz.Height(); 787 788 if( ! (nStyle & QUICKHELP_NOEVADEPOINTER) ) 789 { 790 /* the remark below should be obsolete by now as the helpwindow should 791 not be focusable, leaving it as a hint. However it is sensible in most 792 conditions to evade the mouse pointer so the content window is fully visible. 793 794 // the popup must not appear under the mouse 795 // otherwise it would directly be closed due to a focus change... 796 */ 797 Rectangle aHelpRect( aPos, aSz ); 798 if( aHelpRect.IsInside( mPos ) ) 799 { 800 Point delta(2,2); 801 Point pSize( aSz.Width(), aSz.Height() ); 802 Point pTest( mPos - pSize - delta ); 803 if( pTest.X() > aScreenRect.Left() && pTest.Y() > aScreenRect.Top() ) 804 aPos = pTest; 805 else 806 aPos = mPos + delta; 807 } 808 } 809 810 Window* pWindow = pHelpWin->GetParent()->ImplGetFrameWindow(); 811 aPos = pWindow->AbsoluteScreenToOutputPixel( aPos ); 812 pHelpWin->SetPosPixel( aPos ); 813 } 814