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 208 : Help::Help()
49 : {
50 208 : }
51 :
52 119 : Help::~Help()
53 : {
54 119 : }
55 :
56 0 : bool Help::Start( const OUString&, const vcl::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 vcl::Window* )
67 : {
68 0 : return OUString();
69 : }
70 :
71 208 : void Help::EnableContextHelp()
72 : {
73 208 : ImplGetSVData()->maHelpData.mbContextHelp = true;
74 208 : }
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 208 : void Help::EnableExtHelp()
87 : {
88 208 : ImplGetSVData()->maHelpData.mbExtHelp = true;
89 208 : }
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 208 : void Help::DisableBalloonHelp()
140 : {
141 208 : ImplGetSVData()->maHelpData.mbBalloonHelp = false;
142 208 : }
143 :
144 208 : bool Help::IsBalloonHelpEnabled()
145 : {
146 208 : return ImplGetSVData()->maHelpData.mbBalloonHelp;
147 : }
148 :
149 0 : bool Help::ShowBalloon( vcl::Window* pParent,
150 : const Point& rScreenPos,
151 : const OUString& rHelpText )
152 : {
153 : ImplShowHelpWindow( pParent, HELPWINSTYLE_BALLOON, QuickHelpFlags::NONE,
154 0 : rHelpText, OUString(), rScreenPos );
155 :
156 0 : return true;
157 : }
158 :
159 0 : bool Help::ShowBalloon( vcl::Window* pParent,
160 : const Point& rScreenPos, const Rectangle& rRect,
161 : const OUString& rHelpText )
162 : {
163 : ImplShowHelpWindow( pParent, HELPWINSTYLE_BALLOON, QuickHelpFlags::NONE,
164 0 : rHelpText, OUString(), rScreenPos, &rRect );
165 :
166 0 : return true;
167 : }
168 :
169 416 : void Help::EnableQuickHelp()
170 : {
171 416 : ImplGetSVData()->maHelpData.mbQuickHelp = true;
172 416 : }
173 :
174 0 : void Help::DisableQuickHelp()
175 : {
176 0 : ImplGetSVData()->maHelpData.mbQuickHelp = false;
177 0 : }
178 :
179 208 : bool Help::IsQuickHelpEnabled()
180 : {
181 208 : return ImplGetSVData()->maHelpData.mbQuickHelp;
182 : }
183 :
184 0 : bool Help::ShowQuickHelp( vcl::Window* pParent,
185 : const Rectangle& rScreenRect,
186 : const OUString& rHelpText,
187 : const OUString& rLongHelpText,
188 : QuickHelpFlags 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( vcl::Window* pParent, const Rectangle& rScreenRect,
204 : const OUString& rText, QuickHelpFlags nStyle )
205 : {
206 0 : sal_uInt16 nHelpWinStyle = ( nStyle & QuickHelpFlags::TipStyleBalloon ) ? HELPWINSTYLE_BALLOON : HELPWINSTYLE_QUICK;
207 0 : VclPtrInstance<HelpTextWindow> pHelpWin( pParent, rText, nHelpWinStyle, nStyle );
208 :
209 0 : sal_uIntPtr nId = reinterpret_cast< sal_uIntPtr >( pHelpWin.get() );
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, vcl::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 : VclPtr<HelpTextWindow> pHelpWin = reinterpret_cast<HelpTextWindow*>(nId);
233 0 : vcl::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 : pHelpWin.disposeAndClear();
238 0 : ImplGetSVData()->maHelpData.mnLastHelpHideTime = tools::Time::GetSystemTicks();
239 0 : }
240 :
241 0 : HelpTextWindow::HelpTextWindow( vcl::Window* pParent, const OUString& rText, sal_uInt16 nHelpWinStyle, QuickHelpFlags 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 : if( mnStyle & QuickHelpFlags::BiDiRtl )
254 : {
255 0 : ComplexTextLayoutMode nLayoutMode = GetLayoutMode();
256 0 : nLayoutMode |= TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT;
257 0 : SetLayoutMode( nLayoutMode );
258 : }
259 0 : SetHelpText( rText );
260 0 : Window::SetHelpText( rText );
261 :
262 0 : ImplSVData* pSVData = ImplGetSVData();
263 0 : if ( pSVData->maHelpData.mbSetKeyboardHelp )
264 0 : pSVData->maHelpData.mbKeyboardHelp = true;
265 :
266 0 : const HelpSettings& rHelpSettings = pParent->GetSettings().GetHelpSettings();
267 0 : maShowTimer.SetTimeoutHdl( LINK( this, HelpTextWindow, TimerHdl ) );
268 0 : maHideTimer.SetTimeoutHdl( LINK( this, HelpTextWindow, TimerHdl ) );
269 0 : maHideTimer.SetTimeout( rHelpSettings.GetTipTimeout() );
270 0 : }
271 :
272 0 : void HelpTextWindow::ApplySettings(vcl::RenderContext& rRenderContext)
273 : {
274 0 : const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
275 0 : SetPointFont(rRenderContext, rStyleSettings.GetHelpFont());
276 0 : rRenderContext.SetTextColor(rStyleSettings.GetHelpTextColor());
277 0 : rRenderContext.SetTextAlign(ALIGN_TOP);
278 :
279 0 : if (rRenderContext.IsNativeControlSupported(CTRL_TOOLTIP, PART_ENTIRE_CONTROL))
280 : {
281 0 : EnableChildTransparentMode(true);
282 0 : SetParentClipMode(ParentClipMode::NoClip);
283 0 : SetPaintTransparent(true);
284 0 : rRenderContext.SetBackground();
285 : }
286 : else
287 0 : rRenderContext.SetBackground(Wallpaper(rStyleSettings.GetHelpColor()));
288 :
289 0 : if (rStyleSettings.GetHelpColor().IsDark())
290 0 : rRenderContext.SetLineColor(COL_WHITE);
291 : else
292 0 : rRenderContext.SetLineColor(COL_BLACK);
293 0 : rRenderContext.SetFillColor();
294 0 : }
295 :
296 0 : HelpTextWindow::~HelpTextWindow()
297 : {
298 0 : disposeOnce();
299 0 : }
300 :
301 0 : void HelpTextWindow::dispose()
302 : {
303 0 : maShowTimer.Stop();
304 0 : maHideTimer.Stop();
305 :
306 0 : if( this == ImplGetSVData()->maHelpData.mpHelpWin )
307 0 : ImplGetSVData()->maHelpData.mpHelpWin = NULL;
308 0 : FloatingWindow::dispose();
309 0 : }
310 :
311 0 : void HelpTextWindow::SetHelpText( const OUString& rHelpText )
312 : {
313 0 : maHelpText = rHelpText;
314 0 : if ( mnHelpWinStyle == HELPWINSTYLE_QUICK && maHelpText.getLength() < HELPTEXTMAXLEN)
315 : {
316 0 : Size aSize;
317 0 : aSize.Height() = GetTextHeight();
318 0 : if ( mnStyle & QuickHelpFlags::CtrlText )
319 0 : aSize.Width() = GetCtrlTextWidth( maHelpText );
320 : else
321 0 : aSize.Width() = GetTextWidth( maHelpText );
322 0 : maTextRect = Rectangle( Point( HELPTEXTMARGIN_QUICK, HELPTEXTMARGIN_QUICK ), aSize );
323 : }
324 : else // HELPWINSTYLE_BALLOON
325 : {
326 0 : Point aTmpPoint;
327 0 : sal_Int32 nCharsInLine = 35 + ((maHelpText.getLength()/100)*5);
328 : // average width to have all windows consistent
329 0 : OUStringBuffer aBuf;
330 0 : comphelper::string::padToLength(aBuf, nCharsInLine, 'x');
331 0 : OUString aXXX = aBuf.makeStringAndClear();
332 0 : long nWidth = GetTextWidth( aXXX );
333 0 : Size aTmpSize( nWidth, 0x7FFFFFFF );
334 0 : Rectangle aTry1( aTmpPoint, aTmpSize );
335 : DrawTextFlags nDrawFlags = DrawTextFlags::MultiLine | DrawTextFlags::WordBreak |
336 0 : DrawTextFlags::Left | DrawTextFlags::Top;
337 0 : if ( mnStyle & QuickHelpFlags::CtrlText )
338 0 : nDrawFlags |= DrawTextFlags::Mnemonic;
339 0 : Rectangle aTextRect = GetTextRect( aTry1, maHelpText, nDrawFlags );
340 :
341 : // get a better width later...
342 0 : maTextRect = aTextRect;
343 :
344 : // safety distance...
345 0 : maTextRect.SetPos( Point( HELPTEXTMARGIN_BALLOON, HELPTEXTMARGIN_BALLOON ) );
346 : }
347 :
348 0 : Size aSize( CalcOutSize() );
349 0 : SetOutputSizePixel( aSize );
350 0 : }
351 :
352 0 : void HelpTextWindow::ImplShow()
353 : {
354 0 : ImplDelData aDogTag( this );
355 0 : Show( true, ShowFlags::NoActivate );
356 0 : if( !aDogTag.IsDead() )
357 0 : Update();
358 0 : }
359 :
360 0 : void HelpTextWindow::Paint( vcl::RenderContext& rRenderContext, const Rectangle& )
361 : {
362 : // paint native background
363 0 : bool bNativeOK = false;
364 0 : if (rRenderContext.IsNativeControlSupported(CTRL_TOOLTIP, PART_ENTIRE_CONTROL))
365 : {
366 : // #i46472# workaround gcc3.3 temporary problem
367 0 : Rectangle aCtrlRegion(Point(0, 0), GetOutputSizePixel());
368 0 : ImplControlValue aControlValue;
369 : bNativeOK = rRenderContext.DrawNativeControl(CTRL_TOOLTIP, PART_ENTIRE_CONTROL, aCtrlRegion,
370 0 : ControlState::NONE, aControlValue, OUString());
371 : }
372 :
373 : // paint text
374 0 : if (mnHelpWinStyle == HELPWINSTYLE_QUICK && maHelpText.getLength() < HELPTEXTMAXLEN)
375 : {
376 0 : if ( mnStyle & QuickHelpFlags::CtrlText )
377 0 : rRenderContext.DrawCtrlText(maTextRect.TopLeft(), maHelpText);
378 : else
379 0 : rRenderContext.DrawText(maTextRect.TopLeft(), maHelpText);
380 : }
381 : else // HELPWINSTYLE_BALLOON
382 : {
383 : DrawTextFlags nDrawFlags = DrawTextFlags::MultiLine|DrawTextFlags::WordBreak|
384 0 : DrawTextFlags::Left|DrawTextFlags::Top;
385 0 : if (mnStyle & QuickHelpFlags::CtrlText)
386 0 : nDrawFlags |= DrawTextFlags::Mnemonic;
387 0 : rRenderContext.DrawText(maTextRect, maHelpText, nDrawFlags);
388 : }
389 :
390 : // border
391 0 : if (!bNativeOK)
392 : {
393 0 : Size aSz = GetOutputSizePixel();
394 0 : rRenderContext.DrawRect(Rectangle(Point(), aSz));
395 0 : if (mnHelpWinStyle == HELPWINSTYLE_BALLOON)
396 : {
397 0 : aSz.Width() -= 2;
398 0 : aSz.Height() -= 2;
399 0 : Color aColor(rRenderContext.GetLineColor());
400 0 : rRenderContext.SetLineColor(COL_GRAY);
401 0 : rRenderContext.DrawRect(Rectangle(Point(1, 1), aSz));
402 0 : rRenderContext.SetLineColor(aColor);
403 : }
404 : }
405 0 : }
406 :
407 0 : void HelpTextWindow::ShowHelp( sal_uInt16 nDelayMode )
408 : {
409 0 : sal_uLong nTimeout = 0;
410 0 : if ( nDelayMode != HELPDELAY_NONE )
411 : {
412 : // In case of ExtendedHelp display help sooner
413 0 : if ( ImplGetSVData()->maHelpData.mbExtHelpMode )
414 0 : nTimeout = 15;
415 : else
416 : {
417 0 : const HelpSettings& rHelpSettings = GetSettings().GetHelpSettings();
418 0 : if ( mnHelpWinStyle == HELPWINSTYLE_QUICK )
419 0 : nTimeout = rHelpSettings.GetTipDelay();
420 : else
421 0 : nTimeout = rHelpSettings.GetBalloonDelay();
422 : }
423 :
424 0 : if ( nDelayMode == HELPDELAY_SHORT )
425 0 : nTimeout /= 3;
426 : }
427 :
428 0 : maShowTimer.SetTimeout( nTimeout );
429 0 : maShowTimer.Start();
430 0 : }
431 :
432 0 : IMPL_LINK_TYPED( HelpTextWindow, TimerHdl, Timer*, pTimer, void)
433 : {
434 0 : if ( pTimer == &maShowTimer )
435 : {
436 0 : if ( mnHelpWinStyle == HELPWINSTYLE_QUICK )
437 : {
438 : // start auto-hide-timer for non-ShowTip windows
439 0 : ImplSVData* pSVData = ImplGetSVData();
440 0 : if ( this == pSVData->maHelpData.mpHelpWin )
441 0 : maHideTimer.Start();
442 : }
443 0 : ImplShow();
444 : }
445 : else
446 : {
447 : DBG_ASSERT( pTimer == &maHideTimer, "HelpTextWindow::TimerHdl with bad Timer" );
448 0 : ImplDestroyHelpWindow( true );
449 : }
450 0 : }
451 :
452 0 : Size HelpTextWindow::CalcOutSize() const
453 : {
454 0 : Size aSz = maTextRect.GetSize();
455 0 : aSz.Width() += 2*maTextRect.Left();
456 0 : aSz.Height() += 2*maTextRect.Top();
457 0 : return aSz;
458 : }
459 :
460 0 : void HelpTextWindow::RequestHelp( const HelpEvent& /*rHEvt*/ )
461 : {
462 : // Just to assure that Window::RequestHelp() is not called by
463 : // ShowQuickHelp/ShowBalloonHelp in the HelpTextWindow.
464 0 : }
465 :
466 0 : OUString HelpTextWindow::GetText() const
467 : {
468 0 : return maHelpText;
469 : }
470 :
471 0 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > HelpTextWindow::CreateAccessible()
472 : {
473 0 : return FloatingWindow::CreateAccessible();
474 : }
475 :
476 0 : void ImplShowHelpWindow( vcl::Window* pParent, sal_uInt16 nHelpWinStyle, QuickHelpFlags nStyle,
477 : const OUString& rHelpText, const OUString& rStatusText,
478 : const Point& rScreenPos, const Rectangle* pHelpArea )
479 : {
480 0 : ImplSVData* pSVData = ImplGetSVData();
481 :
482 0 : if (rHelpText.isEmpty() && !pSVData->maHelpData.mbRequestingHelp)
483 0 : return;
484 :
485 0 : HelpTextWindow* pHelpWin = pSVData->maHelpData.mpHelpWin;
486 0 : sal_uInt16 nDelayMode = HELPDELAY_NORMAL;
487 0 : if ( pHelpWin )
488 : {
489 : DBG_ASSERT( pHelpWin != pParent, "HelpInHelp ?!" );
490 :
491 0 : if ( ( ( pHelpWin->GetHelpText() != rHelpText )
492 0 : || ( pHelpWin->GetWinStyle() != nHelpWinStyle )
493 0 : || ( pHelpArea
494 0 : && ( pHelpWin->GetHelpArea() != *pHelpArea )
495 : )
496 : )
497 0 : && pSVData->maHelpData.mbRequestingHelp
498 : )
499 : {
500 : // remove help window if no HelpText or other HelpText or
501 : // other help mode. but keep it if we are scrolling, ie not requesting help
502 0 : bool bWasVisible = pHelpWin->IsVisible();
503 0 : if ( bWasVisible )
504 0 : nDelayMode = HELPDELAY_NONE; // display it quickly if we were already in quick help mode
505 0 : pHelpWin = NULL;
506 0 : ImplDestroyHelpWindow( bWasVisible );
507 : }
508 : else
509 : {
510 0 : bool const bTextChanged = rHelpText != pHelpWin->GetHelpText();
511 0 : if ( bTextChanged || ( nStyle & QuickHelpFlags::ForceReposition ) )
512 : {
513 0 : vcl::Window * pWindow = pHelpWin->GetParent()->ImplGetFrameWindow();
514 0 : Rectangle aInvRect( pHelpWin->GetWindowExtentsRelative( pWindow ) );
515 0 : if( pHelpWin->IsVisible() )
516 0 : pWindow->Invalidate( aInvRect );
517 :
518 0 : pHelpWin->SetHelpText( rHelpText );
519 : // approach mouse position
520 0 : ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, pHelpArea );
521 0 : if( pHelpWin->IsVisible() )
522 0 : pHelpWin->Invalidate();
523 : }
524 : }
525 : }
526 :
527 0 : if (!pHelpWin && !rHelpText.isEmpty())
528 : {
529 0 : sal_uInt64 nCurTime = tools::Time::GetSystemTicks();
530 0 : if ( ( ( nCurTime - pSVData->maHelpData.mnLastHelpHideTime ) < pParent->GetSettings().GetHelpSettings().GetTipDelay() )
531 0 : || ( nStyle & QuickHelpFlags::NoDelay )
532 : )
533 0 : nDelayMode = HELPDELAY_NONE;
534 :
535 : DBG_ASSERT( !pHelpWin, "Noch ein HelpWin ?!" );
536 0 : pHelpWin = VclPtr<HelpTextWindow>::Create( pParent, rHelpText, nHelpWinStyle, nStyle );
537 0 : pSVData->maHelpData.mpHelpWin = pHelpWin;
538 0 : pHelpWin->SetStatusText( rStatusText );
539 0 : if ( pHelpArea )
540 0 : pHelpWin->SetHelpArea( *pHelpArea );
541 :
542 : // positioning
543 0 : Size aSz = pHelpWin->CalcOutSize();
544 0 : pHelpWin->SetOutputSizePixel( aSz );
545 0 : ImplSetHelpWindowPos( pHelpWin, nHelpWinStyle, nStyle, rScreenPos, pHelpArea );
546 : // if not called from Window::RequestHelp, then without delay...
547 0 : if ( !pSVData->maHelpData.mbRequestingHelp )
548 0 : nDelayMode = HELPDELAY_NONE;
549 0 : pHelpWin->ShowHelp( nDelayMode );
550 : }
551 : }
552 :
553 6249 : void ImplDestroyHelpWindow( bool bUpdateHideTime )
554 : {
555 6249 : ImplSVData* pSVData = ImplGetSVData();
556 6249 : VclPtr<HelpTextWindow> pHelpWin = pSVData->maHelpData.mpHelpWin;
557 6249 : if ( pHelpWin )
558 : {
559 0 : vcl::Window * pWindow = pHelpWin->GetParent()->ImplGetFrameWindow();
560 : // find out screen area covered by system help window
561 0 : Rectangle aInvRect( pHelpWin->GetWindowExtentsRelative( pWindow ) );
562 0 : if( pHelpWin->IsVisible() )
563 0 : pWindow->Invalidate( aInvRect );
564 0 : pSVData->maHelpData.mpHelpWin = NULL;
565 0 : pSVData->maHelpData.mbKeyboardHelp = false;
566 0 : pHelpWin->Hide();
567 0 : pHelpWin.disposeAndClear();
568 0 : if( bUpdateHideTime )
569 0 : pSVData->maHelpData.mnLastHelpHideTime = tools::Time::GetSystemTicks();
570 6249 : }
571 6249 : }
572 :
573 0 : void ImplSetHelpWindowPos( vcl::Window* pHelpWin, sal_uInt16 nHelpWinStyle, QuickHelpFlags nStyle,
574 : const Point& rPos, const Rectangle* pHelpArea )
575 : {
576 0 : Point aPos = rPos;
577 0 : Size aSz = pHelpWin->GetSizePixel();
578 0 : Rectangle aScreenRect = pHelpWin->ImplGetFrameWindow()->GetDesktopRectPixel();
579 0 : aPos = pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( aPos );
580 : // get mouse screen coords
581 0 : Point mPos( pHelpWin->GetParent()->ImplGetFrameWindow()->GetPointerPosPixel() );
582 0 : mPos = pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( mPos );
583 :
584 0 : if ( nHelpWinStyle == HELPWINSTYLE_QUICK )
585 : {
586 0 : if ( !(nStyle & QuickHelpFlags::NoAutoPos) )
587 : {
588 0 : long nScreenHeight = aScreenRect.GetHeight();
589 0 : aPos.X() -= 4;
590 0 : if ( aPos.Y() > aScreenRect.Top()+nScreenHeight-(nScreenHeight/4) )
591 0 : aPos.Y() -= aSz.Height()+4;
592 : else
593 0 : aPos.Y() += 21;
594 : }
595 : }
596 : else
597 : {
598 : // If it's the mouse position, move the window slightly
599 : // so the mouse pointer does not cover it
600 0 : if ( aPos == mPos )
601 : {
602 0 : aPos.X() += 12;
603 0 : aPos.Y() += 16;
604 : }
605 : }
606 :
607 0 : if ( nStyle & QuickHelpFlags::NoAutoPos )
608 : {
609 0 : if ( pHelpArea )
610 : {
611 : // convert help area to screen coords
612 : Rectangle devHelpArea(
613 0 : pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( pHelpArea->TopLeft() ),
614 0 : pHelpWin->GetParent()->ImplGetFrameWindow()->OutputToAbsoluteScreenPixel( pHelpArea->BottomRight() ) );
615 :
616 : // Welche Position vom Rechteck?
617 0 : aPos = devHelpArea.Center();
618 :
619 0 : if ( nStyle & QuickHelpFlags::Left )
620 0 : aPos.X() = devHelpArea.Left();
621 0 : else if ( nStyle & QuickHelpFlags::Right )
622 0 : aPos.X() = devHelpArea.Right();
623 :
624 0 : if ( nStyle & QuickHelpFlags::Top )
625 0 : aPos.Y() = devHelpArea.Top();
626 0 : else if ( nStyle & QuickHelpFlags::Bottom )
627 0 : aPos.Y() = devHelpArea.Bottom();
628 : }
629 :
630 : // which direction?
631 0 : if ( nStyle & QuickHelpFlags::Left )
632 : ;
633 0 : else if ( nStyle & QuickHelpFlags::Right )
634 0 : aPos.X() -= aSz.Width();
635 : else
636 0 : aPos.X() -= aSz.Width()/2;
637 :
638 0 : if ( nStyle & QuickHelpFlags::Top )
639 : ;
640 0 : else if ( nStyle & QuickHelpFlags::Bottom )
641 0 : aPos.Y() -= aSz.Height();
642 : else
643 0 : aPos.Y() -= aSz.Height()/2;
644 : }
645 :
646 0 : if ( aPos.X() < aScreenRect.Left() )
647 0 : aPos.X() = aScreenRect.Left();
648 0 : else if ( ( aPos.X() + aSz.Width() ) > aScreenRect.Right() )
649 0 : aPos.X() = aScreenRect.Right() - aSz.Width();
650 0 : if ( aPos.Y() < aScreenRect.Top() )
651 0 : aPos.Y() = aScreenRect.Top();
652 0 : else if ( ( aPos.Y() + aSz.Height() ) > aScreenRect.Bottom() )
653 0 : aPos.Y() = aScreenRect.Bottom() - aSz.Height();
654 :
655 0 : if( ! (nStyle & QuickHelpFlags::NoEvadePointer) )
656 : {
657 : /* the remark below should be obsolete by now as the helpwindow should
658 : not be focusable, leaving it as a hint. However it is sensible in most
659 : conditions to evade the mouse pointer so the content window is fully visible.
660 :
661 : // the popup must not appear under the mouse
662 : // otherwise it would directly be closed due to a focus change...
663 : */
664 0 : Rectangle aHelpRect( aPos, aSz );
665 0 : if( aHelpRect.IsInside( mPos ) )
666 : {
667 0 : Point delta(2,2);
668 0 : Point pSize( aSz.Width(), aSz.Height() );
669 0 : Point pTest( mPos - pSize - delta );
670 0 : if( pTest.X() > aScreenRect.Left() && pTest.Y() > aScreenRect.Top() )
671 0 : aPos = pTest;
672 : else
673 0 : aPos = mPos + delta;
674 : }
675 : }
676 :
677 0 : vcl::Window* pWindow = pHelpWin->GetParent()->ImplGetFrameWindow();
678 0 : aPos = pWindow->AbsoluteScreenToOutputPixel( aPos );
679 0 : pHelpWin->SetPosPixel( aPos );
680 0 : }
681 :
682 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|