update dev300-m58
[ooovba.git] / framework / source / uielement / menubarmerger.cxx
blob9e497b62c1639fc53c094239f86bea69fad4c3bb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: menubarmerger.cxx,v $
10 * $Revision: 1.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
34 #include <uielement/menubarmerger.hxx>
35 #include <classes/addonsoptions.hxx>
37 using namespace ::com::sun::star;
39 static const char SEPARATOR_STRING[] = "private:separator";
40 static const sal_uInt32 SEPARATOR_STRING_LEN = 17;
42 static const char MERGECOMMAND_ADDAFTER[] = "AddAfter";
43 static const sal_uInt32 MERGECOMMAND_ADDAFTER_LEN = 8;
44 static const char MERGECOMMAND_ADDBEFORE[] = "AddBefore";
45 static const sal_uInt32 MERGECOMMAND_ADDBEFORE_LEN = 9;
46 static const char MERGECOMMAND_REPLACE[] = "Replace";
47 static const sal_uInt32 MERGECOMMAND_REPLACE_LEN = 7;
48 static const char MERGECOMMAND_REMOVE[] = "Remove";
49 static const sal_uInt32 MERGECOMMAND_REMOVE_LEN = 6;
51 static const char MERGEFALLBACK_ADDPATH[] = "AddPath";
52 static const char MERGEFALLBACK_ADDPATH_LEN = 7;
53 static const char MERGEFALLBACK_IGNORE[] = "Ignore";
54 static const char MERGEFALLBACK_IGNORE_LEN = 6;
57 namespace framework
60 /**
61 Check whether a module identifier is part of a context
62 defined by a colon separated list of module identifier.
64 @param
65 rContext
67 Describes a context string list where all contexts
68 are delimited by a colon. For more information about
69 the module identifier used as context strings see the
70 IDL description of com::sun::star::frame::XModuleManager
72 @param
73 rModuleIdentifier
75 A string describing a module identifier. See IDL
76 description of com::sun::star::frame::XModuleManager.
79 bool MenuBarMerger::IsCorrectContext( const ::rtl::OUString& rContext, const ::rtl::OUString& rModuleIdentifier )
81 return (( rContext.getLength() == 0 ) || ( rContext.indexOf( rModuleIdentifier ) >= 0 ));
84 void MenuBarMerger::RetrieveReferencePath(
85 const ::rtl::OUString& rReferencePathString,
86 ::std::vector< ::rtl::OUString >& rReferencePath )
88 const sal_Char aDelimiter = '\\';
90 rReferencePath.clear();
91 sal_Int32 nIndex( 0 );
94 ::rtl::OUString aToken = rReferencePathString.getToken( 0, aDelimiter, nIndex );
95 if ( aToken.getLength() > 0 )
96 rReferencePath.push_back( aToken );
98 while ( nIndex >= 0 );
101 ReferencePathInfo MenuBarMerger::FindReferencePath(
102 const ::std::vector< ::rtl::OUString >& rReferencePath,
103 Menu* pMenu )
105 sal_uInt32 i( 0 );
106 const sal_uInt32 nCount( rReferencePath.size() );
107 Menu* pCurrMenu( pMenu );
108 RPResultInfo eResult( RP_OK );
110 sal_Int32 nLevel( - 1 );
111 sal_uInt16 nPos( MENU_ITEM_NOTFOUND );
114 ++nLevel;
115 ::rtl::OUString aCmd( rReferencePath[i] );
117 if ( i == nCount-1 )
119 // Check last reference path element. Must be a leave (menu item).
120 sal_uInt16 nTmpPos = FindMenuItem( aCmd, pCurrMenu );
121 if ( nTmpPos != MENU_ITEM_NOTFOUND )
122 nPos = nTmpPos;
123 eResult = ( nTmpPos != MENU_ITEM_NOTFOUND ) ? RP_OK : RP_MENUITEM_NOT_FOUND;
125 else
127 // Check reference path element. Must be a node (popup menu)!
128 sal_uInt16 nTmpPos = FindMenuItem( aCmd, pCurrMenu );
129 if ( nTmpPos != MENU_ITEM_NOTFOUND )
131 sal_uInt16 nItemId = pCurrMenu->GetItemId( nTmpPos );
132 Menu* pTmpMenu = pCurrMenu->GetPopupMenu( nItemId );
133 if ( pTmpMenu != 0 )
134 pCurrMenu = pTmpMenu;
135 else
137 nPos = nTmpPos;
138 eResult = RP_MENUITEM_INSTEAD_OF_POPUPMENU_FOUND;
141 else
142 eResult = RP_POPUPMENU_NOT_FOUND;
144 i++;
146 while (( pCurrMenu != 0 ) && ( i < nCount ) && ( eResult == RP_OK ));
148 ReferencePathInfo aResult;
149 aResult.pPopupMenu = pCurrMenu;
150 aResult.nPos = nPos;
151 aResult.nLevel = nLevel;
152 aResult.eResult = eResult;
154 return aResult;
157 sal_uInt16 MenuBarMerger::FindMenuItem( const ::rtl::OUString& rCmd, Menu* pCurrMenu )
159 for ( sal_uInt16 i = 0; i < pCurrMenu->GetItemCount(); i++ )
161 const sal_uInt16 nItemId = pCurrMenu->GetItemId( i );
162 if ( nItemId > 0 )
164 if ( rCmd == ::rtl::OUString( pCurrMenu->GetItemCommand( nItemId )))
165 return i;
169 return MENU_ITEM_NOTFOUND;
172 bool MenuBarMerger::CreateSubMenu(
173 Menu* pSubMenu,
174 sal_uInt16& nItemId,
175 const ::rtl::OUString& rModuleIdentifier,
176 const AddonMenuContainer& rAddonSubMenu )
178 const sal_uInt32 nSize = rAddonSubMenu.size();
179 for ( sal_uInt32 i = 0; i < nSize; i++ )
181 const AddonMenuItem& rMenuItem = rAddonSubMenu[i];
183 if ( IsCorrectContext( rMenuItem.aContext, rModuleIdentifier ))
185 if ( rMenuItem.aURL.equalsAsciiL( SEPARATOR_STRING, SEPARATOR_STRING_LEN ))
187 pSubMenu->InsertSeparator( MENU_APPEND );
189 else
191 pSubMenu->InsertItem( nItemId, rMenuItem.aTitle, 0, MENU_APPEND );
192 pSubMenu->SetItemCommand( nItemId, rMenuItem.aURL );
193 if ( !rMenuItem.aSubMenu.empty() )
195 PopupMenu* pPopupMenu = new PopupMenu();
196 pSubMenu->SetPopupMenu( nItemId, pPopupMenu );
197 ++nItemId;
199 CreateSubMenu( pPopupMenu, nItemId, rModuleIdentifier, rMenuItem.aSubMenu );
201 else
202 ++nItemId;
207 return true;
210 bool MenuBarMerger::MergeMenuItems(
211 Menu* pMenu,
212 sal_uInt16 nPos,
213 sal_uInt16 nModIndex,
214 sal_uInt16& nItemId,
215 const ::rtl::OUString& rModuleIdentifier,
216 const AddonMenuContainer& rAddonMenuItems )
218 sal_uInt16 nIndex( 0 );
219 const sal_uInt32 nSize = rAddonMenuItems.size();
220 for ( sal_uInt32 i = 0; i < nSize; i++ )
222 const AddonMenuItem& rMenuItem = rAddonMenuItems[i];
224 if ( IsCorrectContext( rMenuItem.aContext, rModuleIdentifier ))
226 if ( rMenuItem.aURL.equalsAsciiL( SEPARATOR_STRING, SEPARATOR_STRING_LEN ))
228 pMenu->InsertSeparator( nPos+nModIndex+nIndex );
230 else
232 pMenu->InsertItem( nItemId, rMenuItem.aTitle, 0, nPos+nModIndex+nIndex );
233 pMenu->SetItemCommand( nItemId, rMenuItem.aURL );
234 if ( !rMenuItem.aSubMenu.empty() )
236 PopupMenu* pSubMenu = new PopupMenu();
237 pMenu->SetPopupMenu( nItemId, pSubMenu );
238 ++nItemId;
240 CreateSubMenu( pSubMenu, nItemId, rModuleIdentifier, rMenuItem.aSubMenu );
242 else
243 ++nItemId;
245 ++nIndex;
249 return true;
252 bool MenuBarMerger::ReplaceMenuItem(
253 Menu* pMenu,
254 sal_uInt16 nPos,
255 sal_uInt16& rItemId,
256 const ::rtl::OUString& rModuleIdentifier,
257 const AddonMenuContainer& rAddonMenuItems )
259 // There is no replace available. Therfore we first have to
260 // remove the old menu entry,
261 pMenu->RemoveItem( nPos );
263 return MergeMenuItems( pMenu, nPos, 0, rItemId, rModuleIdentifier, rAddonMenuItems );
266 bool MenuBarMerger::RemoveMenuItems(
267 Menu* pMenu,
268 sal_uInt16 nPos,
269 const ::rtl::OUString& rMergeCommandParameter )
271 const sal_uInt16 nParam( sal_uInt16( rMergeCommandParameter.toInt32() ));
272 sal_uInt16 nCount( 1 );
274 nCount = std::max( nParam, nCount );
276 sal_uInt16 i = 0;
277 while (( nPos < pMenu->GetItemCount() ) && ( i < nCount ))
279 pMenu->RemoveItem( nPos );
280 ++i;
283 return true;
286 bool MenuBarMerger::ProcessMergeOperation(
287 Menu* pMenu,
288 sal_uInt16 nPos,
289 sal_uInt16& nItemId,
290 const ::rtl::OUString& rMergeCommand,
291 const ::rtl::OUString& rMergeCommandParameter,
292 const ::rtl::OUString& rModuleIdentifier,
293 const AddonMenuContainer& rAddonMenuItems )
295 sal_uInt16 nModIndex( 0 );
297 if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_ADDBEFORE, MERGECOMMAND_ADDBEFORE_LEN ))
299 nModIndex = 0;
300 return MergeMenuItems( pMenu, nPos, nModIndex, nItemId, rModuleIdentifier, rAddonMenuItems );
302 else if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_ADDAFTER, MERGECOMMAND_ADDAFTER_LEN ))
304 nModIndex = 1;
305 return MergeMenuItems( pMenu, nPos, nModIndex, nItemId, rModuleIdentifier, rAddonMenuItems );
307 else if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_REPLACE, MERGECOMMAND_REPLACE_LEN ))
309 return ReplaceMenuItem( pMenu, nPos, nItemId, rModuleIdentifier, rAddonMenuItems );
311 else if ( rMergeCommand.equalsAsciiL( MERGECOMMAND_REMOVE, MERGECOMMAND_REMOVE_LEN ))
313 return RemoveMenuItems( pMenu, nPos, rMergeCommandParameter );
316 return false;
319 bool MenuBarMerger::ProcessFallbackOperation(
320 const ReferencePathInfo& aRefPathInfo,
321 sal_uInt16& rItemId,
322 const ::rtl::OUString& rMergeCommand,
323 const ::rtl::OUString& rMergeFallback,
324 const ::std::vector< ::rtl::OUString >& rReferencePath,
325 const ::rtl::OUString& rModuleIdentifier,
326 const AddonMenuContainer& rAddonMenuItems )
328 if (( rMergeFallback.equalsAsciiL( MERGEFALLBACK_IGNORE, MERGEFALLBACK_IGNORE_LEN )) ||
329 ( rMergeCommand.equalsAsciiL( MERGECOMMAND_REPLACE, MERGECOMMAND_REPLACE_LEN )) ||
330 ( rMergeCommand.equalsAsciiL( MERGECOMMAND_REMOVE, MERGECOMMAND_REMOVE_LEN )) )
332 return true;
334 else if ( rMergeFallback.equalsAsciiL( MERGEFALLBACK_ADDPATH, MERGEFALLBACK_ADDPATH_LEN ))
336 Menu* pCurrMenu( aRefPathInfo.pPopupMenu );
337 sal_Int32 nLevel( aRefPathInfo.nLevel );
338 const sal_Int32 nSize( rReferencePath.size() );
339 bool bFirstLevel( true );
341 while ( nLevel < nSize )
343 if ( nLevel == nSize-1 )
345 const sal_uInt32 nCount = rAddonMenuItems.size();
346 for ( sal_uInt32 i = 0; i < nCount; ++i )
348 const AddonMenuItem& rMenuItem = rAddonMenuItems[i];
349 if ( IsCorrectContext( rMenuItem.aContext, rModuleIdentifier ))
351 if ( rMenuItem.aURL.equalsAsciiL( SEPARATOR_STRING, SEPARATOR_STRING_LEN ))
352 pCurrMenu->InsertSeparator( MENU_APPEND );
353 else
355 pCurrMenu->InsertItem( rItemId, rMenuItem.aTitle, 0, MENU_APPEND );
356 pCurrMenu->SetItemCommand( rItemId, rMenuItem.aURL );
357 ++rItemId;
362 else
364 const ::rtl::OUString aCmd( rReferencePath[nLevel] );
366 sal_uInt16 nInsPos( MENU_APPEND );
367 PopupMenu* pPopupMenu( new PopupMenu );
369 if ( bFirstLevel && ( aRefPathInfo.eResult == RP_MENUITEM_INSTEAD_OF_POPUPMENU_FOUND ))
371 // special case: menu item without popup
372 nInsPos = aRefPathInfo.nPos;
373 sal_uInt16 nSetItemId = pCurrMenu->GetItemId( nInsPos );
374 pCurrMenu->SetItemCommand( nSetItemId, aCmd );
375 pCurrMenu->SetPopupMenu( nSetItemId, pPopupMenu );
377 else
379 // normal case: insert a new item with popup
380 pCurrMenu->InsertItem( rItemId, ::rtl::OUString(), 0, MENU_APPEND );
381 pCurrMenu->SetItemCommand( rItemId, aCmd );
382 pCurrMenu->SetPopupMenu( rItemId, pPopupMenu );
385 pCurrMenu = pPopupMenu;
386 ++rItemId;
387 bFirstLevel = false;
389 ++nLevel;
391 return true;
394 return false;
397 void MenuBarMerger::GetMenuEntry(
398 const uno::Sequence< beans::PropertyValue >& rAddonMenuEntry,
399 AddonMenuItem& rAddonMenuItem )
401 // Reset submenu member
402 rAddonMenuItem.aSubMenu.clear();
404 for ( sal_Int32 i = 0; i < rAddonMenuEntry.getLength(); i++ )
406 ::rtl::OUString aMenuEntryPropName = rAddonMenuEntry[i].Name;
407 if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_URL, ADDONSMENUITEM_URL_LEN ))
408 rAddonMenuEntry[i].Value >>= rAddonMenuItem.aURL;
409 else if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_TITLE, ADDONSMENUITEM_TITLE_LEN ))
410 rAddonMenuEntry[i].Value >>= rAddonMenuItem.aTitle;
411 else if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_TARGET, ADDONSMENUITEM_TARGET_LEN ))
412 rAddonMenuEntry[i].Value >>= rAddonMenuItem.aTarget;
413 else if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_SUBMENU, ADDONSMENUITEM_SUBMENU_LEN ))
415 uno::Sequence< uno::Sequence< beans::PropertyValue > > aSubMenu;
416 rAddonMenuEntry[i].Value >>= aSubMenu;
417 GetSubMenu( aSubMenu, rAddonMenuItem.aSubMenu );
419 else if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_CONTEXT, ADDONSMENUITEM_CONTEXT_LEN ))
420 rAddonMenuEntry[i].Value >>= rAddonMenuItem.aContext;
421 else if ( aMenuEntryPropName.equalsAsciiL( ADDONSMENUITEM_STRING_IMAGEIDENTIFIER, ADDONSMENUITEM_IMAGEIDENTIFIER_LEN ))
422 rAddonMenuEntry[i].Value >>= rAddonMenuItem.aImageId;
426 void MenuBarMerger::GetSubMenu(
427 const uno::Sequence< uno::Sequence< beans::PropertyValue > >& rSubMenuEntries,
428 AddonMenuContainer& rSubMenu )
430 rSubMenu.clear();
432 const sal_Int32 nCount = rSubMenuEntries.getLength();
433 rSubMenu.reserve(rSubMenu.size() + nCount);
434 for ( sal_Int32 i = 0; i < nCount; i++ )
436 const uno::Sequence< beans::PropertyValue >& rMenuEntry = rSubMenuEntries[ i ];
438 AddonMenuItem aMenuItem;
439 GetMenuEntry( rMenuEntry, aMenuItem );
440 rSubMenu.push_back( aMenuItem );
444 } // namespace framework