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