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
Help()52 Help::Help()
53 {
54 }
55
~Help()56 Help::~Help()
57 {
58 }
59
60 // -----------------------------------------------------------------------
61
OpenHelpAgent(const rtl::OString &)62 void Help::OpenHelpAgent( const rtl::OString& )
63 {
64 }
65
66 // -----------------------------------------------------------------------
67
Start(const XubString &,const Window *)68 sal_Bool Help::Start( const XubString&, const Window* )
69 {
70 return sal_False;
71 }
72
SearchKeyword(const XubString &)73 sal_Bool Help::SearchKeyword( const XubString& )
74 {
75 return sal_False;
76 }
77
78 // -----------------------------------------------------------------------
79
GetHelpText(const String &,const Window *)80 XubString Help::GetHelpText( const String&, const Window* )
81 {
82 return ImplGetSVEmptyStr();
83 }
84
85 // -----------------------------------------------------------------------
86
EnableContextHelp()87 void Help::EnableContextHelp()
88 {
89 ImplGetSVData()->maHelpData.mbContextHelp = sal_True;
90 }
91
92 // -----------------------------------------------------------------------
93
DisableContextHelp()94 void Help::DisableContextHelp()
95 {
96 ImplGetSVData()->maHelpData.mbContextHelp = sal_False;
97 }
98
99 // -----------------------------------------------------------------------
100
IsContextHelpEnabled()101 sal_Bool Help::IsContextHelpEnabled()
102 {
103 return ImplGetSVData()->maHelpData.mbContextHelp;
104 }
105
106 // -----------------------------------------------------------------------
107
StartContextHelp()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
EnableExtHelp()129 void Help::EnableExtHelp()
130 {
131 ImplGetSVData()->maHelpData.mbExtHelp = sal_True;
132 }
133
134 // -----------------------------------------------------------------------
135
DisableExtHelp()136 void Help::DisableExtHelp()
137 {
138 ImplGetSVData()->maHelpData.mbExtHelp = sal_False;
139 }
140
141 // -----------------------------------------------------------------------
142
IsExtHelpEnabled()143 sal_Bool Help::IsExtHelpEnabled()
144 {
145 return ImplGetSVData()->maHelpData.mbExtHelp;
146 }
147
148 // -----------------------------------------------------------------------
149
StartExtHelp()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
EndExtHelp()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
IsExtHelpActive()187 sal_Bool Help::IsExtHelpActive()
188 {
189 return ImplGetSVData()->maHelpData.mbExtHelpMode;
190 }
191
192 // -----------------------------------------------------------------------
193
EnableBalloonHelp()194 void Help::EnableBalloonHelp()
195 {
196 ImplGetSVData()->maHelpData.mbBalloonHelp = sal_True;
197 }
198
199 // -----------------------------------------------------------------------
200
DisableBalloonHelp()201 void Help::DisableBalloonHelp()
202 {
203 ImplGetSVData()->maHelpData.mbBalloonHelp = sal_False;
204 }
205
206 // -----------------------------------------------------------------------
207
IsBalloonHelpEnabled()208 sal_Bool Help::IsBalloonHelpEnabled()
209 {
210 return ImplGetSVData()->maHelpData.mbBalloonHelp;
211 }
212
213 // -----------------------------------------------------------------------
214
ShowBalloon(Window * pParent,const Point & rScreenPos,const XubString & rHelpText)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
ShowBalloon(Window * pParent,const Point & rScreenPos,const Rectangle & rRect,const XubString & rHelpText)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
EnableQuickHelp()239 void Help::EnableQuickHelp()
240 {
241 ImplGetSVData()->maHelpData.mbQuickHelp = sal_True;
242 }
243
244 // -----------------------------------------------------------------------
245
DisableQuickHelp()246 void Help::DisableQuickHelp()
247 {
248 ImplGetSVData()->maHelpData.mbQuickHelp = sal_False;
249 }
250
251 // -----------------------------------------------------------------------
252
IsQuickHelpEnabled()253 sal_Bool Help::IsQuickHelpEnabled()
254 {
255 return ImplGetSVData()->maHelpData.mbQuickHelp;
256 }
257
258 // -----------------------------------------------------------------------
259
ShowQuickHelp(Window * pParent,const Rectangle & rScreenRect,const XubString & rHelpText,const XubString & rLongHelpText,sal_uInt16 nStyle)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
HideBalloonAndQuickHelp()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
ShowTip(Window * pParent,const Rectangle & rScreenRect,const XubString & rText,sal_uInt16 nStyle)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
UpdateTip(sal_uIntPtr nId,Window * pParent,const Rectangle & rScreenRect,const XubString & rText)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
HideTip(sal_uLong nId)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
HelpTextWindow(Window * pParent,const XubString & rText,sal_uInt16 nHelpWinStyle,sal_uInt16 nStyle)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
~HelpTextWindow()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
SetHelpText(const String & rHelpText)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
ImplShow()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
Paint(const Rectangle &)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
ShowHelp(sal_uInt16 nDelayMode)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
IMPL_LINK(HelpTextWindow,TimerHdl,Timer *,pTimer)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
CalcOutSize() const554 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
RequestHelp(const HelpEvent &)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
GetText() const572 String HelpTextWindow::GetText() const
573 {
574 return maHelpText;
575 }
576
577 // -----------------------------------------------------------------------
578
CreateAccessible()579 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > HelpTextWindow::CreateAccessible()
580 {
581 return FloatingWindow::CreateAccessible();
582 }
583
584 // -----------------------------------------------------------------------
585
RegisterAccessibleParent()586 sal_Bool HelpTextWindow::RegisterAccessibleParent()
587 {
588 return sal_False;
589 }
590
591 // -----------------------------------------------------------------------
592
RevokeAccessibleParent()593 void HelpTextWindow::RevokeAccessibleParent()
594 {
595 }
596
597 // =======================================================================
598
ImplShowHelpWindow(Window * pParent,sal_uInt16 nHelpWinStyle,sal_uInt16 nStyle,const XubString & rHelpText,const XubString & rStatusText,const Point & rScreenPos,const Rectangle * pHelpArea)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
ImplDestroyHelpWindow(bool bUpdateHideTime)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
ImplSetHelpWindowPos(Window * pHelpWin,sal_uInt16 nHelpWinStyle,sal_uInt16 nStyle,const Point & rPos,const Rectangle * pHelpArea)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