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