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 "menufloatingwindow.hxx"
21 : #include "menuitemlist.hxx"
22 :
23 : #include <svdata.hxx>
24 : #include <vcl/decoview.hxx>
25 : #include <vcl/settings.hxx>
26 : #include <window.h>
27 :
28 8 : MenuFloatingWindow::MenuFloatingWindow( Menu* pMen, vcl::Window* pParent, WinBits nStyle ) :
29 8 : FloatingWindow( pParent, nStyle )
30 : {
31 8 : mpWindowImpl->mbMenuFloatingWindow= true;
32 8 : pMenu = pMen;
33 8 : pActivePopup = 0;
34 8 : nSaveFocusId = 0;
35 8 : bInExecute = false;
36 8 : bScrollMenu = false;
37 8 : nHighlightedItem = ITEMPOS_INVALID;
38 8 : nMBDownPos = ITEMPOS_INVALID;
39 8 : nPosInParent = ITEMPOS_INVALID;
40 8 : nScrollerHeight = 0;
41 8 : nBorder = EXTRASPACEY;
42 8 : nFirstEntry = 0;
43 8 : bScrollUp = false;
44 8 : bScrollDown = false;
45 8 : bIgnoreFirstMove = true;
46 8 : bKeyInput = false;
47 :
48 8 : EnableSaveBackground();
49 8 : ApplySettings(*this);
50 :
51 8 : SetPopupModeEndHdl( LINK( this, MenuFloatingWindow, PopupEnd ) );
52 :
53 8 : aHighlightChangedTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, HighlightChanged ) );
54 8 : aHighlightChangedTimer.SetTimeout( GetSettings().GetMouseSettings().GetMenuDelay() );
55 8 : aSubmenuCloseTimer.SetTimeout( GetSettings().GetMouseSettings().GetMenuDelay() );
56 8 : aSubmenuCloseTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, SubmenuClose ) );
57 8 : aScrollTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, AutoScroll ) );
58 :
59 8 : AddEventListener( LINK( this, MenuFloatingWindow, ShowHideListener ) );
60 8 : }
61 :
62 16 : void MenuFloatingWindow::doShutdown()
63 : {
64 16 : if( pMenu )
65 : {
66 : // #105373# notify toolkit that highlight was removed
67 : // otherwise the entry will not be read when the menu is opened again
68 8 : if( nHighlightedItem != ITEMPOS_INVALID )
69 0 : pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
70 8 : if (!bKeyInput && pMenu && pMenu->pStartedFrom && !pMenu->pStartedFrom->IsMenuBar())
71 : {
72 : // #102461# remove highlight in parent
73 0 : size_t i, nCount = pMenu->pStartedFrom->pItemList->size();
74 0 : for(i = 0; i < nCount; i++)
75 : {
76 0 : MenuItemData* pData = pMenu->pStartedFrom->pItemList->GetDataFromPos( i );
77 0 : if( pData && ( pData->pSubMenu == pMenu ) )
78 0 : break;
79 : }
80 0 : if( i < nCount )
81 : {
82 0 : MenuFloatingWindow* pPWin = static_cast<MenuFloatingWindow*>(pMenu->pStartedFrom->ImplGetWindow());
83 0 : if (pPWin)
84 0 : pPWin->InvalidateItem(i);
85 : }
86 : }
87 :
88 : // free the reference to the accessible component
89 8 : SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >() );
90 :
91 8 : aHighlightChangedTimer.Stop();
92 :
93 : // #95056# invalidate screen area covered by system window
94 : // so this can be taken into account if the commandhandler performs a scroll operation
95 8 : if( GetParent() )
96 : {
97 8 : Rectangle aInvRect( GetWindowExtentsRelative( GetParent() ) );
98 8 : GetParent()->Invalidate( aInvRect );
99 : }
100 8 : pMenu = NULL;
101 8 : RemoveEventListener( LINK( this, MenuFloatingWindow, ShowHideListener ) );
102 : }
103 16 : }
104 :
105 24 : MenuFloatingWindow::~MenuFloatingWindow()
106 : {
107 8 : disposeOnce();
108 16 : }
109 :
110 8 : void MenuFloatingWindow::dispose()
111 : {
112 8 : doShutdown();
113 :
114 8 : FloatingWindow::dispose();
115 8 : }
116 :
117 8 : void MenuFloatingWindow::Resize()
118 : {
119 8 : InitMenuClipRegion(*this); // FIXME
120 8 : }
121 :
122 16 : void MenuFloatingWindow::ApplySettings(vcl::RenderContext& rRenderContext)
123 : {
124 16 : FloatingWindow::ApplySettings(rRenderContext);
125 :
126 16 : const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
127 :
128 16 : SetPointFont(rRenderContext, rStyleSettings.GetMenuFont());
129 :
130 16 : if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
131 : {
132 0 : rRenderContext.SetBackground(); // background will be drawn by NWF
133 : }
134 : else
135 16 : rRenderContext.SetBackground(Wallpaper(rStyleSettings.GetMenuColor()));
136 :
137 16 : rRenderContext.SetTextColor(rStyleSettings.GetMenuTextColor());
138 16 : rRenderContext.SetTextFillColor();
139 16 : rRenderContext.SetLineColor();
140 16 : }
141 :
142 : /// Get a negative pixel offset for an offset menu
143 9 : long MenuFloatingWindow::ImplGetStartY() const
144 : {
145 9 : long nY = 0;
146 9 : if( pMenu )
147 : {
148 9 : for ( sal_uInt16 n = 0; n < nFirstEntry; n++ )
149 0 : nY += pMenu->GetItemList()->GetDataFromPos( n )->aSz.Height();
150 9 : nY -= pMenu->GetTitleHeight();
151 : }
152 9 : return -nY;
153 : }
154 :
155 0 : vcl::Region MenuFloatingWindow::ImplCalcClipRegion( bool bIncludeLogo ) const
156 : {
157 0 : Size aOutSz = GetOutputSizePixel();
158 0 : Point aPos;
159 0 : Rectangle aRect( aPos, aOutSz );
160 0 : aRect.Top() += nScrollerHeight;
161 0 : aRect.Bottom() -= nScrollerHeight;
162 :
163 0 : if ( pMenu && pMenu->pLogo && !bIncludeLogo )
164 0 : aRect.Left() += pMenu->pLogo->aBitmap.GetSizePixel().Width();
165 :
166 0 : vcl::Region aRegion(aRect);
167 0 : if ( pMenu && pMenu->pLogo && bIncludeLogo && nScrollerHeight )
168 0 : aRegion.Union( Rectangle( Point(), Size( pMenu->pLogo->aBitmap.GetSizePixel().Width(), aOutSz.Height() ) ) );
169 :
170 0 : return aRegion;
171 : }
172 :
173 8 : void MenuFloatingWindow::InitMenuClipRegion(vcl::RenderContext& rRenderContext)
174 : {
175 8 : if (IsScrollMenu())
176 : {
177 0 : rRenderContext.SetClipRegion(ImplCalcClipRegion());
178 : }
179 : else
180 : {
181 8 : rRenderContext.SetClipRegion();
182 : }
183 8 : }
184 :
185 0 : void MenuFloatingWindow::ImplHighlightItem( const MouseEvent& rMEvt, bool bMBDown )
186 : {
187 0 : if( ! pMenu )
188 0 : return;
189 :
190 0 : long nY = GetInitialItemY();
191 0 : long nMouseY = rMEvt.GetPosPixel().Y();
192 0 : Size aOutSz = GetOutputSizePixel();
193 0 : if ( ( nMouseY >= nY ) && ( nMouseY < ( aOutSz.Height() + nY ) ) )
194 : {
195 0 : bool bHighlighted = false;
196 0 : size_t nCount = pMenu->pItemList->size();
197 0 : for ( size_t n = 0; !bHighlighted && ( n < nCount ); n++ )
198 : {
199 0 : if ( pMenu->ImplIsVisible( n ) )
200 : {
201 0 : MenuItemData* pItemData = pMenu->pItemList->GetDataFromPos( n );
202 0 : long nOldY = nY;
203 0 : nY += pItemData->aSz.Height();
204 0 : if ( ( nOldY <= nMouseY ) && ( nY > nMouseY ) && pMenu->ImplIsSelectable( n ) )
205 : {
206 0 : bool bPopupArea = true;
207 0 : if ( pItemData->nBits & MenuItemBits::POPUPSELECT )
208 : {
209 : // only when clicked over the arrow...
210 0 : Size aSz = GetOutputSizePixel();
211 0 : long nFontHeight = GetTextHeight();
212 0 : bPopupArea = ( rMEvt.GetPosPixel().X() >= ( aSz.Width() - nFontHeight - nFontHeight/4 ) );
213 : }
214 :
215 0 : if ( bMBDown )
216 : {
217 0 : if ( n != nHighlightedItem )
218 : {
219 0 : ChangeHighlightItem( (sal_uInt16)n, false );
220 : }
221 :
222 0 : bool bAllowNewPopup = true;
223 0 : if ( pActivePopup )
224 : {
225 0 : MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
226 0 : bAllowNewPopup = pData && ( pData->pSubMenu != pActivePopup );
227 0 : if ( bAllowNewPopup )
228 0 : KillActivePopup();
229 : }
230 :
231 0 : if ( bPopupArea && bAllowNewPopup )
232 : {
233 0 : HighlightChanged( NULL );
234 : }
235 : }
236 : else
237 : {
238 0 : if ( n != nHighlightedItem )
239 : {
240 0 : ChangeHighlightItem( (sal_uInt16)n, true );
241 : }
242 0 : else if ( pItemData->nBits & MenuItemBits::POPUPSELECT )
243 : {
244 0 : if ( bPopupArea && ( pActivePopup != pItemData->pSubMenu ) )
245 0 : HighlightChanged( NULL );
246 : }
247 : }
248 0 : bHighlighted = true;
249 : }
250 : }
251 : }
252 0 : if ( !bHighlighted )
253 0 : ChangeHighlightItem( ITEMPOS_INVALID, true );
254 : }
255 : else
256 : {
257 0 : ImplScroll( rMEvt.GetPosPixel() );
258 0 : ChangeHighlightItem( ITEMPOS_INVALID, true );
259 : }
260 : }
261 :
262 0 : IMPL_LINK_NOARG(MenuFloatingWindow, PopupEnd)
263 : {
264 : // "this" will be deleted before the end of this method!
265 0 : Menu* pM = pMenu;
266 0 : if ( bInExecute )
267 : {
268 0 : if ( pActivePopup )
269 : {
270 : //DBG_ASSERT( !pActivePopup->ImplGetWindow(), "PopupEnd, obwohl pActivePopup MIT Window!" );
271 0 : KillActivePopup(); // should be ok to just remove it
272 : //pActivePopup->bCanceled = true;
273 : }
274 0 : bInExecute = false;
275 0 : pMenu->bInCallback = true;
276 0 : pMenu->Deactivate();
277 0 : pMenu->bInCallback = false;
278 : }
279 : else
280 : {
281 0 : if (pMenu && pMenu->pStartedFrom)
282 0 : pMenu->pStartedFrom->ClosePopup(pMenu);
283 : }
284 :
285 0 : if ( pM )
286 0 : pM->pStartedFrom = 0;
287 :
288 0 : return 0;
289 : }
290 :
291 0 : IMPL_LINK_NOARG_TYPED(MenuFloatingWindow, AutoScroll, Timer *, void)
292 : {
293 0 : ImplScroll( GetPointerPosPixel() );
294 0 : }
295 :
296 0 : IMPL_LINK_TYPED( MenuFloatingWindow, HighlightChanged, Timer*, pTimer, void )
297 : {
298 0 : if( ! pMenu )
299 0 : return;
300 :
301 0 : MenuItemData* pItemData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
302 0 : if ( pItemData )
303 : {
304 0 : if ( pActivePopup && ( pActivePopup != pItemData->pSubMenu ) )
305 : {
306 0 : FloatWinPopupFlags nOldFlags = GetPopupModeFlags();
307 0 : SetPopupModeFlags( GetPopupModeFlags() | FloatWinPopupFlags::NoAppFocusClose );
308 0 : KillActivePopup();
309 0 : SetPopupModeFlags( nOldFlags );
310 : }
311 0 : if ( pItemData->bEnabled && pItemData->pSubMenu && pItemData->pSubMenu->GetItemCount() && ( pItemData->pSubMenu != pActivePopup ) )
312 : {
313 0 : pActivePopup = static_cast<PopupMenu*>(pItemData->pSubMenu);
314 0 : long nY = nScrollerHeight+ImplGetStartY();
315 0 : MenuItemData* pData = 0;
316 0 : for ( sal_uLong n = 0; n < nHighlightedItem; n++ )
317 : {
318 0 : pData = pMenu->pItemList->GetDataFromPos( n );
319 0 : nY += pData->aSz.Height();
320 : }
321 0 : pData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
322 0 : Size MySize = GetOutputSizePixel();
323 0 : Point aItemTopLeft( 0, nY );
324 0 : Point aItemBottomRight( aItemTopLeft );
325 0 : aItemBottomRight.X() += MySize.Width();
326 0 : aItemBottomRight.Y() += pData->aSz.Height();
327 :
328 : // shift the popups a little
329 0 : aItemTopLeft.X() += 2;
330 0 : aItemBottomRight.X() -= 2;
331 0 : if ( nHighlightedItem )
332 0 : aItemTopLeft.Y() -= 2;
333 : else
334 : {
335 : sal_Int32 nL, nT, nR, nB;
336 0 : GetBorder( nL, nT, nR, nB );
337 0 : aItemTopLeft.Y() -= nT;
338 : }
339 :
340 : // pTest: crash due to Reschedule() in call of Activate()
341 : // Also it is prevented that submenus are displayed which
342 : // were for long in Activate Rescheduled and which should not be
343 : // displayed now.
344 0 : Menu* pTest = pActivePopup;
345 0 : FloatWinPopupFlags nOldFlags = GetPopupModeFlags();
346 0 : SetPopupModeFlags( GetPopupModeFlags() | FloatWinPopupFlags::NoAppFocusClose );
347 0 : sal_uInt16 nRet = pActivePopup->ImplExecute( this, Rectangle( aItemTopLeft, aItemBottomRight ), FloatWinPopupFlags::Right, pMenu, pTimer == nullptr );
348 0 : SetPopupModeFlags( nOldFlags );
349 :
350 : // nRet != 0, wenn es waerend Activate() abgeschossen wurde...
351 0 : if ( !nRet && ( pActivePopup == pTest ) && pActivePopup->ImplGetWindow() )
352 0 : pActivePopup->ImplGetFloatingWindow()->AddPopupModeWindow( this );
353 : }
354 : }
355 : }
356 :
357 0 : IMPL_LINK_NOARG_TYPED(MenuFloatingWindow, SubmenuClose, Timer *, void)
358 : {
359 0 : if( pMenu && pMenu->pStartedFrom )
360 : {
361 0 : MenuFloatingWindow* pWin = static_cast<MenuFloatingWindow*>(pMenu->pStartedFrom->GetWindow());
362 0 : if( pWin )
363 0 : pWin->KillActivePopup();
364 : }
365 0 : }
366 :
367 96 : IMPL_LINK( MenuFloatingWindow, ShowHideListener, VclWindowEvent*, pEvent )
368 : {
369 48 : if( ! pMenu )
370 0 : return 0;
371 :
372 48 : if( pEvent->GetId() == VCLEVENT_WINDOW_SHOW )
373 16 : pMenu->ImplCallEventListeners( VCLEVENT_MENU_SHOW, ITEMPOS_INVALID );
374 32 : else if( pEvent->GetId() == VCLEVENT_WINDOW_HIDE )
375 16 : pMenu->ImplCallEventListeners( VCLEVENT_MENU_HIDE, ITEMPOS_INVALID );
376 48 : return 0;
377 : }
378 :
379 0 : void MenuFloatingWindow::EnableScrollMenu( bool b )
380 : {
381 0 : bScrollMenu = b;
382 0 : nScrollerHeight = b ? (sal_uInt16) GetSettings().GetStyleSettings().GetScrollBarSize() /2 : 0;
383 0 : bScrollDown = true;
384 0 : InitMenuClipRegion(*this);
385 0 : }
386 :
387 0 : void MenuFloatingWindow::Execute()
388 : {
389 0 : ImplSVData* pSVData = ImplGetSVData();
390 :
391 0 : pSVData->maAppData.mpActivePopupMenu = static_cast<PopupMenu*>(pMenu);
392 :
393 0 : bInExecute = true;
394 : // bCallingSelect = false;
395 :
396 0 : while ( bInExecute )
397 0 : Application::Yield();
398 :
399 0 : pSVData->maAppData.mpActivePopupMenu = NULL;
400 0 : }
401 :
402 8 : void MenuFloatingWindow::StopExecute( sal_uLong nFocusId )
403 : {
404 : // restore focus
405 : // (could have been restored in Select)
406 8 : if ( nSaveFocusId )
407 : {
408 0 : Window::EndSaveFocus( nFocusId, false );
409 0 : nFocusId = nSaveFocusId;
410 0 : if ( nFocusId )
411 : {
412 0 : nSaveFocusId = 0;
413 0 : ImplGetSVData()->maWinData.mbNoDeactivate = false;
414 : }
415 : }
416 8 : ImplEndPopupMode( FloatWinPopupEndFlags::NONE, nFocusId );
417 :
418 8 : aHighlightChangedTimer.Stop();
419 8 : bInExecute = false;
420 8 : if ( pActivePopup )
421 : {
422 0 : KillActivePopup();
423 : }
424 : // notify parent, needed for accessibility
425 8 : if( pMenu && pMenu->pStartedFrom )
426 8 : pMenu->pStartedFrom->ImplCallEventListeners( VCLEVENT_MENU_SUBMENUDEACTIVATE, nPosInParent );
427 8 : }
428 :
429 0 : void MenuFloatingWindow::KillActivePopup( PopupMenu* pThisOnly )
430 : {
431 0 : if ( pActivePopup && ( !pThisOnly || ( pThisOnly == pActivePopup ) ) )
432 : {
433 0 : if( pActivePopup->pWindow )
434 0 : if( static_cast<FloatingWindow *>(pActivePopup->pWindow.get())->IsInCleanUp() )
435 0 : return; // kill it later
436 0 : if ( pActivePopup->bInCallback )
437 0 : pActivePopup->bCanceled = true;
438 :
439 : // For all actions pActivePopup = 0, if e.g.
440 : // PopupModeEndHdl the popups to destroy were called synchronous
441 0 : PopupMenu* pPopup = pActivePopup;
442 0 : pActivePopup = NULL;
443 0 : pPopup->bInCallback = true;
444 0 : pPopup->Deactivate();
445 0 : pPopup->bInCallback = false;
446 0 : if ( pPopup->ImplGetWindow() )
447 : {
448 0 : pPopup->ImplGetFloatingWindow()->StopExecute();
449 0 : pPopup->ImplGetFloatingWindow()->doShutdown();
450 0 : pPopup->pWindow->doLazyDelete();
451 0 : pPopup->pWindow = NULL;
452 :
453 0 : Update();
454 : }
455 : }
456 : }
457 :
458 0 : void MenuFloatingWindow::EndExecute()
459 : {
460 0 : Menu* pStart = pMenu ? pMenu->ImplGetStartMenu() : NULL;
461 0 : sal_uLong nFocusId = 0;
462 0 : if (pStart)
463 0 : nFocusId = pStart->DeactivateMenuBar(nFocusId);
464 :
465 : // if started elsewhere, cleanup there as well
466 0 : MenuFloatingWindow* pCleanUpFrom = this;
467 0 : MenuFloatingWindow* pWin = this;
468 0 : while (pWin && !pWin->bInExecute &&
469 0 : pWin->pMenu->pStartedFrom && !pWin->pMenu->pStartedFrom->IsMenuBar())
470 : {
471 0 : pWin = static_cast<PopupMenu*>(pWin->pMenu->pStartedFrom)->ImplGetFloatingWindow();
472 : }
473 0 : if ( pWin )
474 0 : pCleanUpFrom = pWin;
475 :
476 : // this window will be destroyed => store date locally...
477 0 : Menu* pM = pMenu;
478 0 : sal_uInt16 nItem = nHighlightedItem;
479 :
480 0 : pCleanUpFrom->StopExecute( nFocusId );
481 :
482 0 : if ( nItem != ITEMPOS_INVALID && pM )
483 : {
484 0 : MenuItemData* pItemData = pM->GetItemList()->GetDataFromPos( nItem );
485 0 : if ( pItemData && !pItemData->bIsTemporary )
486 : {
487 0 : pM->nSelectedId = pItemData->nId;
488 0 : if ( pStart )
489 0 : pStart->nSelectedId = pItemData->nId;
490 :
491 0 : pM->ImplSelect();
492 : }
493 : }
494 0 : }
495 :
496 0 : void MenuFloatingWindow::EndExecute( sal_uInt16 nId )
497 : {
498 : size_t nPos;
499 0 : if ( pMenu && pMenu->GetItemList()->GetData( nId, nPos ) )
500 0 : nHighlightedItem = nPos;
501 : else
502 0 : nHighlightedItem = ITEMPOS_INVALID;
503 :
504 0 : EndExecute();
505 0 : }
506 :
507 0 : void MenuFloatingWindow::MouseButtonDown( const MouseEvent& rMEvt )
508 : {
509 : // TH creates a ToTop on this window, but the active popup
510 : // should stay on top...
511 : // due to focus change this would close all menus -> don't do it (#94123)
512 : //if ( pActivePopup && pActivePopup->ImplGetWindow() && !pActivePopup->ImplGetFloatingWindow()->pActivePopup )
513 : // pActivePopup->ImplGetFloatingWindow()->ToTop( ToTopFlags::NoGrabFocus );
514 :
515 0 : ImplHighlightItem( rMEvt, true );
516 :
517 0 : nMBDownPos = nHighlightedItem;
518 0 : }
519 :
520 0 : void MenuFloatingWindow::MouseButtonUp( const MouseEvent& rMEvt )
521 : {
522 0 : MenuItemData* pData = pMenu ? pMenu->GetItemList()->GetDataFromPos( nHighlightedItem ) : NULL;
523 : // nMBDownPos store in local variable and reset immediately,
524 : // as it will be too late after EndExecute
525 0 : sal_uInt16 _nMBDownPos = nMBDownPos;
526 0 : nMBDownPos = ITEMPOS_INVALID;
527 0 : if ( pData && pData->bEnabled && ( pData->eType != MenuItemType::SEPARATOR ) )
528 : {
529 0 : if ( !pData->pSubMenu )
530 : {
531 0 : EndExecute();
532 : }
533 0 : else if ( ( pData->nBits & MenuItemBits::POPUPSELECT ) && ( nHighlightedItem == _nMBDownPos ) && ( rMEvt.GetClicks() == 2 ) )
534 : {
535 : // not when clicked over the arrow...
536 0 : Size aSz = GetOutputSizePixel();
537 0 : long nFontHeight = GetTextHeight();
538 0 : if ( rMEvt.GetPosPixel().X() < ( aSz.Width() - nFontHeight - nFontHeight/4 ) )
539 0 : EndExecute();
540 : }
541 : }
542 :
543 0 : }
544 :
545 0 : void MenuFloatingWindow::MouseMove( const MouseEvent& rMEvt )
546 : {
547 0 : if ( !IsVisible() || rMEvt.IsSynthetic() || rMEvt.IsEnterWindow() )
548 0 : return;
549 :
550 0 : if ( rMEvt.IsLeaveWindow() )
551 : {
552 : // #102461# do not remove highlight if a popup menu is open at this position
553 0 : MenuItemData* pData = pMenu ? pMenu->pItemList->GetDataFromPos( nHighlightedItem ) : NULL;
554 : // close popup with some delayed if we leave somewhere else
555 0 : if( pActivePopup && pData && pData->pSubMenu != pActivePopup )
556 0 : pActivePopup->ImplGetFloatingWindow()->aSubmenuCloseTimer.Start();
557 :
558 0 : if( !pActivePopup || (pData && pData->pSubMenu != pActivePopup ) )
559 0 : ChangeHighlightItem( ITEMPOS_INVALID, false );
560 :
561 0 : if ( IsScrollMenu() )
562 0 : ImplScroll( rMEvt.GetPosPixel() );
563 : }
564 : else
565 : {
566 0 : aSubmenuCloseTimer.Stop();
567 0 : if( bIgnoreFirstMove )
568 0 : bIgnoreFirstMove = false;
569 : else
570 0 : ImplHighlightItem( rMEvt, false );
571 : }
572 : }
573 :
574 0 : void MenuFloatingWindow::ImplScroll( bool bUp )
575 : {
576 0 : KillActivePopup();
577 0 : Update();
578 :
579 0 : if (!pMenu)
580 0 : return;
581 :
582 0 : Invalidate();
583 :
584 0 : pMenu->ImplKillLayoutData();
585 :
586 0 : if ( bScrollUp && bUp )
587 : {
588 0 : nFirstEntry = pMenu->ImplGetPrevVisible( nFirstEntry );
589 : DBG_ASSERT( nFirstEntry != ITEMPOS_INVALID, "Scroll?!" );
590 :
591 0 : long nScrollEntryHeight = pMenu->GetItemList()->GetDataFromPos( nFirstEntry )->aSz.Height();
592 :
593 0 : if ( !bScrollDown )
594 : {
595 0 : bScrollDown = true;
596 0 : Invalidate();
597 : }
598 :
599 0 : if ( pMenu->ImplGetPrevVisible( nFirstEntry ) == ITEMPOS_INVALID )
600 : {
601 0 : bScrollUp = false;
602 0 : Invalidate();
603 : }
604 :
605 0 : Scroll( 0, nScrollEntryHeight, ImplCalcClipRegion( false ).GetBoundRect(), ScrollFlags::Clip );
606 : }
607 0 : else if ( bScrollDown && !bUp )
608 : {
609 0 : long nScrollEntryHeight = pMenu->GetItemList()->GetDataFromPos( nFirstEntry )->aSz.Height();
610 :
611 0 : nFirstEntry = pMenu->ImplGetNextVisible( nFirstEntry );
612 : DBG_ASSERT( nFirstEntry != ITEMPOS_INVALID, "Scroll?!" );
613 :
614 0 : if ( !bScrollUp )
615 : {
616 0 : bScrollUp = true;
617 0 : Invalidate();
618 : }
619 :
620 0 : long nHeight = GetOutputSizePixel().Height();
621 : sal_uInt16 nLastVisible;
622 0 : static_cast<PopupMenu*>(pMenu)->ImplCalcVisEntries( nHeight, nFirstEntry, &nLastVisible );
623 0 : if ( pMenu->ImplGetNextVisible( nLastVisible ) == ITEMPOS_INVALID )
624 : {
625 0 : bScrollDown = false;
626 0 : Invalidate();
627 : }
628 :
629 0 : Scroll( 0, -nScrollEntryHeight, ImplCalcClipRegion( false ).GetBoundRect(), ScrollFlags::Clip );
630 : }
631 :
632 0 : Invalidate();
633 : }
634 :
635 0 : void MenuFloatingWindow::ImplScroll( const Point& rMousePos )
636 : {
637 0 : Size aOutSz = GetOutputSizePixel();
638 :
639 0 : long nY = nScrollerHeight;
640 0 : long nMouseY = rMousePos.Y();
641 0 : long nDelta = 0;
642 :
643 0 : if ( bScrollUp && ( nMouseY < nY ) )
644 : {
645 0 : ImplScroll( true );
646 0 : nDelta = nY - nMouseY;
647 : }
648 0 : else if ( bScrollDown && ( nMouseY > ( aOutSz.Height() - nY ) ) )
649 : {
650 0 : ImplScroll( false );
651 0 : nDelta = nMouseY - ( aOutSz.Height() - nY );
652 : }
653 :
654 0 : if ( nDelta )
655 : {
656 0 : aScrollTimer.Stop(); // if scrolled through MouseMove.
657 : long nTimeout;
658 0 : if ( nDelta < 3 )
659 0 : nTimeout = 200;
660 0 : else if ( nDelta < 5 )
661 0 : nTimeout = 100;
662 0 : else if ( nDelta < 8 )
663 0 : nTimeout = 70;
664 0 : else if ( nDelta < 12 )
665 0 : nTimeout = 40;
666 : else
667 0 : nTimeout = 20;
668 0 : aScrollTimer.SetTimeout( nTimeout );
669 0 : aScrollTimer.Start();
670 : }
671 0 : }
672 0 : void MenuFloatingWindow::ChangeHighlightItem( sal_uInt16 n, bool bStartPopupTimer )
673 : {
674 : // #57934# ggf. immediately close the active, as TH's backgroundstorage works.
675 : // #65750# we prefer to refrain from the background storage of small lines.
676 : // otherwise the menus are difficult to operate.
677 : // MenuItemData* pNextData = pMenu->pItemList->GetDataFromPos( n );
678 : // if ( pActivePopup && pNextData && ( pActivePopup != pNextData->pSubMenu ) )
679 : // KillActivePopup();
680 :
681 0 : aSubmenuCloseTimer.Stop();
682 0 : if( ! pMenu )
683 0 : return;
684 :
685 0 : if ( nHighlightedItem != ITEMPOS_INVALID )
686 : {
687 0 : InvalidateItem(nHighlightedItem);
688 0 : pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
689 : }
690 :
691 0 : nHighlightedItem = (sal_uInt16)n;
692 : DBG_ASSERT( pMenu->ImplIsVisible( nHighlightedItem ) || nHighlightedItem == ITEMPOS_INVALID, "ChangeHighlightItem: Not visible!" );
693 0 : if( nHighlightedItem != ITEMPOS_INVALID )
694 : {
695 0 : if (pMenu->pStartedFrom && !pMenu->pStartedFrom->IsMenuBar())
696 : {
697 : // #102461# make sure parent entry is highlighted as well
698 0 : size_t i, nCount = pMenu->pStartedFrom->pItemList->size();
699 0 : for(i = 0; i < nCount; i++)
700 : {
701 0 : MenuItemData* pData = pMenu->pStartedFrom->pItemList->GetDataFromPos( i );
702 0 : if( pData && ( pData->pSubMenu == pMenu ) )
703 0 : break;
704 : }
705 0 : if( i < nCount )
706 : {
707 0 : MenuFloatingWindow* pPWin = static_cast<MenuFloatingWindow*>(pMenu->pStartedFrom->ImplGetWindow());
708 0 : if( pPWin && pPWin->nHighlightedItem != i )
709 : {
710 0 : pPWin->InvalidateItem(i);
711 0 : pPWin->nHighlightedItem = i;
712 : }
713 : }
714 : }
715 0 : InvalidateItem(nHighlightedItem);
716 0 : pMenu->ImplCallHighlight( nHighlightedItem );
717 : }
718 : else
719 0 : pMenu->nSelectedId = 0;
720 :
721 0 : if ( bStartPopupTimer )
722 : {
723 : // #102438# Menu items are not selectable
724 : // If a menu item is selected by an AT-tool via the XAccessibleAction, XAccessibleValue
725 : // or XAccessibleSelection interface, and the parent popup menus are not executed yet,
726 : // the parent popup menus must be executed SYNCHRONOUSLY, before the menu item is selected.
727 0 : if ( GetSettings().GetMouseSettings().GetMenuDelay() )
728 0 : aHighlightChangedTimer.Start();
729 : else
730 0 : HighlightChanged( &aHighlightChangedTimer );
731 : }
732 : }
733 :
734 : /// Calculate the initial vertical pixel offset of the first item.
735 : /// May be negative for scrolled windows.
736 0 : long MenuFloatingWindow::GetInitialItemY(long *pStartY) const
737 : {
738 0 : long nStartY = ImplGetStartY();
739 0 : if (pStartY)
740 0 : *pStartY = nStartY;
741 0 : return nScrollerHeight + nStartY +
742 0 : ImplGetSVData()->maNWFData.mnMenuFormatBorderY;
743 : }
744 :
745 : /// Emit an Invalidate just for this item's area
746 0 : void MenuFloatingWindow::InvalidateItem(sal_uInt16 nPos)
747 : {
748 0 : if (!pMenu)
749 0 : return;
750 :
751 0 : long nY = GetInitialItemY();
752 0 : size_t nCount = pMenu->pItemList->size();
753 0 : for (size_t n = 0; n < nCount; n++)
754 : {
755 0 : MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
756 0 : long nHeight = pData->aSz.Height();
757 0 : if (n == nPos)
758 : {
759 0 : Size aWidth( GetSizePixel() );
760 0 : Rectangle aRect(Point(0, nY), Size(aWidth.Width(), nHeight));
761 0 : Invalidate( aRect );
762 : }
763 0 : nY += nHeight;
764 : }
765 : }
766 :
767 0 : void MenuFloatingWindow::RenderHighlightItem(vcl::RenderContext& rRenderContext, sal_uInt16 nPos, bool bHighlight)
768 : {
769 0 : if (!pMenu)
770 0 : return;
771 :
772 0 : Size aSz = rRenderContext.GetOutputSizePixel();
773 :
774 0 : long nX = 0;
775 : long nStartY;
776 0 : long nY = GetInitialItemY(&nStartY);
777 :
778 0 : if (pMenu->pLogo)
779 0 : nX = pMenu->pLogo->aBitmap.GetSizePixel().Width();
780 :
781 0 : int nOuterSpaceX = ImplGetSVData()->maNWFData.mnMenuFormatBorderX;
782 :
783 0 : size_t nCount = pMenu->pItemList->size();
784 0 : for (size_t n = 0; n < nCount; n++)
785 : {
786 0 : MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
787 0 : if (n == nPos)
788 : {
789 : DBG_ASSERT(pMenu->ImplIsVisible(n), "Highlight: Item not visible!");
790 0 : if (pData->eType != MenuItemType::SEPARATOR)
791 : {
792 0 : bool bRestoreLineColor = false;
793 0 : Color oldLineColor;
794 0 : bool bDrawItemRect = true;
795 :
796 0 : Rectangle aItemRect(Point(nX + nOuterSpaceX, nY), Size(aSz.Width() - 2 * nOuterSpaceX, pData->aSz.Height()));
797 0 : if (pData->nBits & MenuItemBits::POPUPSELECT)
798 : {
799 0 : long nFontHeight = GetTextHeight();
800 0 : aItemRect.Right() -= nFontHeight + nFontHeight / 4;
801 : }
802 :
803 0 : if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
804 : {
805 0 : Size aPxSize(rRenderContext.GetOutputSizePixel());
806 0 : rRenderContext.Push(PushFlags::CLIPREGION);
807 0 : rRenderContext.IntersectClipRegion(Rectangle(Point(nX, nY), Size(aSz.Width(), pData->aSz.Height())));
808 0 : Rectangle aCtrlRect(Point(nX, 0), Size(aPxSize.Width()-nX, aPxSize.Height()));
809 0 : MenupopupValue aVal(pMenu->nTextPos-GUTTERBORDER, aItemRect);
810 : rRenderContext.DrawNativeControl(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL,
811 0 : aCtrlRect, ControlState::ENABLED, aVal, OUString());
812 0 : if (bHighlight &&
813 0 : rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_MENU_ITEM))
814 : {
815 0 : bDrawItemRect = false;
816 0 : if (!rRenderContext.DrawNativeControl(CTRL_MENU_POPUP, PART_MENU_ITEM, aItemRect,
817 0 : ControlState::SELECTED | (pData->bEnabled
818 : ? ControlState::ENABLED
819 0 : : ControlState::NONE),
820 0 : aVal, OUString()))
821 : {
822 0 : bDrawItemRect = bHighlight;
823 : }
824 : }
825 : else
826 0 : bDrawItemRect = bHighlight;
827 0 : rRenderContext.Pop();
828 : }
829 0 : if (bDrawItemRect)
830 : {
831 0 : if (bHighlight)
832 : {
833 0 : if (pData->bEnabled)
834 0 : rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetMenuHighlightColor());
835 : else
836 : {
837 0 : rRenderContext.SetFillColor();
838 0 : oldLineColor = rRenderContext.GetLineColor();
839 0 : rRenderContext.SetLineColor(rRenderContext.GetSettings().GetStyleSettings().GetMenuHighlightColor());
840 0 : bRestoreLineColor = true;
841 : }
842 : }
843 : else
844 0 : rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetMenuColor());
845 :
846 0 : rRenderContext.DrawRect(aItemRect);
847 : }
848 0 : pMenu->ImplPaint(rRenderContext, nScrollerHeight, nStartY, pData, bHighlight);
849 0 : if (bRestoreLineColor)
850 0 : rRenderContext.SetLineColor(oldLineColor);
851 : }
852 0 : return;
853 : }
854 :
855 0 : nY += pData->aSz.Height();
856 : }
857 : }
858 :
859 0 : Rectangle MenuFloatingWindow::ImplGetItemRect( sal_uInt16 nPos )
860 : {
861 0 : if( ! pMenu )
862 0 : return Rectangle();
863 :
864 0 : Rectangle aRect;
865 0 : Size aSz = GetOutputSizePixel();
866 0 : long nStartY = ImplGetStartY();
867 0 : long nY = nScrollerHeight+nStartY;
868 0 : long nX = 0;
869 :
870 0 : if ( pMenu->pLogo )
871 0 : nX = pMenu->pLogo->aBitmap.GetSizePixel().Width();
872 :
873 0 : size_t nCount = pMenu->pItemList->size();
874 0 : for ( size_t n = 0; n < nCount; n++ )
875 : {
876 0 : MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
877 0 : if ( n == nPos )
878 : {
879 : DBG_ASSERT( pMenu->ImplIsVisible( n ), "ImplGetItemRect: Item not visible!" );
880 0 : if ( pData->eType != MenuItemType::SEPARATOR )
881 : {
882 0 : aRect = Rectangle( Point( nX, nY ), Size( aSz.Width(), pData->aSz.Height() ) );
883 0 : if ( pData->nBits & MenuItemBits::POPUPSELECT )
884 : {
885 0 : long nFontHeight = GetTextHeight();
886 0 : aRect.Right() -= nFontHeight + nFontHeight/4;
887 : }
888 : }
889 0 : break;
890 : }
891 0 : nY += pData->aSz.Height();
892 : }
893 0 : return aRect;
894 : }
895 :
896 0 : void MenuFloatingWindow::ImplCursorUpDown( bool bUp, bool bHomeEnd )
897 : {
898 0 : if( ! pMenu )
899 0 : return;
900 :
901 0 : const StyleSettings& rSettings = GetSettings().GetStyleSettings();
902 :
903 0 : sal_uInt16 n = nHighlightedItem;
904 0 : if ( n == ITEMPOS_INVALID )
905 : {
906 0 : if ( bUp )
907 0 : n = 0;
908 : else
909 0 : n = pMenu->GetItemCount()-1;
910 : }
911 :
912 0 : sal_uInt16 nLoop = n;
913 :
914 0 : if( bHomeEnd )
915 : {
916 : // absolute positioning
917 0 : if( bUp )
918 : {
919 0 : n = pMenu->GetItemCount();
920 0 : nLoop = n-1;
921 : }
922 : else
923 : {
924 0 : n = (sal_uInt16)-1;
925 0 : nLoop = n+1;
926 : }
927 : }
928 :
929 0 : do
930 : {
931 0 : if ( bUp )
932 : {
933 0 : if ( n )
934 0 : n--;
935 : else
936 0 : if ( !IsScrollMenu() || ( nHighlightedItem == ITEMPOS_INVALID ) )
937 0 : n = pMenu->GetItemCount()-1;
938 : else
939 0 : break;
940 : }
941 : else
942 : {
943 0 : n++;
944 0 : if ( n >= pMenu->GetItemCount() )
945 : {
946 0 : if ( !IsScrollMenu() || ( nHighlightedItem == ITEMPOS_INVALID ) )
947 0 : n = 0;
948 : else
949 0 : break;
950 : }
951 : }
952 :
953 0 : MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( n );
954 0 : if ( ( pData->bEnabled || !rSettings.GetSkipDisabledInMenus() )
955 0 : && ( pData->eType != MenuItemType::SEPARATOR ) && pMenu->ImplIsVisible( n ) && pMenu->ImplIsSelectable( n ) )
956 : {
957 : // Is selection in visible area?
958 0 : if ( IsScrollMenu() )
959 : {
960 0 : ChangeHighlightItem( ITEMPOS_INVALID, false );
961 :
962 0 : while ( n < nFirstEntry )
963 0 : ImplScroll( true );
964 :
965 0 : Size aOutSz = GetOutputSizePixel();
966 : sal_uInt16 nLastVisible;
967 0 : static_cast<PopupMenu*>(pMenu)->ImplCalcVisEntries( aOutSz.Height(), nFirstEntry, &nLastVisible );
968 0 : while ( n > nLastVisible )
969 : {
970 0 : ImplScroll( false );
971 0 : static_cast<PopupMenu*>(pMenu)->ImplCalcVisEntries( aOutSz.Height(), nFirstEntry, &nLastVisible );
972 : }
973 : }
974 0 : ChangeHighlightItem( n, false );
975 0 : break;
976 : }
977 : } while ( n != nLoop );
978 : }
979 :
980 0 : void MenuFloatingWindow::KeyInput( const KeyEvent& rKEvent )
981 : {
982 0 : ImplDelData aDelData;
983 0 : ImplAddDel( &aDelData );
984 :
985 0 : sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
986 0 : bKeyInput = true;
987 0 : switch ( nCode )
988 : {
989 : case KEY_UP:
990 : case KEY_DOWN:
991 : {
992 0 : ImplCursorUpDown( nCode == KEY_UP );
993 : }
994 0 : break;
995 : case KEY_END:
996 : case KEY_HOME:
997 : {
998 0 : ImplCursorUpDown( nCode == KEY_END, true );
999 : }
1000 0 : break;
1001 : case KEY_F6:
1002 : case KEY_ESCAPE:
1003 : {
1004 : // Ctrl-F6 acts like ESC here, the menu bar however will then put the focus in the document
1005 0 : if( nCode == KEY_F6 && !rKEvent.GetKeyCode().IsMod1() )
1006 0 : break;
1007 0 : if( pMenu )
1008 : {
1009 0 : if ( !pMenu->pStartedFrom )
1010 : {
1011 0 : StopExecute();
1012 0 : KillActivePopup();
1013 : }
1014 0 : else if (pMenu->pStartedFrom->IsMenuBar())
1015 : {
1016 0 : pMenu->pStartedFrom->MenuBarKeyInput(rKEvent);
1017 : }
1018 : else
1019 : {
1020 0 : StopExecute();
1021 0 : PopupMenu* pPopupMenu = static_cast<PopupMenu*>(pMenu->pStartedFrom);
1022 0 : MenuFloatingWindow* pFloat = pPopupMenu->ImplGetFloatingWindow();
1023 0 : pFloat->GrabFocus();
1024 0 : pFloat->KillActivePopup();
1025 0 : pPopupMenu->ImplCallHighlight(pFloat->nHighlightedItem);
1026 : }
1027 : }
1028 : }
1029 0 : break;
1030 : case KEY_LEFT:
1031 : {
1032 0 : if ( pMenu && pMenu->pStartedFrom )
1033 : {
1034 0 : StopExecute();
1035 0 : if (pMenu->pStartedFrom->IsMenuBar())
1036 : {
1037 0 : pMenu->pStartedFrom->MenuBarKeyInput(rKEvent);
1038 : }
1039 : else
1040 : {
1041 0 : MenuFloatingWindow* pFloat = static_cast<PopupMenu*>(pMenu->pStartedFrom)->ImplGetFloatingWindow();
1042 0 : pFloat->GrabFocus();
1043 0 : pFloat->KillActivePopup();
1044 0 : sal_uInt16 highlightItem = pFloat->GetHighlightedItem();
1045 0 : pFloat->ChangeHighlightItem(highlightItem, false);
1046 : }
1047 : }
1048 : }
1049 0 : break;
1050 : case KEY_RIGHT:
1051 : {
1052 0 : if( pMenu )
1053 : {
1054 0 : bool bDone = false;
1055 0 : if ( nHighlightedItem != ITEMPOS_INVALID )
1056 : {
1057 0 : MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
1058 0 : if ( pData && pData->pSubMenu )
1059 : {
1060 0 : HighlightChanged( 0 );
1061 0 : bDone = true;
1062 : }
1063 : }
1064 0 : if ( !bDone )
1065 : {
1066 0 : Menu* pStart = pMenu->ImplGetStartMenu();
1067 0 : if (pStart && pStart->IsMenuBar())
1068 : {
1069 : // Forward...
1070 0 : pStart->ImplGetWindow()->KeyInput( rKEvent );
1071 : }
1072 : }
1073 : }
1074 : }
1075 0 : break;
1076 : case KEY_RETURN:
1077 : {
1078 0 : if( pMenu )
1079 : {
1080 0 : MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
1081 0 : if ( pData && pData->bEnabled )
1082 : {
1083 0 : if ( pData->pSubMenu )
1084 0 : HighlightChanged( 0 );
1085 : else
1086 0 : EndExecute();
1087 : }
1088 : else
1089 0 : StopExecute();
1090 : }
1091 : }
1092 0 : break;
1093 : case KEY_MENU:
1094 : {
1095 0 : if( pMenu )
1096 : {
1097 0 : Menu* pStart = pMenu->ImplGetStartMenu();
1098 0 : if (pStart && pStart->IsMenuBar())
1099 : {
1100 : // Forward...
1101 0 : pStart->ImplGetWindow()->KeyInput( rKEvent );
1102 : }
1103 : }
1104 : }
1105 0 : break;
1106 : default:
1107 : {
1108 0 : sal_Unicode nCharCode = rKEvent.GetCharCode();
1109 0 : sal_uInt16 nPos = 0;
1110 0 : sal_uInt16 nDuplicates = 0;
1111 0 : MenuItemData* pData = (nCharCode && pMenu) ? pMenu->GetItemList()->SearchItem( nCharCode, rKEvent.GetKeyCode(), nPos, nDuplicates, nHighlightedItem ) : NULL;
1112 0 : if ( pData )
1113 : {
1114 0 : if ( pData->pSubMenu || nDuplicates > 1 )
1115 : {
1116 0 : ChangeHighlightItem( nPos, false );
1117 0 : HighlightChanged( 0 );
1118 : }
1119 : else
1120 : {
1121 0 : nHighlightedItem = nPos;
1122 0 : EndExecute();
1123 : }
1124 : }
1125 : else
1126 0 : FloatingWindow::KeyInput( rKEvent );
1127 : }
1128 : }
1129 : // #105474# check if menu window was not destroyed
1130 0 : if ( !aDelData.IsDead() )
1131 : {
1132 0 : ImplRemoveDel( &aDelData );
1133 0 : bKeyInput = false;
1134 0 : }
1135 0 : }
1136 :
1137 8 : void MenuFloatingWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle &rPaintRect)
1138 : {
1139 8 : if (!pMenu)
1140 8 : return;
1141 :
1142 8 : rRenderContext.Push( PushFlags::CLIPREGION );
1143 8 : rRenderContext.SetClipRegion(vcl::Region(rPaintRect));
1144 :
1145 8 : if (rRenderContext.IsNativeControlSupported(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL))
1146 : {
1147 0 : rRenderContext.SetClipRegion();
1148 0 : long nX = pMenu->pLogo ? pMenu->pLogo->aBitmap.GetSizePixel().Width() : 0;
1149 0 : Size aPxSize(rRenderContext.GetOutputSizePixel());
1150 0 : aPxSize.Width() -= nX;
1151 0 : ImplControlValue aVal(pMenu->nTextPos - GUTTERBORDER);
1152 : rRenderContext.DrawNativeControl(CTRL_MENU_POPUP, PART_ENTIRE_CONTROL,
1153 : Rectangle(Point(nX, 0), aPxSize),
1154 0 : ControlState::ENABLED, aVal, OUString());
1155 0 : InitMenuClipRegion(rRenderContext);
1156 : }
1157 8 : if (IsScrollMenu())
1158 : {
1159 0 : ImplDrawScroller(rRenderContext, true);
1160 0 : ImplDrawScroller(rRenderContext, false);
1161 : }
1162 8 : rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetMenuColor());
1163 8 : pMenu->ImplPaint(rRenderContext, nScrollerHeight, ImplGetStartY());
1164 8 : if (nHighlightedItem != ITEMPOS_INVALID)
1165 0 : RenderHighlightItem(rRenderContext, nHighlightedItem, true);
1166 :
1167 8 : rRenderContext.Pop();
1168 : }
1169 :
1170 0 : void MenuFloatingWindow::ImplDrawScroller(vcl::RenderContext& rRenderContext, bool bUp)
1171 : {
1172 0 : if (!pMenu)
1173 0 : return;
1174 :
1175 0 : rRenderContext.SetClipRegion();
1176 :
1177 0 : Size aOutSz = rRenderContext.GetOutputSizePixel();
1178 0 : long nY = bUp ? 0 : (aOutSz.Height() - nScrollerHeight);
1179 0 : long nX = pMenu->pLogo ? pMenu->pLogo->aBitmap.GetSizePixel().Width() : 0;
1180 0 : Rectangle aRect(Point(nX, nY), Size(aOutSz.Width() - nX, nScrollerHeight));
1181 :
1182 0 : DecorationView aDecoView(&rRenderContext);
1183 0 : SymbolType eSymbol = bUp ? SymbolType::SPIN_UP : SymbolType::SPIN_DOWN;
1184 :
1185 0 : DrawSymbolFlags nStyle = DrawSymbolFlags::NONE;
1186 0 : if ((bUp && !bScrollUp) || (!bUp && !bScrollDown))
1187 0 : nStyle |= DrawSymbolFlags::Disable;
1188 :
1189 0 : aDecoView.DrawSymbol(aRect, eSymbol, rRenderContext.GetSettings().GetStyleSettings().GetButtonTextColor(), nStyle);
1190 :
1191 0 : InitMenuClipRegion(rRenderContext);
1192 : }
1193 :
1194 0 : void MenuFloatingWindow::RequestHelp( const HelpEvent& rHEvt )
1195 : {
1196 0 : sal_uInt16 nId = nHighlightedItem;
1197 0 : Menu* pM = pMenu;
1198 0 : vcl::Window* pW = this;
1199 :
1200 : // #102618# Get item rect before destroying the window in EndExecute() call
1201 0 : Rectangle aHighlightRect( ImplGetItemRect( nHighlightedItem ) );
1202 :
1203 0 : if ( rHEvt.GetMode() & (HelpEventMode::CONTEXT | HelpEventMode::EXTENDED) )
1204 : {
1205 0 : nHighlightedItem = ITEMPOS_INVALID;
1206 0 : EndExecute();
1207 0 : pW = NULL;
1208 : }
1209 :
1210 0 : if( !ImplHandleHelpEvent( pW, pM, nId, rHEvt, aHighlightRect ) )
1211 0 : Window::RequestHelp( rHEvt );
1212 0 : }
1213 :
1214 24 : void MenuFloatingWindow::StateChanged( StateChangedType nType )
1215 : {
1216 24 : FloatingWindow::StateChanged( nType );
1217 :
1218 24 : if ( ( nType == StateChangedType::ControlForeground ) || ( nType == StateChangedType::ControlBackground ) )
1219 : {
1220 0 : ApplySettings(*this);
1221 0 : Invalidate();
1222 : }
1223 24 : }
1224 :
1225 0 : void MenuFloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
1226 : {
1227 0 : FloatingWindow::DataChanged( rDCEvt );
1228 :
1229 0 : if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
1230 0 : (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
1231 0 : ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1232 0 : (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
1233 : {
1234 0 : ApplySettings(*this);
1235 0 : Invalidate();
1236 : }
1237 0 : }
1238 :
1239 0 : void MenuFloatingWindow::Command( const CommandEvent& rCEvt )
1240 : {
1241 0 : if ( rCEvt.GetCommand() == CommandEventId::Wheel )
1242 : {
1243 0 : const CommandWheelData* pData = rCEvt.GetWheelData();
1244 0 : if( !pData->GetModifier() && ( pData->GetMode() == CommandWheelMode::SCROLL ) )
1245 : {
1246 0 : ImplScroll( pData->GetDelta() > 0L );
1247 0 : MouseMove( MouseEvent( GetPointerPosPixel(), 0 ) );
1248 : }
1249 : }
1250 0 : }
1251 :
1252 0 : css::uno::Reference<css::accessibility::XAccessible> MenuFloatingWindow::CreateAccessible()
1253 : {
1254 0 : css::uno::Reference<css::accessibility::XAccessible> xAcc;
1255 :
1256 0 : if (pMenu && !pMenu->pStartedFrom)
1257 0 : xAcc = pMenu->GetAccessible();
1258 :
1259 0 : return xAcc;
1260 : }
1261 :
1262 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|