diff options
Diffstat (limited to 'framework/source/uielement/toolbarmerger.cxx')
-rw-r--r-- | framework/source/uielement/toolbarmerger.cxx | 645 |
1 files changed, 645 insertions, 0 deletions
diff --git a/framework/source/uielement/toolbarmerger.cxx b/framework/source/uielement/toolbarmerger.cxx new file mode 100644 index 000000000..2657873c3 --- /dev/null +++ b/framework/source/uielement/toolbarmerger.cxx @@ -0,0 +1,645 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <string_view> + +#include <uielement/toolbarmerger.hxx> +#include <framework/generictoolbarcontroller.hxx> + +#include <uielement/buttontoolbarcontroller.hxx> +#include <uielement/comboboxtoolbarcontroller.hxx> +#include <uielement/dropdownboxtoolbarcontroller.hxx> +#include <uielement/edittoolbarcontroller.hxx> +#include <uielement/imagebuttontoolbarcontroller.hxx> +#include <uielement/spinfieldtoolbarcontroller.hxx> +#include <uielement/togglebuttontoolbarcontroller.hxx> +#include <uielement/FixedTextToolbarController.hxx> +#include <uielement/FixedImageToolbarController.hxx> +#include <o3tl/string_view.hxx> + +namespace framework +{ + +const char MERGE_TOOLBAR_URL[] = "URL"; +const char MERGE_TOOLBAR_TITLE[] = "Title"; +const char MERGE_TOOLBAR_CONTEXT[] = "Context"; +const char MERGE_TOOLBAR_TARGET[] = "Target"; +const char MERGE_TOOLBAR_CONTROLTYPE[] = "ControlType"; +const char MERGE_TOOLBAR_WIDTH[] = "Width"; + +const char16_t MERGECOMMAND_ADDAFTER[] = u"AddAfter"; +const char16_t MERGECOMMAND_ADDBEFORE[] = u"AddBefore"; +const char16_t MERGECOMMAND_REPLACE[] = u"Replace"; +const char16_t MERGECOMMAND_REMOVE[] = u"Remove"; + +const char16_t MERGEFALLBACK_ADDLAST[] = u"AddLast"; +const char16_t MERGEFALLBACK_ADDFIRST[] = u"AddFirst"; +const char16_t MERGEFALLBACK_IGNORE[] = u"Ignore"; + +const char16_t TOOLBARCONTROLLER_BUTTON[] = u"Button"; +const char16_t TOOLBARCONTROLLER_COMBOBOX[] = u"Combobox"; +const char16_t TOOLBARCONTROLLER_EDIT[] = u"Editfield"; +const char16_t TOOLBARCONTROLLER_SPINFIELD[] = u"Spinfield"; +const char16_t TOOLBARCONTROLLER_IMGBUTTON[] = u"ImageButton"; +const char16_t TOOLBARCONTROLLER_DROPDOWNBOX[] = u"Dropdownbox"; +const char16_t TOOLBARCONTROLLER_DROPDOWNBTN[] = u"DropdownButton"; +const char16_t TOOLBARCONTROLLER_TOGGLEDDBTN[] = u"ToggleDropdownButton"; +const char16_t TOOLBARCONTROLLER_FIXEDIMAGE[] = u"FixedImage"; +const char16_t TOOLBARCONTROLLER_FIXEDTEXT[] = u"FixedText"; + +const char TOOLBOXITEM_SEPARATOR_STR[] = "private:separator"; + +using namespace ::com::sun::star; + +/** + Check whether a module identifier is part of a context + defined by a colon separated list of module identifier. + + @param + rContext + + Describes a context string list where all contexts + are delimited by a colon. For more information about + the module identifier used as context strings see the + IDL description of css::frame::XModuleManager + + @param + rModuleIdentifier + + A string describing a module identifier. See IDL + description of css::frame::XModuleManager. + + @result + The result is true if the rContext is an empty string + or rModuleIdentifier is part of the context string. + +*/ +bool ToolBarMerger::IsCorrectContext( + std::u16string_view rContext, + std::u16string_view rModuleIdentifier ) +{ + return ( rContext.empty() || ( rContext.find( rModuleIdentifier ) != std::u16string_view::npos )); +} + +/** + Converts a sequence, sequence of property values to + a vector of structs. + + @param + rSequence + + Provides a sequence, sequence of property values. + + @param + rContainer + + A vector of AddonToolbarItems which will hold the + conversion from the rSequence argument. +*/ +void ToolBarMerger::ConvertSeqSeqToVector( + const uno::Sequence< uno::Sequence< beans::PropertyValue > >& rSequence, + AddonToolbarItemContainer& rContainer ) +{ + sal_Int32 nLen( rSequence.getLength() ); + for ( sal_Int32 i = 0; i < nLen; i++ ) + { + AddonToolbarItem aAddonToolbarItem; + ConvertSequenceToValues( rSequence[i], + aAddonToolbarItem.aCommandURL, + aAddonToolbarItem.aLabel, + aAddonToolbarItem.aTarget, + aAddonToolbarItem.aContext, + aAddonToolbarItem.aControlType, + aAddonToolbarItem.nWidth ); + rContainer.push_back( aAddonToolbarItem ); + } +} + +/** + Converts a sequence of property values to single + values. + + @param + rSequence + + Provides a sequence of property values. + + @param + rCommandURL + + Contains the value of the property with + Name="CommandURL". + + @param + rLabel + + Contains the value of the property with + Name="Title" + + @param + rTarget + + Contains the value of the property with + Name="Target" + + @param + rContext + + Contains the value of the property with + Name="Context" + + @param + rControlType + + Contains the value of the property with + Name="ControlType" + + @result + All possible mapping between sequence of property + values and the single values are done. + +*/ +void ToolBarMerger::ConvertSequenceToValues( + const uno::Sequence< beans::PropertyValue >& rSequence, + OUString& rCommandURL, + OUString& rLabel, + OUString& rTarget, + OUString& rContext, + OUString& rControlType, + sal_uInt16& rWidth ) +{ + for ( beans::PropertyValue const & prop : rSequence ) + { + if ( prop.Name == MERGE_TOOLBAR_URL ) + prop.Value >>= rCommandURL; + else if ( prop.Name == MERGE_TOOLBAR_TITLE ) + prop.Value >>= rLabel; + else if ( prop.Name == MERGE_TOOLBAR_CONTEXT ) + prop.Value >>= rContext; + else if ( prop.Name == MERGE_TOOLBAR_TARGET ) + prop.Value >>= rTarget; + else if ( prop.Name == MERGE_TOOLBAR_CONTROLTYPE ) + prop.Value >>= rControlType; + else if ( prop.Name == MERGE_TOOLBAR_WIDTH ) + { + sal_Int32 aValue = 0; + prop.Value >>= aValue; + rWidth = sal_uInt16( aValue ); + } + } +} + +/** + Tries to find the reference point provided and delivers + position and result of the search process. + + @param + pToolbar + + Must be a valid pointer to a toolbar with items which + should be searched. + + @param + rReferencePoint + + A command URL which should be the reference point for + the coming merge operation. + + @result + Provides information about the search result, the + position of the reference point and the toolbar used. +*/ +ReferenceToolbarPathInfo ToolBarMerger::FindReferencePoint( + const ToolBox* pToolbar, + std::u16string_view rReferencePoint ) +{ + ReferenceToolbarPathInfo aResult; + aResult.bResult = false; + aResult.nPos = ToolBox::ITEM_NOTFOUND; + + const ToolBox::ImplToolItems::size_type nSize( pToolbar->GetItemCount() ); + + for ( ToolBox::ImplToolItems::size_type i = 0; i < nSize; i++ ) + { + const ToolBoxItemId nItemId = pToolbar->GetItemId( i ); + if ( nItemId > ToolBoxItemId(0) ) + { + const OUString rCmd = pToolbar->GetItemCommand( nItemId ); + if ( rCmd == rReferencePoint ) + { + aResult.bResult = true; + aResult.nPos = i; + return aResult; + } + } + } + + return aResult; +} + +/** + Processes a merge operation. + + @param + pToolbar + + A valid pointer to the toolbar where the merge + operation is applied to. + + @param + nPos + + The reference position of the toolbar item for + the merge operation. Value must be between + 0 and number of toolbar items - 1. + + @param + rItemId + + A unique item ID. + + @param + rModuleIdentifier + + The current application module context. + + @param + rMergeCommand + + A merge command. + + @param + rMergeCommandParameter. + + An optional argument for the merge command. + + @param + rItems + + Toolbar items which are associated to the merge + command. + + @result + Returns true for a successful operation otherwise + false. +*/ +bool ToolBarMerger::ProcessMergeOperation( + ToolBox* pToolbar, + ToolBox::ImplToolItems::size_type nPos, + ToolBoxItemId& rItemId, + CommandToInfoMap& rCommandMap, + std::u16string_view rModuleIdentifier, + std::u16string_view rMergeCommand, + std::u16string_view rMergeCommandParameter, + const AddonToolbarItemContainer& rItems ) +{ + if ( rMergeCommand == MERGECOMMAND_ADDAFTER ) + MergeItems( pToolbar, nPos, 1, rItemId, rCommandMap, rModuleIdentifier, rItems ); + else if ( rMergeCommand == MERGECOMMAND_ADDBEFORE ) + MergeItems( pToolbar, nPos, 0, rItemId, rCommandMap, rModuleIdentifier, rItems ); + else if ( rMergeCommand == MERGECOMMAND_REPLACE ) + ReplaceItem( pToolbar, nPos, rItemId, rCommandMap, rModuleIdentifier, rItems ); + else if ( rMergeCommand == MERGECOMMAND_REMOVE ) + RemoveItems( pToolbar, nPos, rMergeCommandParameter ); + else + return false; + return true; +} + +/** + Processes a merge fallback operation. + + @param + pToolbar + + A valid pointer to the toolbar where the merge + fall back operation is applied to. + + @param + nPos + + The reference position of the toolbar item for + the merge operation. Value must be between + 0 and number of toolbar items - 1. + + @param + rItemId + + A unique item ID. + + @param + rModuleIdentifier + + The current application module context. + + @param + rMergeCommand + + A merge command. + + @param + rItems + + Toolbar items which are associated to the merge + command. + + @result + Returns true for a successful operation otherwise + false. +*/ +bool ToolBarMerger::ProcessMergeFallback( + ToolBox* pToolbar, + ToolBoxItemId& rItemId, + CommandToInfoMap& rCommandMap, + std::u16string_view rModuleIdentifier, + std::u16string_view rMergeCommand, + std::u16string_view rMergeFallback, + const AddonToolbarItemContainer& rItems ) +{ + if (( rMergeFallback == MERGEFALLBACK_IGNORE ) || + ( rMergeCommand == MERGECOMMAND_REPLACE ) || + ( rMergeCommand == MERGECOMMAND_REMOVE ) ) + { + return true; + } + else if (( rMergeCommand == MERGECOMMAND_ADDBEFORE ) || + ( rMergeCommand == MERGECOMMAND_ADDAFTER ) ) + { + if ( rMergeFallback == MERGEFALLBACK_ADDFIRST ) + MergeItems( pToolbar, 0, 0, rItemId, rCommandMap, rModuleIdentifier, rItems ); + else if ( rMergeFallback == MERGEFALLBACK_ADDLAST ) + MergeItems( pToolbar, ToolBox::APPEND, 0, rItemId, rCommandMap, rModuleIdentifier, rItems ); + else + return false; + return true; + } + + return false; +} + +/** + Merges (adds) toolbar items into an existing toolbar. + + @param + pToolbar + + A valid pointer to the toolbar where the merge + fall back operation is applied to. + + @param + nPos + + The reference position of the toolbar item for + the merge operation. Value must be between + 0 and number of toolbar items - 1. + + @param + rItemId + + A unique item ID. + + @param + rModuleIdentifier + + The current application module context. + + @param + rItems + + Toolbar items which are associated to the merge + command. +*/ +void ToolBarMerger::MergeItems( + ToolBox* pToolbar, + ToolBox::ImplToolItems::size_type nPos, + sal_uInt16 nModIndex, + ToolBoxItemId& rItemId, + CommandToInfoMap& rCommandMap, + std::u16string_view rModuleIdentifier, + const AddonToolbarItemContainer& rAddonToolbarItems ) +{ + const sal_Int32 nSize( rAddonToolbarItems.size() ); + + for ( sal_Int32 i = 0; i < nSize; i++ ) + { + const AddonToolbarItem& rItem = rAddonToolbarItems[i]; + if ( IsCorrectContext( rItem.aContext, rModuleIdentifier )) + { + ToolBox::ImplToolItems::size_type nInsPos = nPos; + if (nInsPos != ToolBox::APPEND) + { + nInsPos += nModIndex+i; + if ( nInsPos > pToolbar->GetItemCount() ) + nInsPos = ToolBox::APPEND; + } + + if ( rItem.aCommandURL == TOOLBOXITEM_SEPARATOR_STR ) + pToolbar->InsertSeparator( nInsPos ); + else + { + CommandToInfoMap::iterator pIter = rCommandMap.find( rItem.aCommandURL ); + if ( pIter == rCommandMap.end()) + { + CommandInfo aCmdInfo; + aCmdInfo.nId = rItemId; + const CommandToInfoMap::value_type aValue( rItem.aCommandURL, aCmdInfo ); + rCommandMap.insert( aValue ); + } + else + { + pIter->second.aIds.push_back( rItemId ); + } + + ToolBarMerger::CreateToolbarItem( pToolbar, nInsPos, rItemId, rItem ); + } + + ++rItemId; + } + } +} + +/** + Replaces a toolbar item with new items for an + existing toolbar. + + @param + pToolbar + + A valid pointer to the toolbar where the merge + fall back operation is applied to. + + @param + nPos + + The reference position of the toolbar item for + the merge operation. Value must be between + 0 and number of toolbar items - 1. + + @param + rItemId + + A unique item ID. + + @param + rModuleIdentifier + + The current application module context. + + @param + rItems + + Toolbar items which are associated to the merge + command. +*/ +void ToolBarMerger::ReplaceItem( + ToolBox* pToolbar, + ToolBox::ImplToolItems::size_type nPos, + ToolBoxItemId& rItemId, + CommandToInfoMap& rCommandMap, + std::u16string_view rModuleIdentifier, + const AddonToolbarItemContainer& rAddonToolbarItems ) +{ + pToolbar->RemoveItem( nPos ); + MergeItems( pToolbar, nPos, 0, rItemId, rCommandMap, rModuleIdentifier, rAddonToolbarItems ); +} + +/** + Removes toolbar items from an existing toolbar. + + @param + pToolbar + + A valid pointer to the toolbar where the merge + fall back operation is applied to. + + @param + nPos + + The reference position of the toolbar item for + the merge operation. Value must be between + 0 and number of toolbar items - 1. + + @param + rMergeCommandParameter. + + An optional argument for the merge command. +*/ +void ToolBarMerger::RemoveItems( + ToolBox* pToolbar, + ToolBox::ImplToolItems::size_type nPos, + std::u16string_view rMergeCommandParameter ) +{ + sal_Int32 nCount = o3tl::toInt32(rMergeCommandParameter); + if ( nCount > 0 ) + { + for ( sal_Int32 i = 0; i < nCount; i++ ) + { + if ( nPos < pToolbar->GetItemCount() ) + pToolbar->RemoveItem( nPos ); + } + } +} + +/** + Removes toolbar items from an existing toolbar. + + @param + pToolbar + + A valid pointer to the toolbar where the merge + fall back operation is applied to. + + @param + nPos + + The reference position of the toolbar item for + the merge operation. Value must be between + 0 and number of toolbar items - 1. + + @param + rMergeCommandParameter. + + An optional argument for the merge command. + + @result + Returns true for a successful operation otherwise + false. +*/ +rtl::Reference<::cppu::OWeakObject> ToolBarMerger::CreateController( + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Reference< frame::XFrame > & xFrame, + ToolBox* pToolbar, + const OUString& rCommandURL, + ToolBoxItemId nId, + sal_uInt16 nWidth, + std::u16string_view rControlType ) +{ + rtl::Reference<::cppu::OWeakObject> pResult; + + if ( rControlType == TOOLBARCONTROLLER_BUTTON ) + pResult = new ButtonToolbarController( rxContext, pToolbar, rCommandURL ); + else if ( rControlType == TOOLBARCONTROLLER_COMBOBOX ) + pResult = new ComboboxToolbarController( rxContext, xFrame, pToolbar, nId, nWidth, rCommandURL ); + else if ( rControlType == TOOLBARCONTROLLER_EDIT ) + pResult = new EditToolbarController( rxContext, xFrame, pToolbar, nId, nWidth, rCommandURL ); + else if ( rControlType == TOOLBARCONTROLLER_SPINFIELD ) + pResult = new SpinfieldToolbarController( rxContext, xFrame, pToolbar, nId, nWidth, rCommandURL ); + else if ( rControlType == TOOLBARCONTROLLER_IMGBUTTON ) + pResult = new ImageButtonToolbarController( rxContext, xFrame, pToolbar, nId, rCommandURL ); + else if ( rControlType == TOOLBARCONTROLLER_DROPDOWNBOX ) + pResult = new DropdownToolbarController( rxContext, xFrame, pToolbar, nId, nWidth, rCommandURL ); + else if ( rControlType == TOOLBARCONTROLLER_DROPDOWNBTN ) + pResult = new ToggleButtonToolbarController( rxContext, xFrame, pToolbar, nId, + ToggleButtonToolbarController::Style::DropDownButton, rCommandURL ); + else if ( rControlType == TOOLBARCONTROLLER_FIXEDIMAGE ) + pResult = new FixedImageToolbarController( rxContext, xFrame, pToolbar, nId, rCommandURL ); + else if ( rControlType == TOOLBARCONTROLLER_FIXEDTEXT ) + pResult = new FixedTextToolbarController( rxContext, xFrame, pToolbar, nId, rCommandURL ); + else if ( rControlType == TOOLBARCONTROLLER_TOGGLEDDBTN ) + pResult = new ToggleButtonToolbarController( rxContext, xFrame, pToolbar, nId, + ToggleButtonToolbarController::Style::ToggleDropDownButton, rCommandURL ); + else + pResult = new GenericToolbarController( rxContext, xFrame, pToolbar, nId, rCommandURL ); + + return pResult; +} + +void ToolBarMerger::CreateToolbarItem( ToolBox* pToolbar, ToolBox::ImplToolItems::size_type nPos, ToolBoxItemId nItemId, const AddonToolbarItem& rItem ) +{ + assert(pToolbar->GetItemData(nItemId) == nullptr); // that future would contain a double free + + pToolbar->InsertItem( nItemId, rItem.aLabel, ToolBoxItemBits::NONE, nPos ); + pToolbar->SetItemCommand( nItemId, rItem.aCommandURL ); + pToolbar->SetQuickHelpText( nItemId, rItem.aLabel ); + pToolbar->SetItemText( nItemId, rItem.aLabel ); + pToolbar->EnableItem( nItemId ); + pToolbar->SetItemState( nItemId, TRISTATE_FALSE ); + + // Use the user data to store add-on specific data with the toolbar item + AddonsParams* pAddonParams = new AddonsParams; + pAddonParams->aControlType = rItem.aControlType; + pAddonParams->nWidth = rItem.nWidth; + pToolbar->SetItemData( nItemId, pAddonParams ); +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |