Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <comphelper/string.hxx>
21 :
22 : #include "tools/debug.hxx"
23 : #include "tools/diagnose_ex.h"
24 : #include "tools/time.hxx"
25 :
26 : #include "vcl/window.hxx"
27 : #include "vcl/event.hxx"
28 : #include "vcl/svapp.hxx"
29 : #include "vcl/wrkwin.hxx"
30 : #include "vcl/help.hxx"
31 : #include "vcl/settings.hxx"
32 :
33 : #include "helpwin.hxx"
34 : #include "svdata.hxx"
35 :
36 : #define HELPWINSTYLE_QUICK 0
37 : #define HELPWINSTYLE_BALLOON 1
38 :
39 : #define HELPTEXTMARGIN_QUICK 3
40 : #define HELPTEXTMARGIN_BALLOON 6
41 :
42 : #define HELPDELAY_NORMAL 1
43 : #define HELPDELAY_SHORT 2
44 : #define HELPDELAY_NONE 3
45 :
46 : #define HELPTEXTMAXLEN 150
47 :
48 0 : Help::Help()
49 : {
50 0 : }
51 :
52 0 : Help::~Help()
53 : {
54 0 : }
55 :
56 0 : bool Help::Start( const OUString&, const Window* )
57 : {
58 0 : return false;
59 : }
60 :
61 0 : bool Help::SearchKeyword( const OUString& )
62 : {
63 0 : return false;
64 : }
65 :
66 0 : OUString Help::GetHelpText( const OUString&, const Window* )
67 : {
68 0 : return OUString();
69 : }
70 :
71 0 : void Help::EnableContextHelp()
72 : {
73 0 : ImplGetSVData()->maHelpData.mbContextHelp = true;
74 0 : }
75 :
76 0 : void Help::DisableContextHelp()
77 : {
78 0 : ImplGetSVData()->maHelpData.mbContextHelp = false;
79 0 : }
80 :
81 0 : bool Help::IsContextHelpEnabled()
82 : {
83 0 : return ImplGetSVData()->maHelpData.mbContextHelp;
84 : }
85 :
86 0 : void Help::EnableExtHelp()
87 : {
88 0 : ImplGetSVData()->maHelpData.mbExtHelp = true;
89 0 : }
90 :
91 0 : void Help::DisableExtHelp()
92 : {
93 0 : ImplGetSVData()->maHelpData.mbExtHelp = false;
94 0 : }
95 :
96 0 : bool Help::IsExtHelpEnabled()
97 : {
98 0 : return ImplGetSVData()->maHelpData.mbExtHelp;
99 : }
100 :
101 0 : bool Help::StartExtHelp()
102 : {
103 0 : ImplSVData* pSVData = ImplGetSVData();
104 :
105 0 : if ( pSVData->maHelpData.mbExtHelp && !pSVData->maHelpData.mbExtHelpMode )
106 : {
107 0 : pSVData->maHelpData.mbExtHelpMode = true;
108 0 : pSVData->maHelpData.mbOldBalloonMode = pSVData->maHelpData.mbBalloonHelp;
109 0 : pSVData->maHelpData.mbBalloonHelp = true;
110 0 : if ( pSVData->maWinData.mpAppWin )
111 0 : pSVData->maWinData.mpAppWin->ImplGenerateMouseMove();
112 0 : return true;
113 : }
114 :
115 0 : return false;
116 : }
117 :
118 0 : bool Help::EndExtHelp()
119 : {
120 0 : ImplSVData* pSVData = ImplGetSVData();
121 :
122 0 : if ( pSVData->maHelpData.mbExtHelp && pSVData->maHelpData.mbExtHelpMode )
123 : {
124 0 : pSVData->maHelpData.mbExtHelpMode = false;
125 0 : pSVData->maHelpData.mbBalloonHelp = pSVData->maHelpData.mbOldBalloonMode;
126 0 : if ( pSVData->maWinData.mpAppWin )
127 0 : pSVData->maWinData.mpAppWin->ImplGenerateMouseMove();
128 0 : return true;
129 : }
130 :
131 0 : return false;
132 : }
133 :
134 0 : void Help::EnableBalloonHelp()
135 : {
136 0 : ImplGetSVData()->maHelpData.mbBalloonHelp = true;
137 0 : }
138 :
139 0 : void Help::DisableBalloonHelp()
140 : {
141 0 : ImplGetSVData()->maHelpData.mbBalloonHelp = false;
142 0 : }
143 :
144 0 : bool Help::IsBalloonHelpEnabled()
145 : {
146 0 : return ImplGetSVData()->maHelpData.mbBalloonHelp;
147 : }
148 :
149 0 : bool Help::ShowBalloon( Window* pParent,
150 : const Point& rScreenPos,
151 : const OUString& rHelpText )
152 : {
153 : ImplShowHelpWindow( pParent, HELPWINSTYLE_BALLOON, 0,
154 0 : rHelpText, OUString(), rScreenPos );
155 :
156 0 : return true;
157 : }
158 :
159 0 : bool Help::ShowBalloon( Window* pParent,
160 : const Point& rScreenPos, const Rectangle& rRect,
161 : const OUString& rHelpText )
162 : {
163 : ImplShowHelpWindow( pParent, HELPWINSTYLE_BALLOON, 0,
164 0 : rHelpText, OUString(), rScreenPos, &rRect );
165 :
166 0 : return true;
167 : }
168 :
169 0 : void Help::EnableQuickHelp()
170 : {
171 0 : ImplGetSVData()->maHelpData.mbQuickHelp = true;
172 0 : }
173 :
174 0 : void Help::DisableQuickHelp()
175 : {
176 0 : ImplGetSVData()->maHelpData.mbQuickHelp = false;
177 0 : }
178 :
179 0 : bool Help::IsQuickHelpEnabled()
180 : {
181 0 : return ImplGetSVData()->maHelpData.mbQuickHelp;
182 : }
183 :
184 0 : bool Help::ShowQuickHelp( Window* pParent,
185 : const Rectangle& rScreenRect,
186 : const OUString& rHelpText,
187 : const OUString& rLongHelpText,
188 : sal_uInt16 nStyle )
189 : {
190 : ImplShowHelpWindow( pParent, HELPWINSTYLE_QUICK, nStyle,
191 : rHelpText, rLongHelpText,
192 0 : pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), &rScreenRect );
193 0 : return true;
194 : }
195 :
196 0 : void Help::HideBalloonAndQuickHelp()
197 : {
198 0 : HelpTextWindow const * pHelpWin = ImplGetSVData()->maHelpData.mpHelpWin;
199 0 : bool const bIsVisible = ( pHelpWin != NULL ) && pHelpWin->IsVisible();
200 0 : ImplDestroyHelpWindow( bIsVisible );
201 0 : }
202 :
203 0 : sal_uIntPtr Help::ShowTip( Window* pParent, const Rectangle& rScreenRect,
204 : const OUString& rText, sal_uInt16 nStyle )
205 : {
206 0 : sal_uInt16 nHelpWinStyle = ( ( nStyle & QUICKHELP_TIP_STYLE_BALLOON ) != 0 ) ? HELPWINSTYLE_BALLOON : HELPWINSTYLE_QUICK;
207 0 : HelpTextWindow* pHelpWin = new HelpTextWindow( pParent, rText, nHelpWinStyle, nStyle );
208 :
209 0 : sal_uIntPtr nId = reinterpret_cast< sal_uIntPtr >( pHelpWin );
210 0 : UpdateTip( nId, pParent, rScreenRect, rText );
211 :
212 0 : pHelpWin->ShowHelp( HELPDELAY_NONE );
213 0 : return nId;
214 : }
215 :
216 0 : void Help::UpdateTip( sal_uIntPtr nId, Window* pParent, const Rectangle& rScreenRect, const OUString& rText )
217 : {
218 0 : HelpTextWindow* pHelpWin = reinterpret_cast< HelpTextWindow* >( nId );
219 0 : ENSURE_OR_RETURN_VOID( pHelpWin != NULL, "Help::UpdateTip: invalid ID!" );
220 :
221 0 : Size aSz = pHelpWin->CalcOutSize();
222 0 : pHelpWin->SetOutputSizePixel( aSz );
223 0 : ImplSetHelpWindowPos( pHelpWin, pHelpWin->GetWinStyle(), pHelpWin->GetStyle(),
224 0 : pParent->OutputToScreenPixel( pParent->GetPointerPosPixel() ), &rScreenRect );
225 :
226 0 : pHelpWin->SetHelpText( rText );
227 0 : pHelpWin->Invalidate();
228 : }
229 :
230 0 : void Help::HideTip( sal_uLong nId )
231 : {
232 0 : HelpTextWindow* pHelpWin = (HelpTextWindow*)nId;
233 0 : Window* pFrameWindow = pHelpWin->ImplGetFrameWindow();
234 0 : pHelpWin->Hide();
235 : // trigger update, so that a Paint is instantly triggered since we do not save the background
236 0 : pFrameWindow->ImplUpdateAll();
237 0 : delete pHelpWin;
238 0 : ImplGetSVData()->maHelpData.mnLastHelpHideTime = Time::GetSystemTicks();
239 0 : }
240 :
241 0 : HelpTextWindow::HelpTextWindow( Window* pParent, const OUString& rText, sal_uInt16 nHelpWinStyle, sal_uInt16 nStyle ) :
242 : FloatingWindow( pParent, WB_SYSTEMWINDOW|WB_TOOLTIPWIN ), // #105827# if we change the parent, mirroring will not work correctly when positioning this window
243 0 : maHelpText( rText )
244 : {
245 0 : SetType( WINDOW_HELPTEXTWINDOW );
246 0 : ImplSetMouseTransparent( true );
247 0 : mnHelpWinStyle = nHelpWinStyle;
248 0 : mnStyle = nStyle;
249 : // on windows this will raise the application window, because help windows are system windows now
250 : // EnableAlwaysOnTop();
251 0 : EnableSaveBackground();
252 :
253 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
254 0 : SetPointFont( rStyleSettings.GetHelpFont() );
255 0 : SetTextColor( rStyleSettings.GetHelpTextColor() );
256 0 : SetTextAlign( ALIGN_TOP );
257 0 : if ( IsNativeControlSupported( CTRL_TOOLTIP, PART_ENTIRE_CONTROL ) )
258 : {
259 0 : EnableChildTransparentMode( true );
260 0 : SetParentClipMode( PARENTCLIPMODE_NOCLIP );
261 0 : SetPaintTransparent( true );
262 0 : SetBackground();
263 : }
264 : else
265 0 : SetBackground( Wallpaper( rStyleSettings.GetHelpColor() ) );
266 0 : if( rStyleSettings.GetHelpColor().IsDark() )
267 0 : SetLineColor( COL_WHITE );
268 : else
269 0 : SetLineColor( COL_BLACK );
270 0 : SetFillColor();
271 :
272 0 : if( mnStyle & QUICKHELP_BIDI_RTL )
273 : {
274 0 : sal_uLong nLayoutMode = GetLayoutMode();
275 0 : nLayoutMode |= TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT;
276 0 : SetLayoutMode( nLayoutMode );
277 : }
278 0 : SetHelpText( rText );
279 0 : Window::SetHelpText( rText );
280 :
281 0 : ImplSVData* pSVData = ImplGetSVData();
282 0 : if ( pSVData->maHelpData.mbSetKeyboardHelp )
283 0 : pSVData->maHelpData.mbKeyboardHelp = true;
284 :
285 0 : const HelpSettings& rHelpSettings = pParent->GetSettings().GetHelpSettings();
286 0 : maShowTimer.SetTimeoutHdl( LINK( this, HelpTextWindow, TimerHdl ) );
287 0 : maHideTimer.SetTimeoutHdl( LINK( this, HelpTextWindow, TimerHdl ) );
288 0 : maHideTimer.SetTimeout( rHelpSettings.GetTipTimeout() );
289 0 : }
290 :
291 0 : HelpTextWindow::~HelpTextWindow()
292 : {
293 0 : maShowTimer.Stop();
294 0 : maHideTimer.Stop();
295 :
296 0 : if( this == ImplGetSVData()->maHelpData.mpHelpWin )
297 0 : ImplGetSVData()->maHelpData.mpHelpWin = NULL;
298 0 : }
299 :
300 0 : void HelpTextWindow::SetHelpText( const OUString& rHelpText )
301 : {
302 0 : maHelpText = rHelpText;
303 0 : if ( mnHelpWinStyle == HELPWINSTYLE_QUICK && maHelpText.getLength() < HELPTEXTMAXLEN)
304 : {
305 0 : Size aSize;
306 0 : aSize.Height() = GetTextHeight();
307 0 : if ( mnStyle & QUICKHELP_CTRLTEXT )
308 0 : aSize.Width() = GetCtrlTextWidth( maHelpText );
309 : else
310 0 : aSize.Width() = GetTextWidth( maHelpText );
311 0 : maTextRect = Rectangle( Point( HELPTEXTMARGIN_QUICK, HELPTEXTMARGIN_QUICK ), aSize );
312 : }
313 : else // HELPWINSTYLE_BALLOON
314 : {
315 0 : Point aTmpPoint;
316 0 : sal_Int32 nCharsInLine = 35 + ((maHelpText.getLength()/100)*5);
317 : // average width to have all windows consistent
318 0 : OUStringBuffer aBuf;
319 0 : comphelper::string::padToLength(aBuf, nCharsInLine, 'x');
320 0 : OUString aXXX = aBuf.makeStringAndClear();
321 0 : long nWidth = GetTextWidth( aXXX );
322 0 : Size aTmpSize( nWidth, 0x7FFFFFFF );
323 0 : Rectangle aTry1( aTmpPoint, aTmpSize );
324 : sal_uInt16 nDrawFlags = TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK |
325 0 : TEXT_DRAW_LEFT | TEXT_DRAW_TOP;
326 0 : if ( mnStyle & QUICKHELP_CTRLTEXT )
327 0 : nDrawFlags |= TEXT_DRAW_MNEMONIC;
328 0 : Rectangle aTextRect = GetTextRect( aTry1, maHelpText, nDrawFlags );
329 :
330 : // get a better width later...
331 0 : maTextRect = aTextRect;
332 :
333 : // safety distance...
334 0 : maTextRect.SetPos( Point( HELPTEXTMARGIN_BALLOON, HELPTEXTMARGIN_BALLOON ) );
335 : }
336 :
337 0 : Size aSize( CalcOutSize() );
338 0 : SetOutputSizePixel( aSize );
339 0 : }
340 :
341 0 : void HelpTextWindow::ImplShow()
342 : {
343 0 : ImplDelData aDogTag( this );
344 0 : Show( true, SHOW_NOACTIVATE );
345 0 : if( !aDogTag.IsDead() )
346 0 : Update();
347 0 : }
348 :
349 0 : void HelpTextWindow::Paint( const Rectangle& )
350 : {
351 : // paint native background
352 0 : bool bNativeOK = false;
353 0 : if ( IsNativeControlSupported( CTRL_TOOLTIP, PART_ENTIRE_CONTROL ) )
354 : {
355 : // #i46472# workaround gcc3.3 temporary problem
356 0 : Rectangle aCtrlRegion( Point( 0, 0 ), GetOutputSizePixel() );
357 0 : ImplControlValue aControlValue;
358 : bNativeOK = DrawNativeControl( CTRL_TOOLTIP, PART_ENTIRE_CONTROL, aCtrlRegion,
359 0 : 0, aControlValue, OUString() );
360 : }
361 :
362 : // paint text
363 0 : if ( mnHelpWinStyle == HELPWINSTYLE_QUICK && maHelpText.getLength() < HELPTEXTMAXLEN)
364 : {
365 0 : if ( mnStyle & QUICKHELP_CTRLTEXT )
366 0 : DrawCtrlText( maTextRect.TopLeft(), maHelpText );
367 : else
368 0 : DrawText( maTextRect.TopLeft(), maHelpText );
369 : }
370 : else // HELPWINSTYLE_BALLOON
371 : {
372 : sal_uInt16 nDrawFlags = TEXT_DRAW_MULTILINE|TEXT_DRAW_WORDBREAK|
373 0 : TEXT_DRAW_LEFT|TEXT_DRAW_TOP;
374 0 : if ( mnStyle & QUICKHELP_CTRLTEXT )
375 0 : nDrawFlags |= TEXT_DRAW_MNEMONIC;
376 0 : DrawText( maTextRect, maHelpText, nDrawFlags );
377 : }
378 :
379 : // border
380 0 : if( ! bNativeOK )
381 : {
382 0 : Size aSz = GetOutputSizePixel();
383 0 : DrawRect( Rectangle( Point(), aSz ) );
384 0 : if ( mnHelpWinStyle == HELPWINSTYLE_BALLOON )
385 : {
386 0 : aSz.Width() -= 2;
387 0 : aSz.Height() -= 2;
388 0 : Color aColor( GetLineColor() );
389 0 : SetLineColor( ( COL_GRAY ) );
390 0 : DrawRect( Rectangle( Point( 1, 1 ), aSz ) );
391 0 : SetLineColor( aColor );
392 : }
393 : }
394 0 : }
395 :
396 0 : void HelpTextWindow::ShowHelp( sal_uInt16 nDelayMode )
397 : {
398 0 : sal_uLong nTimeout = 0;
399 0 : if ( nDelayMode != HELPDELAY_NONE )
400 : {
401 : // In case of ExtendedHelp display help sooner
402 0 : if ( ImplGetSVData()->maHelpData.mbExtHelpMode )
403 0 : nTimeout = 15;
404 : else
405 : {
406 0 : const HelpSettings& rHelpSettings = GetSettings().GetHelpSettings();
407 0 : if ( mnHelpWinStyle == HELPWINSTYLE_QUICK )
408 0 : nTimeout = rHelpSettings.GetTipDelay();
409 : else
410 0 : nTimeout = rHelpSettings.GetBalloonDelay();
411 : }
412 :
413 0 : if ( nDelayMode == HELPDELAY_SHORT )
414 0 : nTimeout /= 3;
415 : }
416 :
417 0 : maShowTimer.SetTimeout( nTimeout );
418 0 : maShowTimer.Start();
419 0 : }
420 :
421 0 : IMPL_LINK( HelpTextWindow, TimerHdl, Timer*, pTimer)
422 : {
423 0 : if ( pTimer == &maShowTimer )
424 : {
425 0 : if ( mnHelpWinStyle == HELPWINSTYLE_QUICK )
426 : {
427 : // start auto-hide-timer for non-ShowTip windows
428 0 : ImplSVData* pSVData = ImplGetSVData();
429 0 : if ( this == pSVData->maHelpData.mpHelpWin )
430 0 : maHideTimer.Start();
431 : }
432 0 : ImplShow();
433 : }
434 : else
435 : {
436 : DBG_ASSERT( pTimer == &maHideTimer, "HelpTextWindow::TimerHdl with bad Timer" );
437 0 : ImplDestroyHelpWindow( true );
438 : }
439 :
440 0 : return 1;
441 : }
442 :
443 0 : Size HelpTextWindow::CalcOutSize() const
444 : {
445 0 : Size aSz = maTextRect.GetSize();
446 0 : aSz.Width() += 2*maTextRect.Left();
447 0 : aSz.Height() += 2*maTextRect.Top();
448 0 : return aSz;
449 : }
450 :
451 0 : void HelpTextWindow::RequestHelp( const HelpEvent& /*rHEvt*/ )
452 : {
453 : // Just to assure that Window::RequestHelp() is not called by
454 : // ShowQuickHelp/ShowBalloonHelp in the HelpTextWindow.
455 0 : }
456 :
457 0 : OUString HelpTextWindow::GetText() const
458 : {
459 0 : return maHelpText;
460 : }
461 :
462 0 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > HelpTextWindow::CreateAccessible()
463 : {
464 0 : return FloatingWindow::CreateAccessible();
465 : }
466 :
467 0 : void ImplShowHelpWindow( Window* pParent, sal_uInt16 nHelpWinStyle, sal_uInt16 nStyle,
468 : const OUString& rHelpText, const OUString& rStatusText,
469 : const Point& rScreenPos, const Rectangle* pHelpArea )
470 : {
471 0 : ImplSVData* pSVData = ImplGetSVData();
472 :
473 0 : if (rHelpText.isEmpty() && !pSVData->maHelpData.mbRequestingHelp)
474 0 : return;
475 :
476 0 : HelpTextWindow* pHelpWin = pSVData->maHelpData.mpHelpWin;
477 0 : sal_uInt16 nDelayMode = HELPDELAY_NORMAL;
478 0 : if ( pHelpWin )
479 : {
480 : DBG_ASSERT( pHelpWin != pParent, "HelpInHelp ?!" );
481 :
482 0 : if ( ( ( pHelpWin->GetHelpText() != rHelpText )
483 0 : || ( pHelpWin->GetWinStyle() != nHelpWinStyle )
484 0 : || ( pHelpArea
485 0 : && ( pHelpWin->GetHelpArea() != *pHelpArea )
486 : )
487 : )
488 0 : && pSVData->maHelpData.mbRequestingHelp
489 : )
490 : {
491 : // remove help window if no HelpText or other HelpText or
492 : // other help mode. but keep it if we are scrolling, ie not requesting help
493 0 : bool bWasVisible = pHelpWin->IsVisible();
494 0 : if ( bWasVisible )
495 0 : nDelayMode = HELPDELAY_NONE; // display it quickly if we were already in quick help mode
496 0 : pHelpWin = NULL;
497 0 : ImplDestroyHelpWindow( bWasVisible );
498 : }
499 : else
500 : {
501 0 : bool const bTextChanged = rHelpText != pHelpWin->GetHelpText();
502 0 : if ( bTextChanged || ( ( nStyle & QUICKHELP_FORCE_REPOSITION ) != 0 ) )
503 : {
504 0 : Window * pWindow = pHelpWin->GetParent()->ImplGetFrameWindow();
505 0 : Rectangle aInvRect( pHelpWin->GetWindowExtentsRelative( pWindow ) );
506 0 : if( pHelpWin->IsVisible() )
507 0 : pWindow->Invalidate( aInvRect );
508 :
509 0 : pHelpWin->SetHelpText( rHelpText );
510 : // approach mouse position
511 0 : ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, pHelpArea );
512 0 : if( pHelpWin->IsVisible() )
513 0 : pHelpWin->Invalidate();
514 : }
515 : }
516 : }
517 :
518 0 : if (!pHelpWin && !rHelpText.isEmpty())
519 : {
520 0 : sal_uLong nCurTime = Time::GetSystemTicks();
521 0 : if ( ( ( nCurTime - pSVData->maHelpData.mnLastHelpHideTime ) < pParent->GetSettings().GetHelpSettings().GetTipDelay() )
522 0 : || ( ( nStyle & QUICKHELP_NO_DELAY ) != 0 )
523 : )
524 0 : nDelayMode = HELPDELAY_NONE;
525 :
526 : DBG_ASSERT( !pHelpWin, "Noch ein HelpWin ?!" );
527 0 : pHelpWin = new HelpTextWindow( pParent, rHelpText, nHelpWinStyle, nStyle );
528 0 : pSVData->maHelpData.mpHelpWin = pHelpWin;
529 0 : pHelpWin->SetStatusText( rStatusText );
530 0 : if ( pHelpArea )
531 0 : pHelpWin->SetHelpArea( *pHelpArea );
532 :
533 : // positioning
534 0 : Size aSz = pHelpWin->CalcOutSize();
535 0 : pHelpWin->SetOutputSizePixel( aSz );
536 0 : ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, pHelpArea );
537 : // if not called from Window::RequestHelp, then without delay...
538 0 : if ( !pSVData->maHelpData.mbRequestingHelp )
539 0 : nDelayMode = HELPDELAY_NONE;
540 0 : pHelpWin->ShowHelp( nDelayMode );
541 : }
542 : }
543 :
544 0 : void ImplDestroyHelpWindow( bool bUpdateHideTime )
545 : {
546 0 : ImplSVData* pSVData = ImplGetSVData();
547 0 : HelpTextWindow* pHelpWin = pSVData->maHelpData.mpHelpWin;
548 0 : if ( pHelpWin )
549 : {
550 0 : Window * pWindow = pHelpWin->GetParent()->ImplGetFrameWindow();
551 : // find out screen area covered by system help window
552 0 : Rectangle aInvRect( pHelpWin->GetWindowExtentsRelative( pWindow ) );
553 0 : if( pHelpWin->IsVisible() )
554 0 : pWindow->Invalidate( aInvRect );
555 0 : pSVData->maHelpData.mpHelpWin = NULL;
556 0 : pSVData->maHelpData.mbKeyboardHelp = false;
557 0 : pHelpWin->Hide();
558 0 : delete pHelpWin;
559 0 : if( bUpdateHideTime )
560 0 : pSVData->maHelpData.mnLastHelpHideTime = Time::GetSystemTicks();
561 : }
562 0 : }
563 :
564 0 : void ImplSetHelpWindowPos( Window* pHelpWin, sal_uInt16 nHelpWinStyle, sal_uInt16 nStyle,
565 : const Point& rPos, const Rectangle* pHelpArea )
566 : {
567 0 : Point aPos = rPos;
568 0 : Size aSz = pHelpWin->GetSizePixel();
569 0 : Rectangle aScreenRect = pHelpWin->ImplGetFrameWindow()->GetDesktopRectPixel();
570 0 : aPos = pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( aPos );
571 : // get mouse screen coords
572 0 : Point mPos( pHelpWin->GetParent()->ImplGetFrameWindow()->GetPointerPosPixel() );
573 0 : mPos = pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( mPos );
574 :
575 0 : if ( nHelpWinStyle == HELPWINSTYLE_QUICK )
576 : {
577 0 : if ( !(nStyle & QUICKHELP_NOAUTOPOS) )
578 : {
579 0 : long nScreenHeight = aScreenRect.GetHeight();
580 0 : aPos.X() -= 4;
581 0 : if ( aPos.Y() > aScreenRect.Top()+nScreenHeight-(nScreenHeight/4) )
582 0 : aPos.Y() -= aSz.Height()+4;
583 : else
584 0 : aPos.Y() += 21;
585 : }
586 : }
587 : else
588 : {
589 : // If it's the mouse position, move the window slightly
590 : // so the mouse pointer does not cover it
591 0 : if ( aPos == mPos )
592 : {
593 0 : aPos.X() += 12;
594 0 : aPos.Y() += 16;
595 : }
596 : }
597 :
598 0 : if ( nStyle & QUICKHELP_NOAUTOPOS )
599 : {
600 0 : if ( pHelpArea )
601 : {
602 : // convert help area to screen coords
603 : Rectangle devHelpArea(
604 0 : pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( pHelpArea->TopLeft() ),
605 0 : pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( pHelpArea->BottomRight() ) );
606 :
607 : // Welche Position vom Rechteck?
608 0 : aPos = devHelpArea.Center();
609 :
610 0 : if ( nStyle & QUICKHELP_LEFT )
611 0 : aPos.X() = devHelpArea.Left();
612 0 : else if ( nStyle & QUICKHELP_RIGHT )
613 0 : aPos.X() = devHelpArea.Right();
614 :
615 0 : if ( nStyle & QUICKHELP_TOP )
616 0 : aPos.Y() = devHelpArea.Top();
617 0 : else if ( nStyle & QUICKHELP_BOTTOM )
618 0 : aPos.Y() = devHelpArea.Bottom();
619 : }
620 :
621 : // which direction?
622 0 : if ( nStyle & QUICKHELP_LEFT )
623 : ;
624 0 : else if ( nStyle & QUICKHELP_RIGHT )
625 0 : aPos.X() -= aSz.Width();
626 : else
627 0 : aPos.X() -= aSz.Width()/2;
628 :
629 0 : if ( nStyle & QUICKHELP_TOP )
630 : ;
631 0 : else if ( nStyle & QUICKHELP_BOTTOM )
632 0 : aPos.Y() -= aSz.Height();
633 : else
634 0 : aPos.Y() -= aSz.Height()/2;
635 : }
636 :
637 0 : if ( aPos.X() < aScreenRect.Left() )
638 0 : aPos.X() = aScreenRect.Left();
639 0 : else if ( ( aPos.X() + aSz.Width() ) > aScreenRect.Right() )
640 0 : aPos.X() = aScreenRect.Right() - aSz.Width();
641 0 : if ( aPos.Y() < aScreenRect.Top() )
642 0 : aPos.Y() = aScreenRect.Top();
643 0 : else if ( ( aPos.Y() + aSz.Height() ) > aScreenRect.Bottom() )
644 0 : aPos.Y() = aScreenRect.Bottom() - aSz.Height();
645 :
646 0 : if( ! (nStyle & QUICKHELP_NOEVADEPOINTER) )
647 : {
648 : /* the remark below should be obsolete by now as the helpwindow should
649 : not be focusable, leaving it as a hint. However it is sensible in most
650 : conditions to evade the mouse pointer so the content window is fully visible.
651 :
652 : // the popup must not appear under the mouse
653 : // otherwise it would directly be closed due to a focus change...
654 : */
655 0 : Rectangle aHelpRect( aPos, aSz );
656 0 : if( aHelpRect.IsInside( mPos ) )
657 : {
658 0 : Point delta(2,2);
659 0 : Point pSize( aSz.Width(), aSz.Height() );
660 0 : Point pTest( mPos - pSize - delta );
661 0 : if( pTest.X() > aScreenRect.Left() && pTest.Y() > aScreenRect.Top() )
662 0 : aPos = pTest;
663 : else
664 0 : aPos = mPos + delta;
665 : }
666 : }
667 :
668 0 : Window* pWindow = pHelpWin->GetParent()->ImplGetFrameWindow();
669 0 : aPos = pWindow->AbsoluteScreenToOutputPixel( aPos );
670 0 : pHelpWin->SetPosPixel( aPos );
671 0 : }
672 :
673 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|