xref: /trunk/main/vcl/source/app/help.cxx (revision 9f62ea84)
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