fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / framework / source / uielement / menubarmerger.cxx
blob076dcb620a0a6ba3e23856d56c39a0fd4059d9fb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <uielement/menubarmerger.hxx>
21 #include <framework/addonsoptions.hxx>
23 using namespace ::com::sun::star;
25 static const char SEPARATOR_STRING[] = "private:separator";
27 static const char MERGECOMMAND_ADDAFTER[] = "AddAfter";
28 static const char MERGECOMMAND_ADDBEFORE[] = "AddBefore";
29 static const char MERGECOMMAND_REPLACE[] = "Replace";
30 static const char MERGECOMMAND_REMOVE[] = "Remove";
32 static const char MERGEFALLBACK_ADDPATH[] = "AddPath";
33 static const char MERGEFALLBACK_IGNORE[] = "Ignore";
35 namespace framework
38 /**
39 Check whether a module identifier is part of a context
40 defined by a colon separated list of module identifier.
42 @param
43 rContext
45 Describes a context string list where all contexts
46 are delimited by a colon. For more information about
47 the module identifier used as context strings see the
48 IDL description of com::sun::star::frame::XModuleManager
50 @param
51 rModuleIdentifier
53 A string describing a module identifier. See IDL
54 description of com::sun::star::frame::XModuleManager.
57 bool MenuBarMerger::IsCorrectContext( const OUString& rContext, const OUString& rModuleIdentifier )
59 return ( rContext.isEmpty() || ( rContext.indexOf( rModuleIdentifier ) >= 0 ));
62 void MenuBarMerger::RetrieveReferencePath(
63 const OUString& rReferencePathString,
64 ::std::vector< OUString >& rReferencePath )
66 const sal_Char aDelimiter = '\\';
68 rReferencePath.clear();
69 sal_Int32 nIndex( 0 );
72 OUString aToken = rReferencePathString.getToken( 0, aDelimiter, nIndex );
73 if ( !aToken.isEmpty() )
74 rReferencePath.push_back( aToken );
76 while ( nIndex >= 0 );
79 ReferencePathInfo MenuBarMerger::FindReferencePath(
80 const ::std::vector< OUString >& rReferencePath,
81 Menu* pMenu )
83 sal_uInt32 i( 0 );
84 const sal_uInt32 nCount( rReferencePath.size() );
86 ReferencePathInfo aResult;
87 if ( !nCount )
89 aResult.pPopupMenu = NULL;
90 aResult.nPos = 0;
91 aResult.nLevel = -1;
92 aResult.eResult = RP_MENUITEM_NOT_FOUND;
93 return aResult;
96 Menu* pCurrMenu( pMenu );
97 RPResultInfo eResult( RP_OK );
99 sal_Int32 nLevel( - 1 );
100 sal_uInt16 nPos( MENU_ITEM_NOTFOUND );
103 ++nLevel;
104 OUString aCmd( rReferencePath[i] );
106 if ( i == nCount-1 )
108 // Check last reference path element. Must be a leave (menu item).
109 sal_uInt16 nTmpPos = FindMenuItem( aCmd, pCurrMenu );
110 if ( nTmpPos != MENU_ITEM_NOTFOUND )
111 nPos = nTmpPos;
112 eResult = ( nTmpPos != MENU_ITEM_NOTFOUND ) ? RP_OK : RP_MENUITEM_NOT_FOUND;
114 else
116 // Check reference path element. Must be a node (popup menu)!
117 sal_uInt16 nTmpPos = FindMenuItem( aCmd, pCurrMenu );
118 if ( nTmpPos != MENU_ITEM_NOTFOUND )
120 sal_uInt16 nItemId = pCurrMenu->GetItemId( nTmpPos );
121 Menu* pTmpMenu = pCurrMenu->GetPopupMenu( nItemId );
122 if ( pTmpMenu != 0 )
123 pCurrMenu = pTmpMenu;
124 else
126 nPos = nTmpPos;
127 eResult = RP_MENUITEM_INSTEAD_OF_POPUPMENU_FOUND;
130 else
131 eResult = RP_POPUPMENU_NOT_FOUND;
133 i++;
135 while ((i < nCount) && (eResult == RP_OK));
137 aResult.pPopupMenu = pCurrMenu;
138 aResult.nPos = nPos;
139 aResult.nLevel = nLevel;
140 aResult.eResult = eResult;
142 return aResult;
145 sal_uInt16 MenuBarMerger::FindMenuItem( const OUString& rCmd, Menu* pCurrMenu )
147 for ( sal_uInt16 i = 0; i < pCurrMenu->GetItemCount(); i++ )
149 const sal_uInt16 nItemId = pCurrMenu->GetItemId( i );
150 if ( nItemId > 0 )
152 if ( rCmd == pCurrMenu->GetItemCommand( nItemId ) )
153 return i;
157 return MENU_ITEM_NOTFOUND;
160 bool MenuBarMerger::CreateSubMenu(
161 Menu* pSubMenu,
162 sal_uInt16& nItemId,
163 const OUString& rModuleIdentifier,
164 const AddonMenuContainer& rAddonSubMenu )
166 const sal_uInt32 nSize = rAddonSubMenu.size();
167 for ( sal_uInt32 i = 0; i < nSize; i++ )
169 const AddonMenuItem& rMenuItem = rAddonSubMenu[i];
171 if ( IsCorrectContext( rMenuItem.aContext, rModuleIdentifier ))
173 if ( rMenuItem.aURL == SEPARATOR_STRING )
175 pSubMenu->InsertSeparator();
177 else
179 pSubMenu->InsertItem(nItemId, rMenuItem.aTitle);
180 pSubMenu->SetItemCommand( nItemId, rMenuItem.aURL );
181 if ( !rMenuItem.aSubMenu.empty() )
183 PopupMenu* pPopupMenu = new PopupMenu();
184 pSubMenu->SetPopupMenu( nItemId, pPopupMenu );
185 ++nItemId;
187 CreateSubMenu( pPopupMenu, nItemId, rModuleIdentifier, rMenuItem.aSubMenu );
189 else
190 ++nItemId;
195 return true;
198 bool MenuBarMerger::MergeMenuItems(
199 Menu* pMenu,
200 sal_uInt16 nPos,
201 sal_uInt16 nModIndex,
202 sal_uInt16& nItemId,
203 const OUString& rModuleIdentifier,
204 const AddonMenuContainer& rAddonMenuItems )
206 sal_uInt16 nIndex( 0 );
207 const sal_uInt32 nSize = rAddonMenuItems.size();
208 for ( sal_uInt32 i = 0; i < nSize; i++ )
210 const AddonMenuItem& rMenuItem = rAddonMenuItems[i];
212 if ( IsCorrectContext( rMenuItem.aContext, rModuleIdentifier ))
214 if ( rMenuItem.aURL == SEPARATOR_STRING )
216 pMenu->InsertSeparator(OString(), nPos+nModIndex+nIndex);
218 else
220 pMenu->InsertItem(nItemId, rMenuItem.aTitle, MenuItemBits::NONE, OString(), nPos+nModIndex+nIndex);
221 pMenu->SetItemCommand( nItemId, rMenuItem.aURL );
222 if ( !rMenuItem.aSubMenu.empty() )
224 PopupMenu* pSubMenu = new PopupMenu();
225 pMenu->SetPopupMenu( nItemId, pSubMenu );
226 ++nItemId;
228 CreateSubMenu( pSubMenu, nItemId, rModuleIdentifier, rMenuItem.aSubMenu );
230 else
231 ++nItemId;
233 ++nIndex;
237 return true;
240 bool MenuBarMerger::ReplaceMenuItem(
241 Menu* pMenu,
242 sal_uInt16 nPos,
243 sal_uInt16& rItemId,
244 const OUString& rModuleIdentifier,
245 const AddonMenuContainer& rAddonMenuItems )
247 // There is no replace available. Therfore we first have to
248 // remove the old menu entry,
249 pMenu->RemoveItem( nPos );
251 return MergeMenuItems( pMenu, nPos, 0, rItemId, rModuleIdentifier, rAddonMenuItems );
254 bool MenuBarMerger::RemoveMenuItems(
255 Menu* pMenu,
256 sal_uInt16 nPos,
257 const OUString& rMergeCommandParameter )
259 const sal_uInt16 nParam( sal_uInt16( rMergeCommandParameter.toInt32() ));
260 sal_uInt16 nCount( 1 );
262 nCount = std::max( nParam, nCount );
264 sal_uInt16 i = 0;
265 while (( nPos < pMenu->GetItemCount() ) && ( i < nCount ))
267 pMenu->RemoveItem( nPos );
268 ++i;
271 return true;
274 bool MenuBarMerger::ProcessMergeOperation(
275 Menu* pMenu,
276 sal_uInt16 nPos,
277 sal_uInt16& nItemId,
278 const OUString& rMergeCommand,
279 const OUString& rMergeCommandParameter,
280 const OUString& rModuleIdentifier,
281 const AddonMenuContainer& rAddonMenuItems )
283 sal_uInt16 nModIndex( 0 );
285 if ( rMergeCommand == MERGECOMMAND_ADDBEFORE )
287 nModIndex = 0;
288 return MergeMenuItems( pMenu, nPos, nModIndex, nItemId, rModuleIdentifier, rAddonMenuItems );
290 else if ( rMergeCommand == MERGECOMMAND_ADDAFTER )
292 nModIndex = 1;
293 return MergeMenuItems( pMenu, nPos, nModIndex, nItemId, rModuleIdentifier, rAddonMenuItems );
295 else if ( rMergeCommand == MERGECOMMAND_REPLACE )
297 return ReplaceMenuItem( pMenu, nPos, nItemId, rModuleIdentifier, rAddonMenuItems );
299 else if ( rMergeCommand == MERGECOMMAND_REMOVE )
301 return RemoveMenuItems( pMenu, nPos, rMergeCommandParameter );
304 return false;
307 bool MenuBarMerger::ProcessFallbackOperation(
308 const ReferencePathInfo& aRefPathInfo,
309 sal_uInt16& rItemId,
310 const OUString& rMergeCommand,
311 const OUString& rMergeFallback,
312 const ::std::vector< OUString >& rReferencePath,
313 const OUString& rModuleIdentifier,
314 const AddonMenuContainer& rAddonMenuItems )
316 if (( rMergeFallback == MERGEFALLBACK_IGNORE ) ||
317 ( rMergeCommand == MERGECOMMAND_REPLACE ) ||
318 ( rMergeCommand == MERGECOMMAND_REMOVE ) )
320 return true;
322 else if ( rMergeFallback == MERGEFALLBACK_ADDPATH )
324 Menu* pCurrMenu( aRefPathInfo.pPopupMenu );
325 sal_Int32 nLevel( aRefPathInfo.nLevel );
326 const sal_Int32 nSize( rReferencePath.size() );
327 bool bFirstLevel( true );
329 while ( nLevel < nSize )
331 if ( nLevel == nSize-1 )
333 const sal_uInt32 nCount = rAddonMenuItems.size();
334 for ( sal_uInt32 i = 0; i < nCount; ++i )
336 const AddonMenuItem& rMenuItem = rAddonMenuItems[i];
337 if ( IsCorrectContext( rMenuItem.aContext, rModuleIdentifier ))
339 if ( rMenuItem.aURL == SEPARATOR_STRING )
340 pCurrMenu->InsertSeparator(OString(), MENU_APPEND);
341 else
343 pCurrMenu->InsertItem(rItemId, rMenuItem.aTitle);
344 pCurrMenu->SetItemCommand( rItemId, rMenuItem.aURL );
345 ++rItemId;
350 else
352 const OUString aCmd( rReferencePath[nLevel] );
354 sal_uInt16 nInsPos( MENU_APPEND );
355 PopupMenu* pPopupMenu( new PopupMenu );
357 if ( bFirstLevel && ( aRefPathInfo.eResult == RP_MENUITEM_INSTEAD_OF_POPUPMENU_FOUND ))
359 // special case: menu item without popup
360 nInsPos = aRefPathInfo.nPos;
361 sal_uInt16 nSetItemId = pCurrMenu->GetItemId( nInsPos );
362 pCurrMenu->SetItemCommand( nSetItemId, aCmd );
363 pCurrMenu->SetPopupMenu( nSetItemId, pPopupMenu );
365 else
367 // normal case: insert a new item with popup
368 pCurrMenu->InsertItem(rItemId, OUString());
369 pCurrMenu->SetItemCommand( rItemId, aCmd );
370 pCurrMenu->SetPopupMenu( rItemId, pPopupMenu );
373 pCurrMenu = pPopupMenu;
374 ++rItemId;
375 bFirstLevel = false;
377 ++nLevel;
379 return true;
382 return false;
385 void MenuBarMerger::GetMenuEntry(
386 const uno::Sequence< beans::PropertyValue >& rAddonMenuEntry,
387 AddonMenuItem& rAddonMenuItem )
389 // Reset submenu member
390 rAddonMenuItem.aSubMenu.clear();
392 for ( sal_Int32 i = 0; i < rAddonMenuEntry.getLength(); i++ )
394 OUString aMenuEntryPropName = rAddonMenuEntry[i].Name;
395 if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_URL )
396 rAddonMenuEntry[i].Value >>= rAddonMenuItem.aURL;
397 else if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_TITLE )
398 rAddonMenuEntry[i].Value >>= rAddonMenuItem.aTitle;
399 else if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_TARGET )
400 rAddonMenuEntry[i].Value >>= rAddonMenuItem.aTarget;
401 else if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_SUBMENU )
403 uno::Sequence< uno::Sequence< beans::PropertyValue > > aSubMenu;
404 rAddonMenuEntry[i].Value >>= aSubMenu;
405 GetSubMenu( aSubMenu, rAddonMenuItem.aSubMenu );
407 else if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_CONTEXT )
408 rAddonMenuEntry[i].Value >>= rAddonMenuItem.aContext;
409 else if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_IMAGEIDENTIFIER )
410 rAddonMenuEntry[i].Value >>= rAddonMenuItem.aImageId;
414 void MenuBarMerger::GetSubMenu(
415 const uno::Sequence< uno::Sequence< beans::PropertyValue > >& rSubMenuEntries,
416 AddonMenuContainer& rSubMenu )
418 rSubMenu.clear();
420 const sal_Int32 nCount = rSubMenuEntries.getLength();
421 rSubMenu.reserve(rSubMenu.size() + nCount);
422 for ( sal_Int32 i = 0; i < nCount; i++ )
424 const uno::Sequence< beans::PropertyValue >& rMenuEntry = rSubMenuEntries[ i ];
426 AddonMenuItem aMenuItem;
427 GetMenuEntry( rMenuEntry, aMenuItem );
428 rSubMenu.push_back( aMenuItem );
432 } // namespace framework
434 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */