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