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 "menubarwindow.hxx"
21 #include "menuitemlist.hxx"
22 #include "menufloatingwindow.hxx"
23
24 #include <vcl/dockingarea.hxx>
25 #include <vcl/settings.hxx>
26 #include <vcl/taskpanelist.hxx>
27 #include <sal/log.hxx>
28
29 #include <salframe.hxx>
30 #include <salmenu.hxx>
31 #include <svdata.hxx>
32 #include <strings.hrc>
33 #include <bitmaps.hlst>
34 #include <window.h>
35 #include "bufferdevice.hxx"
36 #include <menubarvalue.hxx>
37
38 // document closing button
39 #define IID_DOCUMENTCLOSE 1
40
DecoToolBox(vcl::Window * pParent)41 DecoToolBox::DecoToolBox( vcl::Window* pParent ) :
42 ToolBox( pParent, 0 ),
43 lastSize(-1)
44 {
45 calcMinSize();
46 }
47
DataChanged(const DataChangedEvent & rDCEvt)48 void DecoToolBox::DataChanged( const DataChangedEvent& rDCEvt )
49 {
50 Window::DataChanged( rDCEvt );
51
52 if ( rDCEvt.GetFlags() & AllSettingsFlags::STYLE )
53 {
54 calcMinSize();
55 SetBackground();
56 SetImages( 0, true);
57 }
58 }
59
calcMinSize()60 void DecoToolBox::calcMinSize()
61 {
62 ScopedVclPtrInstance<ToolBox> aTbx( GetParent() );
63 if( GetItemCount() == 0 )
64 {
65 aTbx->InsertItem(ToolBoxItemId(IID_DOCUMENTCLOSE), Image(StockImage::Yes, SV_RESID_BITMAP_CLOSEDOC));
66 }
67 else
68 {
69 ImplToolItems::size_type nItems = GetItemCount();
70 for( ImplToolItems::size_type i = 0; i < nItems; i++ )
71 {
72 ToolBoxItemId nId = GetItemId( i );
73 aTbx->InsertItem( nId, GetItemImage( nId ) );
74 }
75 }
76 maMinSize = aTbx->CalcWindowSizePixel();
77
78 aTbx.disposeAndClear();
79 }
80
SetImages(tools::Long nMaxHeight,bool bForce)81 void DecoToolBox::SetImages( tools::Long nMaxHeight, bool bForce )
82 {
83 tools::Long border = getMinSize().Height() - maImage.GetSizePixel().Height();
84
85 if( !nMaxHeight && lastSize != -1 )
86 nMaxHeight = lastSize + border; // don't change anything if called with 0
87
88 if( nMaxHeight < getMinSize().Height() )
89 nMaxHeight = getMinSize().Height();
90
91 if( (lastSize == nMaxHeight - border) && !bForce )
92 return;
93
94 lastSize = nMaxHeight - border;
95
96 Color aEraseColor( ColorTransparency, 255, 255, 255, 255 );
97 BitmapEx aBmpExDst( maImage.GetBitmapEx() );
98 BitmapEx aBmpExSrc( aBmpExDst );
99
100 aEraseColor.SetAlpha( 0 );
101 aBmpExDst.Erase( aEraseColor );
102 aBmpExDst.Scale( Size( lastSize, lastSize ) );
103
104 tools::Rectangle aSrcRect( Point(0,0), maImage.GetSizePixel() );
105 tools::Rectangle aDestRect( Point((lastSize - maImage.GetSizePixel().Width())/2,
106 (lastSize - maImage.GetSizePixel().Height())/2 ),
107 maImage.GetSizePixel() );
108
109 aBmpExDst.CopyPixel( aDestRect, aSrcRect, aBmpExSrc );
110 SetItemImage( ToolBoxItemId(IID_DOCUMENTCLOSE), Image( aBmpExDst ) );
111
112 }
113
MenuBarWindow(vcl::Window * pParent)114 MenuBarWindow::MenuBarWindow( vcl::Window* pParent ) :
115 Window( pParent, 0 ),
116 m_aCloseBtn(VclPtr<DecoToolBox>::Create(this)),
117 m_aFloatBtn(VclPtr<PushButton>::Create(this, WB_NOPOINTERFOCUS | WB_SMALLSTYLE | WB_RECTSTYLE)),
118 m_aHideBtn(VclPtr<PushButton>::Create(this, WB_NOPOINTERFOCUS | WB_SMALLSTYLE | WB_RECTSTYLE))
119 {
120 SetType(WindowType::MENUBARWINDOW);
121 m_pMenu = nullptr;
122 m_pActivePopup = nullptr;
123 m_nHighlightedItem = ITEMPOS_INVALID;
124 m_nRolloveredItem = ITEMPOS_INVALID;
125 mbAutoPopup = true;
126 m_bIgnoreFirstMove = true;
127 SetMBWHideAccel(ImplGetSVData()->maNWFData.mbAutoAccel);
128 SetMBWMenuKey(false);
129
130 m_aCloseBtn->maImage = Image(StockImage::Yes, SV_RESID_BITMAP_CLOSEDOC);
131
132 m_aCloseBtn->SetBackground();
133 m_aCloseBtn->SetPaintTransparent(true);
134 m_aCloseBtn->SetParentClipMode(ParentClipMode::NoClip);
135
136 m_aCloseBtn->InsertItem(ToolBoxItemId(IID_DOCUMENTCLOSE), m_aCloseBtn->maImage);
137 m_aCloseBtn->SetSelectHdl(LINK(this, MenuBarWindow, CloseHdl));
138 m_aCloseBtn->AddEventListener(LINK(this, MenuBarWindow, ToolboxEventHdl));
139 m_aCloseBtn->SetQuickHelpText(ToolBoxItemId(IID_DOCUMENTCLOSE), VclResId(SV_HELPTEXT_CLOSEDOCUMENT));
140
141 m_aFloatBtn->SetSymbol( SymbolType::FLOAT );
142 m_aFloatBtn->SetQuickHelpText(VclResId(SV_HELPTEXT_RESTORE));
143
144 m_aHideBtn->SetSymbol( SymbolType::HIDE );
145 m_aHideBtn->SetQuickHelpText(VclResId(SV_HELPTEXT_MINIMIZE));
146
147 ImplInitStyleSettings();
148
149 AddEventListener(LINK(this, MenuBarWindow, ShowHideListener));
150 }
151
~MenuBarWindow()152 MenuBarWindow::~MenuBarWindow()
153 {
154 disposeOnce();
155 }
156
dispose()157 void MenuBarWindow::dispose()
158 {
159 m_aCloseBtn->RemoveEventListener(LINK(this, MenuBarWindow, ToolboxEventHdl));
160 RemoveEventListener(LINK(this, MenuBarWindow, ShowHideListener));
161
162 mpParentPopup.disposeAndClear();
163 m_aHideBtn.disposeAndClear();
164 m_aFloatBtn.disposeAndClear();
165 m_aCloseBtn.disposeAndClear();
166 m_pMenu.clear();
167 m_pActivePopup.clear();
168 m_xSaveFocusId.clear();
169
170 Window::dispose();
171 }
172
SetMenu(MenuBar * pMen)173 void MenuBarWindow::SetMenu( MenuBar* pMen )
174 {
175 m_pMenu = pMen;
176 KillActivePopup();
177 m_nHighlightedItem = ITEMPOS_INVALID;
178 if (pMen)
179 {
180 m_aCloseBtn->ShowItem(ToolBoxItemId(IID_DOCUMENTCLOSE), pMen->HasCloseButton());
181 m_aCloseBtn->Show(pMen->HasCloseButton() || !m_aAddButtons.empty());
182 m_aFloatBtn->Show(pMen->HasFloatButton());
183 m_aHideBtn->Show(pMen->HasHideButton());
184 }
185 Invalidate();
186
187 // show and connect native menubar
188 if( m_pMenu && m_pMenu->ImplGetSalMenu() )
189 {
190 if( m_pMenu->ImplGetSalMenu()->VisibleMenuBar() )
191 ImplGetFrame()->SetMenu( m_pMenu->ImplGetSalMenu() );
192
193 m_pMenu->ImplGetSalMenu()->SetFrame( ImplGetFrame() );
194 m_pMenu->ImplGetSalMenu()->ShowMenuBar(true);
195 }
196 }
197
SetHeight(tools::Long nHeight)198 void MenuBarWindow::SetHeight(tools::Long nHeight)
199 {
200 setPosSizePixel(0, 0, 0, nHeight, PosSizeFlags::Height);
201 }
202
ShowButtons(bool bClose,bool bFloat,bool bHide)203 void MenuBarWindow::ShowButtons( bool bClose, bool bFloat, bool bHide )
204 {
205 m_aCloseBtn->ShowItem(ToolBoxItemId(IID_DOCUMENTCLOSE), bClose);
206 m_aCloseBtn->Show(bClose || !m_aAddButtons.empty());
207 if (m_pMenu->mpSalMenu)
208 m_pMenu->mpSalMenu->ShowCloseButton(bClose);
209 m_aFloatBtn->Show( bFloat );
210 m_aHideBtn->Show( bHide );
211 Resize();
212 }
213
MinCloseButtonSize() const214 Size const & MenuBarWindow::MinCloseButtonSize() const
215 {
216 return m_aCloseBtn->getMinSize();
217 }
218
IMPL_LINK_NOARG(MenuBarWindow,CloseHdl,ToolBox *,void)219 IMPL_LINK_NOARG(MenuBarWindow, CloseHdl, ToolBox *, void)
220 {
221 if( ! m_pMenu )
222 return;
223
224 if( m_aCloseBtn->GetCurItemId() == ToolBoxItemId(IID_DOCUMENTCLOSE) )
225 {
226 // #i106052# call close hdl asynchronously to ease handler implementation
227 // this avoids still being in the handler while the DecoToolBox already
228 // gets destroyed
229 Application::PostUserEvent(m_pMenu->GetCloseButtonClickHdl());
230 }
231 else
232 {
233 std::map<sal_uInt16,AddButtonEntry>::iterator it = m_aAddButtons.find(sal_uInt16(m_aCloseBtn->GetCurItemId()));
234 if( it != m_aAddButtons.end() )
235 {
236 MenuBarButtonCallbackArg aArg;
237 aArg.nId = it->first;
238 aArg.bHighlight = (sal_uInt16(m_aCloseBtn->GetHighlightItemId()) == it->first);
239 it->second.m_aSelectLink.Call( aArg );
240 }
241 }
242 }
243
IMPL_LINK(MenuBarWindow,ToolboxEventHdl,VclWindowEvent &,rEvent,void)244 IMPL_LINK( MenuBarWindow, ToolboxEventHdl, VclWindowEvent&, rEvent, void )
245 {
246 if( ! m_pMenu )
247 return;
248
249 MenuBarButtonCallbackArg aArg;
250 aArg.nId = 0xffff;
251 aArg.bHighlight = (rEvent.GetId() == VclEventId::ToolboxHighlight);
252 if( rEvent.GetId() == VclEventId::ToolboxHighlight )
253 aArg.nId =sal_uInt16(m_aCloseBtn->GetHighlightItemId());
254 else if( rEvent.GetId() == VclEventId::ToolboxHighlightOff )
255 {
256 auto nPos = static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rEvent.GetData()));
257 aArg.nId = sal_uInt16(m_aCloseBtn->GetItemId(nPos));
258 }
259 std::map< sal_uInt16, AddButtonEntry >::iterator it = m_aAddButtons.find( aArg.nId );
260 if( it != m_aAddButtons.end() )
261 {
262 it->second.m_aHighlightLink.Call( aArg );
263 }
264 }
265
IMPL_LINK(MenuBarWindow,ShowHideListener,VclWindowEvent &,rEvent,void)266 IMPL_LINK( MenuBarWindow, ShowHideListener, VclWindowEvent&, rEvent, void )
267 {
268 if( ! m_pMenu )
269 return;
270
271 if( rEvent.GetId() == VclEventId::WindowShow )
272 m_pMenu->ImplCallEventListeners( VclEventId::MenuShow, ITEMPOS_INVALID );
273 else if( rEvent.GetId() == VclEventId::WindowHide )
274 m_pMenu->ImplCallEventListeners( VclEventId::MenuHide, ITEMPOS_INVALID );
275 }
276
ImplCreatePopup(bool bPreSelectFirst)277 void MenuBarWindow::ImplCreatePopup( bool bPreSelectFirst )
278 {
279 MenuItemData* pItemData = m_pMenu ? m_pMenu->GetItemList()->GetDataFromPos( m_nHighlightedItem ) : nullptr;
280 if ( !pItemData )
281 return;
282
283 m_bIgnoreFirstMove = true;
284 if ( m_pActivePopup && ( m_pActivePopup != pItemData->pSubMenu ) )
285 {
286 KillActivePopup();
287 }
288 if ( !(pItemData->bEnabled && pItemData->pSubMenu && ( m_nHighlightedItem != ITEMPOS_INVALID ) &&
289 ( pItemData->pSubMenu != m_pActivePopup )) )
290 return;
291
292 m_pActivePopup = pItemData->pSubMenu.get();
293 tools::Long nX = 0;
294 MenuItemData* pData = nullptr;
295 for ( sal_uLong n = 0; n < m_nHighlightedItem; n++ )
296 {
297 pData = m_pMenu->GetItemList()->GetDataFromPos( n );
298 nX += pData->aSz.Width();
299 }
300 pData = m_pMenu->pItemList->GetDataFromPos( m_nHighlightedItem );
301 Point aItemTopLeft( nX, 0 );
302 Point aItemBottomRight( aItemTopLeft );
303 aItemBottomRight.AdjustX(pData->aSz.Width() );
304
305 if (pData->bHiddenOnGUI)
306 {
307 mpParentPopup.disposeAndClear();
308 mpParentPopup = VclPtr<PopupMenu>::Create();
309 m_pActivePopup = mpParentPopup.get();
310
311 for (sal_uInt16 i = m_nHighlightedItem; i < m_pMenu->GetItemCount(); ++i)
312 {
313 sal_uInt16 nId = m_pMenu->GetItemId(i);
314
315 MenuItemData* pParentItemData = m_pMenu->GetItemList()->GetData(nId);
316 assert(pParentItemData);
317 mpParentPopup->InsertItem(nId, pParentItemData->aText, pParentItemData->nBits, pParentItemData->sIdent);
318 mpParentPopup->SetHelpId(nId, pParentItemData->aHelpId);
319 mpParentPopup->SetHelpText(nId, pParentItemData->aHelpText);
320 mpParentPopup->SetAccelKey(nId, pParentItemData->aAccelKey);
321 mpParentPopup->SetItemCommand(nId, pParentItemData->aCommandStr);
322 mpParentPopup->SetHelpCommand(nId, pParentItemData->aHelpCommandStr);
323
324 PopupMenu* pPopup = m_pMenu->GetPopupMenu(nId);
325 mpParentPopup->SetPopupMenu(nId, pPopup);
326 }
327 }
328 // the menu bar could have height 0 in fullscreen mode:
329 // so do not use always WindowHeight, as ItemHeight < WindowHeight.
330 if ( GetSizePixel().Height() )
331 {
332 // #107747# give menuitems the height of the menubar
333 aItemBottomRight.AdjustY(GetOutputSizePixel().Height()-1 );
334 }
335
336 // ImplExecute is not modal...
337 // #99071# do not grab the focus, otherwise it will be restored to the menubar
338 // when the frame is reactivated later
339 //GrabFocus();
340 m_pActivePopup->ImplExecute( this, tools::Rectangle( aItemTopLeft, aItemBottomRight ), FloatWinPopupFlags::Down | FloatWinPopupFlags::NoHorzPlacement, m_pMenu, bPreSelectFirst );
341 // does not have a window, if aborted before or if there are no entries
342 if ( m_pActivePopup->ImplGetFloatingWindow() )
343 m_pActivePopup->ImplGetFloatingWindow()->AddPopupModeWindow( this );
344 else
345 m_pActivePopup = nullptr;
346 }
347
KillActivePopup()348 void MenuBarWindow::KillActivePopup()
349 {
350 if ( !m_pActivePopup )
351 return;
352
353 if( m_pActivePopup->pWindow )
354 if( static_cast<FloatingWindow *>(m_pActivePopup->pWindow.get())->IsInCleanUp() )
355 return; // kill it later
356
357 if ( m_pActivePopup->bInCallback )
358 m_pActivePopup->bCanceled = true;
359
360 m_pActivePopup->bInCallback = true;
361 m_pActivePopup->Deactivate();
362 m_pActivePopup->bInCallback = false;
363 // check for pActivePopup, if stopped by deactivate...
364 if ( m_pActivePopup->ImplGetWindow() )
365 {
366 if (mpParentPopup)
367 {
368 for (sal_uInt16 i = 0; i < mpParentPopup->GetItemCount(); ++i)
369 {
370 sal_uInt16 nId = mpParentPopup->GetItemId(i);
371 MenuItemData* pParentItemData = mpParentPopup->GetItemList()->GetData(nId);
372 assert(pParentItemData);
373 pParentItemData->pSubMenu = nullptr;
374 }
375 }
376 m_pActivePopup->ImplGetFloatingWindow()->StopExecute();
377 m_pActivePopup->ImplGetFloatingWindow()->doShutdown();
378 m_pActivePopup->pWindow.disposeAndClear();
379 }
380 m_pActivePopup = nullptr;
381 }
382
PopupClosed(Menu const * pPopup)383 void MenuBarWindow::PopupClosed( Menu const * pPopup )
384 {
385 if ( pPopup == m_pActivePopup )
386 {
387 KillActivePopup();
388 ChangeHighlightItem( ITEMPOS_INVALID, false, ImplGetFrameWindow()->ImplGetFrameData()->mbHasFocus, false );
389 }
390 }
391
MouseButtonDown(const MouseEvent & rMEvt)392 void MenuBarWindow::MouseButtonDown( const MouseEvent& rMEvt )
393 {
394 mbAutoPopup = true;
395 SetMBWMenuKey(false);
396 sal_uInt16 nEntry = ImplFindEntry( rMEvt.GetPosPixel() );
397 if ( ( nEntry != ITEMPOS_INVALID ) && !m_pActivePopup )
398 {
399 ChangeHighlightItem( nEntry, false );
400 }
401 else
402 {
403 KillActivePopup();
404 ChangeHighlightItem( ITEMPOS_INVALID, false );
405 }
406 }
407
MouseButtonUp(const MouseEvent &)408 void MenuBarWindow::MouseButtonUp( const MouseEvent& )
409 {
410 }
411
MouseMove(const MouseEvent & rMEvt)412 void MenuBarWindow::MouseMove( const MouseEvent& rMEvt )
413 {
414 if ( rMEvt.IsSynthetic() || rMEvt.IsEnterWindow() )
415 return;
416
417 if ( rMEvt.IsLeaveWindow() )
418 {
419 if ( m_nRolloveredItem != ITEMPOS_INVALID && m_nRolloveredItem != m_nHighlightedItem )
420 {
421 // there is a spurious MouseMove generated after a menu is launched from the keyboard, hence this...
422 if (m_nHighlightedItem != ITEMPOS_INVALID)
423 {
424 bool hide = GetMBWHideAccel();
425 SetMBWHideAccel(ImplGetSVData()->maNWFData.mbAutoAccel);
426 Invalidate(); //HighlightItem( nRolloveredItem, false );
427 SetMBWHideAccel(hide);
428 }
429 else
430 Invalidate(); //HighlightItem( nRolloveredItem, false );
431 }
432
433 m_nRolloveredItem = ITEMPOS_INVALID;
434 return;
435 }
436
437 sal_uInt16 nEntry = ImplFindEntry( rMEvt.GetPosPixel() );
438 if ( m_nHighlightedItem == ITEMPOS_INVALID )
439 {
440 if ( m_nRolloveredItem != nEntry )
441 {
442 if ( m_nRolloveredItem != ITEMPOS_INVALID )
443 Invalidate(); //HighlightItem( nRolloveredItem, false );
444
445 m_nRolloveredItem = nEntry;
446 Invalidate(); //HighlightItem( nRolloveredItem, true );
447 }
448 return;
449 }
450 m_nRolloveredItem = nEntry;
451
452 if( m_bIgnoreFirstMove )
453 {
454 m_bIgnoreFirstMove = false;
455 return;
456 }
457
458 if ( ( nEntry != ITEMPOS_INVALID )
459 && ( nEntry != m_nHighlightedItem ) )
460 ChangeHighlightItem( nEntry, false );
461 }
462
ChangeHighlightItem(sal_uInt16 n,bool bSelectEntry,bool bAllowRestoreFocus,bool bDefaultToDocument)463 void MenuBarWindow::ChangeHighlightItem( sal_uInt16 n, bool bSelectEntry, bool bAllowRestoreFocus, bool bDefaultToDocument)
464 {
465 if( ! m_pMenu )
466 return;
467
468 if (n == ITEMPOS_INVALID)
469 SetMBWHideAccel(ImplGetSVData()->maNWFData.mbAutoAccel);
470
471 // #57934# close active popup if applicable, as TH's background storage works.
472 MenuItemData* pNextData = m_pMenu->pItemList->GetDataFromPos( n );
473 if ( m_pActivePopup && m_pActivePopup->ImplGetWindow() && ( !pNextData || ( m_pActivePopup != pNextData->pSubMenu ) ) )
474 KillActivePopup(); // pActivePopup when applicable without pWin, if Rescheduled in Activate()
475
476 // activate menubar only ones per cycle...
477 bool bJustActivated = false;
478 if ( ( m_nHighlightedItem == ITEMPOS_INVALID ) && ( n != ITEMPOS_INVALID ) )
479 {
480 ImplGetSVData()->mpWinData->mbNoDeactivate = true;
481 // #105406# avoid saving the focus when we already have the focus
482 bool bNoSaveFocus = (this == ImplGetSVData()->mpWinData->mpFocusWin.get());
483
484 if( m_xSaveFocusId != nullptr )
485 {
486 if (!ImplGetSVData()->mpWinData->mbNoSaveFocus)
487 {
488 m_xSaveFocusId = nullptr;
489 if( !bNoSaveFocus )
490 m_xSaveFocusId = Window::SaveFocus(); // only save focus when initially activated
491 }
492 else {
493 ; // do nothing: we 're activated again from taskpanelist, focus was already saved
494 }
495 }
496 else
497 {
498 if( !bNoSaveFocus )
499 m_xSaveFocusId = Window::SaveFocus(); // only save focus when initially activated
500 }
501 m_pMenu->bInCallback = true; // set here if Activate overridden
502 m_pMenu->Activate();
503 m_pMenu->bInCallback = false;
504 bJustActivated = true;
505 }
506 else if ( ( m_nHighlightedItem != ITEMPOS_INVALID ) && ( n == ITEMPOS_INVALID ) )
507 {
508 m_pMenu->bInCallback = true;
509 m_pMenu->Deactivate();
510 m_pMenu->bInCallback = false;
511 ImplGetSVData()->mpWinData->mbNoDeactivate = false;
512 if (!ImplGetSVData()->mpWinData->mbNoSaveFocus)
513 {
514 VclPtr<vcl::Window> xTempFocusId;
515 if (m_xSaveFocusId && !m_xSaveFocusId->isDisposed())
516 xTempFocusId = m_xSaveFocusId;
517 m_xSaveFocusId = nullptr;
518
519 if (bAllowRestoreFocus)
520 {
521 // tdf#115227 the popup is already killed, so temporarily set us as the
522 // focus window, so we could avoid sending superfluous activate events
523 // to top window listeners.
524 if (xTempFocusId || bDefaultToDocument)
525 ImplGetSVData()->mpWinData->mpFocusWin = this;
526
527 // #105406# restore focus to document if we could not save focus before
528 if (!xTempFocusId && bDefaultToDocument)
529 GrabFocusToDocument();
530 else
531 Window::EndSaveFocus(xTempFocusId);
532 }
533 }
534 }
535
536 if ( m_nHighlightedItem != ITEMPOS_INVALID )
537 {
538 if ( m_nHighlightedItem != m_nRolloveredItem )
539 Invalidate(); //HighlightItem( nHighlightedItem, false );
540
541 m_pMenu->ImplCallEventListeners( VclEventId::MenuDehighlight, m_nHighlightedItem );
542 }
543
544 m_nHighlightedItem = n;
545 SAL_WARN_IF( ( m_nHighlightedItem != ITEMPOS_INVALID ) && !m_pMenu->ImplIsVisible( m_nHighlightedItem ), "vcl", "ChangeHighlightItem: Not visible!" );
546 if ( m_nHighlightedItem != ITEMPOS_INVALID )
547 Invalidate(); //HighlightItem( nHighlightedItem, true );
548 else if ( m_nRolloveredItem != ITEMPOS_INVALID )
549 Invalidate(); //HighlightItem( nRolloveredItem, true );
550 m_pMenu->ImplCallHighlight(m_nHighlightedItem);
551
552 if( mbAutoPopup )
553 ImplCreatePopup( bSelectEntry );
554
555 // #58935# #73659# Focus, if no popup underneath...
556 if ( bJustActivated && !m_pActivePopup )
557 GrabFocus();
558 }
559
ImplGetTopDockingAreaHeight(vcl::Window const * pWindow)560 static int ImplGetTopDockingAreaHeight( vcl::Window const *pWindow )
561 {
562 // find docking area that is top aligned and return its height
563 // note: dockingareas are direct children of the SystemWindow
564 if( pWindow->ImplGetFrameWindow() )
565 {
566 vcl::Window *pWin = pWindow->ImplGetFrameWindow()->GetWindow( GetWindowType::FirstChild ); //mpWindowImpl->mpFirstChild;
567 while( pWin )
568 {
569 if( pWin->IsSystemWindow() )
570 {
571 vcl::Window *pChildWin = pWin->GetWindow( GetWindowType::FirstChild ); //mpWindowImpl->mpFirstChild;
572 while( pChildWin )
573 {
574 DockingAreaWindow *pDockingArea = nullptr;
575 if ( pChildWin->GetType() == WindowType::DOCKINGAREA )
576 pDockingArea = static_cast< DockingAreaWindow* >( pChildWin );
577
578 if( pDockingArea && pDockingArea->GetAlign() == WindowAlign::Top &&
579 pDockingArea->IsVisible() && pDockingArea->GetOutputSizePixel().Height() != 0 )
580 {
581 return pDockingArea->GetOutputSizePixel().Height();
582 }
583
584 pChildWin = pChildWin->GetWindow( GetWindowType::Next ); //mpWindowImpl->mpNext;
585 }
586
587 }
588
589 pWin = pWin->GetWindow( GetWindowType::Next ); //mpWindowImpl->mpNext;
590 }
591 }
592 return 0;
593 }
594
ImplAddNWFSeparator(vcl::RenderContext & rRenderContext,const Size & rSize,const MenubarValue & rMenubarValue)595 static void ImplAddNWFSeparator(vcl::RenderContext& rRenderContext, const Size& rSize, const MenubarValue& rMenubarValue)
596 {
597 // add a separator if
598 // - we have an adjacent docking area
599 // - and if toolbars would draw them as well (mbDockingAreaSeparateTB must not be set, see dockingarea.cxx)
600 if (rMenubarValue.maTopDockingAreaHeight
601 && !ImplGetSVData()->maNWFData.mbDockingAreaSeparateTB
602 && !ImplGetSVData()->maNWFData.mbDockingAreaAvoidTBFrames)
603 {
604 // note: the menubar only provides the upper (dark) half of it, the rest (bright part) is drawn by the docking area
605
606 rRenderContext.SetLineColor(rRenderContext.GetSettings().GetStyleSettings().GetSeparatorColor());
607 tools::Rectangle aRect(Point(), rSize);
608 rRenderContext.DrawLine(aRect.BottomLeft(), aRect.BottomRight());
609 }
610 }
611
HighlightItem(vcl::RenderContext & rRenderContext,sal_uInt16 nPos)612 void MenuBarWindow::HighlightItem(vcl::RenderContext& rRenderContext, sal_uInt16 nPos)
613 {
614 if (!m_pMenu)
615 return;
616
617 tools::Long nX = 0;
618 size_t nCount = m_pMenu->pItemList->size();
619
620 Size aOutputSize = GetOutputSizePixel();
621 aOutputSize.AdjustWidth( -(m_aCloseBtn->GetSizePixel().Width()) );
622
623 for (size_t n = 0; n < nCount; n++)
624 {
625 MenuItemData* pData = m_pMenu->pItemList->GetDataFromPos( n );
626 if (n == nPos)
627 {
628 if (pData->eType != MenuItemType::SEPARATOR)
629 {
630 // #107747# give menuitems the height of the menubar
631 tools::Rectangle aRect(Point(nX, 1), Size(pData->aSz.Width(), aOutputSize.Height() - 2));
632 rRenderContext.Push(vcl::PushFlags::CLIPREGION);
633 rRenderContext.IntersectClipRegion(aRect);
634 bool bRollover, bHighlight;
635 if (!ImplGetSVData()->maNWFData.mbRolloverMenubar)
636 {
637 bHighlight = true;
638 bRollover = nPos != m_nHighlightedItem;
639 }
640 else
641 {
642 bRollover = nPos == m_nRolloveredItem;
643 bHighlight = nPos == m_nHighlightedItem;
644 }
645 if (rRenderContext.IsNativeControlSupported(ControlType::Menubar, ControlPart::MenuItem) &&
646 rRenderContext.IsNativeControlSupported(ControlType::Menubar, ControlPart::Entire))
647 {
648 // draw background (transparency)
649 MenubarValue aControlValue;
650 aControlValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight( this );
651
652 if (!Application::GetSettings().GetStyleSettings().GetPersonaHeader().IsEmpty() )
653 Erase(rRenderContext);
654 else
655 {
656 tools::Rectangle aBgRegion(Point(), aOutputSize);
657 rRenderContext.DrawNativeControl(ControlType::Menubar, ControlPart::Entire, aBgRegion,
658 ControlState::ENABLED, aControlValue, OUString());
659 }
660
661 ImplAddNWFSeparator(rRenderContext, aOutputSize, aControlValue);
662
663 // draw selected item
664 ControlState nState = ControlState::ENABLED;
665 if (bRollover)
666 nState |= ControlState::ROLLOVER;
667 else
668 nState |= ControlState::SELECTED;
669 rRenderContext.DrawNativeControl(ControlType::Menubar, ControlPart::MenuItem,
670 aRect, nState, aControlValue, OUString() );
671 }
672 else
673 {
674 if (bRollover)
675 rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetMenuBarRolloverColor());
676 else
677 rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetMenuHighlightColor());
678 rRenderContext.SetLineColor();
679 rRenderContext.DrawRect(aRect);
680 }
681 rRenderContext.Pop();
682
683 m_pMenu->ImplPaint(rRenderContext, aOutputSize, 0, 0, pData, bHighlight, false, bRollover);
684 }
685 return;
686 }
687
688 nX += pData->aSz.Width();
689 }
690 }
691
ImplGetItemRect(sal_uInt16 nPos) const692 tools::Rectangle MenuBarWindow::ImplGetItemRect( sal_uInt16 nPos ) const
693 {
694 tools::Rectangle aRect;
695 if( m_pMenu )
696 {
697 tools::Long nX = 0;
698 size_t nCount = m_pMenu->pItemList->size();
699 for ( size_t n = 0; n < nCount; n++ )
700 {
701 MenuItemData* pData = m_pMenu->pItemList->GetDataFromPos( n );
702 if ( n == nPos )
703 {
704 if ( pData->eType != MenuItemType::SEPARATOR )
705 // #107747# give menuitems the height of the menubar
706 aRect = tools::Rectangle( Point( nX, 1 ), Size( pData->aSz.Width(), GetOutputSizePixel().Height()-2 ) );
707 break;
708 }
709
710 nX += pData->aSz.Width();
711 }
712 }
713 return aRect;
714 }
715
KeyInput(const KeyEvent & rKEvent)716 void MenuBarWindow::KeyInput( const KeyEvent& rKEvent )
717 {
718 if ( !HandleKeyEvent( rKEvent ) )
719 Window::KeyInput( rKEvent );
720 }
721
HandleKeyEvent(const KeyEvent & rKEvent,bool bFromMenu)722 bool MenuBarWindow::HandleKeyEvent( const KeyEvent& rKEvent, bool bFromMenu )
723 {
724 if (!m_pMenu)
725 return false;
726
727 if (m_pMenu->bInCallback)
728 return true; // swallow
729
730 bool bDone = false;
731 sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
732
733 if( GetParent() )
734 {
735 if( GetParent()->GetWindow( GetWindowType::Client )->IsSystemWindow() )
736 {
737 SystemWindow *pSysWin = static_cast<SystemWindow*>(GetParent()->GetWindow( GetWindowType::Client ));
738 if( pSysWin->GetTaskPaneList() )
739 if( pSysWin->GetTaskPaneList()->HandleKeyEvent( rKEvent ) )
740 return true;
741 }
742 }
743
744 // no key events if native menus
745 if (m_pMenu->ImplGetSalMenu() && m_pMenu->ImplGetSalMenu()->VisibleMenuBar())
746 {
747 return false;
748 }
749
750 if ( nCode == KEY_MENU && !rKEvent.GetKeyCode().IsShift() ) // only F10, not Shift-F10
751 {
752 mbAutoPopup = false;
753 if ( m_nHighlightedItem == ITEMPOS_INVALID )
754 {
755 ChangeHighlightItem( 0, false );
756 GrabFocus();
757 }
758 else
759 {
760 ChangeHighlightItem( ITEMPOS_INVALID, false );
761 m_xSaveFocusId = nullptr;
762 }
763 bDone = true;
764 }
765 else if ( bFromMenu )
766 {
767 if ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) ||
768 ( nCode == KEY_HOME ) || ( nCode == KEY_END ) )
769 {
770 sal_uInt16 n = m_nHighlightedItem;
771 if ( n == ITEMPOS_INVALID )
772 {
773 if ( nCode == KEY_LEFT)
774 n = 0;
775 else
776 n = m_pMenu->GetItemCount()-1;
777 }
778
779 sal_uInt16 nLoop = n;
780
781 if( nCode == KEY_HOME )
782 { n = sal_uInt16(-1); nLoop = n+1; }
783 if( nCode == KEY_END )
784 { n = m_pMenu->GetItemCount(); nLoop = n-1; }
785
786 do
787 {
788 if ( nCode == KEY_LEFT || nCode == KEY_END )
789 {
790 if ( n )
791 n--;
792 else
793 n = m_pMenu->GetItemCount()-1;
794 }
795 if ( nCode == KEY_RIGHT || nCode == KEY_HOME )
796 {
797 n++;
798 if ( n >= m_pMenu->GetItemCount() )
799 n = 0;
800 }
801
802 MenuItemData* pData = m_pMenu->GetItemList()->GetDataFromPos( n );
803 if (pData->eType != MenuItemType::SEPARATOR &&
804 m_pMenu->ImplIsVisible(n) &&
805 !m_pMenu->ImplCurrentlyHiddenOnGUI(n))
806 {
807 ChangeHighlightItem( n, true );
808 break;
809 }
810 } while ( n != nLoop );
811 bDone = true;
812 }
813 else if ( nCode == KEY_RETURN )
814 {
815 if( m_pActivePopup ) KillActivePopup();
816 else
817 if ( !mbAutoPopup )
818 {
819 ImplCreatePopup( true );
820 mbAutoPopup = true;
821 }
822 bDone = true;
823 }
824 else if ( ( nCode == KEY_UP ) || ( nCode == KEY_DOWN ) )
825 {
826 if ( !mbAutoPopup )
827 {
828 ImplCreatePopup( true );
829 mbAutoPopup = true;
830 }
831 bDone = true;
832 }
833 else if ( nCode == KEY_ESCAPE || ( nCode == KEY_F6 && rKEvent.GetKeyCode().IsMod1() ) )
834 {
835 if( m_pActivePopup )
836 {
837 // hide the menu and remove the focus...
838 mbAutoPopup = false;
839 KillActivePopup();
840 }
841
842 ChangeHighlightItem( ITEMPOS_INVALID, false );
843
844 if( nCode == KEY_F6 && rKEvent.GetKeyCode().IsMod1() )
845 {
846 // put focus into document
847 GrabFocusToDocument();
848 }
849
850 bDone = true;
851 }
852 }
853
854 if ( !bDone && ( bFromMenu || rKEvent.GetKeyCode().IsMod2() ) )
855 {
856 sal_Unicode nCharCode = rKEvent.GetCharCode();
857 if ( nCharCode )
858 {
859 size_t nEntry, nDuplicates;
860 MenuItemData* pData = m_pMenu->GetItemList()->SearchItem( nCharCode, rKEvent.GetKeyCode(), nEntry, nDuplicates, m_nHighlightedItem );
861 if ( pData && (nEntry != ITEMPOS_INVALID) )
862 {
863 mbAutoPopup = true;
864 ChangeHighlightItem( nEntry, true );
865 bDone = true;
866 }
867 }
868 }
869
870 return bDone;
871 }
872
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)873 void MenuBarWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
874 {
875 if (!m_pMenu)
876 return;
877
878 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
879
880 Size aOutputSize = GetOutputSizePixel();
881
882 // no VCL paint if native menus
883 if (m_pMenu->ImplGetSalMenu() && m_pMenu->ImplGetSalMenu()->VisibleMenuBar())
884 return;
885
886 // Make sure that all actual rendering happens in one go to avoid flicker.
887 vcl::BufferDevice pBuffer(this, rRenderContext);
888
889 if (rRenderContext.IsNativeControlSupported(ControlType::Menubar, ControlPart::Entire))
890 {
891 MenubarValue aMenubarValue;
892 aMenubarValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight(this);
893
894 if (!rStyleSettings.GetPersonaHeader().IsEmpty())
895 Erase(*pBuffer);
896 else
897 {
898 tools::Rectangle aCtrlRegion( Point(), aOutputSize );
899
900 pBuffer->DrawNativeControl(ControlType::Menubar, ControlPart::Entire, aCtrlRegion,
901 ControlState::ENABLED, aMenubarValue, OUString());
902 }
903
904 ImplAddNWFSeparator(*pBuffer, aOutputSize, aMenubarValue);
905 }
906
907 // shrink the area of the buttons
908 aOutputSize.AdjustWidth( -(m_aCloseBtn->GetSizePixel().Width()) );
909
910 pBuffer->SetFillColor(rStyleSettings.GetMenuColor());
911 m_pMenu->ImplPaint(*pBuffer, aOutputSize, 0);
912
913 if (m_nHighlightedItem != ITEMPOS_INVALID && m_pMenu && !m_pMenu->GetItemList()->GetDataFromPos(m_nHighlightedItem)->bHiddenOnGUI)
914 HighlightItem(*pBuffer, m_nHighlightedItem);
915 else if (m_nRolloveredItem != ITEMPOS_INVALID)
916 HighlightItem(*pBuffer, m_nRolloveredItem);
917
918 // in high contrast mode draw a separating line on the lower edge
919 if (!rRenderContext.IsNativeControlSupported( ControlType::Menubar, ControlPart::Entire) &&
920 rStyleSettings.GetHighContrastMode())
921 {
922 pBuffer->Push(vcl::PushFlags::LINECOLOR | vcl::PushFlags::MAPMODE);
923 pBuffer->SetLineColor(COL_WHITE);
924 pBuffer->SetMapMode(MapMode(MapUnit::MapPixel));
925 Size aSize = GetSizePixel();
926 pBuffer->DrawLine(Point(0, aSize.Height() - 1),
927 Point(aSize.Width() - 1, aSize.Height() - 1));
928 pBuffer->Pop();
929 }
930 }
931
Resize()932 void MenuBarWindow::Resize()
933 {
934 Size aOutSz = GetOutputSizePixel();
935 tools::Long n = aOutSz.Height()-4;
936 tools::Long nX = aOutSz.Width()-3;
937 tools::Long nY = 2;
938
939 if ( m_aCloseBtn->IsVisible() )
940 {
941 m_aCloseBtn->Hide();
942 m_aCloseBtn->SetImages(n);
943 Size aTbxSize( m_aCloseBtn->CalcWindowSizePixel() );
944 nX -= aTbxSize.Width();
945 tools::Long nTbxY = (aOutSz.Height() - aTbxSize.Height())/2;
946 m_aCloseBtn->setPosSizePixel(nX, nTbxY, aTbxSize.Width(), aTbxSize.Height());
947 nX -= 3;
948 m_aCloseBtn->Show();
949 }
950 if ( m_aFloatBtn->IsVisible() )
951 {
952 nX -= n;
953 m_aFloatBtn->setPosSizePixel( nX, nY, n, n );
954 }
955 if ( m_aHideBtn->IsVisible() )
956 {
957 nX -= n;
958 m_aHideBtn->setPosSizePixel( nX, nY, n, n );
959 }
960
961 m_aFloatBtn->SetSymbol( SymbolType::FLOAT );
962 m_aHideBtn->SetSymbol( SymbolType::HIDE );
963
964 Invalidate();
965 }
966
ImplFindEntry(const Point & rMousePos) const967 sal_uInt16 MenuBarWindow::ImplFindEntry( const Point& rMousePos ) const
968 {
969 if( m_pMenu )
970 {
971 tools::Long nX = 0;
972 size_t nCount = m_pMenu->pItemList->size();
973 for ( size_t n = 0; n < nCount; n++ )
974 {
975 MenuItemData* pData = m_pMenu->pItemList->GetDataFromPos( n );
976 if ( m_pMenu->ImplIsVisible( n ) )
977 {
978 nX += pData->aSz.Width();
979 if ( nX > rMousePos.X() )
980 return static_cast<sal_uInt16>(n);
981 }
982 }
983 }
984 return ITEMPOS_INVALID;
985 }
986
RequestHelp(const HelpEvent & rHEvt)987 void MenuBarWindow::RequestHelp( const HelpEvent& rHEvt )
988 {
989 sal_uInt16 nId = m_nHighlightedItem;
990 if ( rHEvt.GetMode() & HelpEventMode::CONTEXT )
991 ChangeHighlightItem( ITEMPOS_INVALID, true );
992
993 tools::Rectangle aHighlightRect( ImplGetItemRect( m_nHighlightedItem ) );
994 if( !ImplHandleHelpEvent( this, m_pMenu, nId, rHEvt, aHighlightRect ) )
995 Window::RequestHelp( rHEvt );
996 }
997
StateChanged(StateChangedType nType)998 void MenuBarWindow::StateChanged( StateChangedType nType )
999 {
1000 Window::StateChanged( nType );
1001
1002 if (nType == StateChangedType::ControlForeground ||
1003 nType == StateChangedType::ControlBackground)
1004 {
1005 ApplySettings(*GetOutDev());
1006 Invalidate();
1007 }
1008 else if (nType == StateChangedType::Enable)
1009 {
1010 Invalidate();
1011 }
1012 else if(m_pMenu)
1013 {
1014 m_pMenu->ImplKillLayoutData();
1015 }
1016 }
1017
LayoutChanged()1018 void MenuBarWindow::LayoutChanged()
1019 {
1020 if (!m_pMenu)
1021 return;
1022
1023 ApplySettings(*GetOutDev());
1024
1025 // if the font was changed.
1026 tools::Long nHeight = m_pMenu->ImplCalcSize(this).Height();
1027
1028 // depending on the native implementation or the displayable flag
1029 // the menubar windows is suppressed (ie, height=0)
1030 if (!m_pMenu->IsDisplayable() ||
1031 (m_pMenu->ImplGetSalMenu() && m_pMenu->ImplGetSalMenu()->VisibleMenuBar()))
1032 {
1033 nHeight = 0;
1034 }
1035 setPosSizePixel(0, 0, 0, nHeight, PosSizeFlags::Height);
1036 GetParent()->Resize();
1037 Invalidate();
1038 Resize();
1039
1040 m_pMenu->ImplKillLayoutData();
1041 }
1042
ApplySettings(vcl::RenderContext & rRenderContext)1043 void MenuBarWindow::ApplySettings(vcl::RenderContext& rRenderContext)
1044 {
1045 Window::ApplySettings(rRenderContext);
1046 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1047
1048 SetPointFont(rRenderContext, rStyleSettings.GetMenuFont());
1049
1050 const BitmapEx& rPersonaBitmap = Application::GetSettings().GetStyleSettings().GetPersonaHeader();
1051 SalMenu *pNativeMenu = m_pMenu ? m_pMenu->ImplGetSalMenu() : nullptr;
1052 if (pNativeMenu)
1053 pNativeMenu->ApplyPersona();
1054 if (!rPersonaBitmap.IsEmpty())
1055 {
1056 Wallpaper aWallpaper(rPersonaBitmap);
1057 aWallpaper.SetStyle(WallpaperStyle::TopRight);
1058 aWallpaper.SetColor(Application::GetSettings().GetStyleSettings().GetWorkspaceColor());
1059
1060 rRenderContext.SetBackground(aWallpaper);
1061 SetPaintTransparent(false);
1062 SetParentClipMode();
1063 }
1064 else if (rRenderContext.IsNativeControlSupported(ControlType::Menubar, ControlPart::Entire))
1065 {
1066 rRenderContext.SetBackground(); // background will be drawn by NWF
1067 }
1068 else
1069 {
1070 Wallpaper aWallpaper;
1071 aWallpaper.SetStyle(WallpaperStyle::ApplicationGradient);
1072 rRenderContext.SetBackground(aWallpaper);
1073 SetPaintTransparent(false);
1074 SetParentClipMode();
1075 }
1076
1077 rRenderContext.SetTextColor(rStyleSettings.GetMenuBarTextColor());
1078 rRenderContext.SetTextFillColor();
1079 rRenderContext.SetLineColor();
1080 }
1081
ImplInitStyleSettings()1082 void MenuBarWindow::ImplInitStyleSettings()
1083 {
1084 if (!(IsNativeControlSupported(ControlType::Menubar, ControlPart::MenuItem) &&
1085 IsNativeControlSupported(ControlType::Menubar, ControlPart::Entire)))
1086 return;
1087
1088 AllSettings aSettings(GetSettings());
1089 ImplGetFrame()->UpdateSettings(aSettings); // to update persona
1090 StyleSettings aStyle(aSettings.GetStyleSettings());
1091 Color aHighlightTextColor = ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor;
1092 if (aHighlightTextColor != COL_TRANSPARENT)
1093 {
1094 aStyle.SetMenuHighlightTextColor(aHighlightTextColor);
1095 }
1096 aSettings.SetStyleSettings(aStyle);
1097 GetOutDev()->SetSettings(aSettings);
1098 }
1099
DataChanged(const DataChangedEvent & rDCEvt)1100 void MenuBarWindow::DataChanged( const DataChangedEvent& rDCEvt )
1101 {
1102 Window::DataChanged( rDCEvt );
1103
1104 if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
1105 (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
1106 ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1107 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
1108 {
1109 ApplySettings(*GetOutDev());
1110 ImplInitStyleSettings();
1111 LayoutChanged();
1112 }
1113 }
1114
LoseFocus()1115 void MenuBarWindow::LoseFocus()
1116 {
1117 if ( !HasChildPathFocus( true ) )
1118 ChangeHighlightItem( ITEMPOS_INVALID, false, false );
1119 }
1120
GetFocus()1121 void MenuBarWindow::GetFocus()
1122 {
1123 SalMenu *pNativeMenu = m_pMenu ? m_pMenu->ImplGetSalMenu() : nullptr;
1124 if (pNativeMenu && pNativeMenu->TakeFocus())
1125 return;
1126
1127 if ( m_nHighlightedItem == ITEMPOS_INVALID )
1128 {
1129 mbAutoPopup = false; // do not open menu when activated by focus handling like taskpane cycling
1130 ChangeHighlightItem( 0, false );
1131 }
1132 }
1133
CreateAccessible()1134 css::uno::Reference<css::accessibility::XAccessible> MenuBarWindow::CreateAccessible()
1135 {
1136 css::uno::Reference<css::accessibility::XAccessible> xAcc;
1137
1138 if (m_pMenu)
1139 xAcc = m_pMenu->GetAccessible();
1140
1141 return xAcc;
1142 }
1143
AddMenuBarButton(const Image & i_rImage,const Link<MenuBarButtonCallbackArg &,bool> & i_rLink,const OUString & i_rToolTip)1144 sal_uInt16 MenuBarWindow::AddMenuBarButton( const Image& i_rImage, const Link<MenuBarButtonCallbackArg&,bool>& i_rLink, const OUString& i_rToolTip )
1145 {
1146 // find first free button id
1147 sal_uInt16 nId = IID_DOCUMENTCLOSE;
1148 std::map< sal_uInt16, AddButtonEntry >::const_iterator it;
1149 do
1150 {
1151 nId++;
1152 it = m_aAddButtons.find( nId );
1153 } while( it != m_aAddButtons.end() && nId < 128 );
1154 SAL_WARN_IF( nId >= 128, "vcl", "too many addbuttons in menubar" );
1155 AddButtonEntry& rNewEntry = m_aAddButtons[nId];
1156 rNewEntry.m_aSelectLink = i_rLink;
1157 m_aCloseBtn->InsertItem(ToolBoxItemId(nId), i_rImage, ToolBoxItemBits::NONE, 0);
1158 m_aCloseBtn->calcMinSize();
1159 ShowButtons(m_aCloseBtn->IsItemVisible(ToolBoxItemId(IID_DOCUMENTCLOSE)), m_aFloatBtn->IsVisible(), m_aHideBtn->IsVisible());
1160 LayoutChanged();
1161
1162 if( m_pMenu->mpSalMenu )
1163 m_pMenu->mpSalMenu->AddMenuBarButton( SalMenuButtonItem( nId, i_rImage, i_rToolTip ) );
1164
1165 return nId;
1166 }
1167
SetMenuBarButtonHighlightHdl(sal_uInt16 nId,const Link<MenuBarButtonCallbackArg &,bool> & rLink)1168 void MenuBarWindow::SetMenuBarButtonHighlightHdl( sal_uInt16 nId, const Link<MenuBarButtonCallbackArg&,bool>& rLink )
1169 {
1170 std::map< sal_uInt16, AddButtonEntry >::iterator it = m_aAddButtons.find( nId );
1171 if( it != m_aAddButtons.end() )
1172 it->second.m_aHighlightLink = rLink;
1173 }
1174
GetMenuBarButtonRectPixel(sal_uInt16 nId)1175 tools::Rectangle MenuBarWindow::GetMenuBarButtonRectPixel( sal_uInt16 nId )
1176 {
1177 tools::Rectangle aRect;
1178 if( m_aAddButtons.find( nId ) != m_aAddButtons.end() )
1179 {
1180 if( m_pMenu->mpSalMenu )
1181 {
1182 aRect = m_pMenu->mpSalMenu->GetMenuBarButtonRectPixel( nId, ImplGetWindowImpl()->mpFrame );
1183 if( aRect == tools::Rectangle( Point( -1, -1 ), Size( 1, 1 ) ) )
1184 {
1185 // system menu button is somewhere but location cannot be determined
1186 return tools::Rectangle();
1187 }
1188 }
1189
1190 if( aRect.IsEmpty() )
1191 {
1192 aRect = m_aCloseBtn->GetItemRect(ToolBoxItemId(nId));
1193 Point aOffset = m_aCloseBtn->OutputToScreenPixel(Point());
1194 aRect.Move( aOffset.X(), aOffset.Y() );
1195 }
1196 }
1197 return aRect;
1198 }
1199
RemoveMenuBarButton(sal_uInt16 nId)1200 void MenuBarWindow::RemoveMenuBarButton( sal_uInt16 nId )
1201 {
1202 ToolBox::ImplToolItems::size_type nPos = m_aCloseBtn->GetItemPos(ToolBoxItemId(nId));
1203 m_aCloseBtn->RemoveItem(nPos);
1204 m_aAddButtons.erase( nId );
1205 m_aCloseBtn->calcMinSize();
1206 LayoutChanged();
1207
1208 if( m_pMenu->mpSalMenu )
1209 m_pMenu->mpSalMenu->RemoveMenuBarButton( nId );
1210 }
1211
HandleMenuButtonEvent(sal_uInt16 i_nButtonId)1212 bool MenuBarWindow::HandleMenuButtonEvent( sal_uInt16 i_nButtonId )
1213 {
1214 std::map< sal_uInt16, AddButtonEntry >::iterator it = m_aAddButtons.find( i_nButtonId );
1215 if( it != m_aAddButtons.end() )
1216 {
1217 MenuBarButtonCallbackArg aArg;
1218 aArg.nId = it->first;
1219 aArg.bHighlight = true;
1220 return it->second.m_aSelectLink.Call( aArg );
1221 }
1222 return false;
1223 }
1224
CanGetFocus() const1225 bool MenuBarWindow::CanGetFocus() const
1226 {
1227 /* #i83908# do not use the menubar if it is native or invisible
1228 this relies on MenuBar::ImplCreate setting the height of the menubar
1229 to 0 in this case
1230 */
1231 SalMenu *pNativeMenu = m_pMenu ? m_pMenu->ImplGetSalMenu() : nullptr;
1232 if (pNativeMenu && pNativeMenu->VisibleMenuBar())
1233 return pNativeMenu->CanGetFocus();
1234 return GetSizePixel().Height() > 0;
1235 }
1236
1237 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1238