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