office-gobmx/framework/source/uielement/toolbarmerger.cxx
Maxim Monastirsky c76857fe4e Make ToolBox::InsertItem take the command name
For the next patch for tdf#149956 I need the command to be
already set when the VclEventId::ToolboxItemAdded event is emitted.

Change-Id: I3d8ce44b426a3ed5704d4520d6e62bc4efbf8e44
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138038
Tested-by: Jenkins
Reviewed-by: Maxim Monastirsky <momonasmon@gmail.com>
2022-08-10 08:28:18 +02:00

648 lines
19 KiB
C++

/* -*- 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
nFirstItem
First toolbar item to search from.
@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, sal_uInt16 nFirstItem,
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 = nFirstItem; 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, rItem.aCommandURL, ToolBoxItemBits::NONE, nPos );
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: */