Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/framework/source/uielement/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 13 kB image not shown  

Quelle  menubarmerger.cxx   Sprache: 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 <uielement/menubarmerger.hxx>
#include <framework/addonsoptions.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <o3tl/string_view.hxx>

using namespace ::com::sun::star;

const char SEPARATOR_STRING[]               = "private:separator";

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_ADDPATH[]       = u"AddPath";
const char16_t MERGEFALLBACK_IGNORE[]        = u"Ignore";

namespace framework
{

/**
 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.

*/

bool MenuBarMerger::IsCorrectContext(
    std::u16string_view rContext, std::u16string_view rModuleIdentifier )
{
    return ( rContext.empty() || ( rContext.find( rModuleIdentifier ) != std::u16string_view::npos ));
}

void MenuBarMerger::RetrieveReferencePath(
    std::u16string_view rReferencePathString,
    ::std::vector< OUString >& rReferencePath )
{
    const char aDelimiter = '\\';

    rReferencePath.clear();
    sal_Int32 nIndex( 0 );
    do
    {
        OUString aToken( o3tl::getToken(rReferencePathString, 0, aDelimiter, nIndex ) );
        if ( !aToken.isEmpty() )
            rReferencePath.push_back( aToken );
    }
    while ( nIndex >= 0 );
}

ReferencePathInfo MenuBarMerger::FindReferencePath(
    const ::std::vector< OUString >& rReferencePath,
    Menu* pMenu )
{
    sal_uInt32       i( 0 );
    const sal_uInt32 nCount( rReferencePath.size() );

    ReferencePathInfo aResult;
    if ( !nCount )
    {
        aResult.pPopupMenu = nullptr;
        aResult.nPos = 0;
        aResult.nLevel = -1;
        aResult.eResult = RP_MENUITEM_NOT_FOUND;
        return aResult;
    }

    Menu*            pCurrMenu( pMenu );
    RPResultInfo     eResult( RP_OK );

    sal_Int32  nLevel( - 1 );
    sal_uInt16 nPos( MENU_ITEM_NOTFOUND );
    do
    {
        ++nLevel;
        const OUString& aCmd( rReferencePath[i] );

        if ( i == nCount-1 )
        {
            // Check last reference path element. Must be a leave (menu item).
            sal_uInt16 nTmpPos = FindMenuItem( aCmd, pCurrMenu );
            if ( nTmpPos != MENU_ITEM_NOTFOUND )
                nPos = nTmpPos;
            eResult = ( nTmpPos != MENU_ITEM_NOTFOUND ) ? RP_OK : RP_MENUITEM_NOT_FOUND;
        }
        else
        {
            // Check reference path element. Must be a node (popup menu)!
            sal_uInt16 nTmpPos = FindMenuItem( aCmd, pCurrMenu );
            if ( nTmpPos != MENU_ITEM_NOTFOUND )
            {
                sal_uInt16 nItemId = pCurrMenu->GetItemId( nTmpPos );
                Menu* pTmpMenu     = pCurrMenu->GetPopupMenu( nItemId );
                if ( pTmpMenu != nullptr )
                    pCurrMenu = pTmpMenu;
                else
                {
                    nPos    = nTmpPos;
                    eResult = RP_MENUITEM_INSTEAD_OF_POPUPMENU_FOUND;
                }
            }
            else
                eResult = RP_POPUPMENU_NOT_FOUND;
        }
        i++;
    }
    while ((i < nCount) && (eResult == RP_OK));

    aResult.pPopupMenu = pCurrMenu;
    aResult.nPos       = nPos;
    aResult.nLevel     = nLevel;
    aResult.eResult    = eResult;

    return aResult;
}

sal_uInt16 MenuBarMerger::FindMenuItem( std::u16string_view rCmd, Menu const * pCurrMenu )
{
    for ( sal_uInt16 i = 0; i < pCurrMenu->GetItemCount(); i++ )
    {
        const sal_uInt16 nItemId = pCurrMenu->GetItemId( i );
        if ( nItemId > 0 )
        {
            if ( rCmd == pCurrMenu->GetItemCommand( nItemId ) )
                return i;
        }
    }

    return MENU_ITEM_NOTFOUND;
}

bool MenuBarMerger::CreateSubMenu(
    Menu*                     pSubMenu,
    sal_uInt16&               nItemId,
    const OUString&    rModuleIdentifier,
    const AddonMenuContainer& rAddonSubMenu )
{
    const sal_uInt32 nSize = rAddonSubMenu.size();
    for ( sal_uInt32 i = 0; i < nSize; i++ )
    {
        const AddonMenuItem& rMenuItem = rAddonSubMenu[i];

        if ( IsCorrectContext( rMenuItem.aContext, rModuleIdentifier ))
        {
            if ( rMenuItem.aURL == SEPARATOR_STRING )
            {
                pSubMenu->InsertSeparator();
            }
            else
            {
                pSubMenu->InsertItem(nItemId, rMenuItem.aTitle);
                pSubMenu->SetItemCommand( nItemId, rMenuItem.aURL );
                if ( !rMenuItem.aSubMenu.empty() )
                {
                    VclPtr<PopupMenu> pPopupMenu = VclPtr<PopupMenu>::Create();
                    pSubMenu->SetPopupMenu( nItemId, pPopupMenu );
                    ++nItemId;

                    CreateSubMenu( pPopupMenu, nItemId, rModuleIdentifier, rMenuItem.aSubMenu );
                }
                else
                    ++nItemId;
            }
        }
    }

    return true;
}

bool MenuBarMerger::MergeMenuItems(
    Menu*                     pMenu,
    sal_uInt16                nPos,
    sal_uInt16                nModIndex,
    sal_uInt16&               nItemId,
    const OUString&    rModuleIdentifier,
    const AddonMenuContainer& rAddonMenuItems )
{
    sal_uInt16       nIndex( 0 );
    const sal_uInt32 nSize = rAddonMenuItems.size();
    for ( sal_uInt32 i = 0; i < nSize; i++ )
    {
        const AddonMenuItem& rMenuItem = rAddonMenuItems[i];

        if ( IsCorrectContext( rMenuItem.aContext, rModuleIdentifier ))
        {
            if ( rMenuItem.aURL == SEPARATOR_STRING )
            {
                pMenu->InsertSeparator({}, nPos + nModIndex + nIndex);
            }
            else
            {
                pMenu->InsertItem(nItemId, rMenuItem.aTitle, MenuItemBits::NONE, {}, nPos + nModIndex + nIndex);
                pMenu->SetItemCommand( nItemId, rMenuItem.aURL );
                if ( !rMenuItem.aSubMenu.empty() )
                {
                    VclPtr<PopupMenu> pSubMenu = VclPtr<PopupMenu>::Create();
                    pMenu->SetPopupMenu( nItemId, pSubMenu );
                    ++nItemId;

                    CreateSubMenu( pSubMenu, nItemId, rModuleIdentifier, rMenuItem.aSubMenu );
                }
                else
                    ++nItemId;
            }
            ++nIndex;
        }
    }

    return true;
}

bool MenuBarMerger::ReplaceMenuItem(
    Menu*                     pMenu,
    sal_uInt16                nPos,
    sal_uInt16&               rItemId,
    const OUString&    rModuleIdentifier,
    const AddonMenuContainer& rAddonMenuItems )
{
    // There is no replace available. Therefore we first have to
    // remove the old menu entry,
    pMenu->RemoveItem( nPos );

    return MergeMenuItems( pMenu, nPos, 0, rItemId, rModuleIdentifier, rAddonMenuItems );
}

bool MenuBarMerger::RemoveMenuItems(
    Menu*                     pMenu,
    sal_uInt16                nPos,
    std::u16string_view    rMergeCommandParameter )
{
    const sal_uInt16 nParam( sal_uInt16( o3tl::toInt32(rMergeCommandParameter) ));
    sal_uInt16       nCount = std::max( nParam, sal_uInt16(1) );

    sal_uInt16 i = 0;
    while (( nPos < pMenu->GetItemCount() ) && ( i < nCount ))
    {
        pMenu->RemoveItem( nPos );
        ++i;
    }

    return true;
}

bool MenuBarMerger::ProcessMergeOperation(
    Menu*                     pMenu,
    sal_uInt16                nPos,
    sal_uInt16&               nItemId,
    std::u16string_view rMergeCommand,
    std::u16string_view rMergeCommandParameter,
    const OUString&    rModuleIdentifier,
    const AddonMenuContainer& rAddonMenuItems )
{
    sal_uInt16 nModIndex( 0 );

    if ( rMergeCommand == MERGECOMMAND_ADDBEFORE )
    {
        nModIndex = 0;
        return MergeMenuItems( pMenu, nPos, nModIndex, nItemId, rModuleIdentifier, rAddonMenuItems );
    }
    else if ( rMergeCommand == MERGECOMMAND_ADDAFTER )
    {
        nModIndex = 1;
        return MergeMenuItems( pMenu, nPos, nModIndex, nItemId, rModuleIdentifier, rAddonMenuItems );
    }
    else if ( rMergeCommand == MERGECOMMAND_REPLACE )
    {
        return ReplaceMenuItem( pMenu, nPos, nItemId, rModuleIdentifier, rAddonMenuItems );
    }
    else if ( rMergeCommand == MERGECOMMAND_REMOVE )
    {
        return RemoveMenuItems( pMenu, nPos, rMergeCommandParameter );
    }

    return false;
}

bool MenuBarMerger::ProcessFallbackOperation(
    const ReferencePathInfo&                aRefPathInfo,
    sal_uInt16&                             rItemId,
    std::u16string_view              rMergeCommand,
    std::u16string_view              rMergeFallback,
    const ::std::vector< OUString >& rReferencePath,
    const std::u16string_view        rModuleIdentifier,
    const AddonMenuContainer&               rAddonMenuItems )
{
    if (( rMergeFallback == MERGEFALLBACK_IGNORE ) ||
        ( rMergeCommand  == MERGECOMMAND_REPLACE ) ||
        ( rMergeCommand  == MERGECOMMAND_REMOVE  ) )
    {
        return true;
    }
    else if ( rMergeFallback == MERGEFALLBACK_ADDPATH )
    {
        Menu*            pCurrMenu( aRefPathInfo.pPopupMenu );
        sal_Int32        nLevel( aRefPathInfo.nLevel );
        const sal_Int32  nSize( rReferencePath.size() );
        bool             bFirstLevel( true );

        while ( nLevel < nSize )
        {
            if ( nLevel == nSize-1 )
            {
                const sal_uInt32 nCount = rAddonMenuItems.size();
                for ( sal_uInt32 i = 0; i < nCount; ++i )
                {
                    const AddonMenuItem& rMenuItem = rAddonMenuItems[i];
                    if ( IsCorrectContext( rMenuItem.aContext, rModuleIdentifier ))
                    {
                        if ( rMenuItem.aURL == SEPARATOR_STRING )
                            pCurrMenu->InsertSeparator();
                        else
                        {
                            pCurrMenu->InsertItem(rItemId, rMenuItem.aTitle);
                            pCurrMenu->SetItemCommand( rItemId, rMenuItem.aURL );
                            ++rItemId;
                        }
                    }
                }
            }
            else
            {
                const OUString& aCmd( rReferencePath[nLevel] );

                VclPtr<PopupMenu> pPopupMenu = VclPtr<PopupMenu>::Create();

                if ( bFirstLevel && ( aRefPathInfo.eResult == RP_MENUITEM_INSTEAD_OF_POPUPMENU_FOUND ))
                {
                    // special case: menu item without popup
                    sal_uInt16 nInsPos = aRefPathInfo.nPos;
                    sal_uInt16 nSetItemId = pCurrMenu->GetItemId( nInsPos );
                    pCurrMenu->SetItemCommand( nSetItemId, aCmd );
                    pCurrMenu->SetPopupMenu( nSetItemId, pPopupMenu );
                }
                else
                {
                    // normal case: insert a new item with popup
                    pCurrMenu->InsertItem(rItemId, OUString());
                    pCurrMenu->SetItemCommand( rItemId, aCmd );
                    pCurrMenu->SetPopupMenu( rItemId, pPopupMenu );
                }

                pCurrMenu = pPopupMenu;
                ++rItemId;
                bFirstLevel = false;
            }
            ++nLevel;
        }
        return true;
    }

    return false;
}

void MenuBarMerger::GetMenuEntry(
    const uno::Sequence< beans::PropertyValue >& rAddonMenuEntry,
    AddonMenuItem&                               rAddonMenuItem )
{
    // Reset submenu member
    rAddonMenuItem.aSubMenu.clear();

    for ( const beans::PropertyValue& rProp : rAddonMenuEntry )
    {
        OUString aMenuEntryPropName = rProp.Name;
        if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_URL )
            rProp.Value >>= rAddonMenuItem.aURL;
        else if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_TITLE )
            rProp.Value >>= rAddonMenuItem.aTitle;
        else if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_SUBMENU )
        {
            uno::Sequence< uno::Sequence< beans::PropertyValue > > aSubMenu;
            rProp.Value >>= aSubMenu;
            GetSubMenu( aSubMenu, rAddonMenuItem.aSubMenu );
        }
        else if ( aMenuEntryPropName == ADDONSMENUITEM_STRING_CONTEXT )
            rProp.Value >>= rAddonMenuItem.aContext;
    }
}

void MenuBarMerger::GetSubMenu(
    const uno::Sequence< uno::Sequence< beans::PropertyValue > >& rSubMenuEntries,
    AddonMenuContainer&                                           rSubMenu )
{
    rSubMenu.clear();

    const sal_Int32 nCount = rSubMenuEntries.getLength();
    rSubMenu.reserve(rSubMenu.size() + nCount);
    for ( sal_Int32 i = 0; i < nCount; i++ )
    {
        const uno::Sequence< beans::PropertyValue >& rMenuEntry = rSubMenuEntries[ i ];

        AddonMenuItem aMenuItem;
        GetMenuEntry( rMenuEntry, aMenuItem );
        rSubMenu.push_back( aMenuItem );
    }
}

// namespace framework

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=94 H=96 G=94

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.