xref: /AOO41X/main/vcl/source/app/help.cxx (revision 4f6e4eb85772a3db55551304f0b8885a7ef915af)
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
45 
46 #define HELPDELAY_NORMAL		1
47 #define HELPDELAY_SHORT 		2
48 #define HELPDELAY_NONE			3
49 
50 // =======================================================================
51 
52 Help::Help()
53 {
54 }
55 
56 Help::~Help()
57 {
58 }
59 
60 // -----------------------------------------------------------------------
61 
62 void Help::OpenHelpAgent( const rtl::OString& )
63 {
64 }
65 
66 // -----------------------------------------------------------------------
67 
68 sal_Bool Help::Start( const XubString&, const Window* )
69 {
70 	return sal_False;
71 }
72 
73 sal_Bool Help::SearchKeyword( const XubString& )
74 {
75 	return sal_False;
76 }
77 
78 // -----------------------------------------------------------------------
79 
80 XubString Help::GetHelpText( const String&, const Window* )
81 {
82 	return ImplGetSVEmptyStr();
83 }
84 
85 // -----------------------------------------------------------------------
86 
87 void Help::EnableContextHelp()
88 {
89 	ImplGetSVData()->maHelpData.mbContextHelp = sal_True;
90 }
91 
92 // -----------------------------------------------------------------------
93 
94 void Help::DisableContextHelp()
95 {
96 	ImplGetSVData()->maHelpData.mbContextHelp = sal_False;
97 }
98 
99 // -----------------------------------------------------------------------
100 
101 sal_Bool Help::IsContextHelpEnabled()
102 {
103 	return ImplGetSVData()->maHelpData.mbContextHelp;
104 }
105 
106 // -----------------------------------------------------------------------
107 
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 
129 void Help::EnableExtHelp()
130 {
131 	ImplGetSVData()->maHelpData.mbExtHelp = sal_True;
132 }
133 
134 // -----------------------------------------------------------------------
135 
136 void Help::DisableExtHelp()
137 {
138 	ImplGetSVData()->maHelpData.mbExtHelp = sal_False;
139 }
140 
141 // -----------------------------------------------------------------------
142 
143 sal_Bool Help::IsExtHelpEnabled()
144 {
145 	return ImplGetSVData()->maHelpData.mbExtHelp;
146 }
147 
148 // -----------------------------------------------------------------------
149 
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 
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 
187 sal_Bool Help::IsExtHelpActive()
188 {
189 	return ImplGetSVData()->maHelpData.mbExtHelpMode;
190 }
191 
192 // -----------------------------------------------------------------------
193 
194 void Help::EnableBalloonHelp()
195 {
196 	ImplGetSVData()->maHelpData.mbBalloonHelp = sal_True;
197 }
198 
199 // -----------------------------------------------------------------------
200 
201 void Help::DisableBalloonHelp()
202 {
203 	ImplGetSVData()->maHelpData.mbBalloonHelp = sal_False;
204 }
205 
206 // -----------------------------------------------------------------------
207 
208 sal_Bool Help::IsBalloonHelpEnabled()
209 {
210 	return ImplGetSVData()->maHelpData.mbBalloonHelp;
211 }
212 
213 // -----------------------------------------------------------------------
214 
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 
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 
239 void Help::EnableQuickHelp()
240 {
241 	ImplGetSVData()->maHelpData.mbQuickHelp = sal_True;
242 }
243 
244 // -----------------------------------------------------------------------
245 
246 void Help::DisableQuickHelp()
247 {
248 	ImplGetSVData()->maHelpData.mbQuickHelp = sal_False;
249 }
250 
251 // -----------------------------------------------------------------------
252 
253 sal_Bool Help::IsQuickHelpEnabled()
254 {
255 	return ImplGetSVData()->maHelpData.mbQuickHelp;
256 }
257 
258 // -----------------------------------------------------------------------
259 
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 
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 
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 
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 
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 
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 
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 
398 void HelpTextWindow::SetHelpText( const String& rHelpText )
399 {
400 	maHelpText = rHelpText;
401 	if ( mnHelpWinStyle == HELPWINSTYLE_QUICK )
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 
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 
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 )
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 )
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 
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 
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 
554 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 
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 
572 String HelpTextWindow::GetText() const
573 {
574 	return maHelpText;
575 }
576 
577 // -----------------------------------------------------------------------
578 
579 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > HelpTextWindow::CreateAccessible()
580 {
581 	return FloatingWindow::CreateAccessible();
582 }
583 
584 // -----------------------------------------------------------------------
585 
586 sal_Bool HelpTextWindow::RegisterAccessibleParent()
587 {
588 		return sal_False;
589 }
590 
591 // -----------------------------------------------------------------------
592 
593 void HelpTextWindow::RevokeAccessibleParent()
594 {
595 }
596 
597 // =======================================================================
598 
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 
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 
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 		// Welche Richtung?
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