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