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 :
21 : #include "tools/debug.hxx"
22 : #include "tools/diagnose_ex.h"
23 : #include "tools/rc.h"
24 : #include "tools/stream.hxx"
25 :
26 : #include "vcl/svapp.hxx"
27 : #include "vcl/mnemonic.hxx"
28 : #include "vcl/image.hxx"
29 : #include "vcl/event.hxx"
30 : #include "vcl/help.hxx"
31 : #include "vcl/floatwin.hxx"
32 : #include "vcl/wrkwin.hxx"
33 : #include "vcl/timer.hxx"
34 : #include "vcl/decoview.hxx"
35 : #include "vcl/bitmap.hxx"
36 : #include "vcl/menu.hxx"
37 : #include "vcl/button.hxx"
38 : #include "vcl/gradient.hxx"
39 : #include "vcl/i18nhelp.hxx"
40 : #include "vcl/taskpanelist.hxx"
41 : #include "vcl/controllayout.hxx"
42 : #include "vcl/toolbox.hxx"
43 : #include "vcl/dockingarea.hxx"
44 :
45 : #include "salinst.hxx"
46 : #include "svdata.hxx"
47 : #include "svids.hrc"
48 : #include "window.h"
49 : #include "salmenu.hxx"
50 : #include "salframe.hxx"
51 :
52 :
53 : #include <com/sun/star/uno/Reference.h>
54 : #include <com/sun/star/i18n/XCharacterClassification.hpp>
55 : #include <com/sun/star/lang/XComponent.hpp>
56 : #include <com/sun/star/accessibility/XAccessible.hpp>
57 : #include <com/sun/star/accessibility/AccessibleRole.hpp>
58 : #include <vcl/unowrap.hxx>
59 :
60 : #include <vcl/unohelp.hxx>
61 : #include <vcl/configsettings.hxx>
62 :
63 : #include "vcl/lazydelete.hxx"
64 :
65 : #include <map>
66 : #include <vector>
67 :
68 : namespace vcl
69 : {
70 :
71 0 : struct MenuLayoutData : public ControlLayoutData
72 : {
73 : std::vector< sal_uInt16 > m_aLineItemIds;
74 : std::vector< sal_uInt16 > m_aLineItemPositions;
75 : std::map< sal_uInt16, Rectangle > m_aVisibleItemBoundRects;
76 : };
77 :
78 : }
79 :
80 : using namespace ::com::sun::star;
81 : using namespace vcl;
82 :
83 : DBG_NAME( Menu )
84 :
85 : #define ITEMPOS_INVALID 0xFFFF
86 :
87 : #define EXTRASPACEY 2
88 : #define EXTRAITEMHEIGHT 4
89 : #define GUTTERBORDER 8
90 :
91 : // document closer
92 : #define IID_DOCUMENTCLOSE 1
93 :
94 0 : static sal_Bool ImplAccelDisabled()
95 : {
96 : // display of accelerator strings may be suppressed via configuration
97 : static int nAccelDisabled = -1;
98 :
99 0 : if( nAccelDisabled == -1 )
100 : {
101 : rtl::OUString aStr =
102 : vcl::SettingsConfigItem::get()->
103 : getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Menu" ) ),
104 0 : rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SuppressAccelerators" ) ) );
105 0 : nAccelDisabled = aStr.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("true")) ? 1 : 0;
106 : }
107 0 : return (nAccelDisabled == 1) ? sal_True : sal_False;
108 : }
109 :
110 : struct MenuItemData
111 : {
112 : sal_uInt16 nId; // SV Id
113 : MenuItemType eType; // MenuItem-Type
114 : MenuItemBits nBits; // MenuItem-Bits
115 : Menu* pSubMenu; // Pointer to SubMenu
116 : Menu* pAutoSubMenu; // Pointer to SubMenu from Resource
117 : XubString aText; // Menu-Text
118 : XubString aHelpText; // Help-String
119 : XubString aTipHelpText; // TipHelp-String (eg, expanded filenames)
120 : XubString aCommandStr; // CommandString
121 : XubString aHelpCommandStr; // Help command string (to reference external help)
122 : rtl::OString aHelpId; // Help-Id
123 : sal_uLong nUserValue; // User value
124 : Image aImage; // Image
125 : KeyCode aAccelKey; // Accelerator-Key
126 : sal_Bool bChecked; // Checked
127 : sal_Bool bEnabled; // Enabled
128 : sal_Bool bVisible; // Visible (note: this flag will not override MENU_FLAG_HIDEDISABLEDENTRIES when true)
129 : sal_Bool bIsTemporary; // Temporary inserted ('No selection possible')
130 : sal_Bool bMirrorMode;
131 : long nItemImageAngle;
132 : Size aSz; // only temporarily valid
133 : XubString aAccessibleName; // accessible name
134 : XubString aAccessibleDescription; // accessible description
135 :
136 : SalMenuItem* pSalMenuItem; // access to native menu
137 :
138 6 : MenuItemData() :
139 6 : pSalMenuItem ( NULL )
140 6 : {}
141 50 : MenuItemData( const XubString& rStr, const Image& rImage ) :
142 : aText( rStr ),
143 : aImage( rImage ),
144 50 : pSalMenuItem ( NULL )
145 50 : {}
146 : ~MenuItemData();
147 0 : bool HasCheck() const
148 : {
149 0 : return bChecked || ( nBits & ( MIB_RADIOCHECK | MIB_CHECKABLE | MIB_AUTOCHECK ) );
150 : }
151 : };
152 :
153 34 : MenuItemData::~MenuItemData()
154 : {
155 17 : if( pAutoSubMenu )
156 : {
157 0 : ((PopupMenu*)pAutoSubMenu)->pRefAutoSubMenu = NULL;
158 0 : delete pAutoSubMenu;
159 0 : pAutoSubMenu = NULL;
160 : }
161 17 : if( pSalMenuItem )
162 0 : ImplGetSVData()->mpDefInst->DestroyMenuItem( pSalMenuItem );
163 17 : }
164 :
165 : class MenuItemList
166 : {
167 : private:
168 : typedef ::std::vector< MenuItemData* > MenuItemDataList_impl;
169 : MenuItemDataList_impl maItemList;
170 :
171 : uno::Reference< i18n::XCharacterClassification > xCharClass;
172 :
173 : public:
174 1458 : MenuItemList() {}
175 : ~MenuItemList();
176 :
177 : MenuItemData* Insert(
178 : sal_uInt16 nId,
179 : MenuItemType eType,
180 : MenuItemBits nBits,
181 : const XubString& rStr,
182 : const Image& rImage,
183 : Menu* pMenu,
184 : size_t nPos
185 : );
186 : void InsertSeparator( size_t nPos );
187 : void Remove( size_t nPos );
188 :
189 :
190 : MenuItemData* GetData( sal_uInt16 nSVId, size_t& rPos ) const;
191 526 : MenuItemData* GetData( sal_uInt16 nSVId ) const
192 : {
193 : size_t nTemp;
194 526 : return GetData( nSVId, nTemp );
195 : }
196 6 : MenuItemData* GetDataFromPos( size_t nPos ) const
197 : {
198 6 : return ( nPos < maItemList.size() ) ? maItemList[ nPos ] : NULL;
199 : }
200 :
201 : MenuItemData* SearchItem(
202 : sal_Unicode cSelectChar,
203 : KeyCode aKeyCode,
204 : sal_uInt16& rPos,
205 : sal_uInt16& nDuplicates,
206 : sal_uInt16 nCurrentPos
207 : ) const;
208 : size_t GetItemCount( sal_Unicode cSelectChar ) const;
209 : size_t GetItemCount( KeyCode aKeyCode ) const;
210 1609 : size_t size()
211 : {
212 1609 : return maItemList.size();
213 : }
214 : };
215 :
216 :
217 :
218 1112 : MenuItemList::~MenuItemList()
219 : {
220 573 : for( size_t i = 0, n = maItemList.size(); i < n; ++i )
221 17 : delete maItemList[ i ];
222 556 : }
223 :
224 50 : MenuItemData* MenuItemList::Insert(
225 : sal_uInt16 nId,
226 : MenuItemType eType,
227 : MenuItemBits nBits,
228 : const XubString& rStr,
229 : const Image& rImage,
230 : Menu* pMenu,
231 : size_t nPos
232 : )
233 : {
234 50 : MenuItemData* pData = new MenuItemData( rStr, rImage );
235 50 : pData->nId = nId;
236 50 : pData->eType = eType;
237 50 : pData->nBits = nBits;
238 50 : pData->pSubMenu = NULL;
239 50 : pData->pAutoSubMenu = NULL;
240 50 : pData->nUserValue = 0;
241 50 : pData->bChecked = sal_False;
242 50 : pData->bEnabled = sal_True;
243 50 : pData->bVisible = sal_True;
244 50 : pData->bIsTemporary = sal_False;
245 50 : pData->bMirrorMode = sal_False;
246 50 : pData->nItemImageAngle = 0;
247 :
248 50 : SalItemParams aSalMIData;
249 50 : aSalMIData.nId = nId;
250 50 : aSalMIData.eType = eType;
251 50 : aSalMIData.nBits = nBits;
252 50 : aSalMIData.pMenu = pMenu;
253 50 : aSalMIData.aText = rStr;
254 50 : aSalMIData.aImage = rImage;
255 :
256 : // Native-support: returns NULL if not supported
257 50 : pData->pSalMenuItem = ImplGetSVData()->mpDefInst->CreateMenuItem( &aSalMIData );
258 :
259 50 : if( nPos < maItemList.size() ) {
260 0 : maItemList.insert( maItemList.begin() + nPos, pData );
261 : } else {
262 50 : maItemList.push_back( pData );
263 : }
264 50 : return pData;
265 : }
266 :
267 6 : void MenuItemList::InsertSeparator( size_t nPos )
268 : {
269 6 : MenuItemData* pData = new MenuItemData;
270 6 : pData->nId = 0;
271 6 : pData->eType = MENUITEM_SEPARATOR;
272 6 : pData->nBits = 0;
273 6 : pData->pSubMenu = NULL;
274 6 : pData->pAutoSubMenu = NULL;
275 6 : pData->nUserValue = 0;
276 6 : pData->bChecked = sal_False;
277 6 : pData->bEnabled = sal_True;
278 6 : pData->bVisible = sal_True;
279 6 : pData->bIsTemporary = sal_False;
280 6 : pData->bMirrorMode = sal_False;
281 6 : pData->nItemImageAngle = 0;
282 :
283 6 : SalItemParams aSalMIData;
284 6 : aSalMIData.nId = 0;
285 6 : aSalMIData.eType = MENUITEM_SEPARATOR;
286 6 : aSalMIData.nBits = 0;
287 6 : aSalMIData.pMenu = NULL;
288 6 : aSalMIData.aText = XubString();
289 6 : aSalMIData.aImage = Image();
290 :
291 : // Native-support: returns NULL if not supported
292 6 : pData->pSalMenuItem = ImplGetSVData()->mpDefInst->CreateMenuItem( &aSalMIData );
293 :
294 6 : if( nPos < maItemList.size() ) {
295 0 : maItemList.insert( maItemList.begin() + nPos, pData );
296 : } else {
297 6 : maItemList.push_back( pData );
298 6 : }
299 6 : }
300 :
301 0 : void MenuItemList::Remove( size_t nPos )
302 : {
303 0 : if( nPos < maItemList.size() )
304 : {
305 0 : delete maItemList[ nPos ];
306 0 : maItemList.erase( maItemList.begin() + nPos );
307 : }
308 0 : }
309 :
310 538 : MenuItemData* MenuItemList::GetData( sal_uInt16 nSVId, size_t& rPos ) const
311 : {
312 708 : for( size_t i = 0, n = maItemList.size(); i < n; ++i )
313 : {
314 282 : if ( maItemList[ i ]->nId == nSVId )
315 : {
316 112 : rPos = i;
317 112 : return maItemList[ i ];
318 : }
319 : }
320 426 : return NULL;
321 : }
322 :
323 0 : MenuItemData* MenuItemList::SearchItem(
324 : sal_Unicode cSelectChar,
325 : KeyCode aKeyCode,
326 : sal_uInt16& rPos,
327 : sal_uInt16& nDuplicates,
328 : sal_uInt16 nCurrentPos
329 : ) const
330 : {
331 0 : const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
332 :
333 0 : size_t nListCount = maItemList.size();
334 :
335 : // try character code first
336 0 : nDuplicates = GetItemCount( cSelectChar ); // return number of duplicates
337 0 : if( nDuplicates )
338 : {
339 0 : for ( rPos = 0; rPos < nListCount; rPos++)
340 : {
341 0 : MenuItemData* pData = maItemList[ rPos ];
342 0 : if ( pData->bEnabled && rI18nHelper.MatchMnemonic( pData->aText, cSelectChar ) )
343 : {
344 0 : if( nDuplicates > 1 && rPos == nCurrentPos )
345 0 : continue; // select next entry with the same mnemonic
346 : else
347 0 : return pData;
348 : }
349 : }
350 : }
351 :
352 : // nothing found, try keycode instead
353 0 : nDuplicates = GetItemCount( aKeyCode ); // return number of duplicates
354 :
355 0 : if( nDuplicates )
356 : {
357 0 : char ascii = 0;
358 0 : if( aKeyCode.GetCode() >= KEY_A && aKeyCode.GetCode() <= KEY_Z )
359 0 : ascii = sal::static_int_cast<char>('A' + (aKeyCode.GetCode() - KEY_A));
360 :
361 0 : for ( rPos = 0; rPos < nListCount; rPos++)
362 : {
363 0 : MenuItemData* pData = maItemList[ rPos ];
364 0 : if ( pData->bEnabled )
365 : {
366 0 : sal_uInt16 n = pData->aText.Search( '~' );
367 0 : if ( n != STRING_NOTFOUND )
368 : {
369 0 : KeyCode mnKeyCode;
370 0 : sal_Unicode mnUnicode = pData->aText.GetChar(n+1);
371 0 : Window* pDefWindow = ImplGetDefaultWindow();
372 0 : if( ( pDefWindow
373 0 : && pDefWindow->ImplGetFrame()->MapUnicodeToKeyCode( mnUnicode,
374 0 : Application::GetSettings().GetUILanguageTag().getLanguageType(), mnKeyCode )
375 0 : && aKeyCode.GetCode() == mnKeyCode.GetCode()
376 : )
377 : || ( ascii
378 0 : && rI18nHelper.MatchMnemonic( pData->aText, ascii )
379 : )
380 : )
381 : {
382 0 : if( nDuplicates > 1 && rPos == nCurrentPos )
383 0 : continue; // select next entry with the same mnemonic
384 : else
385 0 : return pData;
386 : }
387 : }
388 : }
389 : }
390 : }
391 :
392 0 : return NULL;
393 : }
394 :
395 0 : size_t MenuItemList::GetItemCount( sal_Unicode cSelectChar ) const
396 : {
397 : // returns number of entries with same mnemonic
398 0 : const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
399 :
400 0 : size_t nItems = 0;
401 0 : for ( size_t nPos = maItemList.size(); nPos; )
402 : {
403 0 : MenuItemData* pData = maItemList[ --nPos ];
404 0 : if ( pData->bEnabled && rI18nHelper.MatchMnemonic( pData->aText, cSelectChar ) )
405 0 : nItems++;
406 : }
407 :
408 0 : return nItems;
409 : }
410 :
411 0 : size_t MenuItemList::GetItemCount( KeyCode aKeyCode ) const
412 : {
413 : // returns number of entries with same mnemonic
414 : // uses key codes instead of character codes
415 0 : const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
416 0 : char ascii = 0;
417 0 : if( aKeyCode.GetCode() >= KEY_A && aKeyCode.GetCode() <= KEY_Z )
418 0 : ascii = sal::static_int_cast<char>('A' + (aKeyCode.GetCode() - KEY_A));
419 :
420 0 : size_t nItems = 0;
421 0 : for ( size_t nPos = maItemList.size(); nPos; )
422 : {
423 0 : MenuItemData* pData = maItemList[ --nPos ];
424 0 : if ( pData->bEnabled )
425 : {
426 0 : sal_uInt16 n = pData->aText.Search( '~' );
427 0 : if ( n != STRING_NOTFOUND )
428 : {
429 0 : KeyCode mnKeyCode;
430 : // if MapUnicodeToKeyCode fails or is unsupported we try the pure ascii mapping of the keycodes
431 : // so we have working shortcuts when ascii mnemonics are used
432 0 : Window* pDefWindow = ImplGetDefaultWindow();
433 0 : if( ( pDefWindow
434 0 : && pDefWindow->ImplGetFrame()->MapUnicodeToKeyCode( pData->aText.GetChar(n+1),
435 0 : Application::GetSettings().GetUILanguageTag().getLanguageType(), mnKeyCode )
436 0 : && aKeyCode.GetCode() == mnKeyCode.GetCode()
437 : )
438 : || ( ascii
439 0 : && rI18nHelper.MatchMnemonic( pData->aText, ascii )
440 : )
441 : )
442 0 : nItems++;
443 : }
444 : }
445 : }
446 :
447 0 : return nItems;
448 : }
449 :
450 :
451 : // ----------------------
452 : // - MenuFloatingWindow -
453 : // ----------------------
454 :
455 : class MenuFloatingWindow : public FloatingWindow
456 : {
457 : friend void Menu::ImplFillLayoutData() const;
458 : friend Menu::~Menu();
459 :
460 : private:
461 : Menu* pMenu;
462 : PopupMenu* pActivePopup;
463 : Timer aHighlightChangedTimer;
464 : Timer aSubmenuCloseTimer;
465 : Timer aScrollTimer;
466 : sal_uLong nSaveFocusId;
467 : sal_uInt16 nHighlightedItem; // highlighted/selected Item
468 : sal_uInt16 nMBDownPos;
469 : sal_uInt16 nScrollerHeight;
470 : sal_uInt16 nFirstEntry;
471 : sal_uInt16 nBorder;
472 : sal_uInt16 nPosInParent;
473 : sal_Bool bInExecute;
474 :
475 : sal_Bool bScrollMenu;
476 : sal_Bool bScrollUp;
477 : sal_Bool bScrollDown;
478 : sal_Bool bIgnoreFirstMove;
479 : sal_Bool bKeyInput;
480 :
481 : DECL_LINK(PopupEnd, void *);
482 : DECL_LINK( HighlightChanged, Timer* );
483 : DECL_LINK(SubmenuClose, void *);
484 : DECL_LINK(AutoScroll, void *);
485 : DECL_LINK( ShowHideListener, VclWindowEvent* );
486 :
487 : void StateChanged( StateChangedType nType );
488 : void DataChanged( const DataChangedEvent& rDCEvt );
489 : protected:
490 : Region ImplCalcClipRegion( sal_Bool bIncludeLogo = sal_True ) const;
491 : void ImplInitClipRegion();
492 : void ImplDrawScroller( sal_Bool bUp );
493 : using Window::ImplScroll;
494 : void ImplScroll( const Point& rMousePos );
495 : void ImplScroll( sal_Bool bUp );
496 : void ImplCursorUpDown( sal_Bool bUp, sal_Bool bHomeEnd = sal_False );
497 : void ImplHighlightItem( const MouseEvent& rMEvt, sal_Bool bMBDown );
498 : long ImplGetStartY() const;
499 : Rectangle ImplGetItemRect( sal_uInt16 nPos );
500 :
501 : public:
502 : MenuFloatingWindow( Menu* pMenu, Window* pParent, WinBits nStyle );
503 : ~MenuFloatingWindow();
504 :
505 : void doShutdown();
506 :
507 : virtual void MouseMove( const MouseEvent& rMEvt );
508 : virtual void MouseButtonDown( const MouseEvent& rMEvt );
509 : virtual void MouseButtonUp( const MouseEvent& rMEvt );
510 : virtual void KeyInput( const KeyEvent& rKEvent );
511 : virtual void Command( const CommandEvent& rCEvt );
512 : virtual void Paint( const Rectangle& rRect );
513 : virtual void RequestHelp( const HelpEvent& rHEvt );
514 : virtual void Resize();
515 :
516 0 : void SetFocusId( sal_uLong nId ) { nSaveFocusId = nId; }
517 0 : sal_uLong GetFocusId() const { return nSaveFocusId; }
518 :
519 : void EnableScrollMenu( sal_Bool b );
520 0 : sal_Bool IsScrollMenu() const { return bScrollMenu; }
521 0 : sal_uInt16 GetScrollerHeight() const { return nScrollerHeight; }
522 :
523 : void Execute();
524 : void StopExecute( sal_uLong nFocusId = 0 );
525 : void EndExecute();
526 : void EndExecute( sal_uInt16 nSelectId );
527 :
528 0 : PopupMenu* GetActivePopup() const { return pActivePopup; }
529 : void KillActivePopup( PopupMenu* pThisOnly = NULL );
530 :
531 : void HighlightItem( sal_uInt16 nPos, sal_Bool bHighlight );
532 : void ChangeHighlightItem( sal_uInt16 n, sal_Bool bStartPopupTimer );
533 0 : sal_uInt16 GetHighlightedItem() const { return nHighlightedItem; }
534 :
535 0 : void SetPosInParent( sal_uInt16 nPos ) { nPosInParent = nPos; }
536 : sal_uInt16 GetPosInParent() const { return nPosInParent; }
537 :
538 : virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible();
539 : };
540 :
541 : // To get the transparent mouse-over look, the closer is actually a toolbox
542 : // overload DataChange to handle style changes correctly
543 63 : class DecoToolBox : public ToolBox
544 : {
545 : long lastSize;
546 : Size maMinSize;
547 :
548 : using Window::ImplInit;
549 : public:
550 : DecoToolBox( Window* pParent, WinBits nStyle = 0 );
551 : void ImplInit();
552 :
553 : void DataChanged( const DataChangedEvent& rDCEvt );
554 :
555 : void SetImages( long nMaxHeight = 0, bool bForce = false );
556 :
557 : void calcMinSize();
558 : Size getMinSize();
559 :
560 : Image maImage;
561 : };
562 :
563 236 : DecoToolBox::DecoToolBox( Window* pParent, WinBits nStyle ) :
564 236 : ToolBox( pParent, nStyle )
565 : {
566 236 : ImplInit();
567 236 : }
568 :
569 236 : void DecoToolBox::ImplInit()
570 : {
571 236 : lastSize = -1;
572 236 : calcMinSize();
573 236 : }
574 :
575 92 : void DecoToolBox::DataChanged( const DataChangedEvent& rDCEvt )
576 : {
577 92 : Window::DataChanged( rDCEvt );
578 :
579 92 : if ( rDCEvt.GetFlags() & SETTINGS_STYLE )
580 : {
581 0 : calcMinSize();
582 0 : SetBackground();
583 0 : SetImages( 0, true);
584 : }
585 92 : }
586 :
587 236 : void DecoToolBox::calcMinSize()
588 : {
589 236 : ToolBox aTbx( GetParent() );
590 236 : if( GetItemCount() == 0 )
591 : {
592 236 : ResMgr* pResMgr = ImplGetResMgr();
593 :
594 236 : Bitmap aBitmap;
595 236 : if( pResMgr )
596 236 : aBitmap = Bitmap( ResId( SV_RESID_BITMAP_CLOSEDOC, *pResMgr ) );
597 236 : aTbx.InsertItem( IID_DOCUMENTCLOSE, Image( aBitmap ) );
598 : }
599 : else
600 : {
601 0 : sal_uInt16 nItems = GetItemCount();
602 0 : for( sal_uInt16 i = 0; i < nItems; i++ )
603 : {
604 0 : sal_uInt16 nId = GetItemId( i );
605 0 : aTbx.InsertItem( nId, GetItemImage( nId ) );
606 : }
607 : }
608 236 : aTbx.SetOutStyle( TOOLBOX_STYLE_FLAT );
609 236 : maMinSize = aTbx.CalcWindowSizePixel();
610 236 : }
611 :
612 287 : Size DecoToolBox::getMinSize()
613 : {
614 287 : return maMinSize;
615 : }
616 :
617 17 : void DecoToolBox::SetImages( long nMaxHeight, bool bForce )
618 : {
619 17 : long border = getMinSize().Height() - maImage.GetSizePixel().Height();
620 :
621 17 : if( !nMaxHeight && lastSize != -1 )
622 0 : nMaxHeight = lastSize + border; // don't change anything if called with 0
623 :
624 17 : if( nMaxHeight < getMinSize().Height() )
625 17 : nMaxHeight = getMinSize().Height();
626 :
627 17 : if( (lastSize != nMaxHeight - border) || bForce )
628 : {
629 11 : lastSize = nMaxHeight - border;
630 :
631 11 : Color aEraseColor( 255, 255, 255, 255 );
632 11 : BitmapEx aBmpExDst( maImage.GetBitmapEx() );
633 11 : BitmapEx aBmpExSrc( aBmpExDst );
634 :
635 11 : aEraseColor.SetTransparency( 255 );
636 11 : aBmpExDst.Erase( aEraseColor );
637 11 : aBmpExDst.SetSizePixel( Size( lastSize, lastSize ) );
638 :
639 11 : Rectangle aSrcRect( Point(0,0), maImage.GetSizePixel() );
640 22 : Rectangle aDestRect( Point((lastSize - maImage.GetSizePixel().Width())/2,
641 22 : (lastSize - maImage.GetSizePixel().Height())/2 ),
642 44 : maImage.GetSizePixel() );
643 :
644 :
645 11 : aBmpExDst.CopyPixel( aDestRect, aSrcRect, &aBmpExSrc );
646 11 : SetItemImage( IID_DOCUMENTCLOSE, Image( aBmpExDst ) );
647 : }
648 17 : }
649 :
650 :
651 : // a basic class for both (due to pActivePopup, Timer,...) would be nice,
652 : // but a container class should have been created then, as they
653 : // would be derived from different windows
654 : // In most functions we would have to create exceptions for
655 : // menubar, popupmenu, hence we made two classes
656 :
657 : class MenuBarWindow : public Window
658 : {
659 : friend class MenuBar;
660 : friend class Menu;
661 :
662 : private:
663 : struct AddButtonEntry
664 : {
665 : sal_uInt16 m_nId;
666 : Link m_aSelectLink;
667 : Link m_aHighlightLink;
668 :
669 0 : AddButtonEntry() : m_nId( 0 ) {}
670 : };
671 :
672 : Menu* pMenu;
673 : PopupMenu* pActivePopup;
674 : sal_uInt16 nHighlightedItem;
675 : sal_uLong nSaveFocusId;
676 : sal_Bool mbAutoPopup;
677 : sal_Bool bIgnoreFirstMove;
678 : sal_Bool bStayActive;
679 :
680 : DecoToolBox aCloser;
681 : PushButton aFloatBtn;
682 : PushButton aHideBtn;
683 :
684 : std::map< sal_uInt16, AddButtonEntry > m_aAddButtons;
685 :
686 : void HighlightItem( sal_uInt16 nPos, sal_Bool bHighlight );
687 : void ChangeHighlightItem( sal_uInt16 n, sal_Bool bSelectPopupEntry, sal_Bool bAllowRestoreFocus = sal_True, sal_Bool bDefaultToDocument = sal_True );
688 :
689 : sal_uInt16 ImplFindEntry( const Point& rMousePos ) const;
690 : void ImplCreatePopup( sal_Bool bPreSelectFirst );
691 : sal_Bool ImplHandleKeyEvent( const KeyEvent& rKEvent, sal_Bool bFromMenu = sal_True );
692 : Rectangle ImplGetItemRect( sal_uInt16 nPos );
693 :
694 : void ImplInitStyleSettings();
695 :
696 : DECL_LINK(CloserHdl, void *);
697 : DECL_LINK(FloatHdl, void *);
698 : DECL_LINK(HideHdl, void *);
699 : DECL_LINK( ToolboxEventHdl, VclWindowEvent* );
700 : DECL_LINK( ShowHideListener, VclWindowEvent* );
701 :
702 : void StateChanged( StateChangedType nType );
703 : void DataChanged( const DataChangedEvent& rDCEvt );
704 : void LoseFocus();
705 : void GetFocus();
706 :
707 : public:
708 : MenuBarWindow( Window* pParent );
709 : ~MenuBarWindow();
710 :
711 : void ShowButtons( sal_Bool bClose, sal_Bool bFloat, sal_Bool bHide );
712 :
713 : virtual void MouseMove( const MouseEvent& rMEvt );
714 : virtual void MouseButtonDown( const MouseEvent& rMEvt );
715 : virtual void MouseButtonUp( const MouseEvent& rMEvt );
716 : virtual void KeyInput( const KeyEvent& rKEvent );
717 : virtual void Paint( const Rectangle& rRect );
718 : virtual void Resize();
719 : virtual void RequestHelp( const HelpEvent& rHEvt );
720 :
721 0 : void SetFocusId( sal_uLong nId ) { nSaveFocusId = nId; }
722 0 : sal_uLong GetFocusId() const { return nSaveFocusId; }
723 :
724 : void SetMenu( MenuBar* pMenu );
725 : void KillActivePopup();
726 : PopupMenu* GetActivePopup() const { return pActivePopup; }
727 : void PopupClosed( Menu* pMenu );
728 0 : sal_uInt16 GetHighlightedItem() const { return nHighlightedItem; }
729 : virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible();
730 :
731 0 : void SetAutoPopup( sal_Bool bAuto ) { mbAutoPopup = bAuto; }
732 : void ImplLayoutChanged();
733 : Size MinCloseButtonSize();
734 :
735 : // add an arbitrary button to the menubar (will appear next to closer)
736 : sal_uInt16 AddMenuBarButton( const Image&, const Link&, const String&, sal_uInt16 nPos );
737 : void SetMenuBarButtonHighlightHdl( sal_uInt16 nId, const Link& );
738 : Rectangle GetMenuBarButtonRectPixel( sal_uInt16 nId );
739 : void RemoveMenuBarButton( sal_uInt16 nId );
740 : bool HandleMenuButtonEvent( sal_uInt16 i_nButtonId );
741 : };
742 :
743 0 : static void ImplAddNWFSeparator( Window *pThis, const MenubarValue& rMenubarValue )
744 : {
745 : // add a separator if
746 : // - we have an adjacent docking area
747 : // - and if toolbars would draw them as well (mbDockingAreaSeparateTB must not be set, see dockingarea.cxx)
748 0 : if( rMenubarValue.maTopDockingAreaHeight && !ImplGetSVData()->maNWFData.mbDockingAreaSeparateTB && !ImplGetSVData()->maNWFData.mbDockingAreaAvoidTBFrames )
749 : {
750 : // note: the menubar only provides the upper (dark) half of it, the rest (bright part) is drawn by the docking area
751 :
752 0 : pThis->SetLineColor( pThis->GetSettings().GetStyleSettings().GetSeparatorColor() );
753 0 : Point aPt;
754 0 : Rectangle aRect( aPt, pThis->GetOutputSizePixel() );
755 0 : pThis->DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
756 : }
757 0 : }
758 :
759 6 : static void ImplSetMenuItemData( MenuItemData* pData )
760 : {
761 : // convert data
762 6 : if ( !pData->aImage )
763 6 : pData->eType = MENUITEM_STRING;
764 0 : else if ( !pData->aText.Len() )
765 0 : pData->eType = MENUITEM_IMAGE;
766 : else
767 0 : pData->eType = MENUITEM_STRINGIMAGE;
768 6 : }
769 :
770 0 : static sal_uLong ImplChangeTipTimeout( sal_uLong nTimeout, Window *pWindow )
771 : {
772 0 : AllSettings aAllSettings( pWindow->GetSettings() );
773 0 : HelpSettings aHelpSettings( aAllSettings.GetHelpSettings() );
774 0 : sal_uLong nRet = aHelpSettings.GetTipTimeout();
775 0 : aHelpSettings.SetTipTimeout( nTimeout );
776 0 : aAllSettings.SetHelpSettings( aHelpSettings );
777 0 : pWindow->SetSettings( aAllSettings );
778 0 : return nRet;
779 : }
780 :
781 0 : static sal_Bool ImplHandleHelpEvent( Window* pMenuWindow, Menu* pMenu, sal_uInt16 nHighlightedItem, const HelpEvent& rHEvt, const Rectangle &rHighlightRect )
782 : {
783 0 : if( ! pMenu )
784 0 : return sal_False;
785 :
786 0 : sal_Bool bDone = sal_False;
787 0 : sal_uInt16 nId = 0;
788 :
789 0 : if ( nHighlightedItem != ITEMPOS_INVALID )
790 : {
791 0 : MenuItemData* pItemData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
792 0 : if ( pItemData )
793 0 : nId = pItemData->nId;
794 : }
795 :
796 0 : if ( ( rHEvt.GetMode() & HELPMODE_BALLOON ) && pMenuWindow )
797 : {
798 0 : Point aPos;
799 0 : if( rHEvt.KeyboardActivated() )
800 0 : aPos = rHighlightRect.Center();
801 : else
802 0 : aPos = rHEvt.GetMousePosPixel();
803 :
804 0 : Rectangle aRect( aPos, Size() );
805 0 : if( pMenu->GetHelpText( nId ).Len() )
806 0 : Help::ShowBalloon( pMenuWindow, aPos, pMenu->GetHelpText( nId ) );
807 : else
808 : {
809 : // give user a chance to read the full filename
810 0 : sal_uLong oldTimeout=ImplChangeTipTimeout( 60000, pMenuWindow );
811 : // call always, even when strlen==0 to correctly remove tip
812 0 : Help::ShowQuickHelp( pMenuWindow, aRect, pMenu->GetTipHelpText( nId ) );
813 0 : ImplChangeTipTimeout( oldTimeout, pMenuWindow );
814 : }
815 0 : bDone = sal_True;
816 : }
817 0 : else if ( ( rHEvt.GetMode() & HELPMODE_QUICK ) && pMenuWindow )
818 : {
819 0 : Point aPos = rHEvt.GetMousePosPixel();
820 0 : Rectangle aRect( aPos, Size() );
821 : // give user a chance to read the full filename
822 0 : sal_uLong oldTimeout=ImplChangeTipTimeout( 60000, pMenuWindow );
823 : // call always, even when strlen==0 to correctly remove tip
824 0 : Help::ShowQuickHelp( pMenuWindow, aRect, pMenu->GetTipHelpText( nId ) );
825 0 : ImplChangeTipTimeout( oldTimeout, pMenuWindow );
826 0 : bDone = sal_True;
827 : }
828 0 : else if ( rHEvt.GetMode() & (HELPMODE_CONTEXT | HELPMODE_EXTENDED) )
829 : {
830 : // is help in the application selected
831 0 : Help* pHelp = Application::GetHelp();
832 0 : if ( pHelp )
833 : {
834 : // is an id available, then call help with the id, otherwise
835 : // use help-index
836 0 : String aCommand = pMenu->GetItemCommand( nId );
837 0 : rtl::OString aHelpId( pMenu->GetHelpId( nId ) );
838 0 : if( aHelpId.isEmpty() )
839 0 : aHelpId = OOO_HELP_INDEX;
840 :
841 0 : if ( aCommand.Len() )
842 0 : pHelp->Start( aCommand, NULL );
843 : else
844 0 : pHelp->Start( rtl::OStringToOUString( aHelpId, RTL_TEXTENCODING_UTF8 ), NULL );
845 : }
846 0 : bDone = sal_True;
847 : }
848 0 : return bDone;
849 : }
850 :
851 0 : static int ImplGetTopDockingAreaHeight( Window *pWindow )
852 : {
853 : // find docking area that is top aligned and return its height
854 : // note: dockingareas are direct children of the SystemWindow
855 0 : if( pWindow->ImplGetFrameWindow() )
856 : {
857 0 : Window *pWin = pWindow->ImplGetFrameWindow()->GetWindow( WINDOW_FIRSTCHILD ); //mpWindowImpl->mpFirstChild;
858 0 : while( pWin )
859 : {
860 0 : if( pWin->IsSystemWindow() )
861 : {
862 0 : Window *pChildWin = pWin->GetWindow( WINDOW_FIRSTCHILD ); //mpWindowImpl->mpFirstChild;
863 0 : while( pChildWin )
864 : {
865 0 : DockingAreaWindow *pDockingArea = NULL;
866 0 : if ( pChildWin->GetType() == WINDOW_DOCKINGAREA )
867 0 : pDockingArea = static_cast< DockingAreaWindow* >( pChildWin );
868 :
869 0 : if( pDockingArea && pDockingArea->GetAlign() == WINDOWALIGN_TOP &&
870 0 : pDockingArea->IsVisible() && pDockingArea->GetOutputSizePixel().Height() != 0 )
871 : {
872 0 : return pDockingArea->GetOutputSizePixel().Height();
873 : }
874 :
875 0 : pChildWin = pChildWin->GetWindow( WINDOW_NEXT ); //mpWindowImpl->mpNext;
876 : }
877 :
878 : }
879 :
880 0 : pWin = pWin->GetWindow( WINDOW_NEXT ); //mpWindowImpl->mpNext;
881 : }
882 : }
883 0 : return 0;
884 : }
885 :
886 1222 : Menu::Menu()
887 : {
888 : DBG_CTOR( Menu, NULL );
889 1222 : bIsMenuBar = sal_False;
890 1222 : ImplInit();
891 1222 : }
892 :
893 : // this constructor makes sure we're creating the native menu
894 : // with the correct type (ie, MenuBar vs. PopupMenu)
895 236 : Menu::Menu( sal_Bool bMenubar )
896 : {
897 : DBG_CTOR( Menu, NULL );
898 236 : bIsMenuBar = bMenubar;
899 236 : ImplInit();
900 236 : }
901 :
902 1112 : Menu::~Menu()
903 : {
904 : DBG_DTOR( Menu, NULL );
905 :
906 556 : vcl::LazyDeletor<Menu>::Undelete( this );
907 :
908 556 : ImplCallEventListeners( VCLEVENT_OBJECT_DYING, ITEMPOS_INVALID );
909 :
910 : // at the window free the reference to the accessible component
911 : // and make sure the MenuFloatingWindow knows about our destruction
912 556 : if ( pWindow )
913 : {
914 0 : MenuFloatingWindow* pFloat = (MenuFloatingWindow*)pWindow;
915 0 : if( pFloat->pMenu == this )
916 0 : pFloat->pMenu = NULL;
917 0 : pWindow->SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >() );
918 : }
919 :
920 : // dispose accessible components
921 556 : if ( mxAccessible.is() )
922 : {
923 0 : ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent> xComponent( mxAccessible, ::com::sun::star::uno::UNO_QUERY );
924 0 : if ( xComponent.is() )
925 0 : xComponent->dispose();
926 : }
927 :
928 556 : if ( nEventId )
929 0 : Application::RemoveUserEvent( nEventId );
930 :
931 : // Notify deletion of this menu
932 556 : ImplMenuDelData* pDelData = mpFirstDel;
933 1112 : while ( pDelData )
934 : {
935 0 : pDelData->mpMenu = NULL;
936 0 : pDelData = pDelData->mpNext;
937 : }
938 :
939 556 : bKilled = sal_True;
940 :
941 556 : delete pItemList;
942 556 : delete pLogo;
943 556 : delete mpLayoutData;
944 :
945 : // Native-support: destroy SalMenu
946 556 : ImplSetSalMenu( NULL );
947 556 : }
948 :
949 1458 : void Menu::ImplInit()
950 : {
951 1458 : mnHighlightedItemPos = ITEMPOS_INVALID;
952 1458 : mpSalMenu = NULL;
953 1458 : nMenuFlags = 0;
954 1458 : nDefaultItem = 0;
955 : //bIsMenuBar = sal_False; // this is now set in the ctor, must not be changed here!!!
956 1458 : nSelectedId = 0;
957 1458 : pItemList = new MenuItemList;
958 1458 : pLogo = NULL;
959 1458 : pStartedFrom = NULL;
960 1458 : pWindow = NULL;
961 1458 : nEventId = 0;
962 1458 : bCanceled = sal_False;
963 1458 : bInCallback = sal_False;
964 1458 : bKilled = sal_False;
965 1458 : mpLayoutData = NULL;
966 1458 : mpFirstDel = NULL; // Dtor notification list
967 : // Native-support: returns NULL if not supported
968 1458 : mpSalMenu = ImplGetSVData()->mpDefInst->CreateMenu( bIsMenuBar, this );
969 1458 : }
970 :
971 19 : void Menu::ImplLoadRes( const ResId& rResId )
972 : {
973 19 : ResMgr* pMgr = rResId.GetResMgr();
974 19 : if( ! pMgr )
975 19 : return;
976 :
977 19 : rResId.SetRT( RSC_MENU );
978 19 : GetRes( rResId );
979 :
980 19 : sal_uLong nObjMask = ReadLongRes();
981 :
982 19 : if( nObjMask & RSC_MENU_ITEMS )
983 : {
984 19 : sal_uLong nObjFollows = ReadLongRes();
985 : // insert menu items
986 75 : for( sal_uLong i = 0; i < nObjFollows; i++ )
987 : {
988 56 : InsertItem( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
989 56 : IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
990 : }
991 : }
992 :
993 19 : if( nObjMask & RSC_MENU_TEXT )
994 : {
995 0 : if( bIsMenuBar ) // no title in menubar
996 0 : ReadStringRes();
997 : else
998 0 : aTitleText = ReadStringRes();
999 : }
1000 19 : if( nObjMask & RSC_MENU_DEFAULTITEMID )
1001 0 : SetDefaultItem( sal::static_int_cast<sal_uInt16>(ReadLongRes()) );
1002 : }
1003 :
1004 0 : void Menu::CreateAutoMnemonics()
1005 : {
1006 0 : MnemonicGenerator aMnemonicGenerator;
1007 : size_t n;
1008 0 : for ( n = 0; n < pItemList->size(); n++ )
1009 : {
1010 0 : MenuItemData* pData = pItemList->GetDataFromPos( n );
1011 0 : if ( ! (pData->nBits & MIB_NOSELECT ) )
1012 0 : aMnemonicGenerator.RegisterMnemonic( pData->aText );
1013 : }
1014 0 : for ( n = 0; n < pItemList->size(); n++ )
1015 : {
1016 0 : MenuItemData* pData = pItemList->GetDataFromPos( n );
1017 0 : if ( ! (pData->nBits & MIB_NOSELECT ) )
1018 0 : aMnemonicGenerator.CreateMnemonic( pData->aText );
1019 0 : }
1020 0 : }
1021 :
1022 0 : void Menu::Activate()
1023 : {
1024 0 : bInCallback = sal_True;
1025 :
1026 0 : ImplMenuDelData aDelData( this );
1027 :
1028 0 : ImplCallEventListeners( VCLEVENT_MENU_ACTIVATE, ITEMPOS_INVALID );
1029 :
1030 0 : if( !aDelData.isDeleted() )
1031 : {
1032 0 : if ( !aActivateHdl.Call( this ) )
1033 : {
1034 0 : if( !aDelData.isDeleted() )
1035 : {
1036 0 : Menu* pStartMenu = ImplGetStartMenu();
1037 0 : if ( pStartMenu && ( pStartMenu != this ) )
1038 : {
1039 0 : pStartMenu->bInCallback = sal_True;
1040 : // MT 11/01: Call EventListener here? I don't know...
1041 0 : pStartMenu->aActivateHdl.Call( this );
1042 0 : pStartMenu->bInCallback = sal_False;
1043 : }
1044 : }
1045 : }
1046 0 : bInCallback = sal_False;
1047 0 : }
1048 0 : }
1049 :
1050 0 : void Menu::Deactivate()
1051 : {
1052 0 : for ( size_t n = pItemList->size(); n; )
1053 : {
1054 0 : MenuItemData* pData = pItemList->GetDataFromPos( --n );
1055 0 : if ( pData->bIsTemporary )
1056 0 : pItemList->Remove( n );
1057 : }
1058 :
1059 0 : bInCallback = sal_True;
1060 :
1061 0 : ImplMenuDelData aDelData( this );
1062 :
1063 0 : Menu* pStartMenu = ImplGetStartMenu();
1064 0 : ImplCallEventListeners( VCLEVENT_MENU_DEACTIVATE, ITEMPOS_INVALID );
1065 :
1066 0 : if( !aDelData.isDeleted() )
1067 : {
1068 0 : if ( !aDeactivateHdl.Call( this ) )
1069 : {
1070 0 : if( !aDelData.isDeleted() )
1071 : {
1072 0 : if ( pStartMenu && ( pStartMenu != this ) )
1073 : {
1074 0 : pStartMenu->bInCallback = sal_True;
1075 0 : pStartMenu->aDeactivateHdl.Call( this );
1076 0 : pStartMenu->bInCallback = sal_False;
1077 : }
1078 : }
1079 : }
1080 : }
1081 :
1082 0 : if( !aDelData.isDeleted() )
1083 : {
1084 0 : bInCallback = sal_False;
1085 0 : }
1086 0 : }
1087 :
1088 0 : void Menu::Highlight()
1089 : {
1090 0 : ImplMenuDelData aDelData( this );
1091 :
1092 0 : Menu* pStartMenu = ImplGetStartMenu();
1093 0 : if ( !aHighlightHdl.Call( this ) && !aDelData.isDeleted() )
1094 : {
1095 0 : if ( pStartMenu && ( pStartMenu != this ) )
1096 0 : pStartMenu->aHighlightHdl.Call( this );
1097 0 : }
1098 0 : }
1099 :
1100 0 : void Menu::ImplSelect()
1101 : {
1102 0 : MenuItemData* pData = GetItemList()->GetData( nSelectedId );
1103 0 : if ( pData && (pData->nBits & MIB_AUTOCHECK) )
1104 : {
1105 0 : sal_Bool bChecked = IsItemChecked( nSelectedId );
1106 0 : if ( pData->nBits & MIB_RADIOCHECK )
1107 : {
1108 0 : if ( !bChecked )
1109 0 : CheckItem( nSelectedId, sal_True );
1110 : }
1111 : else
1112 0 : CheckItem( nSelectedId, !bChecked );
1113 : }
1114 :
1115 : // call select
1116 0 : ImplSVData* pSVData = ImplGetSVData();
1117 0 : pSVData->maAppData.mpActivePopupMenu = NULL; // if new execute in select()
1118 0 : Application::PostUserEvent( nEventId, LINK( this, Menu, ImplCallSelect ) );
1119 0 : }
1120 :
1121 0 : void Menu::Select()
1122 : {
1123 0 : ImplMenuDelData aDelData( this );
1124 :
1125 0 : ImplCallEventListeners( VCLEVENT_MENU_SELECT, GetItemPos( GetCurItemId() ) );
1126 0 : if ( !aDelData.isDeleted() && !aSelectHdl.Call( this ) )
1127 : {
1128 0 : if( !aDelData.isDeleted() )
1129 : {
1130 0 : Menu* pStartMenu = ImplGetStartMenu();
1131 0 : if ( pStartMenu && ( pStartMenu != this ) )
1132 : {
1133 0 : pStartMenu->nSelectedId = nSelectedId;
1134 0 : pStartMenu->aSelectHdl.Call( this );
1135 : }
1136 : }
1137 0 : }
1138 0 : }
1139 :
1140 : #if defined(QUARTZ)
1141 : void Menu::ImplSelectWithStart( Menu* pSMenu )
1142 : {
1143 : Menu* pOldStartedFrom = pStartedFrom;
1144 : pStartedFrom = pSMenu;
1145 : Menu* pOldStartedStarted = pOldStartedFrom ? pOldStartedFrom->pStartedFrom : NULL;
1146 : Select();
1147 : if( pOldStartedFrom )
1148 : pOldStartedFrom->pStartedFrom = pOldStartedStarted;
1149 : pStartedFrom = pOldStartedFrom;
1150 : }
1151 : #endif
1152 :
1153 0 : void Menu::RequestHelp( const HelpEvent& )
1154 : {
1155 0 : }
1156 :
1157 948 : void Menu::ImplCallEventListeners( sal_uLong nEvent, sal_uInt16 nPos )
1158 : {
1159 948 : ImplMenuDelData aDelData( this );
1160 :
1161 948 : VclMenuEvent aEvent( this, nEvent, nPos );
1162 :
1163 : // This is needed by atk accessibility bridge
1164 948 : if ( nEvent == VCLEVENT_MENU_HIGHLIGHT )
1165 : {
1166 0 : ImplGetSVData()->mpApp->ImplCallEventListeners( &aEvent );
1167 : }
1168 :
1169 948 : if ( !aDelData.isDeleted() )
1170 948 : maEventListeners.Call( &aEvent );
1171 :
1172 948 : if( !aDelData.isDeleted() )
1173 : {
1174 948 : Menu* pMenu = this;
1175 2844 : while ( pMenu )
1176 : {
1177 948 : maChildEventListeners.Call( &aEvent );
1178 :
1179 948 : if( aDelData.isDeleted() )
1180 0 : break;
1181 :
1182 948 : pMenu = ( pMenu->pStartedFrom != pMenu ) ? pMenu->pStartedFrom : NULL;
1183 : }
1184 948 : }
1185 948 : }
1186 :
1187 0 : void Menu::AddEventListener( const Link& rEventListener )
1188 : {
1189 0 : maEventListeners.addListener( rEventListener );
1190 0 : }
1191 :
1192 63 : void Menu::RemoveEventListener( const Link& rEventListener )
1193 : {
1194 63 : maEventListeners.removeListener( rEventListener );
1195 63 : }
1196 :
1197 50 : void Menu::InsertItem( sal_uInt16 nItemId, const XubString& rStr, MenuItemBits nItemBits, sal_uInt16 nPos )
1198 : {
1199 : DBG_ASSERT( nItemId, "Menu::InsertItem(): ItemId == 0" );
1200 : DBG_ASSERT( GetItemPos( nItemId ) == MENU_ITEM_NOTFOUND,
1201 : "Menu::InsertItem(): ItemId already exists" );
1202 :
1203 : // if Position > ItemCount, append
1204 50 : if ( nPos >= pItemList->size() )
1205 50 : nPos = MENU_APPEND;
1206 :
1207 : // put Item in MenuItemList
1208 : MenuItemData* pData = pItemList->Insert( nItemId, MENUITEM_STRING,
1209 50 : nItemBits, rStr, Image(), this, nPos );
1210 :
1211 : // update native menu
1212 50 : if( ImplGetSalMenu() && pData->pSalMenuItem )
1213 0 : ImplGetSalMenu()->InsertItem( pData->pSalMenuItem, nPos );
1214 :
1215 50 : Window* pWin = ImplGetWindow();
1216 50 : delete mpLayoutData, mpLayoutData = NULL;
1217 50 : if ( pWin )
1218 : {
1219 0 : ImplCalcSize( pWin );
1220 0 : if ( pWin->IsVisible() )
1221 0 : pWin->Invalidate();
1222 : }
1223 50 : ImplCallEventListeners( VCLEVENT_MENU_INSERTITEM, nPos );
1224 50 : }
1225 :
1226 0 : void Menu::InsertItem( sal_uInt16 nItemId, const Image& rImage,
1227 : MenuItemBits nItemBits, sal_uInt16 nPos )
1228 : {
1229 0 : InsertItem( nItemId, ImplGetSVEmptyStr(), nItemBits, nPos );
1230 0 : SetItemImage( nItemId, rImage );
1231 0 : }
1232 :
1233 0 : void Menu::InsertItem( sal_uInt16 nItemId,
1234 : const XubString& rStr, const Image& rImage,
1235 : MenuItemBits nItemBits, sal_uInt16 nPos )
1236 : {
1237 0 : InsertItem( nItemId, rStr, nItemBits, nPos );
1238 0 : SetItemImage( nItemId, rImage );
1239 0 : }
1240 :
1241 56 : void Menu::InsertItem( const ResId& rResId, sal_uInt16 nPos )
1242 : {
1243 56 : ResMgr* pMgr = rResId.GetResMgr();
1244 56 : if( ! pMgr )
1245 56 : return;
1246 :
1247 : sal_uLong nObjMask;
1248 :
1249 56 : GetRes( rResId.SetRT( RSC_MENUITEM ) );
1250 56 : nObjMask = ReadLongRes();
1251 :
1252 56 : sal_Bool bSep = sal_False;
1253 56 : if ( nObjMask & RSC_MENUITEM_SEPARATOR )
1254 6 : bSep = (sal_Bool)ReadShortRes();
1255 :
1256 56 : sal_uInt16 nItemId = 1;
1257 56 : if ( nObjMask & RSC_MENUITEM_ID )
1258 50 : nItemId = sal::static_int_cast<sal_uInt16>(ReadLongRes());
1259 :
1260 56 : MenuItemBits nStatus = 0;
1261 56 : if ( nObjMask & RSC_MENUITEM_STATUS )
1262 0 : nStatus = sal::static_int_cast<MenuItemBits>(ReadLongRes());
1263 :
1264 56 : String aText;
1265 56 : if ( nObjMask & RSC_MENUITEM_TEXT )
1266 50 : aText = ReadStringRes();
1267 :
1268 : // create item
1269 56 : if ( nObjMask & RSC_MENUITEM_BITMAP )
1270 : {
1271 0 : if ( !bSep )
1272 : {
1273 0 : Bitmap aBmp( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
1274 0 : if ( aText.Len() )
1275 0 : InsertItem( nItemId, aText, aBmp, nStatus, nPos );
1276 : else
1277 0 : InsertItem( nItemId, aBmp, nStatus, nPos );
1278 : }
1279 0 : IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
1280 : }
1281 56 : else if ( !bSep )
1282 50 : InsertItem( nItemId, aText, nStatus, nPos );
1283 56 : if ( bSep )
1284 6 : InsertSeparator( nPos );
1285 :
1286 56 : String aHelpText;
1287 56 : if ( nObjMask & RSC_MENUITEM_HELPTEXT )
1288 : {
1289 0 : aHelpText = ReadStringRes();
1290 0 : if( !bSep )
1291 0 : SetHelpText( nItemId, aHelpText );
1292 : }
1293 :
1294 56 : if ( nObjMask & RSC_MENUITEM_HELPID )
1295 : {
1296 50 : rtl::OString aHelpId( ReadByteStringRes() );
1297 50 : if ( !bSep )
1298 50 : SetHelpId( nItemId, aHelpId );
1299 : }
1300 :
1301 56 : if( !bSep )
1302 50 : SetHelpText( nItemId, aHelpText );
1303 :
1304 56 : if ( nObjMask & RSC_MENUITEM_KEYCODE )
1305 : {
1306 0 : if ( !bSep )
1307 0 : SetAccelKey( nItemId, KeyCode( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) ) );
1308 0 : IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
1309 : }
1310 56 : if( nObjMask & RSC_MENUITEM_CHECKED )
1311 : {
1312 0 : if ( !bSep )
1313 0 : CheckItem( nItemId, (sal_Bool)ReadShortRes() );
1314 : }
1315 56 : if ( nObjMask & RSC_MENUITEM_DISABLE )
1316 : {
1317 0 : if ( !bSep )
1318 0 : EnableItem( nItemId, !(sal_Bool)ReadShortRes() );
1319 : }
1320 56 : if ( nObjMask & RSC_MENUITEM_COMMAND )
1321 : {
1322 0 : String aCommandStr = ReadStringRes();
1323 0 : if ( !bSep )
1324 0 : SetItemCommand( nItemId, aCommandStr );
1325 : }
1326 56 : if ( nObjMask & RSC_MENUITEM_MENU )
1327 : {
1328 0 : if ( !bSep )
1329 : {
1330 0 : MenuItemData* pData = GetItemList()->GetData( nItemId );
1331 0 : if ( pData )
1332 : {
1333 0 : PopupMenu* pSubMenu = new PopupMenu( ResId( (RSHEADER_TYPE*)GetClassRes(), *pMgr ) );
1334 0 : pData->pAutoSubMenu = pSubMenu;
1335 : // #111060# keep track of this pointer, may be it will be deleted from outside
1336 0 : pSubMenu->pRefAutoSubMenu = &pData->pAutoSubMenu;
1337 0 : SetPopupMenu( nItemId, pSubMenu );
1338 : }
1339 : }
1340 0 : IncrementRes( GetObjSizeRes( (RSHEADER_TYPE*)GetClassRes() ) );
1341 : }
1342 56 : delete mpLayoutData, mpLayoutData = NULL;
1343 : }
1344 :
1345 6 : void Menu::InsertSeparator( sal_uInt16 nPos )
1346 : {
1347 : // do nothing if its a menu bar
1348 6 : if ( bIsMenuBar )
1349 6 : return;
1350 :
1351 : // if position > ItemCount, append
1352 6 : if ( nPos >= pItemList->size() )
1353 6 : nPos = MENU_APPEND;
1354 :
1355 : // put separator in item list
1356 6 : pItemList->InsertSeparator( nPos );
1357 :
1358 : // update native menu
1359 6 : size_t itemPos = ( nPos != MENU_APPEND ) ? nPos : pItemList->size() - 1;
1360 6 : MenuItemData *pData = pItemList->GetDataFromPos( itemPos );
1361 6 : if( ImplGetSalMenu() && pData && pData->pSalMenuItem )
1362 0 : ImplGetSalMenu()->InsertItem( pData->pSalMenuItem, nPos );
1363 :
1364 6 : delete mpLayoutData, mpLayoutData = NULL;
1365 :
1366 6 : ImplCallEventListeners( VCLEVENT_MENU_INSERTITEM, nPos );
1367 : }
1368 :
1369 0 : void Menu::RemoveItem( sal_uInt16 nPos )
1370 : {
1371 0 : sal_Bool bRemove = sal_False;
1372 :
1373 0 : if ( nPos < GetItemCount() )
1374 : {
1375 : // update native menu
1376 0 : if( ImplGetSalMenu() )
1377 0 : ImplGetSalMenu()->RemoveItem( nPos );
1378 :
1379 0 : pItemList->Remove( nPos );
1380 0 : bRemove = sal_True;
1381 : }
1382 :
1383 0 : Window* pWin = ImplGetWindow();
1384 0 : if ( pWin )
1385 : {
1386 0 : ImplCalcSize( pWin );
1387 0 : if ( pWin->IsVisible() )
1388 0 : pWin->Invalidate();
1389 : }
1390 0 : delete mpLayoutData, mpLayoutData = NULL;
1391 :
1392 0 : if ( bRemove )
1393 0 : ImplCallEventListeners( VCLEVENT_MENU_REMOVEITEM, nPos );
1394 0 : }
1395 :
1396 0 : void ImplCopyItem( Menu* pThis, const Menu& rMenu, sal_uInt16 nPos, sal_uInt16 nNewPos,
1397 : sal_uInt16 nMode = 0 )
1398 : {
1399 0 : MenuItemType eType = rMenu.GetItemType( nPos );
1400 :
1401 0 : if ( eType == MENUITEM_DONTKNOW )
1402 0 : return;
1403 :
1404 0 : if ( eType == MENUITEM_SEPARATOR )
1405 0 : pThis->InsertSeparator( nNewPos );
1406 : else
1407 : {
1408 0 : sal_uInt16 nId = rMenu.GetItemId( nPos );
1409 :
1410 : DBG_ASSERT( pThis->GetItemPos( nId ) == MENU_ITEM_NOTFOUND,
1411 : "Menu::CopyItem(): ItemId already exists" );
1412 :
1413 0 : MenuItemData* pData = rMenu.GetItemList()->GetData( nId );
1414 :
1415 0 : if ( eType == MENUITEM_STRINGIMAGE )
1416 0 : pThis->InsertItem( nId, pData->aText, pData->aImage, pData->nBits, nNewPos );
1417 0 : else if ( eType == MENUITEM_STRING )
1418 0 : pThis->InsertItem( nId, pData->aText, pData->nBits, nNewPos );
1419 : else
1420 0 : pThis->InsertItem( nId, pData->aImage, pData->nBits, nNewPos );
1421 :
1422 0 : if ( rMenu.IsItemChecked( nId ) )
1423 0 : pThis->CheckItem( nId, sal_True );
1424 0 : if ( !rMenu.IsItemEnabled( nId ) )
1425 0 : pThis->EnableItem( nId, sal_False );
1426 0 : pThis->SetHelpId( nId, pData->aHelpId );
1427 0 : pThis->SetHelpText( nId, pData->aHelpText );
1428 0 : pThis->SetAccelKey( nId, pData->aAccelKey );
1429 0 : pThis->SetItemCommand( nId, pData->aCommandStr );
1430 0 : pThis->SetHelpCommand( nId, pData->aHelpCommandStr );
1431 :
1432 0 : PopupMenu* pSubMenu = rMenu.GetPopupMenu( nId );
1433 0 : if ( pSubMenu )
1434 : {
1435 : // create auto-copy
1436 0 : if ( nMode == 1 )
1437 : {
1438 0 : PopupMenu* pNewMenu = new PopupMenu( *pSubMenu );
1439 0 : pThis->SetPopupMenu( nId, pNewMenu );
1440 : }
1441 : else
1442 0 : pThis->SetPopupMenu( nId, pSubMenu );
1443 : }
1444 : }
1445 : }
1446 :
1447 0 : void Menu::CopyItem( const Menu& rMenu, sal_uInt16 nPos, sal_uInt16 nNewPos )
1448 : {
1449 0 : ImplCopyItem( this, rMenu, nPos, nNewPos );
1450 0 : }
1451 :
1452 0 : void Menu::Clear()
1453 : {
1454 0 : for ( sal_uInt16 i = GetItemCount(); i; i-- )
1455 0 : RemoveItem( 0 );
1456 0 : }
1457 :
1458 898 : sal_uInt16 Menu::GetItemCount() const
1459 : {
1460 898 : return (sal_uInt16)pItemList->size();
1461 : }
1462 :
1463 0 : sal_uInt16 Menu::ImplGetVisibleItemCount() const
1464 : {
1465 0 : sal_uInt16 nItems = 0;
1466 0 : for ( size_t n = pItemList->size(); n; )
1467 : {
1468 0 : if ( ImplIsVisible( --n ) )
1469 0 : nItems++;
1470 : }
1471 0 : return nItems;
1472 : }
1473 :
1474 0 : sal_uInt16 Menu::ImplGetFirstVisible() const
1475 : {
1476 0 : for ( size_t n = 0; n < pItemList->size(); n++ )
1477 : {
1478 0 : if ( ImplIsVisible( n ) )
1479 0 : return n;
1480 : }
1481 0 : return ITEMPOS_INVALID;
1482 : }
1483 :
1484 0 : sal_uInt16 Menu::ImplGetPrevVisible( sal_uInt16 nPos ) const
1485 : {
1486 0 : for ( size_t n = nPos; n; )
1487 : {
1488 0 : if ( n && ImplIsVisible( --n ) )
1489 0 : return n;
1490 : }
1491 0 : return ITEMPOS_INVALID;
1492 : }
1493 :
1494 0 : sal_uInt16 Menu::ImplGetNextVisible( sal_uInt16 nPos ) const
1495 : {
1496 0 : for ( size_t n = nPos+1; n < pItemList->size(); n++ )
1497 : {
1498 0 : if ( ImplIsVisible( n ) )
1499 0 : return n;
1500 : }
1501 0 : return ITEMPOS_INVALID;
1502 : }
1503 :
1504 0 : sal_uInt16 Menu::GetItemId( sal_uInt16 nPos ) const
1505 : {
1506 0 : MenuItemData* pData = pItemList->GetDataFromPos( nPos );
1507 :
1508 0 : if ( pData )
1509 0 : return pData->nId;
1510 : else
1511 0 : return 0;
1512 : }
1513 :
1514 0 : sal_uInt16 Menu::GetItemPos( sal_uInt16 nItemId ) const
1515 : {
1516 : size_t nPos;
1517 0 : MenuItemData* pData = pItemList->GetData( nItemId, nPos );
1518 :
1519 0 : if ( pData )
1520 0 : return (sal_uInt16)nPos;
1521 : else
1522 0 : return MENU_ITEM_NOTFOUND;
1523 : }
1524 :
1525 0 : MenuItemType Menu::GetItemType( sal_uInt16 nPos ) const
1526 : {
1527 0 : MenuItemData* pData = pItemList->GetDataFromPos( nPos );
1528 :
1529 0 : if ( pData )
1530 0 : return pData->eType;
1531 : else
1532 0 : return MENUITEM_DONTKNOW;
1533 : }
1534 :
1535 0 : sal_uInt16 Menu::GetCurItemId() const
1536 : {
1537 0 : return nSelectedId;
1538 : }
1539 :
1540 0 : void Menu::SetItemBits( sal_uInt16 nItemId, MenuItemBits nBits )
1541 : {
1542 0 : MenuItemData* pData = pItemList->GetData( nItemId );
1543 0 : if ( pData )
1544 0 : pData->nBits = nBits;
1545 0 : }
1546 :
1547 0 : MenuItemBits Menu::GetItemBits( sal_uInt16 nItemId ) const
1548 : {
1549 0 : MenuItemBits nBits = 0;
1550 0 : MenuItemData* pData = pItemList->GetData( nItemId );
1551 0 : if ( pData )
1552 0 : nBits = pData->nBits;
1553 0 : return nBits;
1554 : }
1555 :
1556 0 : void Menu::SetUserValue( sal_uInt16 nItemId, sal_uLong nValue )
1557 : {
1558 0 : MenuItemData* pData = pItemList->GetData( nItemId );
1559 0 : if ( pData )
1560 0 : pData->nUserValue = nValue;
1561 0 : }
1562 :
1563 0 : sal_uLong Menu::GetUserValue( sal_uInt16 nItemId ) const
1564 : {
1565 0 : MenuItemData* pData = pItemList->GetData( nItemId );
1566 0 : return pData ? pData->nUserValue : 0;
1567 : }
1568 :
1569 0 : void Menu::SetPopupMenu( sal_uInt16 nItemId, PopupMenu* pMenu )
1570 : {
1571 : size_t nPos;
1572 0 : MenuItemData* pData = pItemList->GetData( nItemId, nPos );
1573 :
1574 : // Item does not exist -> return NULL
1575 0 : if ( !pData )
1576 : return;
1577 :
1578 : // same menu, nothing to do
1579 0 : if ( (PopupMenu*)pData->pSubMenu == pMenu )
1580 : return;
1581 :
1582 : // data exchange
1583 0 : pData->pSubMenu = pMenu;
1584 :
1585 : // #112023# Make sure pStartedFrom does not point to invalid (old) data
1586 0 : if ( pData->pSubMenu )
1587 0 : pData->pSubMenu->pStartedFrom = 0;
1588 :
1589 : // set native submenu
1590 0 : if( ImplGetSalMenu() && pData->pSalMenuItem )
1591 : {
1592 0 : if( pMenu )
1593 0 : ImplGetSalMenu()->SetSubMenu( pData->pSalMenuItem, pMenu->ImplGetSalMenu(), nPos );
1594 : else
1595 0 : ImplGetSalMenu()->SetSubMenu( pData->pSalMenuItem, NULL, nPos );
1596 : }
1597 :
1598 0 : ImplCallEventListeners( VCLEVENT_MENU_SUBMENUCHANGED, nPos );
1599 : }
1600 :
1601 426 : PopupMenu* Menu::GetPopupMenu( sal_uInt16 nItemId ) const
1602 : {
1603 426 : MenuItemData* pData = pItemList->GetData( nItemId );
1604 :
1605 426 : if ( pData )
1606 0 : return (PopupMenu*)(pData->pSubMenu);
1607 : else
1608 426 : return NULL;
1609 : }
1610 :
1611 0 : void Menu::SetAccelKey( sal_uInt16 nItemId, const KeyCode& rKeyCode )
1612 : {
1613 : size_t nPos;
1614 0 : MenuItemData* pData = pItemList->GetData( nItemId, nPos );
1615 :
1616 0 : if ( !pData )
1617 : return;
1618 :
1619 0 : if ( pData->aAccelKey == rKeyCode )
1620 : return;
1621 :
1622 0 : pData->aAccelKey = rKeyCode;
1623 :
1624 : // update native menu
1625 0 : if( ImplGetSalMenu() && pData->pSalMenuItem )
1626 0 : ImplGetSalMenu()->SetAccelerator( nPos, pData->pSalMenuItem, rKeyCode, rKeyCode.GetName() );
1627 : }
1628 :
1629 0 : KeyCode Menu::GetAccelKey( sal_uInt16 nItemId ) const
1630 : {
1631 0 : MenuItemData* pData = pItemList->GetData( nItemId );
1632 :
1633 0 : if ( pData )
1634 0 : return pData->aAccelKey;
1635 : else
1636 0 : return KeyCode();
1637 : }
1638 :
1639 0 : KeyEvent Menu::GetActivationKey( sal_uInt16 nItemId ) const
1640 : {
1641 0 : KeyEvent aRet;
1642 0 : MenuItemData* pData = pItemList->GetData( nItemId );
1643 0 : if( pData )
1644 : {
1645 0 : sal_uInt16 nPos = pData->aText.Search( '~' );
1646 0 : if( nPos != STRING_NOTFOUND && nPos < pData->aText.Len()-1 )
1647 : {
1648 0 : sal_uInt16 nCode = 0;
1649 0 : sal_Unicode cAccel = pData->aText.GetChar( nPos+1 );
1650 0 : if( cAccel >= 'a' && cAccel <= 'z' )
1651 0 : nCode = KEY_A + (cAccel-'a');
1652 0 : else if( cAccel >= 'A' && cAccel <= 'Z' )
1653 0 : nCode = KEY_A + (cAccel-'A');
1654 0 : else if( cAccel >= '0' && cAccel <= '9' )
1655 0 : nCode = KEY_0 + (cAccel-'0');
1656 0 : if(nCode )
1657 0 : aRet = KeyEvent( cAccel, KeyCode( nCode, KEY_MOD2 ) );
1658 : }
1659 :
1660 : }
1661 0 : return aRet;
1662 : }
1663 :
1664 0 : void Menu::CheckItem( sal_uInt16 nItemId, sal_Bool bCheck )
1665 : {
1666 : size_t nPos;
1667 0 : MenuItemData* pData = pItemList->GetData( nItemId, nPos );
1668 :
1669 0 : if ( !pData || pData->bChecked == bCheck )
1670 0 : return;
1671 :
1672 : // if radio-check, then uncheck previous
1673 0 : if ( bCheck && (pData->nBits & MIB_AUTOCHECK) &&
1674 : (pData->nBits & MIB_RADIOCHECK) )
1675 : {
1676 : MenuItemData* pGroupData;
1677 : sal_uInt16 nGroupPos;
1678 0 : sal_uInt16 nItemCount = GetItemCount();
1679 0 : sal_Bool bFound = sal_False;
1680 :
1681 0 : nGroupPos = nPos;
1682 0 : while ( nGroupPos )
1683 : {
1684 0 : pGroupData = pItemList->GetDataFromPos( nGroupPos-1 );
1685 0 : if ( pGroupData->nBits & MIB_RADIOCHECK )
1686 : {
1687 0 : if ( IsItemChecked( pGroupData->nId ) )
1688 : {
1689 0 : CheckItem( pGroupData->nId, sal_False );
1690 0 : bFound = sal_True;
1691 0 : break;
1692 : }
1693 : }
1694 : else
1695 0 : break;
1696 0 : nGroupPos--;
1697 : }
1698 :
1699 0 : if ( !bFound )
1700 : {
1701 0 : nGroupPos = nPos+1;
1702 0 : while ( nGroupPos < nItemCount )
1703 : {
1704 0 : pGroupData = pItemList->GetDataFromPos( nGroupPos );
1705 0 : if ( pGroupData->nBits & MIB_RADIOCHECK )
1706 : {
1707 0 : if ( IsItemChecked( pGroupData->nId ) )
1708 : {
1709 0 : CheckItem( pGroupData->nId, sal_False );
1710 0 : break;
1711 : }
1712 : }
1713 : else
1714 0 : break;
1715 0 : nGroupPos++;
1716 : }
1717 : }
1718 : }
1719 :
1720 0 : pData->bChecked = bCheck;
1721 :
1722 : // update native menu
1723 0 : if( ImplGetSalMenu() )
1724 0 : ImplGetSalMenu()->CheckItem( nPos, bCheck );
1725 :
1726 0 : ImplCallEventListeners( bCheck ? VCLEVENT_MENU_ITEMCHECKED : VCLEVENT_MENU_ITEMUNCHECKED, nPos );
1727 : }
1728 :
1729 0 : sal_Bool Menu::IsItemChecked( sal_uInt16 nItemId ) const
1730 : {
1731 : size_t nPos;
1732 0 : MenuItemData* pData = pItemList->GetData( nItemId, nPos );
1733 :
1734 0 : if ( !pData )
1735 0 : return sal_False;
1736 :
1737 0 : return pData->bChecked;
1738 : }
1739 :
1740 0 : void Menu::EnableItem( sal_uInt16 nItemId, sal_Bool bEnable )
1741 : {
1742 : size_t nPos;
1743 0 : MenuItemData* pItemData = pItemList->GetData( nItemId, nPos );
1744 :
1745 0 : if ( pItemData && ( pItemData->bEnabled != bEnable ) )
1746 : {
1747 0 : pItemData->bEnabled = bEnable;
1748 :
1749 0 : Window* pWin = ImplGetWindow();
1750 0 : if ( pWin && pWin->IsVisible() )
1751 : {
1752 : DBG_ASSERT( bIsMenuBar, "Menu::EnableItem - Popup visible!" );
1753 0 : long nX = 0;
1754 0 : size_t nCount = pItemList->size();
1755 0 : for ( size_t n = 0; n < nCount; n++ )
1756 : {
1757 0 : MenuItemData* pData = pItemList->GetDataFromPos( n );
1758 0 : if ( n == nPos )
1759 : {
1760 0 : pWin->Invalidate( Rectangle( Point( nX, 0 ), Size( pData->aSz.Width(), pData->aSz.Height() ) ) );
1761 0 : break;
1762 : }
1763 0 : nX += pData->aSz.Width();
1764 : }
1765 : }
1766 : // update native menu
1767 0 : if( ImplGetSalMenu() )
1768 0 : ImplGetSalMenu()->EnableItem( nPos, bEnable );
1769 :
1770 0 : ImplCallEventListeners( bEnable ? VCLEVENT_MENU_ENABLE : VCLEVENT_MENU_DISABLE, nPos );
1771 : }
1772 0 : }
1773 :
1774 0 : sal_Bool Menu::IsItemEnabled( sal_uInt16 nItemId ) const
1775 : {
1776 : size_t nPos;
1777 0 : MenuItemData* pData = pItemList->GetData( nItemId, nPos );
1778 :
1779 0 : if ( !pData )
1780 0 : return sal_False;
1781 :
1782 0 : return pData->bEnabled;
1783 : }
1784 :
1785 0 : void Menu::ShowItem( sal_uInt16 nItemId, sal_Bool bVisible )
1786 : {
1787 : size_t nPos;
1788 0 : MenuItemData* pData = pItemList->GetData( nItemId, nPos );
1789 :
1790 : DBG_ASSERT( !bIsMenuBar, "Menu::ShowItem - ignored for menu bar entries!" );
1791 0 : if ( !bIsMenuBar && pData && ( pData->bVisible != bVisible ) )
1792 : {
1793 0 : Window* pWin = ImplGetWindow();
1794 0 : if ( pWin && pWin->IsVisible() )
1795 : {
1796 : DBG_ASSERT( 0, "Menu::ShowItem - ignored for visible popups!" );
1797 0 : return;
1798 : }
1799 0 : pData->bVisible = bVisible;
1800 :
1801 : // update native menu
1802 0 : if( ImplGetSalMenu() )
1803 0 : ImplGetSalMenu()->ShowItem( nPos, bVisible );
1804 : }
1805 : }
1806 :
1807 6 : void Menu::SetItemText( sal_uInt16 nItemId, const XubString& rStr )
1808 : {
1809 : size_t nPos;
1810 6 : MenuItemData* pData = pItemList->GetData( nItemId, nPos );
1811 :
1812 6 : if ( !pData )
1813 6 : return;
1814 :
1815 6 : if ( !rStr.Equals( pData->aText ) )
1816 : {
1817 6 : pData->aText = rStr;
1818 6 : ImplSetMenuItemData( pData );
1819 : // update native menu
1820 6 : if( ImplGetSalMenu() && pData->pSalMenuItem )
1821 0 : ImplGetSalMenu()->SetItemText( nPos, pData->pSalMenuItem, rStr );
1822 :
1823 6 : Window* pWin = ImplGetWindow();
1824 6 : delete mpLayoutData, mpLayoutData = NULL;
1825 6 : if ( pWin && IsMenuBar() )
1826 : {
1827 0 : ImplCalcSize( pWin );
1828 0 : if ( pWin->IsVisible() )
1829 0 : pWin->Invalidate();
1830 : }
1831 :
1832 6 : ImplCallEventListeners( VCLEVENT_MENU_ITEMTEXTCHANGED, nPos );
1833 : }
1834 : }
1835 :
1836 6 : XubString Menu::GetItemText( sal_uInt16 nItemId ) const
1837 : {
1838 : size_t nPos;
1839 6 : MenuItemData* pData = pItemList->GetData( nItemId, nPos );
1840 :
1841 6 : if ( pData )
1842 6 : return pData->aText;
1843 : else
1844 0 : return ImplGetSVEmptyStr();
1845 : }
1846 :
1847 0 : void Menu::SetItemImage( sal_uInt16 nItemId, const Image& rImage )
1848 : {
1849 : size_t nPos;
1850 0 : MenuItemData* pData = pItemList->GetData( nItemId, nPos );
1851 :
1852 0 : if ( !pData )
1853 0 : return;
1854 :
1855 0 : pData->aImage = rImage;
1856 0 : ImplSetMenuItemData( pData );
1857 :
1858 : // update native menu
1859 0 : if( ImplGetSalMenu() && pData->pSalMenuItem )
1860 0 : ImplGetSalMenu()->SetItemImage( nPos, pData->pSalMenuItem, rImage );
1861 : }
1862 :
1863 0 : static inline Image ImplRotImage( const Image& rImage, long nAngle10 )
1864 : {
1865 0 : Image aRet;
1866 0 : BitmapEx aBmpEx( rImage.GetBitmapEx() );
1867 :
1868 0 : aBmpEx.Rotate( nAngle10, COL_WHITE );
1869 :
1870 0 : return Image( aBmpEx );
1871 : }
1872 :
1873 0 : void Menu::SetItemImageAngle( sal_uInt16 nItemId, long nAngle10 )
1874 : {
1875 : size_t nPos;
1876 0 : MenuItemData* pData = pItemList->GetData( nItemId, nPos );
1877 :
1878 0 : if ( pData )
1879 : {
1880 0 : long nDeltaAngle = (nAngle10 - pData->nItemImageAngle) % 3600;
1881 0 : while( nDeltaAngle < 0 )
1882 0 : nDeltaAngle += 3600;
1883 :
1884 0 : pData->nItemImageAngle = nAngle10;
1885 0 : if( nDeltaAngle && !!pData->aImage )
1886 0 : pData->aImage = ImplRotImage( pData->aImage, nDeltaAngle );
1887 : }
1888 0 : }
1889 :
1890 0 : static inline Image ImplMirrorImage( const Image& rImage )
1891 : {
1892 0 : Image aRet;
1893 0 : BitmapEx aBmpEx( rImage.GetBitmapEx() );
1894 :
1895 0 : aBmpEx.Mirror( BMP_MIRROR_HORZ );
1896 :
1897 0 : return Image( aBmpEx );
1898 : }
1899 :
1900 0 : void Menu::SetItemImageMirrorMode( sal_uInt16 nItemId, sal_Bool bMirror )
1901 : {
1902 : size_t nPos;
1903 0 : MenuItemData* pData = pItemList->GetData( nItemId, nPos );
1904 :
1905 0 : if ( pData )
1906 : {
1907 0 : if( ( pData->bMirrorMode && ! bMirror ) ||
1908 0 : ( ! pData->bMirrorMode && bMirror )
1909 : )
1910 : {
1911 0 : pData->bMirrorMode = bMirror ? true : false;
1912 0 : if( !!pData->aImage )
1913 0 : pData->aImage = ImplMirrorImage( pData->aImage );
1914 : }
1915 : }
1916 0 : }
1917 :
1918 0 : Image Menu::GetItemImage( sal_uInt16 nItemId ) const
1919 : {
1920 0 : MenuItemData* pData = pItemList->GetData( nItemId );
1921 :
1922 0 : if ( pData )
1923 0 : return pData->aImage;
1924 : else
1925 0 : return Image();
1926 : }
1927 :
1928 0 : long Menu::GetItemImageAngle( sal_uInt16 nItemId ) const
1929 : {
1930 0 : MenuItemData* pData = pItemList->GetData( nItemId );
1931 :
1932 0 : if ( pData )
1933 0 : return pData->nItemImageAngle;
1934 : else
1935 0 : return 0;
1936 : }
1937 :
1938 0 : sal_Bool Menu::GetItemImageMirrorMode( sal_uInt16 nItemId ) const
1939 : {
1940 0 : MenuItemData* pData = pItemList->GetData( nItemId );
1941 :
1942 0 : if ( pData )
1943 0 : return pData->bMirrorMode;
1944 : else
1945 0 : return sal_False;
1946 : }
1947 :
1948 0 : void Menu::SetItemCommand( sal_uInt16 nItemId, const String& rCommand )
1949 : {
1950 : size_t nPos;
1951 0 : MenuItemData* pData = pItemList->GetData( nItemId, nPos );
1952 :
1953 0 : if ( pData )
1954 0 : pData->aCommandStr = rCommand;
1955 0 : }
1956 :
1957 0 : const XubString& Menu::GetItemCommand( sal_uInt16 nItemId ) const
1958 : {
1959 0 : MenuItemData* pData = pItemList->GetData( nItemId );
1960 :
1961 0 : if ( pData )
1962 0 : return pData->aCommandStr;
1963 : else
1964 0 : return ImplGetSVEmptyStr();
1965 : }
1966 :
1967 0 : void Menu::SetHelpCommand( sal_uInt16 nItemId, const XubString& rStr )
1968 : {
1969 0 : MenuItemData* pData = pItemList->GetData( nItemId );
1970 :
1971 0 : if ( pData )
1972 0 : pData->aHelpCommandStr = rStr;
1973 0 : }
1974 :
1975 0 : const XubString& Menu::GetHelpCommand( sal_uInt16 nItemId ) const
1976 : {
1977 0 : MenuItemData* pData = pItemList->GetData( nItemId );
1978 :
1979 0 : if ( pData )
1980 0 : return pData->aHelpCommandStr;
1981 : else
1982 0 : return ImplGetSVEmptyStr();
1983 : }
1984 :
1985 50 : void Menu::SetHelpText( sal_uInt16 nItemId, const XubString& rStr )
1986 : {
1987 50 : MenuItemData* pData = pItemList->GetData( nItemId );
1988 :
1989 50 : if ( pData )
1990 50 : pData->aHelpText = rStr;
1991 50 : }
1992 :
1993 0 : const XubString& Menu::ImplGetHelpText( sal_uInt16 nItemId ) const
1994 : {
1995 0 : MenuItemData* pData = pItemList->GetData( nItemId );
1996 :
1997 0 : if ( pData )
1998 : {
1999 0 : if ( !pData->aHelpText.Len() &&
2000 0 : (( !pData->aHelpId.isEmpty() ) || ( pData->aCommandStr.Len() )))
2001 : {
2002 0 : Help* pHelp = Application::GetHelp();
2003 0 : if ( pHelp )
2004 : {
2005 0 : if ( pData->aCommandStr.Len() )
2006 0 : pData->aHelpText = pHelp->GetHelpText( pData->aCommandStr, NULL );
2007 :
2008 0 : if( !pData->aHelpText.Len() && !pData->aHelpId.isEmpty() )
2009 0 : pData->aHelpText = pHelp->GetHelpText( rtl::OStringToOUString( pData->aHelpId, RTL_TEXTENCODING_UTF8 ), NULL );
2010 : }
2011 : }
2012 :
2013 0 : return pData->aHelpText;
2014 : }
2015 : else
2016 0 : return ImplGetSVEmptyStr();
2017 : }
2018 :
2019 0 : const XubString& Menu::GetHelpText( sal_uInt16 nItemId ) const
2020 : {
2021 0 : return ImplGetHelpText( nItemId );
2022 : }
2023 :
2024 0 : void Menu::SetTipHelpText( sal_uInt16 nItemId, const XubString& rStr )
2025 : {
2026 0 : MenuItemData* pData = pItemList->GetData( nItemId );
2027 :
2028 0 : if ( pData )
2029 0 : pData->aTipHelpText = rStr;
2030 0 : }
2031 :
2032 0 : const XubString& Menu::GetTipHelpText( sal_uInt16 nItemId ) const
2033 : {
2034 0 : MenuItemData* pData = pItemList->GetData( nItemId );
2035 :
2036 0 : if ( pData )
2037 0 : return pData->aTipHelpText;
2038 : else
2039 0 : return ImplGetSVEmptyStr();
2040 : }
2041 :
2042 50 : void Menu::SetHelpId( sal_uInt16 nItemId, const rtl::OString& rHelpId )
2043 : {
2044 50 : MenuItemData* pData = pItemList->GetData( nItemId );
2045 :
2046 50 : if ( pData )
2047 50 : pData->aHelpId = rHelpId;
2048 50 : }
2049 :
2050 0 : rtl::OString Menu::GetHelpId( sal_uInt16 nItemId ) const
2051 : {
2052 0 : rtl::OString aRet;
2053 :
2054 0 : MenuItemData* pData = pItemList->GetData( nItemId );
2055 :
2056 0 : if ( pData )
2057 : {
2058 0 : if ( !pData->aHelpId.isEmpty() )
2059 0 : aRet = pData->aHelpId;
2060 : else
2061 0 : aRet = ::rtl::OUStringToOString( pData->aCommandStr, RTL_TEXTENCODING_UTF8 );
2062 : }
2063 :
2064 0 : return aRet;
2065 : }
2066 :
2067 0 : Menu& Menu::operator=( const Menu& rMenu )
2068 : {
2069 : // clean up
2070 0 : Clear();
2071 :
2072 : // copy items
2073 0 : sal_uInt16 nCount = rMenu.GetItemCount();
2074 0 : for ( sal_uInt16 i = 0; i < nCount; i++ )
2075 0 : ImplCopyItem( this, rMenu, i, MENU_APPEND, 1 );
2076 :
2077 0 : nDefaultItem = rMenu.nDefaultItem;
2078 0 : aActivateHdl = rMenu.aActivateHdl;
2079 0 : aDeactivateHdl = rMenu.aDeactivateHdl;
2080 0 : aHighlightHdl = rMenu.aHighlightHdl;
2081 0 : aSelectHdl = rMenu.aSelectHdl;
2082 0 : aTitleText = rMenu.aTitleText;
2083 0 : bIsMenuBar = rMenu.bIsMenuBar;
2084 :
2085 0 : return *this;
2086 : }
2087 :
2088 0 : sal_Bool Menu::ImplIsVisible( sal_uInt16 nPos ) const
2089 : {
2090 0 : sal_Bool bVisible = sal_True;
2091 :
2092 0 : MenuItemData* pData = pItemList->GetDataFromPos( nPos );
2093 : // check general visibility first
2094 0 : if( pData && !pData->bVisible )
2095 0 : bVisible = sal_False;
2096 :
2097 0 : if ( bVisible && pData && pData->eType == MENUITEM_SEPARATOR )
2098 : {
2099 0 : if( nPos == 0 ) // no separator should be shown at the very beginning
2100 0 : bVisible = sal_False;
2101 : else
2102 : {
2103 : // always avoid adjacent separators
2104 0 : size_t nCount = pItemList->size();
2105 : size_t n;
2106 0 : MenuItemData* pNextData = NULL;
2107 : // search next visible item
2108 0 : for( n = nPos + 1; n < nCount; n++ )
2109 : {
2110 0 : pNextData = pItemList->GetDataFromPos( n );
2111 0 : if( pNextData && pNextData->bVisible )
2112 : {
2113 0 : if( pNextData->eType == MENUITEM_SEPARATOR || ImplIsVisible(n) )
2114 0 : break;
2115 : }
2116 : }
2117 0 : if( n == nCount ) // no next visible item
2118 0 : bVisible = sal_False;
2119 : // check for separator
2120 0 : if( pNextData && pNextData->bVisible && pNextData->eType == MENUITEM_SEPARATOR )
2121 0 : bVisible = sal_False;
2122 :
2123 0 : if( bVisible )
2124 : {
2125 0 : for( n = nPos; n > 0; n-- )
2126 : {
2127 0 : pNextData = pItemList->GetDataFromPos( n-1 );
2128 0 : if( pNextData && pNextData->bVisible )
2129 : {
2130 0 : if( pNextData->eType != MENUITEM_SEPARATOR && ImplIsVisible(n-1) )
2131 0 : break;
2132 : }
2133 : }
2134 0 : if( n == 0 ) // no previous visible item
2135 0 : bVisible = sal_False;
2136 : }
2137 : }
2138 : }
2139 :
2140 : // not allowed for menubar, as I do not know
2141 : // whether a menu-entry will disappear or will appear
2142 0 : if ( bVisible && !bIsMenuBar && ( nMenuFlags & MENU_FLAG_HIDEDISABLEDENTRIES ) &&
2143 0 : !( nMenuFlags & MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES ) )
2144 : {
2145 0 : if( !pData ) // e.g. nPos == ITEMPOS_INVALID
2146 0 : bVisible = sal_False;
2147 0 : else if ( pData->eType != MENUITEM_SEPARATOR ) // separators handled above
2148 : {
2149 : // bVisible = pData->bEnabled && ( !pData->pSubMenu || pData->pSubMenu->HasValidEntries( sal_True ) );
2150 0 : bVisible = pData->bEnabled; // do not check submenus as they might be filled at Activate().
2151 : }
2152 : }
2153 :
2154 0 : return bVisible;
2155 : }
2156 :
2157 0 : sal_Bool Menu::IsItemPosVisible( sal_uInt16 nItemPos ) const
2158 : {
2159 0 : return IsMenuVisible() && ImplIsVisible( nItemPos );
2160 : }
2161 :
2162 0 : sal_Bool Menu::IsMenuVisible() const
2163 : {
2164 0 : return pWindow && pWindow->IsReallyVisible();
2165 : }
2166 :
2167 0 : sal_Bool Menu::ImplIsSelectable( sal_uInt16 nPos ) const
2168 : {
2169 0 : sal_Bool bSelectable = sal_True;
2170 :
2171 0 : MenuItemData* pData = pItemList->GetDataFromPos( nPos );
2172 : // check general visibility first
2173 0 : if ( pData && ( pData->nBits & MIB_NOSELECT ) )
2174 0 : bSelectable = sal_False;
2175 :
2176 0 : return bSelectable;
2177 : }
2178 :
2179 0 : void Menu::SelectItem( sal_uInt16 nItemId )
2180 : {
2181 0 : if( bIsMenuBar )
2182 0 : static_cast<MenuBar*>(this)->SelectEntry( nItemId );
2183 : else
2184 0 : static_cast<PopupMenu*>(this)->SelectEntry( nItemId );
2185 0 : }
2186 :
2187 0 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > Menu::GetAccessible()
2188 : {
2189 : // Since PopupMenu are sometimes shared by different instances of MenuBar, the mxAccessible member gets
2190 : // overwritten and may contain a disposed object when the initial menubar gets set again. So use the
2191 : // mxAccessible member only for sub menus.
2192 0 : if ( pStartedFrom )
2193 : {
2194 0 : for ( sal_uInt16 i = 0, nCount = pStartedFrom->GetItemCount(); i < nCount; ++i )
2195 : {
2196 0 : sal_uInt16 nItemId = pStartedFrom->GetItemId( i );
2197 0 : if ( static_cast< Menu* >( pStartedFrom->GetPopupMenu( nItemId ) ) == this )
2198 : {
2199 0 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xParent = pStartedFrom->GetAccessible();
2200 0 : if ( xParent.is() )
2201 : {
2202 0 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
2203 0 : if ( xParentContext.is() )
2204 0 : return xParentContext->getAccessibleChild( i );
2205 0 : }
2206 : }
2207 : }
2208 : }
2209 0 : else if ( !mxAccessible.is() )
2210 : {
2211 0 : UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
2212 0 : if ( pWrapper )
2213 0 : mxAccessible = pWrapper->CreateAccessible( this, bIsMenuBar );
2214 : }
2215 :
2216 0 : return mxAccessible;
2217 : }
2218 :
2219 0 : void Menu::SetAccessible( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible )
2220 : {
2221 0 : mxAccessible = rxAccessible;
2222 0 : }
2223 :
2224 413 : Size Menu::ImplGetNativeCheckAndRadioSize( Window* pWin, long& rCheckHeight, long& rRadioHeight ) const
2225 : {
2226 413 : long nCheckWidth = 0, nRadioWidth = 0;
2227 413 : rCheckHeight = rRadioHeight = 0;
2228 :
2229 413 : if( ! bIsMenuBar )
2230 : {
2231 0 : ImplControlValue aVal;
2232 0 : Rectangle aNativeBounds;
2233 0 : Rectangle aNativeContent;
2234 0 : Point tmp( 0, 0 );
2235 0 : Rectangle aCtrlRegion( Rectangle( tmp, Size( 100, 15 ) ) );
2236 0 : if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_CHECK_MARK ) )
2237 : {
2238 0 : if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP),
2239 : ControlPart(PART_MENU_ITEM_CHECK_MARK),
2240 : aCtrlRegion,
2241 : ControlState(CTRL_STATE_ENABLED),
2242 : aVal,
2243 : OUString(),
2244 : aNativeBounds,
2245 0 : aNativeContent )
2246 : )
2247 : {
2248 0 : rCheckHeight = aNativeBounds.GetHeight();
2249 0 : nCheckWidth = aNativeContent.GetWidth();
2250 : }
2251 : }
2252 0 : if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_RADIO_MARK ) )
2253 : {
2254 0 : if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP),
2255 : ControlPart(PART_MENU_ITEM_RADIO_MARK),
2256 : aCtrlRegion,
2257 : ControlState(CTRL_STATE_ENABLED),
2258 : aVal,
2259 : OUString(),
2260 : aNativeBounds,
2261 0 : aNativeContent )
2262 : )
2263 : {
2264 0 : rRadioHeight = aNativeBounds.GetHeight();
2265 0 : nRadioWidth = aNativeContent.GetWidth();
2266 : }
2267 0 : }
2268 : }
2269 413 : return Size(Max(nCheckWidth, nRadioWidth), Max(rCheckHeight, rRadioHeight));
2270 : }
2271 :
2272 0 : sal_Bool Menu::ImplGetNativeSubmenuArrowSize( Window* pWin, Size& rArrowSize, long& rArrowSpacing ) const
2273 : {
2274 0 : ImplControlValue aVal;
2275 0 : Rectangle aNativeBounds;
2276 0 : Rectangle aNativeContent;
2277 0 : Point tmp( 0, 0 );
2278 0 : Rectangle aCtrlRegion( Rectangle( tmp, Size( 100, 15 ) ) );
2279 0 : if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP,
2280 0 : PART_MENU_SUBMENU_ARROW ) )
2281 : {
2282 0 : if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP),
2283 : ControlPart(PART_MENU_SUBMENU_ARROW),
2284 : aCtrlRegion,
2285 : ControlState(CTRL_STATE_ENABLED),
2286 : aVal,
2287 : OUString(),
2288 : aNativeBounds,
2289 0 : aNativeContent )
2290 : )
2291 : {
2292 : Size aSize( Size ( aNativeContent.GetWidth(),
2293 0 : aNativeContent.GetHeight() ) );
2294 0 : rArrowSize = aSize;
2295 0 : rArrowSpacing = aNativeBounds.GetWidth() - aNativeContent.GetWidth();
2296 :
2297 0 : return sal_True;
2298 : }
2299 : }
2300 0 : return sal_False;
2301 : }
2302 :
2303 : // -----------------------------------------------------------------------
2304 :
2305 948 : void Menu::ImplAddDel( ImplMenuDelData& rDel )
2306 : {
2307 : DBG_ASSERT( !rDel.mpMenu, "Menu::ImplAddDel(): cannot add ImplMenuDelData twice !" );
2308 948 : if( !rDel.mpMenu )
2309 : {
2310 948 : rDel.mpMenu = this;
2311 948 : rDel.mpNext = mpFirstDel;
2312 948 : mpFirstDel = &rDel;
2313 : }
2314 948 : }
2315 :
2316 : // -----------------------------------------------------------------------
2317 :
2318 948 : void Menu::ImplRemoveDel( ImplMenuDelData& rDel )
2319 : {
2320 948 : rDel.mpMenu = NULL;
2321 948 : if ( mpFirstDel == &rDel )
2322 : {
2323 948 : mpFirstDel = rDel.mpNext;
2324 : }
2325 : else
2326 : {
2327 0 : ImplMenuDelData* pData = mpFirstDel;
2328 0 : while ( pData && (pData->mpNext != &rDel) )
2329 0 : pData = pData->mpNext;
2330 :
2331 : DBG_ASSERT( pData, "Menu::ImplRemoveDel(): ImplMenuDelData not registered !" );
2332 0 : if( pData )
2333 0 : pData->mpNext = rDel.mpNext;
2334 : }
2335 948 : }
2336 :
2337 : // -----------------------------------------------------------------------
2338 :
2339 236 : Size Menu::ImplCalcSize( Window* pWin )
2340 : {
2341 : // | Check/Radio/Image| Text| Accel/Popup|
2342 :
2343 : // for symbols: nFontHeight x nFontHeight
2344 236 : long nFontHeight = pWin->GetTextHeight();
2345 236 : long nExtra = nFontHeight/4;
2346 :
2347 236 : long nMinMenuItemHeight = nFontHeight;
2348 236 : long nCheckHeight = 0, nRadioHeight = 0;
2349 236 : Size aMaxSize = ImplGetNativeCheckAndRadioSize(pWin, nCheckHeight, nRadioHeight);
2350 236 : if( aMaxSize.Height() > nMinMenuItemHeight )
2351 0 : nMinMenuItemHeight = aMaxSize.Height();
2352 :
2353 236 : Size aMaxImgSz;
2354 :
2355 236 : const StyleSettings& rSettings = pWin->GetSettings().GetStyleSettings();
2356 236 : if ( rSettings.GetUseImagesInMenus() )
2357 : {
2358 236 : nMinMenuItemHeight = 16;
2359 472 : for ( size_t i = pItemList->size(); i; )
2360 : {
2361 0 : MenuItemData* pData = pItemList->GetDataFromPos( --i );
2362 0 : if ( ImplIsVisible( i )
2363 : && ( ( pData->eType == MENUITEM_IMAGE )
2364 : || ( pData->eType == MENUITEM_STRINGIMAGE )
2365 : )
2366 : )
2367 : {
2368 0 : Size aImgSz = pData->aImage.GetSizePixel();
2369 0 : if ( aImgSz.Height() > aMaxImgSz.Height() )
2370 0 : aMaxImgSz.Height() = aImgSz.Height();
2371 0 : if ( aImgSz.Height() > nMinMenuItemHeight )
2372 0 : nMinMenuItemHeight = aImgSz.Height();
2373 : break;
2374 : }
2375 : }
2376 : }
2377 :
2378 236 : Size aSz;
2379 236 : long nCheckWidth = 0;
2380 236 : long nMaxWidth = 0;
2381 :
2382 472 : for ( size_t n = pItemList->size(); n; )
2383 : {
2384 0 : MenuItemData* pData = pItemList->GetDataFromPos( --n );
2385 :
2386 0 : pData->aSz.Height() = 0;
2387 0 : pData->aSz.Width() = 0;
2388 :
2389 0 : if ( ImplIsVisible( n ) )
2390 : {
2391 0 : long nWidth = 0;
2392 :
2393 : // Separator
2394 0 : if ( !bIsMenuBar && ( pData->eType == MENUITEM_SEPARATOR ) )
2395 : {
2396 : DBG_ASSERT( !bIsMenuBar, "Separator in MenuBar ?! " );
2397 0 : pData->aSz.Height() = 4;
2398 : }
2399 :
2400 : // Image:
2401 0 : if ( !bIsMenuBar && ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
2402 : {
2403 0 : Size aImgSz = pData->aImage.GetSizePixel();
2404 0 : aImgSz.Height() += 4; // add a border for native marks
2405 0 : aImgSz.Width() += 4; // add a border for native marks
2406 0 : if ( aImgSz.Width() > aMaxImgSz.Width() )
2407 0 : aMaxImgSz.Width() = aImgSz.Width();
2408 0 : if ( aImgSz.Height() > aMaxImgSz.Height() )
2409 0 : aMaxImgSz.Height() = aImgSz.Height();
2410 0 : if ( aImgSz.Height() > pData->aSz.Height() )
2411 0 : pData->aSz.Height() = aImgSz.Height();
2412 : }
2413 :
2414 : // Check Buttons:
2415 0 : if ( !bIsMenuBar && pData->HasCheck() )
2416 : {
2417 0 : nCheckWidth = aMaxSize.Width();
2418 : // checks / images take the same place
2419 0 : if( ! ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
2420 0 : nWidth += nCheckWidth + nExtra * 2;
2421 : }
2422 :
2423 : // Text:
2424 0 : if ( (pData->eType == MENUITEM_STRING) || (pData->eType == MENUITEM_STRINGIMAGE) )
2425 : {
2426 0 : long nTextWidth = pWin->GetCtrlTextWidth( pData->aText );
2427 0 : long nTextHeight = pWin->GetTextHeight();
2428 :
2429 0 : if ( bIsMenuBar )
2430 : {
2431 0 : if ( nTextHeight > pData->aSz.Height() )
2432 0 : pData->aSz.Height() = nTextHeight;
2433 :
2434 0 : pData->aSz.Width() = nTextWidth + 4*nExtra;
2435 0 : aSz.Width() += pData->aSz.Width();
2436 : }
2437 : else
2438 0 : pData->aSz.Height() = Max( Max( nTextHeight, pData->aSz.Height() ), nMinMenuItemHeight );
2439 :
2440 0 : nWidth += nTextWidth;
2441 : }
2442 :
2443 : // Accel
2444 0 : if ( !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() )
2445 : {
2446 0 : String aName = pData->aAccelKey.GetName();
2447 0 : long nAccWidth = pWin->GetTextWidth( aName );
2448 0 : nAccWidth += nExtra;
2449 0 : nWidth += nAccWidth;
2450 : }
2451 :
2452 : // SubMenu?
2453 0 : if ( !bIsMenuBar && pData->pSubMenu )
2454 : {
2455 0 : if ( nFontHeight > nWidth )
2456 0 : nWidth += nFontHeight;
2457 :
2458 0 : pData->aSz.Height() = Max( Max( nFontHeight, pData->aSz.Height() ), nMinMenuItemHeight );
2459 : }
2460 :
2461 0 : pData->aSz.Height() += EXTRAITEMHEIGHT; // little bit more distance
2462 :
2463 0 : if ( !bIsMenuBar )
2464 0 : aSz.Height() += (long)pData->aSz.Height();
2465 :
2466 0 : if ( nWidth > nMaxWidth )
2467 0 : nMaxWidth = nWidth;
2468 :
2469 : }
2470 : }
2471 :
2472 236 : if ( !bIsMenuBar )
2473 : {
2474 : // popup menus should not be wider than half the screen
2475 : // except on rather small screens
2476 : // TODO: move GetScreenNumber from SystemWindow to Window ?
2477 : // currently we rely on internal privileges
2478 0 : unsigned int nDisplayScreen = pWin->ImplGetWindowImpl()->mpFrame->maGeometry.nDisplayScreenNumber;
2479 0 : Rectangle aDispRect( Application::GetScreenPosSizePixel( nDisplayScreen ) );
2480 0 : long nScreenWidth = aDispRect.GetWidth() >= 800 ? aDispRect.GetWidth() : 800;
2481 0 : if( nMaxWidth > nScreenWidth/2 )
2482 0 : nMaxWidth = nScreenWidth/2;
2483 :
2484 0 : sal_uInt16 gfxExtra = (sal_uInt16) Max( nExtra, 7L ); // #107710# increase space between checkmarks/images/text
2485 0 : nImgOrChkPos = (sal_uInt16)nExtra;
2486 0 : long nImgOrChkWidth = 0;
2487 0 : if( aMaxSize.Height() > 0 ) // NWF case
2488 0 : nImgOrChkWidth = aMaxSize.Height() + nExtra;
2489 : else // non NWF case
2490 0 : nImgOrChkWidth = nFontHeight/2 + gfxExtra;
2491 0 : nImgOrChkWidth = Max( nImgOrChkWidth, aMaxImgSz.Width() + gfxExtra );
2492 0 : nTextPos = (sal_uInt16)(nImgOrChkPos + nImgOrChkWidth);
2493 0 : nTextPos = nTextPos + gfxExtra;
2494 :
2495 0 : aSz.Width() = nTextPos + nMaxWidth + nExtra;
2496 0 : aSz.Width() += 4*nExtra; // a _little_ more ...
2497 :
2498 0 : aSz.Width() += 2*ImplGetSVData()->maNWFData.mnMenuFormatBorderX;
2499 0 : aSz.Height() += 2*ImplGetSVData()->maNWFData.mnMenuFormatBorderY;
2500 : }
2501 : else
2502 : {
2503 236 : nTextPos = (sal_uInt16)(2*nExtra);
2504 236 : aSz.Height() = nFontHeight+6;
2505 :
2506 : // get menubar height from native methods if supported
2507 236 : if( pWindow->IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
2508 : {
2509 0 : ImplControlValue aVal;
2510 0 : Rectangle aNativeBounds;
2511 0 : Rectangle aNativeContent;
2512 0 : Point tmp( 0, 0 );
2513 0 : Rectangle aCtrlRegion( tmp, Size( 100, 15 ) );
2514 0 : if( pWindow->GetNativeControlRegion( ControlType(CTRL_MENUBAR),
2515 : ControlPart(PART_ENTIRE_CONTROL),
2516 : aCtrlRegion,
2517 : ControlState(CTRL_STATE_ENABLED),
2518 : aVal,
2519 : OUString(),
2520 : aNativeBounds,
2521 0 : aNativeContent )
2522 : )
2523 : {
2524 0 : int nNativeHeight = aNativeBounds.GetHeight();
2525 0 : if( nNativeHeight > aSz.Height() )
2526 0 : aSz.Height() = nNativeHeight;
2527 0 : }
2528 : }
2529 :
2530 : // account for the size of the close button, which actually is a toolbox
2531 : // due to NWF this is variable
2532 236 : long nCloserHeight = ((MenuBarWindow*) pWindow)->MinCloseButtonSize().Height();
2533 236 : if( aSz.Height() < nCloserHeight )
2534 236 : aSz.Height() = nCloserHeight;
2535 : }
2536 :
2537 236 : if ( pLogo )
2538 0 : aSz.Width() += pLogo->aBitmap.GetSizePixel().Width();
2539 :
2540 236 : return aSz;
2541 : }
2542 :
2543 0 : static void ImplPaintCheckBackground( Window* i_pWindow, const Rectangle& i_rRect, bool i_bHighlight )
2544 : {
2545 0 : sal_Bool bNativeOk = sal_False;
2546 0 : if( i_pWindow->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
2547 : {
2548 0 : ImplControlValue aControlValue;
2549 0 : Rectangle aCtrlRegion( i_rRect );
2550 0 : ControlState nState = CTRL_STATE_PRESSED | CTRL_STATE_ENABLED;
2551 :
2552 0 : aControlValue.setTristateVal( BUTTONVALUE_ON );
2553 :
2554 : bNativeOk = i_pWindow->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON,
2555 : aCtrlRegion, nState, aControlValue,
2556 0 : rtl::OUString() );
2557 : }
2558 :
2559 0 : if( ! bNativeOk )
2560 : {
2561 0 : const StyleSettings& rSettings = i_pWindow->GetSettings().GetStyleSettings();
2562 0 : Color aColor( i_bHighlight ? rSettings.GetMenuHighlightTextColor() : rSettings.GetHighlightColor() );
2563 0 : i_pWindow->DrawSelectionBackground( i_rRect, 0, i_bHighlight, sal_True, sal_False, 2, NULL, &aColor );
2564 : }
2565 0 : }
2566 :
2567 0 : static String getShortenedString( const String& i_rLong, Window* i_pWin, long i_nMaxWidth )
2568 : {
2569 0 : xub_StrLen nPos = STRING_NOTFOUND;
2570 0 : String aNonMnem( OutputDevice::GetNonMnemonicString( i_rLong, nPos ) );
2571 0 : aNonMnem = i_pWin->GetEllipsisString( aNonMnem, i_nMaxWidth, TEXT_DRAW_CENTERELLIPSIS );
2572 : // re-insert mnemonic
2573 0 : if( nPos != STRING_NOTFOUND )
2574 : {
2575 0 : if( nPos < aNonMnem.Len() && i_rLong.GetChar(nPos+1) == aNonMnem.GetChar(nPos) )
2576 : {
2577 0 : rtl::OUStringBuffer aBuf( i_rLong.Len() );
2578 0 : aBuf.append( aNonMnem.GetBuffer(), nPos );
2579 0 : aBuf.append( sal_Unicode('~') );
2580 0 : aBuf.append( aNonMnem.GetBuffer()+nPos );
2581 0 : aNonMnem = aBuf.makeStringAndClear();
2582 : }
2583 : }
2584 0 : return aNonMnem;
2585 : }
2586 :
2587 177 : void Menu::ImplPaint( Window* pWin, sal_uInt16 nBorder, long nStartY, MenuItemData* pThisItemOnly, sal_Bool bHighlighted, bool bLayout ) const
2588 : {
2589 : // for symbols: nFontHeight x nFontHeight
2590 177 : long nFontHeight = pWin->GetTextHeight();
2591 177 : long nExtra = nFontHeight/4;
2592 :
2593 177 : long nCheckHeight = 0, nRadioHeight = 0;
2594 177 : ImplGetNativeCheckAndRadioSize( pWin, nCheckHeight, nRadioHeight );
2595 :
2596 177 : DecorationView aDecoView( pWin );
2597 177 : const StyleSettings& rSettings = pWin->GetSettings().GetStyleSettings();
2598 :
2599 177 : Point aTopLeft, aTmpPos;
2600 :
2601 177 : if ( pLogo )
2602 0 : aTopLeft.X() = pLogo->aBitmap.GetSizePixel().Width();
2603 :
2604 177 : int nOuterSpaceX = 0;
2605 177 : if( !bIsMenuBar )
2606 : {
2607 0 : nOuterSpaceX = ImplGetSVData()->maNWFData.mnMenuFormatBorderX;
2608 0 : aTopLeft.X() += nOuterSpaceX;
2609 0 : aTopLeft.Y() += ImplGetSVData()->maNWFData.mnMenuFormatBorderY;
2610 : }
2611 :
2612 177 : Size aOutSz = pWin->GetOutputSizePixel();
2613 177 : size_t nCount = pItemList->size();
2614 177 : if( bLayout )
2615 0 : mpLayoutData->m_aVisibleItemBoundRects.clear();
2616 :
2617 177 : for ( size_t n = 0; n < nCount; n++ )
2618 : {
2619 0 : MenuItemData* pData = pItemList->GetDataFromPos( n );
2620 0 : if ( ImplIsVisible( n ) && ( !pThisItemOnly || ( pData == pThisItemOnly ) ) )
2621 : {
2622 0 : if ( pThisItemOnly && bHighlighted )
2623 0 : pWin->SetTextColor( rSettings.GetMenuHighlightTextColor() );
2624 :
2625 0 : Point aPos( aTopLeft );
2626 0 : aPos.Y() += nBorder;
2627 0 : aPos.Y() += nStartY;
2628 :
2629 0 : if ( aPos.Y() >= 0 )
2630 : {
2631 0 : long nTextOffsetY = ((pData->aSz.Height()-nFontHeight)/2);
2632 0 : if( bIsMenuBar )
2633 0 : nTextOffsetY += (aOutSz.Height()-pData->aSz.Height()) / 2;
2634 0 : sal_uInt16 nTextStyle = 0;
2635 0 : sal_uInt16 nSymbolStyle = 0;
2636 0 : sal_uInt16 nImageStyle = 0;
2637 :
2638 : // submenus without items are not disabled when no items are
2639 : // contained. The application itself should check for this!
2640 : // Otherwise it could happen entries are disabled due to
2641 : // asynchronous loading
2642 0 : if ( !pData->bEnabled )
2643 : {
2644 0 : nTextStyle |= TEXT_DRAW_DISABLE;
2645 0 : nSymbolStyle |= SYMBOL_DRAW_DISABLE;
2646 0 : nImageStyle |= IMAGE_DRAW_DISABLE;
2647 : }
2648 :
2649 : // Separator
2650 0 : if ( !bLayout && !bIsMenuBar && ( pData->eType == MENUITEM_SEPARATOR ) )
2651 : {
2652 0 : bool bNativeOk = false;
2653 0 : if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP,
2654 0 : PART_MENU_SEPARATOR ) )
2655 : {
2656 0 : ControlState nState = 0;
2657 0 : if ( pData->bEnabled )
2658 0 : nState |= CTRL_STATE_ENABLED;
2659 0 : if ( bHighlighted )
2660 0 : nState |= CTRL_STATE_SELECTED;
2661 0 : Size aSz( pData->aSz );
2662 0 : aSz.Width() = aOutSz.Width() - 2*nOuterSpaceX;
2663 0 : Rectangle aItemRect( aPos, aSz );
2664 0 : MenupopupValue aVal( nTextPos-GUTTERBORDER, aItemRect );
2665 : bNativeOk = pWin->DrawNativeControl( CTRL_MENU_POPUP, PART_MENU_SEPARATOR,
2666 : aItemRect,
2667 : nState,
2668 : aVal,
2669 0 : OUString() );
2670 : }
2671 0 : if( ! bNativeOk )
2672 : {
2673 0 : aTmpPos.Y() = aPos.Y() + ((pData->aSz.Height()-2)/2);
2674 0 : aTmpPos.X() = aPos.X() + 2 + nOuterSpaceX;
2675 0 : pWin->SetLineColor( rSettings.GetShadowColor() );
2676 0 : pWin->DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpaceX, aTmpPos.Y() ) );
2677 0 : aTmpPos.Y()++;
2678 0 : pWin->SetLineColor( rSettings.GetLightColor() );
2679 0 : pWin->DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpaceX, aTmpPos.Y() ) );
2680 0 : pWin->SetLineColor();
2681 : }
2682 : }
2683 :
2684 0 : Rectangle aOuterCheckRect( Point( aPos.X()+nImgOrChkPos, aPos.Y() ), Size( pData->aSz.Height(), pData->aSz.Height() ) );
2685 0 : aOuterCheckRect.Left() += 1;
2686 0 : aOuterCheckRect.Right() -= 1;
2687 0 : aOuterCheckRect.Top() += 1;
2688 0 : aOuterCheckRect.Bottom() -= 1;
2689 :
2690 : // CheckMark
2691 0 : if ( !bLayout && !bIsMenuBar && pData->HasCheck() )
2692 : {
2693 : // draw selection transparent marker if checked
2694 : // onto that either a checkmark or the item image
2695 : // will be painted
2696 : // however do not do this if native checks will be painted since
2697 : // the selection color too often does not fit the theme's check and/or radio
2698 :
2699 0 : if( ! ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
2700 : {
2701 0 : if ( pWin->IsNativeControlSupported( CTRL_MENU_POPUP,
2702 : (pData->nBits & MIB_RADIOCHECK)
2703 : ? PART_MENU_ITEM_CHECK_MARK
2704 0 : : PART_MENU_ITEM_RADIO_MARK ) )
2705 : {
2706 : ControlPart nPart = ((pData->nBits & MIB_RADIOCHECK)
2707 : ? PART_MENU_ITEM_RADIO_MARK
2708 0 : : PART_MENU_ITEM_CHECK_MARK);
2709 :
2710 0 : ControlState nState = 0;
2711 :
2712 0 : if ( pData->bChecked )
2713 0 : nState |= CTRL_STATE_PRESSED;
2714 :
2715 0 : if ( pData->bEnabled )
2716 0 : nState |= CTRL_STATE_ENABLED;
2717 :
2718 0 : if ( bHighlighted )
2719 0 : nState |= CTRL_STATE_SELECTED;
2720 :
2721 0 : long nCtrlHeight = (pData->nBits & MIB_RADIOCHECK) ? nCheckHeight : nRadioHeight;
2722 0 : aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - nCtrlHeight)/2;
2723 0 : aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - nCtrlHeight)/2;
2724 :
2725 0 : Rectangle aCheckRect( aTmpPos, Size( nCtrlHeight, nCtrlHeight ) );
2726 0 : Size aSz( pData->aSz );
2727 0 : aSz.Width() = aOutSz.Width() - 2*nOuterSpaceX;
2728 0 : Rectangle aItemRect( aPos, aSz );
2729 0 : MenupopupValue aVal( nTextPos-GUTTERBORDER, aItemRect );
2730 : pWin->DrawNativeControl( CTRL_MENU_POPUP, nPart,
2731 : aCheckRect,
2732 : nState,
2733 : aVal,
2734 0 : OUString() );
2735 : }
2736 0 : else if ( pData->bChecked ) // by default do nothing for unchecked items
2737 : {
2738 0 : ImplPaintCheckBackground( pWin, aOuterCheckRect, pThisItemOnly && bHighlighted );
2739 :
2740 : SymbolType eSymbol;
2741 0 : Size aSymbolSize;
2742 0 : if ( pData->nBits & MIB_RADIOCHECK )
2743 : {
2744 0 : eSymbol = SYMBOL_RADIOCHECKMARK;
2745 0 : aSymbolSize = Size( nFontHeight/2, nFontHeight/2 );
2746 : }
2747 : else
2748 : {
2749 0 : eSymbol = SYMBOL_CHECKMARK;
2750 0 : aSymbolSize = Size( (nFontHeight*25)/40, nFontHeight/2 );
2751 : }
2752 0 : aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - aSymbolSize.Width())/2;
2753 0 : aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - aSymbolSize.Height())/2;
2754 0 : Rectangle aRect( aTmpPos, aSymbolSize );
2755 0 : aDecoView.DrawSymbol( aRect, eSymbol, pWin->GetTextColor(), nSymbolStyle );
2756 : }
2757 : }
2758 : }
2759 :
2760 : // Image:
2761 0 : if ( !bLayout && !bIsMenuBar && ( ( pData->eType == MENUITEM_IMAGE ) || ( pData->eType == MENUITEM_STRINGIMAGE ) ) )
2762 : {
2763 : // Don't render an image for a check thing
2764 0 : if( pData->bChecked )
2765 0 : ImplPaintCheckBackground( pWin, aOuterCheckRect, pThisItemOnly && bHighlighted );
2766 0 : aTmpPos = aOuterCheckRect.TopLeft();
2767 0 : aTmpPos.X() += (aOuterCheckRect.GetWidth()-pData->aImage.GetSizePixel().Width())/2;
2768 0 : aTmpPos.Y() += (aOuterCheckRect.GetHeight()-pData->aImage.GetSizePixel().Height())/2;
2769 0 : pWin->DrawImage( aTmpPos, pData->aImage, nImageStyle );
2770 : }
2771 :
2772 : // Text:
2773 0 : if ( ( pData->eType == MENUITEM_STRING ) || ( pData->eType == MENUITEM_STRINGIMAGE ) )
2774 : {
2775 0 : aTmpPos.X() = aPos.X() + nTextPos;
2776 0 : aTmpPos.Y() = aPos.Y();
2777 0 : aTmpPos.Y() += nTextOffsetY;
2778 0 : sal_uInt16 nStyle = nTextStyle|TEXT_DRAW_MNEMONIC;
2779 0 : if ( pData->bIsTemporary )
2780 0 : nStyle |= TEXT_DRAW_DISABLE;
2781 0 : MetricVector* pVector = bLayout ? &mpLayoutData->m_aUnicodeBoundRects : NULL;
2782 0 : String* pDisplayText = bLayout ? &mpLayoutData->m_aDisplayText : NULL;
2783 0 : if( bLayout )
2784 : {
2785 0 : mpLayoutData->m_aLineIndices.push_back( mpLayoutData->m_aDisplayText.Len() );
2786 0 : mpLayoutData->m_aLineItemIds.push_back( pData->nId );
2787 0 : mpLayoutData->m_aLineItemPositions.push_back( n );
2788 : }
2789 : // #i47946# with NWF painted menus the background is transparent
2790 : // since DrawCtrlText can depend on the background (e.g. for
2791 : // TEXT_DRAW_DISABLE), temporarily set a background which
2792 : // hopefully matches the NWF background since it is read
2793 : // from the system style settings
2794 0 : bool bSetTmpBackground = !pWin->IsBackground() && pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL );
2795 0 : if( bSetTmpBackground )
2796 : {
2797 : Color aBg = bIsMenuBar ?
2798 0 : pWin->GetSettings().GetStyleSettings().GetMenuBarColor() :
2799 0 : pWin->GetSettings().GetStyleSettings().GetMenuColor();
2800 0 : pWin->SetBackground( Wallpaper( aBg ) );
2801 : }
2802 : // how much space is there for the text ?
2803 0 : long nMaxItemTextWidth = aOutSz.Width() - aTmpPos.X() - nExtra - nOuterSpaceX;
2804 0 : if( !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() )
2805 : {
2806 0 : XubString aAccText = pData->aAccelKey.GetName();
2807 0 : nMaxItemTextWidth -= pWin->GetTextWidth( aAccText ) + 3*nExtra;
2808 : }
2809 0 : if( !bIsMenuBar && pData->pSubMenu )
2810 : {
2811 0 : nMaxItemTextWidth -= nFontHeight - nExtra;
2812 : }
2813 0 : String aItemText( getShortenedString( pData->aText, pWin, nMaxItemTextWidth ) );
2814 0 : pWin->DrawCtrlText( aTmpPos, aItemText, 0, aItemText.Len(), nStyle, pVector, pDisplayText );
2815 0 : if( bSetTmpBackground )
2816 0 : pWin->SetBackground();
2817 : }
2818 :
2819 : // Accel
2820 0 : if ( !bLayout && !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() )
2821 : {
2822 0 : XubString aAccText = pData->aAccelKey.GetName();
2823 0 : aTmpPos.X() = aOutSz.Width() - pWin->GetTextWidth( aAccText );
2824 0 : aTmpPos.X() -= 4*nExtra;
2825 :
2826 0 : aTmpPos.X() -= nOuterSpaceX;
2827 0 : aTmpPos.Y() = aPos.Y();
2828 0 : aTmpPos.Y() += nTextOffsetY;
2829 0 : pWin->DrawCtrlText( aTmpPos, aAccText, 0, aAccText.Len(), nTextStyle );
2830 : }
2831 :
2832 : // SubMenu?
2833 0 : if ( !bLayout && !bIsMenuBar && pData->pSubMenu )
2834 : {
2835 0 : bool bNativeOk = false;
2836 0 : if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP,
2837 0 : PART_MENU_SUBMENU_ARROW ) )
2838 : {
2839 0 : ControlState nState = 0;
2840 0 : Size aTmpSz( 0, 0 );
2841 0 : long aSpacing = 0;
2842 :
2843 0 : if( !ImplGetNativeSubmenuArrowSize( pWin,
2844 0 : aTmpSz, aSpacing ) )
2845 : {
2846 0 : aTmpSz = Size( nFontHeight, nFontHeight );
2847 0 : aSpacing = nOuterSpaceX;
2848 : }
2849 :
2850 0 : if ( pData->bEnabled )
2851 0 : nState |= CTRL_STATE_ENABLED;
2852 0 : if ( bHighlighted )
2853 0 : nState |= CTRL_STATE_SELECTED;
2854 :
2855 0 : aTmpPos.X() = aOutSz.Width() - aTmpSz.Width() - aSpacing - nOuterSpaceX;
2856 0 : aTmpPos.Y() = aPos.Y() + ( pData->aSz.Height() - aTmpSz.Height() ) / 2;
2857 0 : aTmpPos.Y() += nExtra/2;
2858 :
2859 0 : Rectangle aItemRect( aTmpPos, aTmpSz );
2860 0 : MenupopupValue aVal( nTextPos-GUTTERBORDER, aItemRect );
2861 : bNativeOk = pWin->DrawNativeControl( CTRL_MENU_POPUP,
2862 : PART_MENU_SUBMENU_ARROW,
2863 : aItemRect,
2864 : nState,
2865 : aVal,
2866 0 : OUString() );
2867 : }
2868 0 : if( ! bNativeOk )
2869 : {
2870 0 : aTmpPos.X() = aOutSz.Width() - nFontHeight + nExtra - nOuterSpaceX;
2871 0 : aTmpPos.Y() = aPos.Y();
2872 0 : aTmpPos.Y() += nExtra/2;
2873 0 : aTmpPos.Y() += ( pData->aSz.Height() / 2 ) - ( nFontHeight/4 );
2874 0 : if ( pData->nBits & MIB_POPUPSELECT )
2875 : {
2876 0 : pWin->SetTextColor( rSettings.GetMenuTextColor() );
2877 0 : Point aTmpPos2( aPos );
2878 0 : aTmpPos2.X() = aOutSz.Width() - nFontHeight - nFontHeight/4;
2879 : aDecoView.DrawFrame(
2880 0 : Rectangle( aTmpPos2, Size( nFontHeight+nFontHeight/4, pData->aSz.Height() ) ), FRAME_DRAW_GROUP );
2881 : }
2882 : aDecoView.DrawSymbol(
2883 : Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ),
2884 0 : SYMBOL_SPIN_RIGHT, pWin->GetTextColor(), nSymbolStyle );
2885 : }
2886 : }
2887 :
2888 0 : if ( pThisItemOnly && bHighlighted )
2889 : {
2890 : // This restores the normal menu or menu bar text
2891 : // color for when it is no longer highlighted.
2892 0 : if ( bIsMenuBar )
2893 0 : pWin->SetTextColor( rSettings.GetMenuBarTextColor() );
2894 : else
2895 0 : pWin->SetTextColor( rSettings.GetMenuTextColor() );
2896 : }
2897 : }
2898 0 : if( bLayout )
2899 : {
2900 0 : if ( !bIsMenuBar )
2901 0 : mpLayoutData->m_aVisibleItemBoundRects[ n ] = Rectangle( aTopLeft, Size( aOutSz.Width(), pData->aSz.Height() ) );
2902 : else
2903 0 : mpLayoutData->m_aVisibleItemBoundRects[ n ] = Rectangle( aTopLeft, pData->aSz );
2904 : }
2905 : }
2906 :
2907 0 : if ( !bIsMenuBar )
2908 : {
2909 0 : aTopLeft.Y() += pData->aSz.Height();
2910 : }
2911 : else
2912 : {
2913 0 : aTopLeft.X() += pData->aSz.Width();
2914 : }
2915 : }
2916 :
2917 177 : if ( !bLayout && !pThisItemOnly && pLogo )
2918 : {
2919 0 : Size aLogoSz = pLogo->aBitmap.GetSizePixel();
2920 :
2921 0 : Rectangle aRect( Point( 0, 0 ), Point( aLogoSz.Width()-1, aOutSz.Height() ) );
2922 0 : if ( pWin->GetColorCount() >= 256 )
2923 : {
2924 0 : Gradient aGrad( GradientStyle_LINEAR, pLogo->aStartColor, pLogo->aEndColor );
2925 0 : aGrad.SetAngle( 1800 );
2926 0 : aGrad.SetBorder( 15 );
2927 0 : pWin->DrawGradient( aRect, aGrad );
2928 : }
2929 : else
2930 : {
2931 0 : pWin->SetFillColor( pLogo->aStartColor );
2932 0 : pWin->DrawRect( aRect );
2933 : }
2934 :
2935 0 : Point aLogoPos( 0, aOutSz.Height() - aLogoSz.Height() );
2936 0 : pLogo->aBitmap.Draw( pWin, aLogoPos );
2937 : }
2938 177 : }
2939 :
2940 0 : Menu* Menu::ImplGetStartMenu()
2941 : {
2942 0 : Menu* pStart = this;
2943 0 : while ( pStart && pStart->pStartedFrom && ( pStart->pStartedFrom != pStart ) )
2944 0 : pStart = pStart->pStartedFrom;
2945 0 : return pStart;
2946 : }
2947 :
2948 0 : void Menu::ImplCallHighlight( sal_uInt16 nHighlightedItem )
2949 : {
2950 0 : ImplMenuDelData aDelData( this );
2951 :
2952 0 : nSelectedId = 0;
2953 0 : MenuItemData* pData = pItemList->GetDataFromPos( nHighlightedItem );
2954 0 : if ( pData )
2955 0 : nSelectedId = pData->nId;
2956 0 : ImplCallEventListeners( VCLEVENT_MENU_HIGHLIGHT, GetItemPos( GetCurItemId() ) );
2957 :
2958 0 : if( !aDelData.isDeleted() )
2959 : {
2960 0 : Highlight();
2961 0 : nSelectedId = 0;
2962 0 : }
2963 0 : }
2964 :
2965 0 : IMPL_LINK_NOARG(Menu, ImplCallSelect)
2966 : {
2967 0 : nEventId = 0;
2968 0 : Select();
2969 0 : return 0;
2970 : }
2971 :
2972 0 : Menu* Menu::ImplFindSelectMenu()
2973 : {
2974 0 : Menu* pSelMenu = nEventId ? this : NULL;
2975 :
2976 0 : for ( size_t n = GetItemList()->size(); n && !pSelMenu; )
2977 : {
2978 0 : MenuItemData* pData = GetItemList()->GetDataFromPos( --n );
2979 :
2980 0 : if ( pData->pSubMenu )
2981 0 : pSelMenu = pData->pSubMenu->ImplFindSelectMenu();
2982 : }
2983 :
2984 0 : return pSelMenu;
2985 : }
2986 :
2987 0 : Menu* Menu::ImplFindMenu( sal_uInt16 nItemId )
2988 : {
2989 0 : Menu* pSelMenu = NULL;
2990 :
2991 0 : for ( size_t n = GetItemList()->size(); n && !pSelMenu; )
2992 : {
2993 0 : MenuItemData* pData = GetItemList()->GetDataFromPos( --n );
2994 :
2995 0 : if( pData->nId == nItemId )
2996 0 : pSelMenu = this;
2997 0 : else if ( pData->pSubMenu )
2998 0 : pSelMenu = pData->pSubMenu->ImplFindMenu( nItemId );
2999 : }
3000 :
3001 0 : return pSelMenu;
3002 : }
3003 :
3004 0 : void Menu::RemoveDisabledEntries( sal_Bool bCheckPopups, sal_Bool bRemoveEmptyPopups )
3005 : {
3006 0 : for ( sal_uInt16 n = 0; n < GetItemCount(); n++ )
3007 : {
3008 0 : sal_Bool bRemove = sal_False;
3009 0 : MenuItemData* pItem = pItemList->GetDataFromPos( n );
3010 0 : if ( pItem->eType == MENUITEM_SEPARATOR )
3011 : {
3012 0 : if ( !n || ( GetItemType( n-1 ) == MENUITEM_SEPARATOR ) )
3013 0 : bRemove = sal_True;
3014 : }
3015 : else
3016 0 : bRemove = !pItem->bEnabled;
3017 :
3018 0 : if ( bCheckPopups && pItem->pSubMenu )
3019 : {
3020 0 : pItem->pSubMenu->RemoveDisabledEntries( sal_True );
3021 0 : if ( bRemoveEmptyPopups && !pItem->pSubMenu->GetItemCount() )
3022 0 : bRemove = sal_True;
3023 : }
3024 :
3025 0 : if ( bRemove )
3026 0 : RemoveItem( n-- );
3027 : }
3028 :
3029 0 : if ( GetItemCount() )
3030 : {
3031 0 : sal_uInt16 nLast = GetItemCount() - 1;
3032 0 : MenuItemData* pItem = pItemList->GetDataFromPos( nLast );
3033 0 : if ( pItem->eType == MENUITEM_SEPARATOR )
3034 0 : RemoveItem( nLast );
3035 : }
3036 0 : delete mpLayoutData, mpLayoutData = NULL;
3037 0 : }
3038 :
3039 0 : sal_Bool Menu::HasValidEntries( sal_Bool bCheckPopups )
3040 : {
3041 0 : sal_Bool bValidEntries = sal_False;
3042 0 : sal_uInt16 nCount = GetItemCount();
3043 0 : for ( sal_uInt16 n = 0; !bValidEntries && ( n < nCount ); n++ )
3044 : {
3045 0 : MenuItemData* pItem = pItemList->GetDataFromPos( n );
3046 0 : if ( pItem->bEnabled && ( pItem->eType != MENUITEM_SEPARATOR ) )
3047 : {
3048 0 : if ( bCheckPopups && pItem->pSubMenu )
3049 0 : bValidEntries = pItem->pSubMenu->HasValidEntries( sal_True );
3050 : else
3051 0 : bValidEntries = sal_True;
3052 : }
3053 : }
3054 0 : return bValidEntries;
3055 : }
3056 :
3057 0 : void Menu::SetLogo( const MenuLogo& rLogo )
3058 : {
3059 0 : delete pLogo;
3060 0 : pLogo = new MenuLogo( rLogo );
3061 0 : }
3062 :
3063 0 : void Menu::SetLogo()
3064 : {
3065 0 : delete pLogo;
3066 0 : pLogo = NULL;
3067 0 : }
3068 :
3069 0 : MenuLogo Menu::GetLogo() const
3070 : {
3071 0 : MenuLogo aLogo;
3072 0 : if ( pLogo )
3073 0 : aLogo = *pLogo;
3074 0 : return aLogo;
3075 : }
3076 :
3077 582 : void Menu::ImplKillLayoutData() const
3078 : {
3079 582 : delete mpLayoutData, mpLayoutData = NULL;
3080 582 : }
3081 :
3082 0 : void Menu::ImplFillLayoutData() const
3083 : {
3084 0 : if( pWindow && pWindow->IsReallyVisible() )
3085 : {
3086 0 : mpLayoutData = new MenuLayoutData();
3087 0 : if( bIsMenuBar )
3088 : {
3089 0 : ImplPaint( pWindow, 0, 0, 0, sal_False, true );
3090 : }
3091 : else
3092 : {
3093 0 : MenuFloatingWindow* pFloat = (MenuFloatingWindow*)pWindow;
3094 0 : ImplPaint( pWindow, pFloat->nScrollerHeight, pFloat->ImplGetStartY(), 0, sal_False, true );
3095 : }
3096 : }
3097 0 : }
3098 :
3099 0 : Rectangle Menu::GetCharacterBounds( sal_uInt16 nItemID, long nIndex ) const
3100 : {
3101 0 : long nItemIndex = -1;
3102 0 : if( ! mpLayoutData )
3103 0 : ImplFillLayoutData();
3104 0 : if( mpLayoutData )
3105 : {
3106 0 : for( size_t i = 0; i < mpLayoutData->m_aLineItemIds.size(); i++ )
3107 : {
3108 0 : if( mpLayoutData->m_aLineItemIds[i] == nItemID )
3109 : {
3110 0 : nItemIndex = mpLayoutData->m_aLineIndices[i];
3111 0 : break;
3112 : }
3113 : }
3114 : }
3115 0 : return (mpLayoutData && nItemIndex != -1) ? mpLayoutData->GetCharacterBounds( nItemIndex+nIndex ) : Rectangle();
3116 : }
3117 :
3118 :
3119 0 : long Menu::GetIndexForPoint( const Point& rPoint, sal_uInt16& rItemID ) const
3120 : {
3121 0 : long nIndex = -1;
3122 0 : rItemID = 0;
3123 0 : if( ! mpLayoutData )
3124 0 : ImplFillLayoutData();
3125 0 : if( mpLayoutData )
3126 : {
3127 0 : nIndex = mpLayoutData->GetIndexForPoint( rPoint );
3128 0 : for( size_t i = 0; i < mpLayoutData->m_aLineIndices.size(); i++ )
3129 : {
3130 0 : if( mpLayoutData->m_aLineIndices[i] <= nIndex &&
3131 0 : (i == mpLayoutData->m_aLineIndices.size()-1 || mpLayoutData->m_aLineIndices[i+1] > nIndex) )
3132 : {
3133 : // make index relative to item
3134 0 : nIndex -= mpLayoutData->m_aLineIndices[i];
3135 0 : rItemID = mpLayoutData->m_aLineItemIds[i];
3136 0 : break;
3137 : }
3138 : }
3139 : }
3140 0 : return nIndex;
3141 : }
3142 :
3143 0 : Rectangle Menu::GetBoundingRectangle( sal_uInt16 nPos ) const
3144 : {
3145 0 : Rectangle aRet;
3146 :
3147 0 : if( ! mpLayoutData )
3148 0 : ImplFillLayoutData();
3149 0 : if( mpLayoutData )
3150 : {
3151 0 : std::map< sal_uInt16, Rectangle >::const_iterator it = mpLayoutData->m_aVisibleItemBoundRects.find( nPos );
3152 0 : if( it != mpLayoutData->m_aVisibleItemBoundRects.end() )
3153 0 : aRet = it->second;
3154 : }
3155 0 : return aRet;
3156 : }
3157 :
3158 0 : void Menu::SetAccessibleName( sal_uInt16 nItemId, const XubString& rStr )
3159 : {
3160 : size_t nPos;
3161 0 : MenuItemData* pData = pItemList->GetData( nItemId, nPos );
3162 :
3163 0 : if ( pData && !rStr.Equals( pData->aAccessibleName ) )
3164 : {
3165 0 : pData->aAccessibleName = rStr;
3166 0 : ImplCallEventListeners( VCLEVENT_MENU_ACCESSIBLENAMECHANGED, nPos );
3167 : }
3168 0 : }
3169 :
3170 0 : XubString Menu::GetAccessibleName( sal_uInt16 nItemId ) const
3171 : {
3172 0 : MenuItemData* pData = pItemList->GetData( nItemId );
3173 :
3174 0 : if ( pData )
3175 0 : return pData->aAccessibleName;
3176 : else
3177 0 : return ImplGetSVEmptyStr();
3178 : }
3179 :
3180 556 : void Menu::ImplSetSalMenu( SalMenu *pSalMenu )
3181 : {
3182 556 : if( mpSalMenu )
3183 0 : ImplGetSVData()->mpDefInst->DestroyMenu( mpSalMenu );
3184 556 : mpSalMenu = pSalMenu;
3185 556 : }
3186 :
3187 0 : sal_Bool Menu::GetSystemMenuData( SystemMenuData* pData ) const
3188 : {
3189 0 : Menu* pMenu = (Menu*)this;
3190 0 : if( pData && pMenu->ImplGetSalMenu() )
3191 : {
3192 0 : pMenu->ImplGetSalMenu()->GetSystemMenuData( pData );
3193 0 : return sal_True;
3194 : }
3195 : else
3196 0 : return sal_False;
3197 : }
3198 :
3199 0 : bool Menu::IsHighlighted( sal_uInt16 nItemPos ) const
3200 : {
3201 0 : bool bRet = false;
3202 :
3203 0 : if( pWindow )
3204 : {
3205 0 : if( bIsMenuBar )
3206 0 : bRet = ( nItemPos == static_cast< MenuBarWindow * > (pWindow)->GetHighlightedItem() );
3207 : else
3208 0 : bRet = ( nItemPos == static_cast< MenuFloatingWindow * > (pWindow)->GetHighlightedItem() );
3209 : }
3210 :
3211 0 : return bRet;
3212 : }
3213 :
3214 0 : void Menu::HighlightItem( sal_uInt16 nItemPos )
3215 : {
3216 0 : if ( pWindow )
3217 : {
3218 0 : if ( bIsMenuBar )
3219 : {
3220 0 : MenuBarWindow* pMenuWin = static_cast< MenuBarWindow* >( pWindow );
3221 0 : pMenuWin->SetAutoPopup( sal_False );
3222 0 : pMenuWin->ChangeHighlightItem( nItemPos, sal_False );
3223 : }
3224 : else
3225 : {
3226 0 : static_cast< MenuFloatingWindow* >( pWindow )->ChangeHighlightItem( nItemPos, sal_False );
3227 : }
3228 : }
3229 0 : }
3230 :
3231 :
3232 : // -----------
3233 : // - MenuBar -
3234 : // -----------
3235 :
3236 236 : MenuBar::MenuBar() : Menu( sal_True )
3237 : {
3238 236 : mbDisplayable = sal_True;
3239 236 : mbCloserVisible = sal_False;
3240 236 : mbFloatBtnVisible = sal_False;
3241 236 : mbHideBtnVisible = sal_False;
3242 236 : }
3243 :
3244 0 : MenuBar::MenuBar( const MenuBar& rMenu ) : Menu( sal_True )
3245 : {
3246 0 : mbDisplayable = sal_True;
3247 0 : mbCloserVisible = sal_False;
3248 0 : mbFloatBtnVisible = sal_False;
3249 0 : mbHideBtnVisible = sal_False;
3250 0 : *this = rMenu;
3251 0 : bIsMenuBar = sal_True;
3252 0 : }
3253 :
3254 189 : MenuBar::~MenuBar()
3255 : {
3256 63 : ImplDestroy( this, sal_True );
3257 126 : }
3258 :
3259 253 : void MenuBar::ShowCloser( sal_Bool bShow )
3260 : {
3261 253 : ShowButtons( bShow, mbFloatBtnVisible, mbHideBtnVisible );
3262 253 : }
3263 :
3264 253 : void MenuBar::ShowButtons( sal_Bool bClose, sal_Bool bFloat, sal_Bool bHide )
3265 : {
3266 253 : if ( (bClose != mbCloserVisible) ||
3267 : (bFloat != mbFloatBtnVisible) ||
3268 : (bHide != mbHideBtnVisible) )
3269 : {
3270 25 : mbCloserVisible = bClose;
3271 25 : mbFloatBtnVisible = bFloat;
3272 25 : mbHideBtnVisible = bHide;
3273 25 : if ( ImplGetWindow() )
3274 25 : ((MenuBarWindow*)ImplGetWindow())->ShowButtons( bClose, bFloat, bHide );
3275 : }
3276 253 : }
3277 :
3278 236 : void MenuBar::SetDisplayable( sal_Bool bDisplayable )
3279 : {
3280 236 : if( bDisplayable != mbDisplayable )
3281 : {
3282 0 : mbDisplayable = bDisplayable;
3283 0 : MenuBarWindow* pMenuWin = (MenuBarWindow*) ImplGetWindow();
3284 0 : if( pMenuWin )
3285 0 : pMenuWin->ImplLayoutChanged();
3286 : }
3287 236 : }
3288 :
3289 236 : Window* MenuBar::ImplCreate( Window* pParent, Window* pWindow, MenuBar* pMenu )
3290 : {
3291 236 : if ( !pWindow )
3292 236 : pWindow = new MenuBarWindow( pParent );
3293 :
3294 236 : pMenu->pStartedFrom = 0;
3295 236 : pMenu->pWindow = pWindow;
3296 236 : ((MenuBarWindow*)pWindow)->SetMenu( pMenu );
3297 236 : long nHeight = pMenu->ImplCalcSize( pWindow ).Height();
3298 :
3299 : // depending on the native implementation or the displayable flag
3300 : // the menubar windows is supressed (ie, height=0)
3301 472 : if( !((MenuBar*) pMenu)->IsDisplayable() ||
3302 236 : ( pMenu->ImplGetSalMenu() && pMenu->ImplGetSalMenu()->VisibleMenuBar() ) )
3303 0 : nHeight = 0;
3304 :
3305 236 : pWindow->setPosSizePixel( 0, 0, 0, nHeight, WINDOW_POSSIZE_HEIGHT );
3306 236 : return pWindow;
3307 : }
3308 :
3309 126 : void MenuBar::ImplDestroy( MenuBar* pMenu, sal_Bool bDelete )
3310 : {
3311 126 : MenuBarWindow* pWindow = (MenuBarWindow*) pMenu->ImplGetWindow();
3312 126 : if ( pWindow && bDelete )
3313 : {
3314 63 : pWindow->KillActivePopup();
3315 63 : delete pWindow;
3316 : }
3317 126 : pMenu->pWindow = NULL;
3318 126 : }
3319 :
3320 0 : sal_Bool MenuBar::ImplHandleKeyEvent( const KeyEvent& rKEvent, sal_Bool bFromMenu )
3321 : {
3322 0 : sal_Bool bDone = sal_False;
3323 :
3324 : // No keyboard processing when system handles the menu or our menubar is invisible
3325 0 : if( !IsDisplayable() ||
3326 0 : ( ImplGetSalMenu() && ImplGetSalMenu()->VisibleMenuBar() ) )
3327 0 : return bDone;
3328 :
3329 : // check for enabled, if this method is called from another window...
3330 0 : Window* pWin = ImplGetWindow();
3331 0 : if ( pWin && pWin->IsEnabled() && pWin->IsInputEnabled() && ! pWin->IsInModalMode() )
3332 0 : bDone = ((MenuBarWindow*)pWin)->ImplHandleKeyEvent( rKEvent, bFromMenu );
3333 0 : return bDone;
3334 : }
3335 :
3336 : // -----------------------------------------------------------------------
3337 :
3338 0 : void MenuBar::SelectEntry( sal_uInt16 nId )
3339 : {
3340 0 : MenuBarWindow* pMenuWin = (MenuBarWindow*) ImplGetWindow();
3341 :
3342 0 : if( pMenuWin )
3343 : {
3344 0 : pMenuWin->GrabFocus();
3345 0 : nId = GetItemPos( nId );
3346 :
3347 : // #99705# popup the selected menu
3348 0 : pMenuWin->SetAutoPopup( sal_True );
3349 0 : if( ITEMPOS_INVALID != pMenuWin->nHighlightedItem )
3350 : {
3351 0 : pMenuWin->KillActivePopup();
3352 0 : pMenuWin->ChangeHighlightItem( ITEMPOS_INVALID, sal_False );
3353 : }
3354 0 : if( nId != ITEMPOS_INVALID )
3355 0 : pMenuWin->ChangeHighlightItem( nId, sal_False );
3356 : }
3357 0 : }
3358 :
3359 : // -----------------------------------------------------------------------
3360 :
3361 : // handler for native menu selection and command events
3362 :
3363 0 : sal_Bool MenuBar::HandleMenuActivateEvent( Menu *pMenu ) const
3364 : {
3365 0 : if( pMenu )
3366 : {
3367 0 : ImplMenuDelData aDelData( this );
3368 :
3369 0 : pMenu->pStartedFrom = (Menu*)this;
3370 0 : pMenu->bInCallback = sal_True;
3371 0 : pMenu->Activate();
3372 :
3373 0 : if( !aDelData.isDeleted() )
3374 0 : pMenu->bInCallback = sal_False;
3375 : }
3376 0 : return sal_True;
3377 : }
3378 :
3379 0 : sal_Bool MenuBar::HandleMenuDeActivateEvent( Menu *pMenu ) const
3380 : {
3381 0 : if( pMenu )
3382 : {
3383 0 : ImplMenuDelData aDelData( this );
3384 :
3385 0 : pMenu->pStartedFrom = (Menu*)this;
3386 0 : pMenu->bInCallback = sal_True;
3387 0 : pMenu->Deactivate();
3388 0 : if( !aDelData.isDeleted() )
3389 0 : pMenu->bInCallback = sal_False;
3390 : }
3391 0 : return sal_True;
3392 : }
3393 :
3394 0 : sal_Bool MenuBar::HandleMenuHighlightEvent( Menu *pMenu, sal_uInt16 nHighlightEventId ) const
3395 : {
3396 0 : if( !pMenu )
3397 0 : pMenu = ((Menu*) this)->ImplFindMenu( nHighlightEventId );
3398 0 : if( pMenu )
3399 : {
3400 0 : ImplMenuDelData aDelData( pMenu );
3401 :
3402 0 : if( mnHighlightedItemPos != ITEMPOS_INVALID )
3403 0 : pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, mnHighlightedItemPos );
3404 :
3405 0 : if( !aDelData.isDeleted() )
3406 : {
3407 0 : pMenu->mnHighlightedItemPos = pMenu->GetItemPos( nHighlightEventId );
3408 0 : pMenu->nSelectedId = nHighlightEventId;
3409 0 : pMenu->pStartedFrom = (Menu*)this;
3410 0 : pMenu->ImplCallHighlight( pMenu->mnHighlightedItemPos );
3411 : }
3412 0 : return sal_True;
3413 : }
3414 : else
3415 0 : return sal_False;
3416 : }
3417 :
3418 0 : sal_Bool MenuBar::HandleMenuCommandEvent( Menu *pMenu, sal_uInt16 nCommandEventId ) const
3419 : {
3420 0 : if( !pMenu )
3421 0 : pMenu = ((Menu*) this)->ImplFindMenu( nCommandEventId );
3422 0 : if( pMenu )
3423 : {
3424 0 : pMenu->nSelectedId = nCommandEventId;
3425 0 : pMenu->pStartedFrom = (Menu*)this;
3426 0 : pMenu->ImplSelect();
3427 0 : return sal_True;
3428 : }
3429 : else
3430 0 : return sal_False;
3431 : }
3432 :
3433 0 : sal_uInt16 MenuBar::AddMenuBarButton( const Image& i_rImage, const Link& i_rLink, const String& i_rToolTip, sal_uInt16 i_nPos )
3434 : {
3435 0 : return pWindow ? static_cast<MenuBarWindow*>(pWindow)->AddMenuBarButton( i_rImage, i_rLink, i_rToolTip, i_nPos ) : 0;
3436 : }
3437 :
3438 0 : void MenuBar::SetMenuBarButtonHighlightHdl( sal_uInt16 nId, const Link& rLink )
3439 : {
3440 0 : if( pWindow )
3441 0 : static_cast<MenuBarWindow*>(pWindow)->SetMenuBarButtonHighlightHdl( nId, rLink );
3442 0 : }
3443 :
3444 0 : Rectangle MenuBar::GetMenuBarButtonRectPixel( sal_uInt16 nId )
3445 : {
3446 0 : return pWindow ? static_cast<MenuBarWindow*>(pWindow)->GetMenuBarButtonRectPixel( nId ) : Rectangle();
3447 : }
3448 :
3449 0 : void MenuBar::RemoveMenuBarButton( sal_uInt16 nId )
3450 : {
3451 0 : if( pWindow )
3452 0 : static_cast<MenuBarWindow*>(pWindow)->RemoveMenuBarButton( nId );
3453 0 : }
3454 :
3455 0 : sal_Bool MenuBar::HandleMenuButtonEvent( Menu *, sal_uInt16 i_nButtonId ) const
3456 : {
3457 0 : return static_cast<MenuBarWindow*>(pWindow)->HandleMenuButtonEvent( i_nButtonId );
3458 : }
3459 :
3460 : // -----------------------------------------------------------------------
3461 :
3462 : // sal_Bool PopupMenu::bAnyPopupInExecute = sal_False;
3463 :
3464 1203 : PopupMenu::PopupMenu()
3465 : {
3466 1203 : pRefAutoSubMenu = NULL;
3467 1203 : }
3468 :
3469 19 : PopupMenu::PopupMenu( const ResId& rResId )
3470 : {
3471 19 : pRefAutoSubMenu = NULL;
3472 19 : ImplLoadRes( rResId );
3473 19 : }
3474 :
3475 0 : PopupMenu::PopupMenu( const PopupMenu& rMenu ) : Menu()
3476 : {
3477 0 : pRefAutoSubMenu = NULL;
3478 0 : *this = rMenu;
3479 0 : }
3480 :
3481 1479 : PopupMenu::~PopupMenu()
3482 : {
3483 493 : if( pRefAutoSubMenu && *pRefAutoSubMenu == this )
3484 0 : *pRefAutoSubMenu = NULL; // #111060# avoid second delete in ~MenuItemData
3485 986 : }
3486 :
3487 0 : sal_Bool PopupMenu::IsInExecute()
3488 : {
3489 0 : return GetActivePopupMenu() ? sal_True : sal_False;
3490 : }
3491 :
3492 0 : PopupMenu* PopupMenu::GetActivePopupMenu()
3493 : {
3494 0 : ImplSVData* pSVData = ImplGetSVData();
3495 0 : return pSVData->maAppData.mpActivePopupMenu;
3496 : }
3497 :
3498 0 : void PopupMenu::EndExecute( sal_uInt16 nSelectId )
3499 : {
3500 0 : if ( ImplGetWindow() )
3501 0 : ImplGetFloatingWindow()->EndExecute( nSelectId );
3502 0 : }
3503 :
3504 0 : void PopupMenu::SelectEntry( sal_uInt16 nId )
3505 : {
3506 0 : if ( ImplGetWindow() )
3507 : {
3508 0 : if( nId != ITEMPOS_INVALID )
3509 : {
3510 0 : size_t nPos = 0;
3511 0 : MenuItemData* pData = GetItemList()->GetData( nId, nPos );
3512 0 : if ( pData->pSubMenu )
3513 0 : ImplGetFloatingWindow()->ChangeHighlightItem( nPos, sal_True );
3514 : else
3515 0 : ImplGetFloatingWindow()->EndExecute( nId );
3516 : }
3517 : else
3518 : {
3519 0 : MenuFloatingWindow* pFloat = ImplGetFloatingWindow();
3520 0 : pFloat->GrabFocus();
3521 :
3522 0 : for( size_t nPos = 0; nPos < GetItemList()->size(); nPos++ )
3523 : {
3524 0 : MenuItemData* pData = GetItemList()->GetDataFromPos( nPos );
3525 0 : if( pData->pSubMenu )
3526 : {
3527 0 : pFloat->KillActivePopup();
3528 : }
3529 : }
3530 0 : pFloat->ChangeHighlightItem( ITEMPOS_INVALID, sal_False );
3531 : }
3532 : }
3533 0 : }
3534 :
3535 0 : void PopupMenu::SetSelectedEntry( sal_uInt16 nId )
3536 : {
3537 0 : nSelectedId = nId;
3538 0 : }
3539 :
3540 0 : sal_uInt16 PopupMenu::Execute( Window* pExecWindow, const Point& rPopupPos )
3541 : {
3542 0 : return Execute( pExecWindow, Rectangle( rPopupPos, rPopupPos ), POPUPMENU_EXECUTE_DOWN );
3543 : }
3544 :
3545 0 : sal_uInt16 PopupMenu::Execute( Window* pExecWindow, const Rectangle& rRect, sal_uInt16 nFlags )
3546 : {
3547 0 : ENSURE_OR_RETURN( pExecWindow, "PopupMenu::Execute: need a non-NULL window!", 0 );
3548 :
3549 :
3550 0 : sal_uLong nPopupModeFlags = 0;
3551 0 : if ( nFlags & POPUPMENU_EXECUTE_DOWN )
3552 0 : nPopupModeFlags = FLOATWIN_POPUPMODE_DOWN;
3553 0 : else if ( nFlags & POPUPMENU_EXECUTE_UP )
3554 0 : nPopupModeFlags = FLOATWIN_POPUPMODE_UP;
3555 0 : else if ( nFlags & POPUPMENU_EXECUTE_LEFT )
3556 0 : nPopupModeFlags = FLOATWIN_POPUPMODE_LEFT;
3557 0 : else if ( nFlags & POPUPMENU_EXECUTE_RIGHT )
3558 0 : nPopupModeFlags = FLOATWIN_POPUPMODE_RIGHT;
3559 : else
3560 0 : nPopupModeFlags = FLOATWIN_POPUPMODE_DOWN;
3561 :
3562 0 : if (nFlags & POPUPMENU_NOMOUSEUPCLOSE ) // allow popup menus to stay open on mouse button up
3563 0 : nPopupModeFlags |= FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE; // useful if the menu was opened on mousebutton down (eg toolbox configuration)
3564 :
3565 0 : return ImplExecute( pExecWindow, rRect, nPopupModeFlags, 0, sal_False );
3566 : }
3567 :
3568 0 : sal_uInt16 PopupMenu::ImplExecute( Window* pW, const Rectangle& rRect, sal_uLong nPopupModeFlags, Menu* pSFrom, sal_Bool bPreSelectFirst )
3569 : {
3570 0 : if ( !pSFrom && ( PopupMenu::IsInExecute() || !GetItemCount() ) )
3571 0 : return 0;
3572 :
3573 0 : delete mpLayoutData, mpLayoutData = NULL;
3574 :
3575 0 : ImplSVData* pSVData = ImplGetSVData();
3576 :
3577 0 : pStartedFrom = pSFrom;
3578 0 : nSelectedId = 0;
3579 0 : bCanceled = sal_False;
3580 :
3581 0 : sal_uLong nFocusId = 0;
3582 0 : sal_Bool bRealExecute = sal_False;
3583 0 : if ( !pStartedFrom )
3584 : {
3585 0 : pSVData->maWinData.mbNoDeactivate = sal_True;
3586 0 : nFocusId = Window::SaveFocus();
3587 0 : bRealExecute = sal_True;
3588 : }
3589 : else
3590 : {
3591 : // assure that only one menu is open at a time
3592 0 : if( pStartedFrom->bIsMenuBar && pSVData->maWinData.mpFirstFloat )
3593 0 : pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
3594 : }
3595 :
3596 : DBG_ASSERT( !ImplGetWindow(), "Win?!" );
3597 0 : Rectangle aRect( rRect );
3598 0 : aRect.SetPos( pW->OutputToScreenPixel( aRect.TopLeft() ) );
3599 :
3600 0 : WinBits nStyle = WB_BORDER;
3601 0 : if ( bRealExecute )
3602 0 : nPopupModeFlags |= FLOATWIN_POPUPMODE_NEWLEVEL;
3603 0 : if ( !pStartedFrom || !pStartedFrom->bIsMenuBar )
3604 0 : nPopupModeFlags |= FLOATWIN_POPUPMODE_PATHMOUSECANCELCLICK | FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE;
3605 :
3606 0 : nPopupModeFlags |= FLOATWIN_POPUPMODE_NOKEYCLOSE;
3607 :
3608 : // could be usefull during debugging.
3609 : // nPopupModeFlags |= FLOATWIN_POPUPMODE_NOFOCUSCLOSE;
3610 :
3611 0 : ImplDelData aDelData;
3612 0 : pW->ImplAddDel( &aDelData );
3613 :
3614 0 : bInCallback = sal_True; // set it here, if Activate overloaded
3615 0 : Activate();
3616 0 : bInCallback = sal_False;
3617 :
3618 0 : if ( aDelData.IsDead() )
3619 0 : return 0; // Error
3620 :
3621 0 : pW->ImplRemoveDel( &aDelData );
3622 :
3623 0 : if ( bCanceled || bKilled )
3624 0 : return 0;
3625 :
3626 0 : if ( !GetItemCount() )
3627 0 : return 0;
3628 :
3629 : // The flag MENU_FLAG_HIDEDISABLEDENTRIES is inherited.
3630 0 : if ( pSFrom )
3631 : {
3632 0 : if ( pSFrom->nMenuFlags & MENU_FLAG_HIDEDISABLEDENTRIES )
3633 0 : nMenuFlags |= MENU_FLAG_HIDEDISABLEDENTRIES;
3634 : else
3635 0 : nMenuFlags &= ~MENU_FLAG_HIDEDISABLEDENTRIES;
3636 : }
3637 : else
3638 : // #102790# context menus shall never show disabled entries
3639 0 : nMenuFlags |= MENU_FLAG_HIDEDISABLEDENTRIES;
3640 :
3641 :
3642 0 : sal_uInt16 nVisibleEntries = ImplGetVisibleItemCount();
3643 0 : if ( !nVisibleEntries )
3644 : {
3645 0 : ResMgr* pResMgr = ImplGetResMgr();
3646 0 : if( pResMgr )
3647 : {
3648 0 : rtl::OUString aTmpEntryText( ResId( SV_RESID_STRING_NOSELECTIONPOSSIBLE, *pResMgr ) );
3649 : MenuItemData* pData = pItemList->Insert(
3650 0 : 0xFFFF, MENUITEM_STRING, 0, aTmpEntryText, Image(), NULL, 0xFFFF );
3651 0 : pData->bIsTemporary = sal_True;
3652 : }
3653 : }
3654 0 : else if ( Application::GetSettings().GetStyleSettings().GetAutoMnemonic() && !( nMenuFlags & MENU_FLAG_NOAUTOMNEMONICS ) )
3655 : {
3656 0 : CreateAutoMnemonics();
3657 : }
3658 :
3659 0 : MenuFloatingWindow* pWin = new MenuFloatingWindow( this, pW, nStyle | WB_SYSTEMWINDOW );
3660 0 : if( pSVData->maNWFData.mbFlatMenu )
3661 0 : pWin->SetBorderStyle( WINDOW_BORDER_NOBORDER );
3662 : else
3663 0 : pWin->SetBorderStyle( pWin->GetBorderStyle() | WINDOW_BORDER_MENU );
3664 0 : pWindow = pWin;
3665 :
3666 0 : Size aSz = ImplCalcSize( pWin );
3667 :
3668 0 : long nMaxHeight = pWin->GetDesktopRectPixel().GetHeight();
3669 0 : if( Application::GetScreenCount() > 1 && Application::IsUnifiedDisplay() )
3670 : {
3671 0 : Window* pDeskW = pWindow->GetWindow( WINDOW_REALPARENT );
3672 0 : if( ! pDeskW )
3673 0 : pDeskW = pWindow;
3674 0 : Point aDesktopTL( pDeskW->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) );
3675 : nMaxHeight = Application::GetWorkAreaPosSizePixel(
3676 : Application::GetBestScreen( Rectangle( aDesktopTL, aRect.GetSize() ) )
3677 0 : ).GetHeight();
3678 : }
3679 0 : if ( pStartedFrom && pStartedFrom->bIsMenuBar )
3680 0 : nMaxHeight -= pW->GetSizePixel().Height();
3681 : sal_Int32 nLeft, nTop, nRight, nBottom;
3682 0 : pWindow->GetBorder( nLeft, nTop, nRight, nBottom );
3683 0 : nMaxHeight -= nTop+nBottom;
3684 0 : if ( aSz.Height() > nMaxHeight )
3685 : {
3686 0 : pWin->EnableScrollMenu( sal_True );
3687 0 : sal_uInt16 nStart = ImplGetFirstVisible();
3688 0 : sal_uInt16 nEntries = ImplCalcVisEntries( nMaxHeight, nStart );
3689 0 : aSz.Height() = ImplCalcHeight( nEntries );
3690 : }
3691 :
3692 0 : pWin->SetFocusId( nFocusId );
3693 0 : pWin->SetOutputSizePixel( aSz );
3694 : // #102158# menus must never grab the focus, otherwise
3695 : // they will be closed immediately
3696 : // from now on focus grabbing is only prohibited automatically if
3697 : // FLOATWIN_POPUPMODE_GRABFOCUS was set (which is done below), because some
3698 : // floaters (like floating toolboxes) may grab the focus
3699 : // pWin->GrabFocus();
3700 0 : if ( GetItemCount() )
3701 : {
3702 0 : SalMenu* pMenu = ImplGetSalMenu();
3703 0 : if( pMenu && bRealExecute && pMenu->ShowNativePopupMenu( pWin, aRect, nPopupModeFlags | FLOATWIN_POPUPMODE_GRABFOCUS ) )
3704 : {
3705 0 : pWin->StopExecute(0);
3706 0 : pWin->doShutdown();
3707 0 : pWindow->doLazyDelete();
3708 0 : pWindow = NULL;
3709 0 : return nSelectedId;
3710 : }
3711 : else
3712 : {
3713 0 : pWin->StartPopupMode( aRect, nPopupModeFlags | FLOATWIN_POPUPMODE_GRABFOCUS );
3714 : }
3715 0 : if( pSFrom )
3716 : {
3717 : sal_uInt16 aPos;
3718 0 : if( pSFrom->bIsMenuBar )
3719 0 : aPos = ((MenuBarWindow *) pSFrom->pWindow)->GetHighlightedItem();
3720 : else
3721 0 : aPos = ((MenuFloatingWindow *) pSFrom->pWindow)->GetHighlightedItem();
3722 :
3723 0 : pWin->SetPosInParent( aPos ); // store position to be sent in SUBMENUDEACTIVATE
3724 0 : pSFrom->ImplCallEventListeners( VCLEVENT_MENU_SUBMENUACTIVATE, aPos );
3725 : }
3726 : }
3727 0 : if ( bPreSelectFirst )
3728 : {
3729 0 : size_t nCount = pItemList->size();
3730 0 : for ( size_t n = 0; n < nCount; n++ )
3731 : {
3732 0 : MenuItemData* pData = pItemList->GetDataFromPos( n );
3733 0 : if ( ( pData->bEnabled
3734 0 : || !Application::GetSettings().GetStyleSettings().GetSkipDisabledInMenus()
3735 : )
3736 : && ( pData->eType != MENUITEM_SEPARATOR )
3737 0 : && ImplIsVisible( n )
3738 0 : && ImplIsSelectable( n )
3739 : )
3740 : {
3741 0 : pWin->ChangeHighlightItem( n, sal_False );
3742 0 : break;
3743 : }
3744 : }
3745 : }
3746 0 : if ( bRealExecute )
3747 : {
3748 0 : pWin->ImplAddDel( &aDelData );
3749 :
3750 0 : ImplDelData aModalWinDel;
3751 0 : pW->ImplAddDel( &aModalWinDel );
3752 0 : pW->ImplIncModalCount();
3753 :
3754 0 : pWin->Execute();
3755 :
3756 : DBG_ASSERT( ! aModalWinDel.IsDead(), "window for popup died, modal count incorrect !" );
3757 0 : if( ! aModalWinDel.IsDead() )
3758 0 : pW->ImplDecModalCount();
3759 :
3760 0 : if ( !aDelData.IsDead() )
3761 0 : pWin->ImplRemoveDel( &aDelData );
3762 : else
3763 0 : return 0;
3764 :
3765 : // Restore focus (could already have been
3766 : // restored in Select)
3767 0 : nFocusId = pWin->GetFocusId();
3768 0 : if ( nFocusId )
3769 : {
3770 0 : pWin->SetFocusId( 0 );
3771 0 : pSVData->maWinData.mbNoDeactivate = sal_False;
3772 : }
3773 0 : pWin->ImplEndPopupMode( 0, nFocusId );
3774 :
3775 0 : if ( nSelectedId ) // then clean up .. ( otherwise done by TH )
3776 : {
3777 0 : PopupMenu* pSub = pWin->GetActivePopup();
3778 0 : while ( pSub )
3779 : {
3780 0 : pSub->ImplGetFloatingWindow()->EndPopupMode();
3781 0 : pSub = pSub->ImplGetFloatingWindow()->GetActivePopup();
3782 : }
3783 : }
3784 0 : pWin->doShutdown();
3785 0 : pWindow->doLazyDelete();
3786 0 : pWindow = NULL;
3787 :
3788 : // is there still Select?
3789 0 : Menu* pSelect = ImplFindSelectMenu();
3790 0 : if ( pSelect )
3791 : {
3792 : // Select should be called prior to leaving execute in a popup menu!
3793 0 : Application::RemoveUserEvent( pSelect->nEventId );
3794 0 : pSelect->nEventId = 0;
3795 0 : pSelect->Select();
3796 0 : }
3797 : }
3798 :
3799 0 : return bRealExecute ? nSelectedId : 0;
3800 : }
3801 :
3802 0 : sal_uInt16 PopupMenu::ImplCalcVisEntries( long nMaxHeight, sal_uInt16 nStartEntry, sal_uInt16* pLastVisible ) const
3803 : {
3804 0 : nMaxHeight -= 2 * ImplGetFloatingWindow()->GetScrollerHeight();
3805 :
3806 0 : long nHeight = 0;
3807 0 : size_t nEntries = pItemList->size();
3808 0 : sal_uInt16 nVisEntries = 0;
3809 :
3810 0 : if ( pLastVisible )
3811 0 : *pLastVisible = 0;
3812 :
3813 0 : for ( size_t n = nStartEntry; n < nEntries; n++ )
3814 : {
3815 0 : if ( ImplIsVisible( n ) )
3816 : {
3817 0 : MenuItemData* pData = pItemList->GetDataFromPos( n );
3818 0 : nHeight += pData->aSz.Height();
3819 0 : if ( nHeight > nMaxHeight )
3820 0 : break;
3821 :
3822 0 : if ( pLastVisible )
3823 0 : *pLastVisible = n;
3824 0 : nVisEntries++;
3825 : }
3826 : }
3827 0 : return nVisEntries;
3828 : }
3829 :
3830 0 : long PopupMenu::ImplCalcHeight( sal_uInt16 nEntries ) const
3831 : {
3832 0 : long nHeight = 0;
3833 :
3834 0 : sal_uInt16 nFound = 0;
3835 0 : for ( size_t n = 0; ( nFound < nEntries ) && ( n < pItemList->size() ); n++ )
3836 : {
3837 0 : if ( ImplIsVisible( (sal_uInt16) n ) )
3838 : {
3839 0 : MenuItemData* pData = pItemList->GetDataFromPos( n );
3840 0 : nHeight += pData->aSz.Height();
3841 0 : nFound++;
3842 : }
3843 : }
3844 :
3845 0 : nHeight += 2*ImplGetFloatingWindow()->GetScrollerHeight();
3846 :
3847 0 : return nHeight;
3848 : }
3849 :
3850 :
3851 236 : static void ImplInitMenuWindow( Window* pWin, sal_Bool bFont, sal_Bool bMenuBar )
3852 : {
3853 236 : const StyleSettings& rStyleSettings = pWin->GetSettings().GetStyleSettings();
3854 :
3855 236 : if ( bFont )
3856 236 : pWin->SetPointFont( rStyleSettings.GetMenuFont() );
3857 236 : if( bMenuBar )
3858 : {
3859 236 : if( pWin->IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
3860 : {
3861 0 : pWin->SetBackground(); // background will be drawn by NWF
3862 : }
3863 : else
3864 : {
3865 236 : Wallpaper aWallpaper;
3866 236 : aWallpaper.SetStyle( WALLPAPER_APPLICATIONGRADIENT );
3867 236 : pWin->SetBackground( aWallpaper );
3868 236 : pWin->SetPaintTransparent( sal_False );
3869 236 : pWin->SetParentClipMode( 0 );
3870 : }
3871 : }
3872 : else
3873 : {
3874 0 : if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) )
3875 : {
3876 0 : pWin->SetBackground(); // background will be drawn by NWF
3877 : }
3878 : else
3879 0 : pWin->SetBackground( Wallpaper( rStyleSettings.GetMenuColor() ) );
3880 : }
3881 :
3882 236 : if ( bMenuBar )
3883 236 : pWin->SetTextColor( rStyleSettings.GetMenuBarTextColor() );
3884 : else
3885 0 : pWin->SetTextColor( rStyleSettings.GetMenuTextColor() );
3886 236 : pWin->SetTextFillColor();
3887 236 : pWin->SetLineColor();
3888 236 : }
3889 :
3890 0 : MenuFloatingWindow::MenuFloatingWindow( Menu* pMen, Window* pParent, WinBits nStyle ) :
3891 0 : FloatingWindow( pParent, nStyle )
3892 : {
3893 0 : mpWindowImpl->mbMenuFloatingWindow= sal_True;
3894 0 : pMenu = pMen;
3895 0 : pActivePopup = 0;
3896 0 : nSaveFocusId = 0;
3897 0 : bInExecute = sal_False;
3898 0 : bScrollMenu = sal_False;
3899 0 : nHighlightedItem = ITEMPOS_INVALID;
3900 0 : nMBDownPos = ITEMPOS_INVALID;
3901 0 : nPosInParent = ITEMPOS_INVALID;
3902 0 : nScrollerHeight = 0;
3903 0 : nBorder = EXTRASPACEY;
3904 0 : nFirstEntry = 0;
3905 0 : bScrollUp = sal_False;
3906 0 : bScrollDown = sal_False;
3907 0 : bIgnoreFirstMove = sal_True;
3908 0 : bKeyInput = sal_False;
3909 :
3910 0 : EnableSaveBackground();
3911 0 : ImplInitMenuWindow( this, sal_True, sal_False );
3912 :
3913 0 : SetPopupModeEndHdl( LINK( this, MenuFloatingWindow, PopupEnd ) );
3914 :
3915 0 : aHighlightChangedTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, HighlightChanged ) );
3916 0 : aHighlightChangedTimer.SetTimeout( GetSettings().GetMouseSettings().GetMenuDelay() );
3917 0 : aSubmenuCloseTimer.SetTimeout( GetSettings().GetMouseSettings().GetMenuDelay() );
3918 0 : aSubmenuCloseTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, SubmenuClose ) );
3919 0 : aScrollTimer.SetTimeoutHdl( LINK( this, MenuFloatingWindow, AutoScroll ) );
3920 :
3921 0 : AddEventListener( LINK( this, MenuFloatingWindow, ShowHideListener ) );
3922 0 : }
3923 :
3924 0 : void MenuFloatingWindow::doShutdown()
3925 : {
3926 0 : if( pMenu )
3927 : {
3928 : // #105373# notify toolkit that highlight was removed
3929 : // otherwise the entry will not be read when the menu is opened again
3930 0 : if( nHighlightedItem != ITEMPOS_INVALID )
3931 0 : pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
3932 :
3933 0 : if( !bKeyInput && pMenu && pMenu->pStartedFrom && !pMenu->pStartedFrom->bIsMenuBar )
3934 : {
3935 : // #102461# remove highlight in parent
3936 : MenuItemData* pData;
3937 0 : size_t i, nCount = pMenu->pStartedFrom->pItemList->size();
3938 0 : for(i = 0; i < nCount; i++)
3939 : {
3940 0 : pData = pMenu->pStartedFrom->pItemList->GetDataFromPos( i );
3941 0 : if( pData && ( pData->pSubMenu == pMenu ) )
3942 0 : break;
3943 : }
3944 0 : if( i < nCount )
3945 : {
3946 0 : MenuFloatingWindow* pPWin = (MenuFloatingWindow*)pMenu->pStartedFrom->ImplGetWindow();
3947 0 : if( pPWin )
3948 0 : pPWin->HighlightItem( i, sal_False );
3949 : }
3950 : }
3951 :
3952 : // free the reference to the accessible component
3953 0 : SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >() );
3954 :
3955 0 : aHighlightChangedTimer.Stop();
3956 :
3957 : // #95056# invalidate screen area covered by system window
3958 : // so this can be taken into account if the commandhandler performs a scroll operation
3959 0 : if( GetParent() )
3960 : {
3961 0 : Rectangle aInvRect( GetWindowExtentsRelative( GetParent() ) );
3962 0 : GetParent()->Invalidate( aInvRect );
3963 : }
3964 0 : pMenu = NULL;
3965 0 : RemoveEventListener( LINK( this, MenuFloatingWindow, ShowHideListener ) );
3966 : }
3967 0 : }
3968 :
3969 0 : MenuFloatingWindow::~MenuFloatingWindow()
3970 : {
3971 0 : doShutdown();
3972 0 : }
3973 :
3974 0 : void MenuFloatingWindow::Resize()
3975 : {
3976 0 : ImplInitClipRegion();
3977 0 : }
3978 :
3979 0 : long MenuFloatingWindow::ImplGetStartY() const
3980 : {
3981 0 : long nY = 0;
3982 0 : if( pMenu )
3983 : {
3984 0 : for ( sal_uInt16 n = 0; n < nFirstEntry; n++ )
3985 0 : nY += pMenu->GetItemList()->GetDataFromPos( n )->aSz.Height();
3986 : }
3987 0 : return -nY;
3988 : }
3989 :
3990 0 : Region MenuFloatingWindow::ImplCalcClipRegion( sal_Bool bIncludeLogo ) const
3991 : {
3992 0 : Size aOutSz = GetOutputSizePixel();
3993 0 : Point aPos;
3994 0 : Rectangle aRect( aPos, aOutSz );
3995 0 : aRect.Top() += nScrollerHeight;
3996 0 : aRect.Bottom() -= nScrollerHeight;
3997 :
3998 0 : if ( pMenu && pMenu->pLogo && !bIncludeLogo )
3999 0 : aRect.Left() += pMenu->pLogo->aBitmap.GetSizePixel().Width();
4000 :
4001 0 : Region aRegion = aRect;
4002 0 : if ( pMenu && pMenu->pLogo && bIncludeLogo && nScrollerHeight )
4003 0 : aRegion.Union( Rectangle( Point(), Size( pMenu->pLogo->aBitmap.GetSizePixel().Width(), aOutSz.Height() ) ) );
4004 :
4005 0 : return aRegion;
4006 : }
4007 :
4008 0 : void MenuFloatingWindow::ImplInitClipRegion()
4009 : {
4010 0 : if ( IsScrollMenu() )
4011 : {
4012 0 : SetClipRegion( ImplCalcClipRegion() );
4013 : }
4014 : else
4015 : {
4016 0 : SetClipRegion();
4017 : }
4018 0 : }
4019 :
4020 0 : void MenuFloatingWindow::ImplHighlightItem( const MouseEvent& rMEvt, sal_Bool bMBDown )
4021 : {
4022 0 : if( ! pMenu )
4023 0 : return;
4024 :
4025 0 : long nY = nScrollerHeight + ImplGetSVData()->maNWFData.mnMenuFormatBorderY;
4026 0 : long nMouseY = rMEvt.GetPosPixel().Y();
4027 0 : Size aOutSz = GetOutputSizePixel();
4028 0 : if ( ( nMouseY >= nY ) && ( nMouseY < ( aOutSz.Height() - nY ) ) )
4029 : {
4030 0 : sal_Bool bHighlighted = sal_False;
4031 0 : size_t nCount = pMenu->pItemList->size();
4032 0 : nY += ImplGetStartY(); // ggf. gescrollt.
4033 0 : for ( size_t n = 0; !bHighlighted && ( n < nCount ); n++ )
4034 : {
4035 0 : if ( pMenu->ImplIsVisible( n ) )
4036 : {
4037 0 : MenuItemData* pItemData = pMenu->pItemList->GetDataFromPos( n );
4038 0 : long nOldY = nY;
4039 0 : nY += pItemData->aSz.Height();
4040 0 : if ( ( nOldY <= nMouseY ) && ( nY > nMouseY ) && pMenu->ImplIsSelectable( n ) )
4041 : {
4042 0 : sal_Bool bPopupArea = sal_True;
4043 0 : if ( pItemData->nBits & MIB_POPUPSELECT )
4044 : {
4045 : // only when clicked over the arrow...
4046 0 : Size aSz = GetOutputSizePixel();
4047 0 : long nFontHeight = GetTextHeight();
4048 0 : bPopupArea = ( rMEvt.GetPosPixel().X() >= ( aSz.Width() - nFontHeight - nFontHeight/4 ) );
4049 : }
4050 :
4051 0 : if ( bMBDown )
4052 : {
4053 0 : if ( n != nHighlightedItem )
4054 : {
4055 0 : ChangeHighlightItem( (sal_uInt16)n, sal_False );
4056 : }
4057 :
4058 0 : sal_Bool bAllowNewPopup = sal_True;
4059 0 : if ( pActivePopup )
4060 : {
4061 0 : MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
4062 0 : bAllowNewPopup = pData && ( pData->pSubMenu != pActivePopup );
4063 0 : if ( bAllowNewPopup )
4064 0 : KillActivePopup();
4065 : }
4066 :
4067 0 : if ( bPopupArea && bAllowNewPopup )
4068 : {
4069 0 : HighlightChanged( NULL );
4070 : }
4071 : }
4072 : else
4073 : {
4074 0 : if ( n != nHighlightedItem )
4075 : {
4076 0 : ChangeHighlightItem( (sal_uInt16)n, sal_True );
4077 : }
4078 0 : else if ( pItemData->nBits & MIB_POPUPSELECT )
4079 : {
4080 0 : if ( bPopupArea && ( pActivePopup != pItemData->pSubMenu ) )
4081 0 : HighlightChanged( NULL );
4082 : }
4083 : }
4084 0 : bHighlighted = sal_True;
4085 : }
4086 : }
4087 : }
4088 0 : if ( !bHighlighted )
4089 0 : ChangeHighlightItem( ITEMPOS_INVALID, sal_True );
4090 : }
4091 : else
4092 : {
4093 0 : ImplScroll( rMEvt.GetPosPixel() );
4094 0 : ChangeHighlightItem( ITEMPOS_INVALID, sal_True );
4095 : }
4096 : }
4097 :
4098 0 : IMPL_LINK_NOARG(MenuFloatingWindow, PopupEnd)
4099 : {
4100 : // "this" will be deleted before the end of this method!
4101 0 : Menu* pM = pMenu;
4102 0 : if ( bInExecute )
4103 : {
4104 0 : if ( pActivePopup )
4105 : {
4106 : //DBG_ASSERT( !pActivePopup->ImplGetWindow(), "PopupEnd, obwohl pActivePopup MIT Window!" );
4107 0 : KillActivePopup(); // should be ok to just remove it
4108 : //pActivePopup->bCanceled = sal_True;
4109 : }
4110 0 : bInExecute = sal_False;
4111 0 : pMenu->bInCallback = sal_True;
4112 0 : pMenu->Deactivate();
4113 0 : pMenu->bInCallback = sal_False;
4114 : }
4115 : else
4116 : {
4117 0 : if( pMenu )
4118 : {
4119 : // if the window was closed by TH, there is another menu
4120 : // which has this window as pActivePopup
4121 0 : if ( pMenu->pStartedFrom )
4122 : {
4123 : // pWin from parent could be 0, if the list is
4124 : // cleaned from the start, now clean up the endpopup-events
4125 0 : if ( pMenu->pStartedFrom->bIsMenuBar )
4126 : {
4127 0 : MenuBarWindow* p = (MenuBarWindow*) pMenu->pStartedFrom->ImplGetWindow();
4128 0 : if ( p )
4129 0 : p->PopupClosed( pMenu );
4130 : }
4131 : else
4132 : {
4133 0 : MenuFloatingWindow* p = (MenuFloatingWindow*) pMenu->pStartedFrom->ImplGetWindow();
4134 0 : if ( p )
4135 0 : p->KillActivePopup( (PopupMenu*)pMenu );
4136 : }
4137 : }
4138 : }
4139 : }
4140 :
4141 0 : if ( pM )
4142 0 : pM->pStartedFrom = 0;
4143 :
4144 0 : return 0;
4145 : }
4146 :
4147 0 : IMPL_LINK_NOARG(MenuFloatingWindow, AutoScroll)
4148 : {
4149 0 : ImplScroll( GetPointerPosPixel() );
4150 0 : return 1;
4151 : }
4152 :
4153 0 : IMPL_LINK( MenuFloatingWindow, HighlightChanged, Timer*, pTimer )
4154 : {
4155 0 : if( ! pMenu )
4156 0 : return 0;
4157 :
4158 0 : MenuItemData* pItemData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
4159 0 : if ( pItemData )
4160 : {
4161 0 : if ( pActivePopup && ( pActivePopup != pItemData->pSubMenu ) )
4162 : {
4163 0 : sal_uLong nOldFlags = GetPopupModeFlags();
4164 0 : SetPopupModeFlags( GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE );
4165 0 : KillActivePopup();
4166 0 : SetPopupModeFlags( nOldFlags );
4167 : }
4168 0 : if ( pItemData->bEnabled && pItemData->pSubMenu && pItemData->pSubMenu->GetItemCount() && ( pItemData->pSubMenu != pActivePopup ) )
4169 : {
4170 0 : pActivePopup = (PopupMenu*)pItemData->pSubMenu;
4171 0 : long nY = nScrollerHeight+ImplGetStartY();
4172 0 : MenuItemData* pData = 0;
4173 0 : for ( sal_uLong n = 0; n < nHighlightedItem; n++ )
4174 : {
4175 0 : pData = pMenu->pItemList->GetDataFromPos( n );
4176 0 : nY += pData->aSz.Height();
4177 : }
4178 0 : pData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
4179 0 : Size MySize = GetOutputSizePixel();
4180 0 : Point aItemTopLeft( 0, nY );
4181 0 : Point aItemBottomRight( aItemTopLeft );
4182 0 : aItemBottomRight.X() += MySize.Width();
4183 0 : aItemBottomRight.Y() += pData->aSz.Height();
4184 :
4185 : // shift the popups a little
4186 0 : aItemTopLeft.X() += 2;
4187 0 : aItemBottomRight.X() -= 2;
4188 0 : if ( nHighlightedItem )
4189 0 : aItemTopLeft.Y() -= 2;
4190 : else
4191 : {
4192 : sal_Int32 nL, nT, nR, nB;
4193 0 : GetBorder( nL, nT, nR, nB );
4194 0 : aItemTopLeft.Y() -= nT;
4195 : }
4196 :
4197 : // pTest: crash due to Reschedule() in call of Activate()
4198 : // Also it is prevented that submenus are displayed which
4199 : // were for long in Activate Rescheduled and which should not be
4200 : // displayed now.
4201 0 : Menu* pTest = pActivePopup;
4202 0 : sal_uLong nOldFlags = GetPopupModeFlags();
4203 0 : SetPopupModeFlags( GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE );
4204 0 : sal_uInt16 nRet = pActivePopup->ImplExecute( this, Rectangle( aItemTopLeft, aItemBottomRight ), FLOATWIN_POPUPMODE_RIGHT, pMenu, pTimer ? sal_False : sal_True );
4205 0 : SetPopupModeFlags( nOldFlags );
4206 :
4207 : // nRet != 0, wenn es waerend Activate() abgeschossen wurde...
4208 0 : if ( !nRet && ( pActivePopup == pTest ) && pActivePopup->ImplGetWindow() )
4209 0 : pActivePopup->ImplGetFloatingWindow()->AddPopupModeWindow( this );
4210 : }
4211 : }
4212 :
4213 0 : return 0;
4214 : }
4215 :
4216 0 : IMPL_LINK_NOARG(MenuFloatingWindow, SubmenuClose)
4217 : {
4218 0 : if( pMenu && pMenu->pStartedFrom )
4219 : {
4220 0 : MenuFloatingWindow* pWin = (MenuFloatingWindow*) pMenu->pStartedFrom->GetWindow();
4221 0 : if( pWin )
4222 0 : pWin->KillActivePopup();
4223 : }
4224 0 : return 0;
4225 : }
4226 :
4227 0 : IMPL_LINK( MenuFloatingWindow, ShowHideListener, VclWindowEvent*, pEvent )
4228 : {
4229 0 : if( ! pMenu )
4230 0 : return 0;
4231 :
4232 0 : if( pEvent->GetId() == VCLEVENT_WINDOW_SHOW )
4233 0 : pMenu->ImplCallEventListeners( VCLEVENT_MENU_SHOW, ITEMPOS_INVALID );
4234 0 : else if( pEvent->GetId() == VCLEVENT_WINDOW_HIDE )
4235 0 : pMenu->ImplCallEventListeners( VCLEVENT_MENU_HIDE, ITEMPOS_INVALID );
4236 0 : return 0;
4237 : }
4238 :
4239 0 : void MenuFloatingWindow::EnableScrollMenu( sal_Bool b )
4240 : {
4241 0 : bScrollMenu = b;
4242 0 : nScrollerHeight = b ? (sal_uInt16) GetSettings().GetStyleSettings().GetScrollBarSize() /2 : 0;
4243 0 : bScrollDown = sal_True;
4244 0 : ImplInitClipRegion();
4245 0 : }
4246 :
4247 0 : void MenuFloatingWindow::Execute()
4248 : {
4249 0 : ImplSVData* pSVData = ImplGetSVData();
4250 :
4251 0 : pSVData->maAppData.mpActivePopupMenu = (PopupMenu*)pMenu;
4252 :
4253 0 : bInExecute = sal_True;
4254 : // bCallingSelect = sal_False;
4255 :
4256 0 : while ( bInExecute )
4257 0 : Application::Yield();
4258 :
4259 0 : pSVData->maAppData.mpActivePopupMenu = NULL;
4260 0 : }
4261 :
4262 0 : void MenuFloatingWindow::StopExecute( sal_uLong nFocusId )
4263 : {
4264 : // restore focus
4265 : // (could have been restored in Select)
4266 0 : if ( nSaveFocusId )
4267 : {
4268 0 : Window::EndSaveFocus( nFocusId, sal_False );
4269 0 : nFocusId = nSaveFocusId;
4270 0 : if ( nFocusId )
4271 : {
4272 0 : nSaveFocusId = 0;
4273 0 : ImplGetSVData()->maWinData.mbNoDeactivate = sal_False;
4274 : }
4275 : }
4276 0 : ImplEndPopupMode( 0, nFocusId );
4277 :
4278 0 : aHighlightChangedTimer.Stop();
4279 0 : bInExecute = sal_False;
4280 0 : if ( pActivePopup )
4281 : {
4282 0 : KillActivePopup();
4283 : }
4284 : // notify parent, needed for accessibility
4285 0 : if( pMenu && pMenu->pStartedFrom )
4286 0 : pMenu->pStartedFrom->ImplCallEventListeners( VCLEVENT_MENU_SUBMENUDEACTIVATE, nPosInParent );
4287 0 : }
4288 :
4289 0 : void MenuFloatingWindow::KillActivePopup( PopupMenu* pThisOnly )
4290 : {
4291 0 : if ( pActivePopup && ( !pThisOnly || ( pThisOnly == pActivePopup ) ) )
4292 : {
4293 0 : if( pActivePopup->pWindow != NULL )
4294 0 : if( ((FloatingWindow *) pActivePopup->pWindow)->IsInCleanUp() )
4295 0 : return; // kill it later
4296 0 : if ( pActivePopup->bInCallback )
4297 0 : pActivePopup->bCanceled = sal_True;
4298 :
4299 : // For all actions pActivePopup = 0, if e.g.
4300 : // PopupModeEndHdl the popups to destroy were called synchronous
4301 0 : PopupMenu* pPopup = pActivePopup;
4302 0 : pActivePopup = NULL;
4303 0 : pPopup->bInCallback = sal_True;
4304 0 : pPopup->Deactivate();
4305 0 : pPopup->bInCallback = sal_False;
4306 0 : if ( pPopup->ImplGetWindow() )
4307 : {
4308 0 : pPopup->ImplGetFloatingWindow()->StopExecute();
4309 0 : pPopup->ImplGetFloatingWindow()->doShutdown();
4310 0 : pPopup->pWindow->doLazyDelete();
4311 0 : pPopup->pWindow = NULL;
4312 :
4313 0 : Update();
4314 : }
4315 : }
4316 : }
4317 :
4318 0 : void MenuFloatingWindow::EndExecute()
4319 : {
4320 0 : Menu* pStart = pMenu ? pMenu->ImplGetStartMenu() : NULL;
4321 0 : sal_uLong nFocusId = 0;
4322 0 : if ( pStart && pStart->bIsMenuBar )
4323 : {
4324 0 : nFocusId = ((MenuBarWindow*)((MenuBar*)pStart)->ImplGetWindow())->GetFocusId();
4325 0 : if ( nFocusId )
4326 : {
4327 0 : ((MenuBarWindow*)((MenuBar*)pStart)->ImplGetWindow())->SetFocusId( 0 );
4328 0 : ImplGetSVData()->maWinData.mbNoDeactivate = sal_False;
4329 : }
4330 : }
4331 :
4332 : // if started else where, cleanup there as well
4333 0 : MenuFloatingWindow* pCleanUpFrom = this;
4334 0 : MenuFloatingWindow* pWin = this;
4335 0 : while ( pWin && !pWin->bInExecute &&
4336 0 : pWin->pMenu->pStartedFrom && !pWin->pMenu->pStartedFrom->bIsMenuBar )
4337 : {
4338 0 : pWin = ((PopupMenu*)pWin->pMenu->pStartedFrom)->ImplGetFloatingWindow();
4339 : }
4340 0 : if ( pWin )
4341 0 : pCleanUpFrom = pWin;
4342 :
4343 : // this window will be destroyed => store date locally...
4344 0 : Menu* pM = pMenu;
4345 0 : sal_uInt16 nItem = nHighlightedItem;
4346 :
4347 0 : pCleanUpFrom->StopExecute( nFocusId );
4348 :
4349 0 : if ( nItem != ITEMPOS_INVALID && pM )
4350 : {
4351 0 : MenuItemData* pItemData = pM->GetItemList()->GetDataFromPos( nItem );
4352 0 : if ( pItemData && !pItemData->bIsTemporary )
4353 : {
4354 0 : pM->nSelectedId = pItemData->nId;
4355 0 : if ( pStart )
4356 0 : pStart->nSelectedId = pItemData->nId;
4357 :
4358 0 : pM->ImplSelect();
4359 : }
4360 : }
4361 0 : }
4362 :
4363 0 : void MenuFloatingWindow::EndExecute( sal_uInt16 nId )
4364 : {
4365 : size_t nPos;
4366 0 : if ( pMenu && pMenu->GetItemList()->GetData( nId, nPos ) )
4367 0 : nHighlightedItem = nPos;
4368 : else
4369 0 : nHighlightedItem = ITEMPOS_INVALID;
4370 :
4371 0 : EndExecute();
4372 0 : }
4373 :
4374 0 : void MenuFloatingWindow::MouseButtonDown( const MouseEvent& rMEvt )
4375 : {
4376 : // TH creates a ToTop on this window, but the active popup
4377 : // should stay on top...
4378 : // due to focus change this would close all menus -> don't do it (#94123)
4379 : //if ( pActivePopup && pActivePopup->ImplGetWindow() && !pActivePopup->ImplGetFloatingWindow()->pActivePopup )
4380 : // pActivePopup->ImplGetFloatingWindow()->ToTop( TOTOP_NOGRABFOCUS );
4381 :
4382 0 : ImplHighlightItem( rMEvt, sal_True );
4383 :
4384 0 : nMBDownPos = nHighlightedItem;
4385 0 : }
4386 :
4387 0 : void MenuFloatingWindow::MouseButtonUp( const MouseEvent& rMEvt )
4388 : {
4389 0 : MenuItemData* pData = pMenu ? pMenu->GetItemList()->GetDataFromPos( nHighlightedItem ) : NULL;
4390 : // nMBDownPos store in local variable and reset immediately,
4391 : // as it will be too late after EndExecute
4392 0 : sal_uInt16 _nMBDownPos = nMBDownPos;
4393 0 : nMBDownPos = ITEMPOS_INVALID;
4394 0 : if ( pData && pData->bEnabled && ( pData->eType != MENUITEM_SEPARATOR ) )
4395 : {
4396 0 : if ( !pData->pSubMenu )
4397 : {
4398 0 : EndExecute();
4399 : }
4400 0 : else if ( ( pData->nBits & MIB_POPUPSELECT ) && ( nHighlightedItem == _nMBDownPos ) && ( rMEvt.GetClicks() == 2 ) )
4401 : {
4402 : // not when clicked over the arrow...
4403 0 : Size aSz = GetOutputSizePixel();
4404 0 : long nFontHeight = GetTextHeight();
4405 0 : if ( rMEvt.GetPosPixel().X() < ( aSz.Width() - nFontHeight - nFontHeight/4 ) )
4406 0 : EndExecute();
4407 : }
4408 : }
4409 :
4410 0 : }
4411 :
4412 0 : void MenuFloatingWindow::MouseMove( const MouseEvent& rMEvt )
4413 : {
4414 0 : if ( !IsVisible() || rMEvt.IsSynthetic() || rMEvt.IsEnterWindow() )
4415 0 : return;
4416 :
4417 0 : if ( rMEvt.IsLeaveWindow() )
4418 : {
4419 : // #102461# do not remove highlight if a popup menu is open at this position
4420 0 : MenuItemData* pData = pMenu ? pMenu->pItemList->GetDataFromPos( nHighlightedItem ) : NULL;
4421 : // close popup with some delayed if we leave somewhere else
4422 0 : if( pActivePopup && pData && pData->pSubMenu != pActivePopup )
4423 0 : pActivePopup->ImplGetFloatingWindow()->aSubmenuCloseTimer.Start();
4424 :
4425 0 : if( !pActivePopup || (pData && pData->pSubMenu != pActivePopup ) )
4426 0 : ChangeHighlightItem( ITEMPOS_INVALID, sal_False );
4427 :
4428 0 : if ( IsScrollMenu() )
4429 0 : ImplScroll( rMEvt.GetPosPixel() );
4430 : }
4431 : else
4432 : {
4433 0 : aSubmenuCloseTimer.Stop();
4434 0 : if( bIgnoreFirstMove )
4435 0 : bIgnoreFirstMove = sal_False;
4436 : else
4437 0 : ImplHighlightItem( rMEvt, sal_False );
4438 : }
4439 : }
4440 :
4441 0 : void MenuFloatingWindow::ImplScroll( sal_Bool bUp )
4442 : {
4443 0 : KillActivePopup();
4444 0 : Update();
4445 :
4446 0 : if( ! pMenu )
4447 0 : return;
4448 :
4449 0 : HighlightItem( nHighlightedItem, sal_False );
4450 :
4451 0 : pMenu->ImplKillLayoutData();
4452 :
4453 0 : if ( bScrollUp && bUp )
4454 : {
4455 0 : nFirstEntry = pMenu->ImplGetPrevVisible( nFirstEntry );
4456 : DBG_ASSERT( nFirstEntry != ITEMPOS_INVALID, "Scroll?!" );
4457 :
4458 0 : long nScrollEntryHeight = pMenu->GetItemList()->GetDataFromPos( nFirstEntry )->aSz.Height();
4459 :
4460 0 : if ( !bScrollDown )
4461 : {
4462 0 : bScrollDown = sal_True;
4463 0 : ImplDrawScroller( sal_False );
4464 : }
4465 :
4466 0 : if ( pMenu->ImplGetPrevVisible( nFirstEntry ) == ITEMPOS_INVALID )
4467 : {
4468 0 : bScrollUp = sal_False;
4469 0 : ImplDrawScroller( sal_True );
4470 : }
4471 :
4472 0 : Scroll( 0, nScrollEntryHeight, ImplCalcClipRegion( sal_False ).GetBoundRect(), SCROLL_CLIP );
4473 : }
4474 0 : else if ( bScrollDown && !bUp )
4475 : {
4476 0 : long nScrollEntryHeight = pMenu->GetItemList()->GetDataFromPos( nFirstEntry )->aSz.Height();
4477 :
4478 0 : nFirstEntry = pMenu->ImplGetNextVisible( nFirstEntry );
4479 : DBG_ASSERT( nFirstEntry != ITEMPOS_INVALID, "Scroll?!" );
4480 :
4481 :
4482 0 : if ( !bScrollUp )
4483 : {
4484 0 : bScrollUp = sal_True;
4485 0 : ImplDrawScroller( sal_True );
4486 : }
4487 :
4488 0 : long nHeight = GetOutputSizePixel().Height();
4489 : sal_uInt16 nLastVisible;
4490 0 : ((PopupMenu*)pMenu)->ImplCalcVisEntries( nHeight, nFirstEntry, &nLastVisible );
4491 0 : if ( pMenu->ImplGetNextVisible( nLastVisible ) == ITEMPOS_INVALID )
4492 : {
4493 0 : bScrollDown = sal_False;
4494 0 : ImplDrawScroller( sal_False );
4495 : }
4496 :
4497 0 : Scroll( 0, -nScrollEntryHeight, ImplCalcClipRegion( sal_False ).GetBoundRect(), SCROLL_CLIP );
4498 : }
4499 :
4500 0 : HighlightItem( nHighlightedItem, sal_True );
4501 : }
4502 :
4503 0 : void MenuFloatingWindow::ImplScroll( const Point& rMousePos )
4504 : {
4505 0 : Size aOutSz = GetOutputSizePixel();
4506 :
4507 0 : long nY = nScrollerHeight;
4508 0 : long nMouseY = rMousePos.Y();
4509 0 : long nDelta = 0;
4510 :
4511 0 : if ( bScrollUp && ( nMouseY < nY ) )
4512 : {
4513 0 : ImplScroll( sal_True );
4514 0 : nDelta = nY - nMouseY;
4515 : }
4516 0 : else if ( bScrollDown && ( nMouseY > ( aOutSz.Height() - nY ) ) )
4517 : {
4518 0 : ImplScroll( sal_False );
4519 0 : nDelta = nMouseY - ( aOutSz.Height() - nY );
4520 : }
4521 :
4522 0 : if ( nDelta )
4523 : {
4524 0 : aScrollTimer.Stop(); // if scrolled through MouseMove.
4525 : long nTimeout;
4526 0 : if ( nDelta < 3 )
4527 0 : nTimeout = 200;
4528 0 : else if ( nDelta < 5 )
4529 0 : nTimeout = 100;
4530 0 : else if ( nDelta < 8 )
4531 0 : nTimeout = 70;
4532 0 : else if ( nDelta < 12 )
4533 0 : nTimeout = 40;
4534 : else
4535 0 : nTimeout = 20;
4536 0 : aScrollTimer.SetTimeout( nTimeout );
4537 0 : aScrollTimer.Start();
4538 : }
4539 0 : }
4540 0 : void MenuFloatingWindow::ChangeHighlightItem( sal_uInt16 n, sal_Bool bStartPopupTimer )
4541 : {
4542 : // #57934# ggf. immediately close the active, as TH's backgroundstorage works.
4543 : // #65750# we prefer to refrain from the background storage of small lines.
4544 : // otherwise the menus are difficult to operate.
4545 : // MenuItemData* pNextData = pMenu->pItemList->GetDataFromPos( n );
4546 : // if ( pActivePopup && pNextData && ( pActivePopup != pNextData->pSubMenu ) )
4547 : // KillActivePopup();
4548 :
4549 0 : aSubmenuCloseTimer.Stop();
4550 0 : if( ! pMenu )
4551 0 : return;
4552 :
4553 0 : if ( nHighlightedItem != ITEMPOS_INVALID )
4554 : {
4555 0 : HighlightItem( nHighlightedItem, sal_False );
4556 0 : pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
4557 : }
4558 :
4559 0 : nHighlightedItem = (sal_uInt16)n;
4560 : DBG_ASSERT( pMenu->ImplIsVisible( nHighlightedItem ) || nHighlightedItem == ITEMPOS_INVALID, "ChangeHighlightItem: Not visible!" );
4561 0 : if( nHighlightedItem != ITEMPOS_INVALID )
4562 : {
4563 0 : if( pMenu->pStartedFrom && !pMenu->pStartedFrom->bIsMenuBar )
4564 : {
4565 : // #102461# make sure parent entry is highlighted as well
4566 : MenuItemData* pData;
4567 0 : size_t i, nCount = pMenu->pStartedFrom->pItemList->size();
4568 0 : for(i = 0; i < nCount; i++)
4569 : {
4570 0 : pData = pMenu->pStartedFrom->pItemList->GetDataFromPos( i );
4571 0 : if( pData && ( pData->pSubMenu == pMenu ) )
4572 0 : break;
4573 : }
4574 0 : if( i < nCount )
4575 : {
4576 0 : MenuFloatingWindow* pPWin = (MenuFloatingWindow*)pMenu->pStartedFrom->ImplGetWindow();
4577 0 : if( pPWin && pPWin->nHighlightedItem != i )
4578 : {
4579 0 : pPWin->HighlightItem( i, sal_True );
4580 0 : pPWin->nHighlightedItem = i;
4581 : }
4582 : }
4583 : }
4584 0 : HighlightItem( nHighlightedItem, sal_True );
4585 0 : pMenu->ImplCallHighlight( nHighlightedItem );
4586 : }
4587 : else
4588 0 : pMenu->nSelectedId = 0;
4589 :
4590 0 : if ( bStartPopupTimer )
4591 : {
4592 : // #102438# Menu items are not selectable
4593 : // If a menu item is selected by an AT-tool via the XAccessibleAction, XAccessibleValue
4594 : // or XAccessibleSelection interface, and the parent popup menus are not executed yet,
4595 : // the parent popup menus must be executed SYNCHRONOUSLY, before the menu item is selected.
4596 0 : if ( GetSettings().GetMouseSettings().GetMenuDelay() )
4597 0 : aHighlightChangedTimer.Start();
4598 : else
4599 0 : HighlightChanged( &aHighlightChangedTimer );
4600 : }
4601 : }
4602 :
4603 0 : void MenuFloatingWindow::HighlightItem( sal_uInt16 nPos, sal_Bool bHighlight )
4604 : {
4605 0 : if( ! pMenu )
4606 : return;
4607 :
4608 0 : Size aSz = GetOutputSizePixel();
4609 0 : long nStartY = ImplGetStartY();
4610 0 : long nY = nScrollerHeight + nStartY + ImplGetSVData()->maNWFData.mnMenuFormatBorderY;
4611 0 : long nX = 0;
4612 :
4613 0 : if ( pMenu->pLogo )
4614 0 : nX = pMenu->pLogo->aBitmap.GetSizePixel().Width();
4615 :
4616 0 : int nOuterSpaceX = ImplGetSVData()->maNWFData.mnMenuFormatBorderX;
4617 :
4618 0 : size_t nCount = pMenu->pItemList->size();
4619 0 : for ( size_t n = 0; n < nCount; n++ )
4620 : {
4621 0 : MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
4622 0 : if ( n == nPos )
4623 : {
4624 : DBG_ASSERT( pMenu->ImplIsVisible( n ), "Highlight: Item not visible!" );
4625 0 : if ( pData->eType != MENUITEM_SEPARATOR )
4626 : {
4627 0 : sal_Bool bRestoreLineColor = sal_False;
4628 0 : Color oldLineColor;
4629 0 : bool bDrawItemRect = true;
4630 :
4631 0 : Rectangle aItemRect( Point( nX+nOuterSpaceX, nY ), Size( aSz.Width()-2*nOuterSpaceX, pData->aSz.Height() ) );
4632 0 : if ( pData->nBits & MIB_POPUPSELECT )
4633 : {
4634 0 : long nFontHeight = GetTextHeight();
4635 0 : aItemRect.Right() -= nFontHeight + nFontHeight/4;
4636 : }
4637 :
4638 0 : if( IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) )
4639 : {
4640 0 : Size aPxSize( GetOutputSizePixel() );
4641 0 : Push( PUSH_CLIPREGION );
4642 0 : IntersectClipRegion( Rectangle( Point( nX, nY ), Size( aSz.Width(), pData->aSz.Height() ) ) );
4643 0 : Rectangle aCtrlRect( Point( nX, 0 ), Size( aPxSize.Width()-nX, aPxSize.Height() ) );
4644 0 : MenupopupValue aVal( pMenu->nTextPos-GUTTERBORDER, aItemRect );
4645 : DrawNativeControl( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL,
4646 : aCtrlRect,
4647 : CTRL_STATE_ENABLED,
4648 : aVal,
4649 0 : OUString() );
4650 0 : if( bHighlight &&
4651 0 : IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM ) )
4652 : {
4653 0 : bDrawItemRect = false;
4654 0 : if( sal_False == DrawNativeControl( CTRL_MENU_POPUP, PART_MENU_ITEM,
4655 : aItemRect,
4656 : CTRL_STATE_SELECTED | ( pData->bEnabled? CTRL_STATE_ENABLED: 0 ),
4657 : aVal,
4658 0 : OUString() ) )
4659 : {
4660 0 : bDrawItemRect = bHighlight;
4661 : }
4662 : }
4663 : else
4664 0 : bDrawItemRect = bHighlight;
4665 0 : Pop();
4666 : }
4667 0 : if( bDrawItemRect )
4668 : {
4669 0 : if ( bHighlight )
4670 : {
4671 0 : if( pData->bEnabled )
4672 0 : SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
4673 : else
4674 : {
4675 0 : SetFillColor();
4676 0 : oldLineColor = GetLineColor();
4677 0 : SetLineColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
4678 0 : bRestoreLineColor = sal_True;
4679 : }
4680 : }
4681 : else
4682 0 : SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
4683 :
4684 0 : DrawRect( aItemRect );
4685 : }
4686 0 : pMenu->ImplPaint( this, nScrollerHeight, nStartY, pData, bHighlight );
4687 0 : if( bRestoreLineColor )
4688 0 : SetLineColor( oldLineColor );
4689 : }
4690 : return;
4691 : }
4692 :
4693 0 : nY += pData->aSz.Height();
4694 : }
4695 : }
4696 :
4697 0 : Rectangle MenuFloatingWindow::ImplGetItemRect( sal_uInt16 nPos )
4698 : {
4699 0 : if( ! pMenu )
4700 0 : return Rectangle();
4701 :
4702 0 : Rectangle aRect;
4703 0 : Size aSz = GetOutputSizePixel();
4704 0 : long nStartY = ImplGetStartY();
4705 0 : long nY = nScrollerHeight+nStartY;
4706 0 : long nX = 0;
4707 :
4708 0 : if ( pMenu->pLogo )
4709 0 : nX = pMenu->pLogo->aBitmap.GetSizePixel().Width();
4710 :
4711 0 : size_t nCount = pMenu->pItemList->size();
4712 0 : for ( size_t n = 0; n < nCount; n++ )
4713 : {
4714 0 : MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
4715 0 : if ( n == nPos )
4716 : {
4717 : DBG_ASSERT( pMenu->ImplIsVisible( n ), "ImplGetItemRect: Item not visible!" );
4718 0 : if ( pData->eType != MENUITEM_SEPARATOR )
4719 : {
4720 0 : aRect = Rectangle( Point( nX, nY ), Size( aSz.Width(), pData->aSz.Height() ) );
4721 0 : if ( pData->nBits & MIB_POPUPSELECT )
4722 : {
4723 0 : long nFontHeight = GetTextHeight();
4724 0 : aRect.Right() -= nFontHeight + nFontHeight/4;
4725 : }
4726 : }
4727 0 : break;
4728 : }
4729 0 : nY += pData->aSz.Height();
4730 : }
4731 0 : return aRect;
4732 : }
4733 :
4734 :
4735 0 : void MenuFloatingWindow::ImplCursorUpDown( sal_Bool bUp, sal_Bool bHomeEnd )
4736 : {
4737 0 : if( ! pMenu )
4738 0 : return;
4739 :
4740 0 : const StyleSettings& rSettings = GetSettings().GetStyleSettings();
4741 :
4742 0 : sal_uInt16 n = nHighlightedItem;
4743 0 : if ( n == ITEMPOS_INVALID )
4744 : {
4745 0 : if ( bUp )
4746 0 : n = 0;
4747 : else
4748 0 : n = pMenu->GetItemCount()-1;
4749 : }
4750 :
4751 0 : sal_uInt16 nLoop = n;
4752 :
4753 0 : if( bHomeEnd )
4754 : {
4755 : // absolute positioning
4756 0 : if( bUp )
4757 : {
4758 0 : n = pMenu->GetItemCount();
4759 0 : nLoop = n-1;
4760 : }
4761 : else
4762 : {
4763 0 : n = (sal_uInt16)-1;
4764 0 : nLoop = n+1;
4765 : }
4766 : }
4767 :
4768 0 : do
4769 : {
4770 0 : if ( bUp )
4771 : {
4772 0 : if ( n )
4773 0 : n--;
4774 : else
4775 0 : if ( !IsScrollMenu() || ( nHighlightedItem == ITEMPOS_INVALID ) )
4776 0 : n = pMenu->GetItemCount()-1;
4777 : else
4778 0 : break;
4779 : }
4780 : else
4781 : {
4782 0 : n++;
4783 0 : if ( n >= pMenu->GetItemCount() )
4784 : {
4785 0 : if ( !IsScrollMenu() || ( nHighlightedItem == ITEMPOS_INVALID ) )
4786 0 : n = 0;
4787 : else
4788 0 : break;
4789 : }
4790 : }
4791 :
4792 0 : MenuItemData* pData = (MenuItemData*)pMenu->GetItemList()->GetDataFromPos( n );
4793 0 : if ( ( pData->bEnabled || !rSettings.GetSkipDisabledInMenus() )
4794 0 : && ( pData->eType != MENUITEM_SEPARATOR ) && pMenu->ImplIsVisible( n ) && pMenu->ImplIsSelectable( n ) )
4795 : {
4796 : // Is selection in visible area?
4797 0 : if ( IsScrollMenu() )
4798 : {
4799 0 : ChangeHighlightItem( ITEMPOS_INVALID, sal_False );
4800 :
4801 0 : while ( n < nFirstEntry )
4802 0 : ImplScroll( sal_True );
4803 :
4804 0 : Size aOutSz = GetOutputSizePixel();
4805 : sal_uInt16 nLastVisible;
4806 0 : ((PopupMenu*)pMenu)->ImplCalcVisEntries( aOutSz.Height(), nFirstEntry, &nLastVisible );
4807 0 : while ( n > nLastVisible )
4808 : {
4809 0 : ImplScroll( sal_False );
4810 0 : ((PopupMenu*)pMenu)->ImplCalcVisEntries( aOutSz.Height(), nFirstEntry, &nLastVisible );
4811 : }
4812 : }
4813 0 : ChangeHighlightItem( n, sal_False );
4814 0 : break;
4815 : }
4816 : } while ( n != nLoop );
4817 : }
4818 :
4819 0 : void MenuFloatingWindow::KeyInput( const KeyEvent& rKEvent )
4820 : {
4821 0 : ImplDelData aDelData;
4822 0 : ImplAddDel( &aDelData );
4823 :
4824 0 : sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
4825 0 : bKeyInput = sal_True;
4826 0 : switch ( nCode )
4827 : {
4828 : case KEY_UP:
4829 : case KEY_DOWN:
4830 : {
4831 0 : ImplCursorUpDown( nCode == KEY_UP );
4832 : }
4833 0 : break;
4834 : case KEY_END:
4835 : case KEY_HOME:
4836 : {
4837 0 : ImplCursorUpDown( nCode == KEY_END, sal_True );
4838 : }
4839 0 : break;
4840 : case KEY_F6:
4841 : case KEY_ESCAPE:
4842 : {
4843 : // Ctrl-F6 acts like ESC here, the menu bar however will then put the focus in the document
4844 0 : if( nCode == KEY_F6 && !rKEvent.GetKeyCode().IsMod1() )
4845 0 : break;
4846 0 : if( pMenu )
4847 : {
4848 0 : if ( !pMenu->pStartedFrom )
4849 : {
4850 0 : StopExecute();
4851 0 : KillActivePopup();
4852 : }
4853 0 : else if ( pMenu->pStartedFrom->bIsMenuBar )
4854 : {
4855 : // Forward...
4856 0 : ((MenuBarWindow*)((MenuBar*)pMenu->pStartedFrom)->ImplGetWindow())->KeyInput( rKEvent );
4857 : }
4858 : else
4859 : {
4860 0 : StopExecute();
4861 0 : PopupMenu* pPopupMenu = (PopupMenu*)pMenu->pStartedFrom;
4862 0 : MenuFloatingWindow* pFloat = pPopupMenu->ImplGetFloatingWindow();
4863 0 : pFloat->GrabFocus();
4864 0 : pFloat->KillActivePopup();
4865 0 : pPopupMenu->ImplCallHighlight(pFloat->nHighlightedItem);
4866 : }
4867 : }
4868 : }
4869 0 : break;
4870 : case KEY_LEFT:
4871 : {
4872 0 : if ( pMenu && pMenu->pStartedFrom )
4873 : {
4874 0 : StopExecute();
4875 0 : if ( pMenu->pStartedFrom->bIsMenuBar )
4876 : {
4877 : // Forward...
4878 0 : ((MenuBarWindow*)((MenuBar*)pMenu->pStartedFrom)->ImplGetWindow())->KeyInput( rKEvent );
4879 : }
4880 : else
4881 : {
4882 0 : MenuFloatingWindow* pFloat = ((PopupMenu*)pMenu->pStartedFrom)->ImplGetFloatingWindow();
4883 0 : pFloat->GrabFocus();
4884 0 : pFloat->KillActivePopup();
4885 : }
4886 : }
4887 : }
4888 0 : break;
4889 : case KEY_RIGHT:
4890 : {
4891 0 : if( pMenu )
4892 : {
4893 0 : sal_Bool bDone = sal_False;
4894 0 : if ( nHighlightedItem != ITEMPOS_INVALID )
4895 : {
4896 0 : MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
4897 0 : if ( pData && pData->pSubMenu )
4898 : {
4899 0 : HighlightChanged( 0 );
4900 0 : bDone = sal_True;
4901 : }
4902 : }
4903 0 : if ( !bDone )
4904 : {
4905 0 : Menu* pStart = pMenu->ImplGetStartMenu();
4906 0 : if ( pStart && pStart->bIsMenuBar )
4907 : {
4908 : // Forward...
4909 0 : pStart->ImplGetWindow()->KeyInput( rKEvent );
4910 : }
4911 : }
4912 : }
4913 : }
4914 0 : break;
4915 : case KEY_RETURN:
4916 : {
4917 0 : if( pMenu )
4918 : {
4919 0 : MenuItemData* pData = pMenu->GetItemList()->GetDataFromPos( nHighlightedItem );
4920 0 : if ( pData && pData->bEnabled )
4921 : {
4922 0 : if ( pData->pSubMenu )
4923 0 : HighlightChanged( 0 );
4924 : else
4925 0 : EndExecute();
4926 : }
4927 : else
4928 0 : StopExecute();
4929 : }
4930 : }
4931 0 : break;
4932 : case KEY_MENU:
4933 : {
4934 0 : if( pMenu )
4935 : {
4936 0 : Menu* pStart = pMenu->ImplGetStartMenu();
4937 0 : if ( pStart && pStart->bIsMenuBar )
4938 : {
4939 : // Forward...
4940 0 : pStart->ImplGetWindow()->KeyInput( rKEvent );
4941 : }
4942 : }
4943 : }
4944 0 : break;
4945 : default:
4946 : {
4947 0 : sal_Unicode nCharCode = rKEvent.GetCharCode();
4948 0 : sal_uInt16 nPos = 0;
4949 0 : sal_uInt16 nDuplicates = 0;
4950 0 : MenuItemData* pData = (nCharCode && pMenu) ? pMenu->GetItemList()->SearchItem( nCharCode, rKEvent.GetKeyCode(), nPos, nDuplicates, nHighlightedItem ) : NULL;
4951 0 : if ( pData )
4952 : {
4953 0 : if ( pData->pSubMenu || nDuplicates > 1 )
4954 : {
4955 0 : ChangeHighlightItem( nPos, sal_False );
4956 0 : HighlightChanged( 0 );
4957 : }
4958 : else
4959 : {
4960 0 : nHighlightedItem = nPos;
4961 0 : EndExecute();
4962 : }
4963 : }
4964 : else
4965 0 : FloatingWindow::KeyInput( rKEvent );
4966 : }
4967 : }
4968 : // #105474# check if menu window was not destroyed
4969 0 : if ( !aDelData.IsDead() )
4970 : {
4971 0 : ImplRemoveDel( &aDelData );
4972 0 : bKeyInput = sal_False;
4973 0 : }
4974 0 : }
4975 :
4976 0 : void MenuFloatingWindow::Paint( const Rectangle& )
4977 : {
4978 0 : if( ! pMenu )
4979 0 : return;
4980 :
4981 0 : if( IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) )
4982 : {
4983 0 : SetClipRegion();
4984 0 : long nX = pMenu->pLogo ? pMenu->pLogo->aBitmap.GetSizePixel().Width() : 0;
4985 0 : Size aPxSize( GetOutputSizePixel() );
4986 0 : aPxSize.Width() -= nX;
4987 0 : ImplControlValue aVal( pMenu->nTextPos-GUTTERBORDER );
4988 : DrawNativeControl( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL,
4989 : Rectangle( Point( nX, 0 ), aPxSize ),
4990 : CTRL_STATE_ENABLED,
4991 : aVal,
4992 0 : OUString() );
4993 0 : ImplInitClipRegion();
4994 : }
4995 0 : if ( IsScrollMenu() )
4996 : {
4997 0 : ImplDrawScroller( sal_True );
4998 0 : ImplDrawScroller( sal_False );
4999 : }
5000 0 : SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
5001 0 : pMenu->ImplPaint( this, nScrollerHeight, ImplGetStartY() );
5002 0 : if ( nHighlightedItem != ITEMPOS_INVALID )
5003 0 : HighlightItem( nHighlightedItem, sal_True );
5004 : }
5005 :
5006 0 : void MenuFloatingWindow::ImplDrawScroller( sal_Bool bUp )
5007 : {
5008 0 : if( ! pMenu )
5009 0 : return;
5010 :
5011 0 : SetClipRegion();
5012 :
5013 0 : Size aOutSz = GetOutputSizePixel();
5014 0 : long nY = bUp ? 0 : ( aOutSz.Height() - nScrollerHeight );
5015 0 : long nX = pMenu->pLogo ? pMenu->pLogo->aBitmap.GetSizePixel().Width() : 0;
5016 0 : Rectangle aRect( Point( nX, nY ), Size( aOutSz.Width()-nX, nScrollerHeight ) );
5017 :
5018 0 : DecorationView aDecoView( this );
5019 0 : SymbolType eSymbol = bUp ? SYMBOL_SPIN_UP : SYMBOL_SPIN_DOWN;
5020 :
5021 0 : sal_uInt16 nStyle = 0;
5022 0 : if ( ( bUp && !bScrollUp ) || ( !bUp && !bScrollDown ) )
5023 0 : nStyle |= SYMBOL_DRAW_DISABLE;
5024 :
5025 0 : aDecoView.DrawSymbol( aRect, eSymbol, GetSettings().GetStyleSettings().GetButtonTextColor(), nStyle );
5026 :
5027 0 : ImplInitClipRegion();
5028 : }
5029 :
5030 0 : void MenuFloatingWindow::RequestHelp( const HelpEvent& rHEvt )
5031 : {
5032 0 : sal_uInt16 nId = nHighlightedItem;
5033 0 : Menu* pM = pMenu;
5034 0 : Window* pW = this;
5035 :
5036 : // #102618# Get item rect before destroying the window in EndExecute() call
5037 0 : Rectangle aHighlightRect( ImplGetItemRect( nHighlightedItem ) );
5038 :
5039 0 : if ( rHEvt.GetMode() & (HELPMODE_CONTEXT | HELPMODE_EXTENDED) )
5040 : {
5041 0 : nHighlightedItem = ITEMPOS_INVALID;
5042 0 : EndExecute();
5043 0 : pW = NULL;
5044 : }
5045 :
5046 0 : if( !ImplHandleHelpEvent( pW, pM, nId, rHEvt, aHighlightRect ) )
5047 0 : Window::RequestHelp( rHEvt );
5048 0 : }
5049 :
5050 0 : void MenuFloatingWindow::StateChanged( StateChangedType nType )
5051 : {
5052 0 : FloatingWindow::StateChanged( nType );
5053 :
5054 0 : if ( ( nType == STATE_CHANGE_CONTROLFOREGROUND ) || ( nType == STATE_CHANGE_CONTROLBACKGROUND ) )
5055 : {
5056 0 : ImplInitMenuWindow( this, sal_False, sal_False );
5057 0 : Invalidate();
5058 : }
5059 0 : }
5060 :
5061 0 : void MenuFloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
5062 : {
5063 0 : FloatingWindow::DataChanged( rDCEvt );
5064 :
5065 0 : if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
5066 0 : (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
5067 0 : ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
5068 0 : (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
5069 : {
5070 0 : ImplInitMenuWindow( this, sal_False, sal_False );
5071 0 : Invalidate();
5072 : }
5073 0 : }
5074 :
5075 0 : void MenuFloatingWindow::Command( const CommandEvent& rCEvt )
5076 : {
5077 0 : if ( rCEvt.GetCommand() == COMMAND_WHEEL )
5078 : {
5079 0 : const CommandWheelData* pData = rCEvt.GetWheelData();
5080 0 : if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) )
5081 : {
5082 : // ImplCursorUpDown( pData->GetDelta() > 0L );
5083 0 : ImplScroll( pData->GetDelta() > 0L );
5084 0 : MouseMove( MouseEvent( GetPointerPosPixel(), 0 ) );
5085 : }
5086 : }
5087 0 : }
5088 :
5089 0 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > MenuFloatingWindow::CreateAccessible()
5090 : {
5091 0 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xAcc;
5092 :
5093 0 : if ( pMenu && !pMenu->pStartedFrom )
5094 0 : xAcc = pMenu->GetAccessible();
5095 :
5096 0 : return xAcc;
5097 : }
5098 :
5099 236 : MenuBarWindow::MenuBarWindow( Window* pParent ) :
5100 : Window( pParent, 0 ),
5101 : aCloser( this ),
5102 : aFloatBtn( this, WB_NOPOINTERFOCUS | WB_SMALLSTYLE | WB_RECTSTYLE ),
5103 236 : aHideBtn( this, WB_NOPOINTERFOCUS | WB_SMALLSTYLE | WB_RECTSTYLE )
5104 : {
5105 236 : SetType( WINDOW_MENUBARWINDOW );
5106 236 : pMenu = NULL;
5107 236 : pActivePopup = NULL;
5108 236 : nSaveFocusId = 0;
5109 236 : nHighlightedItem = ITEMPOS_INVALID;
5110 236 : mbAutoPopup = sal_True;
5111 236 : nSaveFocusId = 0;
5112 236 : bIgnoreFirstMove = sal_True;
5113 236 : bStayActive = sal_False;
5114 :
5115 236 : ResMgr* pResMgr = ImplGetResMgr();
5116 :
5117 236 : if( pResMgr )
5118 : {
5119 236 : BitmapEx aBitmap( ResId( SV_RESID_BITMAP_CLOSEDOC, *pResMgr ) );
5120 236 : aCloser.maImage = Image( aBitmap );
5121 :
5122 236 : aCloser.SetOutStyle( TOOLBOX_STYLE_FLAT );
5123 236 : aCloser.SetBackground();
5124 236 : aCloser.SetPaintTransparent( sal_True );
5125 236 : aCloser.SetParentClipMode( PARENTCLIPMODE_NOCLIP );
5126 :
5127 236 : aCloser.InsertItem( IID_DOCUMENTCLOSE, aCloser.maImage, 0 );
5128 236 : aCloser.SetSelectHdl( LINK( this, MenuBarWindow, CloserHdl ) );
5129 236 : aCloser.AddEventListener( LINK( this, MenuBarWindow, ToolboxEventHdl ) );
5130 236 : aCloser.SetQuickHelpText( IID_DOCUMENTCLOSE, ResId(SV_HELPTEXT_CLOSEDOCUMENT, *pResMgr).toString() );
5131 :
5132 236 : aFloatBtn.SetClickHdl( LINK( this, MenuBarWindow, FloatHdl ) );
5133 236 : aFloatBtn.SetSymbol( SYMBOL_FLOAT );
5134 236 : aFloatBtn.SetQuickHelpText( ResId(SV_HELPTEXT_RESTORE, *pResMgr).toString() );
5135 :
5136 236 : aHideBtn.SetClickHdl( LINK( this, MenuBarWindow, HideHdl ) );
5137 236 : aHideBtn.SetSymbol( SYMBOL_HIDE );
5138 236 : aHideBtn.SetQuickHelpText( ResId(SV_HELPTEXT_MINIMIZE, *pResMgr).toString() );
5139 : }
5140 :
5141 236 : ImplInitStyleSettings();
5142 :
5143 236 : AddEventListener( LINK( this, MenuBarWindow, ShowHideListener ) );
5144 236 : }
5145 :
5146 189 : MenuBarWindow::~MenuBarWindow()
5147 : {
5148 63 : aCloser.RemoveEventListener( LINK( this, MenuBarWindow, ToolboxEventHdl ) );
5149 63 : RemoveEventListener( LINK( this, MenuBarWindow, ShowHideListener ) );
5150 126 : }
5151 :
5152 236 : void MenuBarWindow::SetMenu( MenuBar* pMen )
5153 : {
5154 236 : pMenu = pMen;
5155 236 : KillActivePopup();
5156 236 : nHighlightedItem = ITEMPOS_INVALID;
5157 236 : ImplInitMenuWindow( this, sal_True, sal_True );
5158 236 : if ( pMen )
5159 : {
5160 236 : aCloser.ShowItem( IID_DOCUMENTCLOSE, pMen->HasCloser() );
5161 236 : aCloser.Show( pMen->HasCloser() || !m_aAddButtons.empty() );
5162 236 : aFloatBtn.Show( pMen->HasFloatButton() );
5163 236 : aHideBtn.Show( pMen->HasHideButton() );
5164 : }
5165 236 : Invalidate();
5166 :
5167 : // show and connect native menubar
5168 236 : if( pMenu && pMenu->ImplGetSalMenu() )
5169 : {
5170 0 : if( pMenu->ImplGetSalMenu()->VisibleMenuBar() )
5171 0 : ImplGetFrame()->SetMenu( pMenu->ImplGetSalMenu() );
5172 :
5173 0 : pMenu->ImplGetSalMenu()->SetFrame( ImplGetFrame() );
5174 : }
5175 236 : }
5176 :
5177 25 : void MenuBarWindow::ShowButtons( sal_Bool bClose, sal_Bool bFloat, sal_Bool bHide )
5178 : {
5179 25 : aCloser.ShowItem( IID_DOCUMENTCLOSE, bClose );
5180 25 : aCloser.Show( bClose || ! m_aAddButtons.empty() );
5181 25 : aFloatBtn.Show( bFloat );
5182 25 : aHideBtn.Show( bHide );
5183 25 : Resize();
5184 25 : }
5185 :
5186 236 : Size MenuBarWindow::MinCloseButtonSize()
5187 : {
5188 236 : return aCloser.getMinSize();
5189 : }
5190 :
5191 0 : IMPL_LINK_NOARG(MenuBarWindow, CloserHdl)
5192 : {
5193 0 : if( ! pMenu )
5194 0 : return 0;
5195 :
5196 0 : if( aCloser.GetCurItemId() == IID_DOCUMENTCLOSE )
5197 : {
5198 : // #i106052# call close hdl asynchronously to ease handler implementation
5199 : // this avoids still being in the handler while the DecoToolBox already
5200 : // gets destroyed
5201 0 : Application::PostUserEvent( ((MenuBar*)pMenu)->GetCloserHdl(), pMenu );
5202 : }
5203 : else
5204 : {
5205 0 : std::map<sal_uInt16,AddButtonEntry>::iterator it = m_aAddButtons.find( aCloser.GetCurItemId() );
5206 0 : if( it != m_aAddButtons.end() )
5207 : {
5208 : MenuBar::MenuBarButtonCallbackArg aArg;
5209 0 : aArg.nId = it->first;
5210 0 : aArg.bHighlight = (aCloser.GetHighlightItemId() == it->first);
5211 0 : aArg.pMenuBar = dynamic_cast<MenuBar*>(pMenu);
5212 0 : return it->second.m_aSelectLink.Call( &aArg );
5213 : }
5214 : }
5215 0 : return 0;
5216 : }
5217 :
5218 1142 : IMPL_LINK( MenuBarWindow, ToolboxEventHdl, VclWindowEvent*, pEvent )
5219 : {
5220 571 : if( ! pMenu )
5221 0 : return 0;
5222 :
5223 : MenuBar::MenuBarButtonCallbackArg aArg;
5224 571 : aArg.nId = 0xffff;
5225 571 : aArg.bHighlight = (pEvent->GetId() == VCLEVENT_TOOLBOX_HIGHLIGHT);
5226 571 : aArg.pMenuBar = dynamic_cast<MenuBar*>(pMenu);
5227 571 : if( pEvent->GetId() == VCLEVENT_TOOLBOX_HIGHLIGHT )
5228 0 : aArg.nId = aCloser.GetHighlightItemId();
5229 571 : else if( pEvent->GetId() == VCLEVENT_TOOLBOX_HIGHLIGHTOFF )
5230 : {
5231 0 : sal_uInt16 nPos = static_cast< sal_uInt16 >(reinterpret_cast<sal_IntPtr>(pEvent->GetData()));
5232 0 : aArg.nId = aCloser.GetItemId( nPos );
5233 : }
5234 571 : std::map< sal_uInt16, AddButtonEntry >::iterator it = m_aAddButtons.find( aArg.nId );
5235 571 : if( it != m_aAddButtons.end() )
5236 : {
5237 0 : it->second.m_aHighlightLink.Call( &aArg );
5238 : }
5239 571 : return 0;
5240 : }
5241 :
5242 2108 : IMPL_LINK( MenuBarWindow, ShowHideListener, VclWindowEvent*, pEvent )
5243 : {
5244 1054 : if( ! pMenu )
5245 0 : return 0;
5246 :
5247 1054 : if( pEvent->GetId() == VCLEVENT_WINDOW_SHOW )
5248 330 : pMenu->ImplCallEventListeners( VCLEVENT_MENU_SHOW, ITEMPOS_INVALID );
5249 724 : else if( pEvent->GetId() == VCLEVENT_WINDOW_HIDE )
5250 0 : pMenu->ImplCallEventListeners( VCLEVENT_MENU_HIDE, ITEMPOS_INVALID );
5251 1054 : return 0;
5252 : }
5253 :
5254 0 : IMPL_LINK_NOARG(MenuBarWindow, FloatHdl)
5255 : {
5256 0 : return pMenu ? ((MenuBar*)pMenu)->GetFloatButtonClickHdl().Call( pMenu ) : 0;
5257 : }
5258 :
5259 0 : IMPL_LINK_NOARG(MenuBarWindow, HideHdl)
5260 : {
5261 0 : return pMenu ? ((MenuBar*)pMenu)->GetHideButtonClickHdl().Call( pMenu ) : 0;
5262 : }
5263 :
5264 0 : void MenuBarWindow::ImplCreatePopup( sal_Bool bPreSelectFirst )
5265 : {
5266 0 : MenuItemData* pItemData = pMenu ? pMenu->GetItemList()->GetDataFromPos( nHighlightedItem ) : NULL;
5267 0 : if ( pItemData )
5268 : {
5269 0 : bIgnoreFirstMove = sal_True;
5270 0 : if ( pActivePopup && ( pActivePopup != pItemData->pSubMenu ) )
5271 : {
5272 0 : KillActivePopup();
5273 : }
5274 0 : if ( pItemData->bEnabled && pItemData->pSubMenu && ( nHighlightedItem != ITEMPOS_INVALID ) && ( pItemData->pSubMenu != pActivePopup ) )
5275 : {
5276 0 : pActivePopup = (PopupMenu*)pItemData->pSubMenu;
5277 0 : long nX = 0;
5278 0 : MenuItemData* pData = 0;
5279 0 : for ( sal_uLong n = 0; n < nHighlightedItem; n++ )
5280 : {
5281 0 : pData = pMenu->GetItemList()->GetDataFromPos( n );
5282 0 : nX += pData->aSz.Width();
5283 : }
5284 0 : pData = pMenu->pItemList->GetDataFromPos( nHighlightedItem );
5285 0 : Point aItemTopLeft( nX, 0 );
5286 0 : Point aItemBottomRight( aItemTopLeft );
5287 0 : aItemBottomRight.X() += pData->aSz.Width();
5288 :
5289 : // the menu bar could have height 0 in fullscreen mode:
5290 : // so do not use always WindowHeight, as ItemHeight < WindowHeight.
5291 0 : if ( GetSizePixel().Height() )
5292 : {
5293 : // #107747# give menuitems the height of the menubar
5294 0 : aItemBottomRight.Y() += GetOutputSizePixel().Height()-1;
5295 : }
5296 :
5297 : // ImplExecute is not modal...
5298 : // #99071# do not grab the focus, otherwise it will be restored to the menubar
5299 : // when the frame is reactivated later
5300 : //GrabFocus();
5301 0 : pActivePopup->ImplExecute( this, Rectangle( aItemTopLeft, aItemBottomRight ), FLOATWIN_POPUPMODE_DOWN, pMenu, bPreSelectFirst );
5302 0 : if ( pActivePopup )
5303 : {
5304 : // does not have a window, if aborted before or if there are no entries
5305 0 : if ( pActivePopup->ImplGetFloatingWindow() )
5306 0 : pActivePopup->ImplGetFloatingWindow()->AddPopupModeWindow( this );
5307 : else
5308 0 : pActivePopup = NULL;
5309 : }
5310 : }
5311 : }
5312 0 : }
5313 :
5314 :
5315 299 : void MenuBarWindow::KillActivePopup()
5316 : {
5317 299 : if ( pActivePopup )
5318 : {
5319 0 : if( pActivePopup->pWindow != NULL )
5320 0 : if( ((FloatingWindow *) pActivePopup->pWindow)->IsInCleanUp() )
5321 299 : return; // kill it later
5322 :
5323 0 : if ( pActivePopup->bInCallback )
5324 0 : pActivePopup->bCanceled = sal_True;
5325 :
5326 0 : pActivePopup->bInCallback = sal_True;
5327 0 : pActivePopup->Deactivate();
5328 0 : pActivePopup->bInCallback = sal_False;
5329 : // check for pActivePopup, if stopped by deactivate...
5330 0 : if ( pActivePopup->ImplGetWindow() )
5331 : {
5332 0 : pActivePopup->ImplGetFloatingWindow()->StopExecute();
5333 0 : pActivePopup->ImplGetFloatingWindow()->doShutdown();
5334 0 : pActivePopup->pWindow->doLazyDelete();
5335 0 : pActivePopup->pWindow = NULL;
5336 : }
5337 0 : pActivePopup = 0;
5338 : }
5339 : }
5340 :
5341 0 : void MenuBarWindow::PopupClosed( Menu* pPopup )
5342 : {
5343 0 : if ( pPopup == pActivePopup )
5344 : {
5345 0 : KillActivePopup();
5346 0 : ChangeHighlightItem( ITEMPOS_INVALID, sal_False, ImplGetFrameWindow()->ImplGetFrameData()->mbHasFocus, sal_False );
5347 : }
5348 0 : }
5349 :
5350 0 : void MenuBarWindow::MouseButtonDown( const MouseEvent& rMEvt )
5351 : {
5352 0 : mbAutoPopup = sal_True;
5353 0 : sal_uInt16 nEntry = ImplFindEntry( rMEvt.GetPosPixel() );
5354 0 : if ( ( nEntry != ITEMPOS_INVALID ) && ( nEntry != nHighlightedItem ) )
5355 : {
5356 0 : ChangeHighlightItem( nEntry, sal_False );
5357 : }
5358 : else
5359 : {
5360 0 : KillActivePopup();
5361 0 : ChangeHighlightItem( ITEMPOS_INVALID, sal_False );
5362 : }
5363 0 : }
5364 :
5365 0 : void MenuBarWindow::MouseButtonUp( const MouseEvent& )
5366 : {
5367 0 : }
5368 :
5369 0 : void MenuBarWindow::MouseMove( const MouseEvent& rMEvt )
5370 : {
5371 : // only highlight during Move if if was already highlighted.
5372 0 : if ( rMEvt.IsSynthetic() || rMEvt.IsLeaveWindow() || rMEvt.IsEnterWindow() || ( nHighlightedItem == ITEMPOS_INVALID ) )
5373 0 : return;
5374 :
5375 0 : if( bIgnoreFirstMove )
5376 : {
5377 0 : bIgnoreFirstMove = sal_False;
5378 0 : return;
5379 : }
5380 :
5381 0 : sal_uInt16 nEntry = ImplFindEntry( rMEvt.GetPosPixel() );
5382 0 : if ( ( nEntry != ITEMPOS_INVALID )
5383 : && ( nEntry != nHighlightedItem ) )
5384 0 : ChangeHighlightItem( nEntry, sal_False );
5385 : }
5386 :
5387 0 : void MenuBarWindow::ChangeHighlightItem( sal_uInt16 n, sal_Bool bSelectEntry, sal_Bool bAllowRestoreFocus, sal_Bool bDefaultToDocument)
5388 : {
5389 0 : if( ! pMenu )
5390 0 : return;
5391 :
5392 : // #57934# close active popup if applicable, as TH's background storage works.
5393 0 : MenuItemData* pNextData = pMenu->pItemList->GetDataFromPos( n );
5394 0 : if ( pActivePopup && pActivePopup->ImplGetWindow() && ( !pNextData || ( pActivePopup != pNextData->pSubMenu ) ) )
5395 0 : KillActivePopup(); // pActivePopup when applicable without pWin, if Rescheduled in Activate()
5396 :
5397 : // activate menubar only ones per cycle...
5398 0 : sal_Bool bJustActivated = sal_False;
5399 0 : if ( ( nHighlightedItem == ITEMPOS_INVALID ) && ( n != ITEMPOS_INVALID ) )
5400 : {
5401 0 : ImplGetSVData()->maWinData.mbNoDeactivate = sal_True;
5402 0 : if( !bStayActive )
5403 : {
5404 : // #105406# avoid saving the focus when we already have the focus
5405 0 : sal_Bool bNoSaveFocus = (this == ImplGetSVData()->maWinData.mpFocusWin );
5406 :
5407 0 : if( nSaveFocusId )
5408 : {
5409 0 : if( !ImplGetSVData()->maWinData.mbNoSaveFocus )
5410 : {
5411 : // we didn't clean up last time
5412 0 : Window::EndSaveFocus( nSaveFocusId, sal_False ); // clean up
5413 0 : nSaveFocusId = 0;
5414 0 : if( !bNoSaveFocus )
5415 0 : nSaveFocusId = Window::SaveFocus(); // only save focus when initially activated
5416 : }
5417 : else {
5418 : ; // do nothing: we 're activated again from taskpanelist, focus was already saved
5419 : }
5420 : }
5421 : else
5422 : {
5423 0 : if( !bNoSaveFocus )
5424 0 : nSaveFocusId = Window::SaveFocus(); // only save focus when initially activated
5425 : }
5426 : }
5427 : else
5428 0 : bStayActive = sal_False;
5429 0 : pMenu->bInCallback = sal_True; // set here if Activate overloaded
5430 0 : pMenu->Activate();
5431 0 : pMenu->bInCallback = sal_False;
5432 0 : bJustActivated = sal_True;
5433 : }
5434 0 : else if ( ( nHighlightedItem != ITEMPOS_INVALID ) && ( n == ITEMPOS_INVALID ) )
5435 : {
5436 0 : pMenu->bInCallback = sal_True;
5437 0 : pMenu->Deactivate();
5438 0 : pMenu->bInCallback = sal_False;
5439 0 : ImplGetSVData()->maWinData.mbNoDeactivate = sal_False;
5440 0 : if( !ImplGetSVData()->maWinData.mbNoSaveFocus )
5441 : {
5442 0 : sal_uLong nTempFocusId = nSaveFocusId;
5443 0 : nSaveFocusId = 0;
5444 0 : Window::EndSaveFocus( nTempFocusId, bAllowRestoreFocus );
5445 : // #105406# restore focus to document if we could not save focus before
5446 0 : if( bDefaultToDocument && !nTempFocusId && bAllowRestoreFocus )
5447 0 : GrabFocusToDocument();
5448 : }
5449 : }
5450 :
5451 0 : if ( nHighlightedItem != ITEMPOS_INVALID )
5452 : {
5453 0 : HighlightItem( nHighlightedItem, sal_False );
5454 0 : pMenu->ImplCallEventListeners( VCLEVENT_MENU_DEHIGHLIGHT, nHighlightedItem );
5455 : }
5456 :
5457 0 : nHighlightedItem = (sal_uInt16)n;
5458 : DBG_ASSERT( ( nHighlightedItem == ITEMPOS_INVALID ) || pMenu->ImplIsVisible( nHighlightedItem ), "ChangeHighlightItem: Not visible!" );
5459 0 : HighlightItem( nHighlightedItem, sal_True );
5460 0 : pMenu->ImplCallHighlight( nHighlightedItem );
5461 :
5462 0 : if( mbAutoPopup )
5463 0 : ImplCreatePopup( bSelectEntry );
5464 :
5465 : // #58935# #73659# Focus, if no popup underneath...
5466 0 : if ( bJustActivated && !pActivePopup )
5467 0 : GrabFocus();
5468 : }
5469 :
5470 0 : void MenuBarWindow::HighlightItem( sal_uInt16 nPos, sal_Bool bHighlight )
5471 : {
5472 0 : if( ! pMenu )
5473 0 : return;
5474 :
5475 0 : long nX = 0;
5476 0 : size_t nCount = pMenu->pItemList->size();
5477 0 : for ( size_t n = 0; n < nCount; n++ )
5478 : {
5479 0 : MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
5480 0 : if ( n == nPos )
5481 : {
5482 0 : if ( pData->eType != MENUITEM_SEPARATOR )
5483 : {
5484 : // #107747# give menuitems the height of the menubar
5485 0 : Rectangle aRect = Rectangle( Point( nX, 1 ), Size( pData->aSz.Width(), GetOutputSizePixel().Height()-2 ) );
5486 0 : Push( PUSH_CLIPREGION );
5487 0 : IntersectClipRegion( aRect );
5488 0 : if ( bHighlight )
5489 : {
5490 0 : if( IsNativeControlSupported( CTRL_MENUBAR, PART_MENU_ITEM ) &&
5491 0 : IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
5492 : {
5493 : // draw background (transparency)
5494 0 : MenubarValue aControlValue;
5495 0 : aControlValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight( this );
5496 :
5497 0 : Point tmp(0,0);
5498 0 : Rectangle aBgRegion( tmp, GetOutputSizePixel() );
5499 : DrawNativeControl( CTRL_MENUBAR, PART_ENTIRE_CONTROL,
5500 : aBgRegion,
5501 : CTRL_STATE_ENABLED,
5502 : aControlValue,
5503 0 : OUString() );
5504 0 : ImplAddNWFSeparator( this, aControlValue );
5505 :
5506 : // draw selected item
5507 : DrawNativeControl( CTRL_MENUBAR, PART_MENU_ITEM,
5508 : aRect,
5509 : CTRL_STATE_ENABLED | CTRL_STATE_SELECTED,
5510 : aControlValue,
5511 0 : OUString() );
5512 : }
5513 : else
5514 : {
5515 0 : SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
5516 0 : SetLineColor();
5517 0 : DrawRect( aRect );
5518 : }
5519 : }
5520 : else
5521 : {
5522 0 : if( IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL) )
5523 : {
5524 0 : MenubarValue aMenubarValue;
5525 0 : aMenubarValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight( this );
5526 :
5527 : // use full window size to get proper gradient
5528 : // but clip accordingly
5529 0 : Point aPt;
5530 0 : Rectangle aCtrlRect( aPt, GetOutputSizePixel() );
5531 :
5532 0 : DrawNativeControl( CTRL_MENUBAR, PART_ENTIRE_CONTROL, aCtrlRect, CTRL_STATE_ENABLED, aMenubarValue, rtl::OUString() );
5533 0 : ImplAddNWFSeparator( this, aMenubarValue );
5534 : }
5535 : else
5536 0 : Erase( aRect );
5537 : }
5538 0 : Pop();
5539 0 : pMenu->ImplPaint( this, 0, 0, pData, bHighlight );
5540 : }
5541 0 : return;
5542 : }
5543 :
5544 0 : nX += pData->aSz.Width();
5545 : }
5546 : }
5547 :
5548 0 : Rectangle MenuBarWindow::ImplGetItemRect( sal_uInt16 nPos )
5549 : {
5550 0 : Rectangle aRect;
5551 0 : if( pMenu )
5552 : {
5553 0 : long nX = 0;
5554 0 : size_t nCount = pMenu->pItemList->size();
5555 0 : for ( size_t n = 0; n < nCount; n++ )
5556 : {
5557 0 : MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
5558 0 : if ( n == nPos )
5559 : {
5560 0 : if ( pData->eType != MENUITEM_SEPARATOR )
5561 : // #107747# give menuitems the height of the menubar
5562 0 : aRect = Rectangle( Point( nX, 1 ), Size( pData->aSz.Width(), GetOutputSizePixel().Height()-2 ) );
5563 0 : break;
5564 : }
5565 :
5566 0 : nX += pData->aSz.Width();
5567 : }
5568 : }
5569 0 : return aRect;
5570 : }
5571 :
5572 0 : void MenuBarWindow::KeyInput( const KeyEvent& rKEvent )
5573 : {
5574 0 : if ( !ImplHandleKeyEvent( rKEvent ) )
5575 0 : Window::KeyInput( rKEvent );
5576 0 : }
5577 :
5578 0 : sal_Bool MenuBarWindow::ImplHandleKeyEvent( const KeyEvent& rKEvent, sal_Bool bFromMenu )
5579 : {
5580 0 : if( ! pMenu )
5581 0 : return sal_False;
5582 :
5583 0 : if ( pMenu->bInCallback )
5584 0 : return sal_True; // swallow
5585 :
5586 0 : sal_Bool bDone = sal_False;
5587 0 : sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
5588 :
5589 0 : if( GetParent() )
5590 : {
5591 0 : if( GetParent()->GetWindow( WINDOW_CLIENT )->IsSystemWindow() )
5592 : {
5593 0 : SystemWindow *pSysWin = (SystemWindow*)GetParent()->GetWindow( WINDOW_CLIENT );
5594 0 : if( pSysWin->GetTaskPaneList() )
5595 0 : if( pSysWin->GetTaskPaneList()->HandleKeyEvent( rKEvent ) )
5596 0 : return sal_True;
5597 : }
5598 : }
5599 :
5600 0 : if ( nCode == KEY_MENU && !rKEvent.GetKeyCode().IsShift() ) // only F10, not Shift-F10
5601 : {
5602 0 : mbAutoPopup = ImplGetSVData()->maNWFData.mbOpenMenuOnF10;
5603 0 : if ( nHighlightedItem == ITEMPOS_INVALID )
5604 : {
5605 0 : ChangeHighlightItem( 0, sal_False );
5606 0 : GrabFocus();
5607 : }
5608 : else
5609 : {
5610 0 : ChangeHighlightItem( ITEMPOS_INVALID, sal_False );
5611 0 : nSaveFocusId = 0;
5612 : }
5613 0 : bDone = sal_True;
5614 : }
5615 0 : else if ( bFromMenu )
5616 : {
5617 0 : if ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) ||
5618 : ( nCode == KEY_HOME ) || ( nCode == KEY_END ) )
5619 : {
5620 0 : sal_uInt16 n = nHighlightedItem;
5621 0 : if ( n == ITEMPOS_INVALID )
5622 : {
5623 0 : if ( nCode == KEY_LEFT)
5624 0 : n = 0;
5625 : else
5626 0 : n = pMenu->GetItemCount()-1;
5627 : }
5628 :
5629 : // handling gtk like (aka mbOpenMenuOnF10)
5630 : // do not highlight an item when opening a sub menu
5631 : // unless there already was a higlighted sub menu item
5632 0 : bool bWasHighlight = false;
5633 0 : if( pActivePopup )
5634 : {
5635 0 : MenuFloatingWindow* pSubWindow = dynamic_cast<MenuFloatingWindow*>(pActivePopup->ImplGetWindow());
5636 0 : if( pSubWindow )
5637 0 : bWasHighlight = (pSubWindow->GetHighlightedItem() != ITEMPOS_INVALID);
5638 : }
5639 :
5640 0 : sal_uInt16 nLoop = n;
5641 :
5642 0 : if( nCode == KEY_HOME )
5643 0 : { n = (sal_uInt16)-1; nLoop = n+1; }
5644 0 : if( nCode == KEY_END )
5645 0 : { n = pMenu->GetItemCount(); nLoop = n-1; }
5646 :
5647 0 : do
5648 : {
5649 0 : if ( nCode == KEY_LEFT || nCode == KEY_END )
5650 : {
5651 0 : if ( n )
5652 0 : n--;
5653 : else
5654 0 : n = pMenu->GetItemCount()-1;
5655 : }
5656 0 : if ( nCode == KEY_RIGHT || nCode == KEY_HOME )
5657 : {
5658 0 : n++;
5659 0 : if ( n >= pMenu->GetItemCount() )
5660 0 : n = 0;
5661 : }
5662 :
5663 0 : MenuItemData* pData = (MenuItemData*)pMenu->GetItemList()->GetDataFromPos( n );
5664 0 : if ( ( pData->eType != MENUITEM_SEPARATOR ) && pMenu->ImplIsVisible( n ) )
5665 : {
5666 0 : sal_Bool bDoSelect = sal_True;
5667 0 : if( ImplGetSVData()->maNWFData.mbOpenMenuOnF10 )
5668 0 : bDoSelect = bWasHighlight;
5669 0 : ChangeHighlightItem( n, bDoSelect );
5670 0 : break;
5671 : }
5672 : } while ( n != nLoop );
5673 0 : bDone = sal_True;
5674 : }
5675 0 : else if ( nCode == KEY_RETURN )
5676 : {
5677 0 : if( pActivePopup ) KillActivePopup();
5678 : else
5679 0 : if ( !mbAutoPopup )
5680 : {
5681 0 : ImplCreatePopup( sal_True );
5682 0 : mbAutoPopup = sal_True;
5683 : }
5684 0 : bDone = sal_True;
5685 : }
5686 0 : else if ( ( nCode == KEY_UP ) || ( nCode == KEY_DOWN ) )
5687 : {
5688 0 : if ( !mbAutoPopup )
5689 : {
5690 0 : ImplCreatePopup( sal_True );
5691 0 : mbAutoPopup = sal_True;
5692 : }
5693 0 : bDone = sal_True;
5694 : }
5695 0 : else if ( nCode == KEY_ESCAPE || ( nCode == KEY_F6 && rKEvent.GetKeyCode().IsMod1() ) )
5696 : {
5697 0 : if( pActivePopup )
5698 : {
5699 : // bring focus to menu bar without any open popup
5700 0 : mbAutoPopup = sal_False;
5701 0 : sal_uInt16 n = nHighlightedItem;
5702 0 : nHighlightedItem = ITEMPOS_INVALID;
5703 0 : bStayActive = sal_True;
5704 0 : ChangeHighlightItem( n, sal_False );
5705 0 : bStayActive = sal_False;
5706 0 : KillActivePopup();
5707 0 : GrabFocus();
5708 : }
5709 : else
5710 0 : ChangeHighlightItem( ITEMPOS_INVALID, sal_False );
5711 :
5712 0 : if( nCode == KEY_F6 && rKEvent.GetKeyCode().IsMod1() )
5713 : {
5714 : // put focus into document
5715 0 : GrabFocusToDocument();
5716 : }
5717 :
5718 0 : bDone = sal_True;
5719 : }
5720 : }
5721 :
5722 0 : if ( !bDone && ( bFromMenu || rKEvent.GetKeyCode().IsMod2() ) )
5723 : {
5724 0 : sal_Unicode nCharCode = rKEvent.GetCharCode();
5725 0 : if ( nCharCode )
5726 : {
5727 : sal_uInt16 nEntry, nDuplicates;
5728 0 : MenuItemData* pData = pMenu->GetItemList()->SearchItem( nCharCode, rKEvent.GetKeyCode(), nEntry, nDuplicates, nHighlightedItem );
5729 0 : if ( pData && (nEntry != ITEMPOS_INVALID) )
5730 : {
5731 0 : mbAutoPopup = sal_True;
5732 0 : ChangeHighlightItem( nEntry, sal_True );
5733 0 : bDone = sal_True;
5734 : }
5735 : }
5736 : }
5737 0 : return bDone;
5738 : }
5739 :
5740 177 : void MenuBarWindow::Paint( const Rectangle& )
5741 : {
5742 177 : if( ! pMenu )
5743 0 : return;
5744 :
5745 : // no VCL paint if native menus
5746 177 : if( pMenu->ImplGetSalMenu() && pMenu->ImplGetSalMenu()->VisibleMenuBar() )
5747 : {
5748 0 : ImplGetFrame()->DrawMenuBar();
5749 0 : return;
5750 : }
5751 :
5752 177 : if( IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL) )
5753 : {
5754 0 : Point aPt;
5755 0 : Rectangle aCtrlRegion( aPt, GetOutputSizePixel() );
5756 :
5757 0 : MenubarValue aMenubarValue;
5758 0 : aMenubarValue.maTopDockingAreaHeight = ImplGetTopDockingAreaHeight( this );
5759 :
5760 0 : DrawNativeControl( CTRL_MENUBAR, PART_ENTIRE_CONTROL, aCtrlRegion, CTRL_STATE_ENABLED, aMenubarValue, rtl::OUString() );
5761 0 : ImplAddNWFSeparator( this, aMenubarValue );
5762 : }
5763 177 : SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
5764 177 : pMenu->ImplPaint( this, 0 );
5765 177 : if ( nHighlightedItem != ITEMPOS_INVALID )
5766 0 : HighlightItem( nHighlightedItem, sal_True );
5767 :
5768 : // in high contrast mode draw a separating line on the lower edge
5769 354 : if( ! IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL) &&
5770 177 : GetSettings().GetStyleSettings().GetHighContrastMode() )
5771 : {
5772 0 : Push( PUSH_LINECOLOR | PUSH_MAPMODE );
5773 0 : SetLineColor( Color( COL_WHITE ) );
5774 0 : SetMapMode( MapMode( MAP_PIXEL ) );
5775 0 : Size aSize = GetSizePixel();
5776 0 : DrawLine( Point( 0, aSize.Height()-1 ), Point( aSize.Width()-1, aSize.Height()-1 ) );
5777 0 : Pop();
5778 : }
5779 :
5780 : }
5781 :
5782 311 : void MenuBarWindow::Resize()
5783 : {
5784 311 : Size aOutSz = GetOutputSizePixel();
5785 311 : long n = aOutSz.Height()-4;
5786 311 : long nX = aOutSz.Width()-3;
5787 311 : long nY = 2;
5788 :
5789 311 : if ( aCloser.IsVisible() )
5790 : {
5791 17 : aCloser.Hide();
5792 17 : aCloser.SetImages( n );
5793 17 : Size aTbxSize( aCloser.CalcWindowSizePixel() );
5794 17 : nX -= aTbxSize.Width();
5795 17 : long nTbxY = (aOutSz.Height() - aTbxSize.Height())/2;
5796 17 : aCloser.setPosSizePixel( nX, nTbxY, aTbxSize.Width(), aTbxSize.Height() );
5797 17 : nX -= 3;
5798 17 : aCloser.Show();
5799 : }
5800 311 : if ( aFloatBtn.IsVisible() )
5801 : {
5802 0 : nX -= n;
5803 0 : aFloatBtn.setPosSizePixel( nX, nY, n, n );
5804 : }
5805 311 : if ( aHideBtn.IsVisible() )
5806 : {
5807 0 : nX -= n;
5808 0 : aHideBtn.setPosSizePixel( nX, nY, n, n );
5809 : }
5810 :
5811 311 : aFloatBtn.SetSymbol( SYMBOL_FLOAT );
5812 311 : aHideBtn.SetSymbol( SYMBOL_HIDE );
5813 : //aCloser.SetSymbol( SYMBOL_CLOSE ); //is a toolbox now
5814 :
5815 311 : Invalidate();
5816 311 : }
5817 :
5818 0 : sal_uInt16 MenuBarWindow::ImplFindEntry( const Point& rMousePos ) const
5819 : {
5820 0 : if( pMenu )
5821 : {
5822 0 : long nX = 0;
5823 0 : size_t nCount = pMenu->pItemList->size();
5824 0 : for ( size_t n = 0; n < nCount; n++ )
5825 : {
5826 0 : MenuItemData* pData = pMenu->pItemList->GetDataFromPos( n );
5827 0 : if ( pMenu->ImplIsVisible( n ) )
5828 : {
5829 0 : nX += pData->aSz.Width();
5830 0 : if ( nX > rMousePos.X() )
5831 0 : return (sal_uInt16)n;
5832 : }
5833 : }
5834 : }
5835 0 : return ITEMPOS_INVALID;
5836 : }
5837 :
5838 0 : void MenuBarWindow::RequestHelp( const HelpEvent& rHEvt )
5839 : {
5840 0 : sal_uInt16 nId = nHighlightedItem;
5841 0 : if ( rHEvt.GetMode() & (HELPMODE_CONTEXT | HELPMODE_EXTENDED) )
5842 0 : ChangeHighlightItem( ITEMPOS_INVALID, sal_True );
5843 :
5844 0 : Rectangle aHighlightRect( ImplGetItemRect( nHighlightedItem ) );
5845 0 : if( !ImplHandleHelpEvent( this, pMenu, nId, rHEvt, aHighlightRect ) )
5846 0 : Window::RequestHelp( rHEvt );
5847 0 : }
5848 :
5849 582 : void MenuBarWindow::StateChanged( StateChangedType nType )
5850 : {
5851 582 : Window::StateChanged( nType );
5852 :
5853 582 : if ( ( nType == STATE_CHANGE_CONTROLFOREGROUND ) ||
5854 : ( nType == STATE_CHANGE_CONTROLBACKGROUND ) )
5855 : {
5856 0 : ImplInitMenuWindow( this, sal_False, sal_True );
5857 0 : Invalidate();
5858 : }
5859 582 : else if( pMenu )
5860 582 : pMenu->ImplKillLayoutData();
5861 :
5862 582 : }
5863 :
5864 0 : void MenuBarWindow::ImplLayoutChanged()
5865 : {
5866 0 : if( pMenu )
5867 : {
5868 0 : ImplInitMenuWindow( this, sal_True, sal_True );
5869 : // if the font was changed.
5870 0 : long nHeight = pMenu->ImplCalcSize( this ).Height();
5871 :
5872 : // depending on the native implementation or the displayable flag
5873 : // the menubar windows is supressed (ie, height=0)
5874 0 : if( !((MenuBar*) pMenu)->IsDisplayable() ||
5875 0 : ( pMenu->ImplGetSalMenu() && pMenu->ImplGetSalMenu()->VisibleMenuBar() ) )
5876 0 : nHeight = 0;
5877 :
5878 0 : setPosSizePixel( 0, 0, 0, nHeight, WINDOW_POSSIZE_HEIGHT );
5879 0 : GetParent()->Resize();
5880 0 : Invalidate();
5881 0 : Resize();
5882 0 : if( pMenu )
5883 0 : pMenu->ImplKillLayoutData();
5884 : }
5885 0 : }
5886 :
5887 236 : void MenuBarWindow::ImplInitStyleSettings()
5888 : {
5889 236 : if( IsNativeControlSupported( CTRL_MENUBAR, PART_MENU_ITEM ) &&
5890 0 : IsNativeControlSupported( CTRL_MENUBAR, PART_ENTIRE_CONTROL ) )
5891 : {
5892 0 : Color aHighlightTextColor = ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor;
5893 0 : if( aHighlightTextColor != Color( COL_TRANSPARENT ) )
5894 : {
5895 0 : AllSettings aSettings( GetSettings() );
5896 0 : StyleSettings aStyle( aSettings.GetStyleSettings() );
5897 0 : aStyle.SetMenuHighlightTextColor( aHighlightTextColor );
5898 0 : aSettings.SetStyleSettings( aStyle );
5899 0 : OutputDevice::SetSettings( aSettings );
5900 : }
5901 : }
5902 236 : }
5903 :
5904 92 : void MenuBarWindow::DataChanged( const DataChangedEvent& rDCEvt )
5905 : {
5906 92 : Window::DataChanged( rDCEvt );
5907 :
5908 368 : if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
5909 92 : (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
5910 92 : ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
5911 92 : (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
5912 : {
5913 0 : ImplLayoutChanged();
5914 0 : ImplInitStyleSettings();
5915 : }
5916 92 : }
5917 :
5918 0 : void MenuBarWindow::LoseFocus()
5919 : {
5920 0 : if ( !HasChildPathFocus( sal_True ) )
5921 0 : ChangeHighlightItem( ITEMPOS_INVALID, sal_False, sal_False );
5922 0 : }
5923 :
5924 0 : void MenuBarWindow::GetFocus()
5925 : {
5926 0 : if ( nHighlightedItem == ITEMPOS_INVALID )
5927 : {
5928 0 : mbAutoPopup = sal_False; // do not open menu when activated by focus handling like taskpane cycling
5929 0 : ChangeHighlightItem( 0, sal_False );
5930 : }
5931 0 : }
5932 :
5933 0 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > MenuBarWindow::CreateAccessible()
5934 : {
5935 0 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xAcc;
5936 :
5937 0 : if ( pMenu )
5938 0 : xAcc = pMenu->GetAccessible();
5939 :
5940 0 : return xAcc;
5941 : }
5942 :
5943 0 : sal_uInt16 MenuBarWindow::AddMenuBarButton( const Image& i_rImage, const Link& i_rLink, const String& i_rToolTip, sal_uInt16 i_nPos )
5944 : {
5945 : // find first free button id
5946 0 : sal_uInt16 nId = IID_DOCUMENTCLOSE;
5947 0 : std::map< sal_uInt16, AddButtonEntry >::const_iterator it;
5948 0 : if( i_nPos > m_aAddButtons.size() )
5949 0 : i_nPos = static_cast<sal_uInt16>(m_aAddButtons.size());
5950 0 : do
5951 : {
5952 0 : nId++;
5953 0 : it = m_aAddButtons.find( nId );
5954 0 : } while( it != m_aAddButtons.end() && nId < 128 );
5955 : DBG_ASSERT( nId < 128, "too many addbuttons in menubar" );
5956 0 : AddButtonEntry& rNewEntry = m_aAddButtons[nId];
5957 0 : rNewEntry.m_nId = nId;
5958 0 : rNewEntry.m_aSelectLink = i_rLink;
5959 0 : aCloser.InsertItem( nId, i_rImage, 0, 0 );
5960 0 : aCloser.calcMinSize();
5961 0 : ShowButtons( aCloser.IsItemVisible( IID_DOCUMENTCLOSE ),
5962 0 : aFloatBtn.IsVisible(),
5963 0 : aHideBtn.IsVisible() );
5964 0 : ImplLayoutChanged();
5965 :
5966 0 : if( pMenu->mpSalMenu )
5967 0 : pMenu->mpSalMenu->AddMenuBarButton( SalMenuButtonItem( nId, i_rImage, i_rToolTip ) );
5968 :
5969 0 : return nId;
5970 : }
5971 :
5972 0 : void MenuBarWindow::SetMenuBarButtonHighlightHdl( sal_uInt16 nId, const Link& rLink )
5973 : {
5974 0 : std::map< sal_uInt16, AddButtonEntry >::iterator it = m_aAddButtons.find( nId );
5975 0 : if( it != m_aAddButtons.end() )
5976 0 : it->second.m_aHighlightLink = rLink;
5977 0 : }
5978 :
5979 0 : Rectangle MenuBarWindow::GetMenuBarButtonRectPixel( sal_uInt16 nId )
5980 : {
5981 0 : Rectangle aRect;
5982 0 : if( m_aAddButtons.find( nId ) != m_aAddButtons.end() )
5983 : {
5984 0 : if( pMenu->mpSalMenu )
5985 : {
5986 0 : aRect = pMenu->mpSalMenu->GetMenuBarButtonRectPixel( nId, ImplGetWindowImpl()->mpFrame );
5987 0 : if( aRect == Rectangle( Point( -1, -1 ), Size( 1, 1 ) ) )
5988 : {
5989 : // system menu button is somehwere but location cannot be determined
5990 0 : return Rectangle();
5991 : }
5992 : }
5993 :
5994 0 : if( aRect.IsEmpty() )
5995 : {
5996 0 : aRect = aCloser.GetItemRect( nId );
5997 0 : Point aOffset = aCloser.OutputToScreenPixel( Point() );
5998 0 : aRect.Move( aOffset.X(), aOffset.Y() );
5999 : }
6000 : }
6001 0 : return aRect;
6002 : }
6003 :
6004 0 : void MenuBarWindow::RemoveMenuBarButton( sal_uInt16 nId )
6005 : {
6006 0 : sal_uInt16 nPos = aCloser.GetItemPos( nId );
6007 0 : aCloser.RemoveItem( nPos );
6008 0 : m_aAddButtons.erase( nId );
6009 0 : aCloser.calcMinSize();
6010 0 : ImplLayoutChanged();
6011 :
6012 0 : if( pMenu->mpSalMenu )
6013 0 : pMenu->mpSalMenu->RemoveMenuBarButton( nId );
6014 0 : }
6015 :
6016 0 : bool MenuBarWindow::HandleMenuButtonEvent( sal_uInt16 i_nButtonId )
6017 : {
6018 0 : std::map< sal_uInt16, AddButtonEntry >::iterator it = m_aAddButtons.find( i_nButtonId );
6019 0 : if( it != m_aAddButtons.end() )
6020 : {
6021 : MenuBar::MenuBarButtonCallbackArg aArg;
6022 0 : aArg.nId = it->first;
6023 0 : aArg.bHighlight = true;
6024 0 : aArg.pMenuBar = dynamic_cast<MenuBar*>(pMenu);
6025 0 : return it->second.m_aSelectLink.Call( &aArg );
6026 : }
6027 0 : return sal_False;
6028 : }
6029 :
6030 948 : ImplMenuDelData::ImplMenuDelData( const Menu* pMenu )
6031 : : mpNext( 0 )
6032 948 : , mpMenu( 0 )
6033 : {
6034 948 : if( pMenu )
6035 948 : const_cast< Menu* >( pMenu )->ImplAddDel( *this );
6036 948 : }
6037 :
6038 948 : ImplMenuDelData::~ImplMenuDelData()
6039 : {
6040 948 : if( mpMenu )
6041 948 : const_cast< Menu* >( mpMenu )->ImplRemoveDel( *this );
6042 948 : }
6043 :
6044 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|