xref: /AOO41X/main/vcl/source/app/help.cxx (revision 0406e650f5976ecb08a09d8623c16d4a678400cc)
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