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