vcl: Allow creation of button content from action name (.uno: commands).

Change-Id: If4b2aef59d45a848fb77de9e1b7bf80d49548a75
diff --git a/framework/source/layoutmanager/layoutmanager.cxx b/framework/source/layoutmanager/layoutmanager.cxx
index 89d1fe4..a9fad1a 100644
--- a/framework/source/layoutmanager/layoutmanager.cxx
+++ b/framework/source/layoutmanager/layoutmanager.cxx
@@ -770,7 +770,7 @@ void LayoutManager::implts_updateUIElementsVisibleState( bool bSetVisible )
        if ( pSysWindow )
        {
            if ( bSetVisible )
                pSysWindow->SetMenuBar( pMenuBar );
                pSysWindow->SetMenuBar(pMenuBar, m_xFrame);
            else
                pSysWindow->SetMenuBar( 0 );
            bMustDoLayout = true;
@@ -1154,7 +1154,7 @@ throw (uno::RuntimeException)

            SystemWindow* pSysWindow = getTopSystemWindow( m_xContainerWindow );
            if ( pSysWindow )
                pSysWindow->SetMenuBar(pMenuBar);
                pSysWindow->SetMenuBar(pMenuBar, m_xFrame);

            m_bInplaceMenuSet = true;
            m_xInplaceMenuBar = Reference< XComponent >( (OWeakObject *)m_pInplaceMenuBar, UNO_QUERY );
@@ -1181,7 +1181,7 @@ throw (uno::RuntimeException)
        if ( pSysWindow )
        {
            if ( pMenuBarWrapper )
                pSysWindow->SetMenuBar((MenuBar *)pMenuBarWrapper->GetMenuBarManager()->GetMenuBar());
                pSysWindow->SetMenuBar((MenuBar *)pMenuBarWrapper->GetMenuBarManager()->GetMenuBar(), m_xFrame);
            else
                pSysWindow->SetMenuBar(0);
        }
@@ -1489,7 +1489,7 @@ throw (RuntimeException, std::exception)
                                MenuBar* pMenuBar = (MenuBar*)pAwtMenuBar->GetMenu();
                                if ( pMenuBar )
                                {
                                    pSysWindow->SetMenuBar( pMenuBar );
                                    pSysWindow->SetMenuBar(pMenuBar, m_xFrame);
                                    pMenuBar->SetDisplayable( m_bMenuVisible );
                                    if ( m_bMenuVisible )
                                        bNotify = true;
@@ -2574,7 +2574,7 @@ bool LayoutManager::implts_resetMenuBar()
    SystemWindow* pSysWindow = getTopSystemWindow( xContainerWindow );
    if ( pSysWindow && bMenuVisible && pSetMenuBar )
    {
        pSysWindow->SetMenuBar( pSetMenuBar );
        pSysWindow->SetMenuBar(pSetMenuBar, m_xFrame);
        pSetMenuBar->SetDisplayable( true );
        return true;
    }
diff --git a/include/vcl/builder.hxx b/include/vcl/builder.hxx
index baa77d3..f9adddb 100644
--- a/include/vcl/builder.hxx
+++ b/include/vcl/builder.hxx
@@ -29,6 +29,7 @@
#include <boost/ptr_container/ptr_map.hpp>

#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>

class ListBox;
class NumericFormatter;
@@ -258,7 +259,7 @@ private:
public:
    VclBuilder(::Window *pParent, const OUString& sUIRootDir, const OUString& sUIFile,
            const OString& sID = OString(),
            const com::sun::star::uno::Reference<com::sun::star::frame::XFrame> &rFrame = com::sun::star::uno::Reference<com::sun::star::frame::XFrame>());
            const css::uno::Reference<css::frame::XFrame> &rFrame = css::uno::Reference<css::frame::XFrame>());
    ~VclBuilder();
    ::Window *get_widget_root();
    //sID must exist and be of type T
@@ -324,6 +325,14 @@ public:
    static void reorderWithinParent(std::vector< ::Window*>& rChilds, bool bIsButtonBox);
    static void reorderWithinParent(::Window &rWindow, sal_uInt16 nNewPosition);

    /// Get label of the command (like of .uno:Save) from the description service
    static OUString getCommandLabel(const OUString& rCommand, const css::uno::Reference<css::uno::XComponentContext>& rContext, const OUString& rModuleId);

    /// Get image of the command (like of .uno:Save) from the description service
    static Image getCommandImage(const OUString& rCommand, bool bLarge,
            const css::uno::Reference<css::uno::XComponentContext>& rContext, const css::uno::Reference<css::frame::XFrame>& rFrame,
            const OUString& rModuleId);

    css::uno::Reference<css::frame::XFrame> getFrame() { return m_xFrame; }
private:
    ::Window *insertObject(::Window *pParent,
diff --git a/include/vcl/menu.hxx b/include/vcl/menu.hxx
index de5dea0..7731301 100644
--- a/include/vcl/menu.hxx
+++ b/include/vcl/menu.hxx
@@ -29,6 +29,7 @@
#include <vcl/bitmapex.hxx>
#include <vcl/keycod.hxx>
#include <vcl/vclevent.hxx>
#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/uno/Reference.hxx>

struct ImplSVEvent;
@@ -407,7 +408,7 @@ class VCL_DLLPUBLIC MenuBar : public Menu
    friend class MenuFloatingWindow;
    friend class SystemWindow;

    SAL_DLLPRIVATE static Window*   ImplCreate( Window* pParent, Window* pWindow, MenuBar* pMenu );
    SAL_DLLPRIVATE static Window* ImplCreate(Window* pParent, Window* pWindow, MenuBar* pMenu, const css::uno::Reference<css::frame::XFrame> &rFrame);
    SAL_DLLPRIVATE static void      ImplDestroy( MenuBar* pMenu, bool bDelete );
    SAL_DLLPRIVATE bool         ImplHandleKeyEvent( const KeyEvent& rKEvent, bool bFromMenu = true );

diff --git a/include/vcl/syswin.hxx b/include/vcl/syswin.hxx
index ce79e11..382e9b1 100644
--- a/include/vcl/syswin.hxx
+++ b/include/vcl/syswin.hxx
@@ -224,7 +224,7 @@ public:
    void            SetWindowState(const OString& rStr);
    OString         GetWindowState(sal_uLong nMask = WINDOWSTATE_MASK_ALL) const;

    void            SetMenuBar( MenuBar* pMenuBar );
    void            SetMenuBar(MenuBar* pMenuBar, const css::uno::Reference<css::frame::XFrame>& rFrame = css::uno::Reference<css::frame::XFrame>());
    MenuBar*        GetMenuBar() const { return mpMenuBar; }
    void            SetMenuBarMode( sal_uInt16 nMode );
    sal_uInt16      GetMenuBarMode() const { return mnMenuBarMode; }
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index 0bfc4e7..824fd17 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -7,7 +7,16 @@
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <com/sun/star/frame/ModuleManager.hpp>
#include <com/sun/star/frame/XModuleManager2.hpp>
#include <com/sun/star/frame/theUICommandDescription.hpp>
#include <com/sun/star/packages/zip/ZipFileAccess.hpp>
#include <com/sun/star/ui/ImageType.hpp>
#include <com/sun/star/ui/XImageManager.hpp>
#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
#include <com/sun/star/ui/XUIConfigurationManager.hpp>
#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>

#include <comphelper/processfactory.hxx>
#include <osl/module.hxx>
@@ -144,7 +153,7 @@ void VclBuilder::loadTranslations(const LanguageTag &rLanguageTag, const OUStrin
            handleTranslations(reader);
            break;
        }
        catch (const ::com::sun::star::uno::Exception &)
        catch (const uno::Exception &)
        {
        }
    }
@@ -197,7 +206,7 @@ VclBuilder::VclBuilder(Window *pParent, const OUString& sUIDir, const OUString& 

        handleChild(pParent, reader);
    }
    catch (const ::com::sun::star::uno::Exception &rExcept)
    catch (const uno::Exception &rExcept)
    {
        SAL_WARN("vcl.layout", "Unable to read .ui file: " << rExcept.Message);
        throw;
@@ -805,6 +814,27 @@ namespace
        return sTooltipText;
    }

    void setupFromActionName(Button *pButton, VclBuilder::stringmap &rMap, const uno::Reference<frame::XFrame>& rFrame)
    {
        if (!rFrame.is())
            return;

        OUString aCommand(OStringToOUString(extractActionName(rMap), RTL_TEXTENCODING_UTF8));
        if (aCommand.isEmpty())
            return;

        uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
        uno::Reference<frame::XModuleManager2> xModuleManager(frame::ModuleManager::create(xContext));
        OUString aModuleId(xModuleManager->identify(rFrame));

        OUString aLabel(VclBuilder::getCommandLabel(aCommand, xContext, aModuleId));
        if (!aLabel.isEmpty())
            pButton->SetText(aLabel);

        Image aImage(VclBuilder::getCommandImage(aCommand, /* bLarge = */ false, xContext, rFrame, aModuleId));
        pButton->SetModeImage(aImage);
    }

    Button* extractStockAndBuildPushButton(Window *pParent, VclBuilder::stringmap &rMap)
    {
        WinBits nBits = WB_CLIPCHILDREN|WB_CENTER|WB_VCENTER;
@@ -1275,6 +1305,7 @@ Window *VclBuilder::makeObject(Window *pParent, const OString &name, const OStri
            m_pParserState->m_aButtonMenuMaps.push_back(ButtonMenuMap(id, sMenu));
        }
        pButton->SetImageAlign(IMAGEALIGN_LEFT); //default to left
        setupFromActionName(pButton, rMap, m_xFrame);
        pWindow = pButton;
    }
    else if (name == "GtkRadioButton")
@@ -2050,6 +2081,98 @@ void VclBuilder::reorderWithinParent(std::vector<Window*>& rChilds, bool bIsButt
    }
}

OUString VclBuilder::getCommandLabel(const OUString& rCommand, const uno::Reference<uno::XComponentContext>& rContext, const OUString& rModuleId)
{
    if (rCommand.isEmpty())
        return OUString();

    try
    {
        uno::Reference<container::XNameAccess> xUICommandLabels;
        uno::Reference<container::XNameAccess> xUICommandDescription(frame::theUICommandDescription::get(rContext));

        if ((xUICommandDescription->getByName(rModuleId) >>= xUICommandLabels) && xUICommandLabels.is())
        {
            uno::Sequence<beans::PropertyValue> aProperties;
            if (xUICommandLabels->getByName(rCommand) >>= aProperties)
            {
                for ( sal_Int32 i = 0; i < aProperties.getLength(); i++ )
                {
                    if (aProperties[i].Name == "Label")
                    {
                        OUString aLabel;
                        if (aProperties[i].Value >>= aLabel)
                            return aLabel;
                    }
                }
            }
        }
    }
    catch (uno::Exception&)
    {
    }

    return OUString();
}

Image VclBuilder::getCommandImage(const OUString& rCommand, bool bLarge,
        const uno::Reference<uno::XComponentContext>& rContext, const uno::Reference<frame::XFrame>& rFrame,
        const OUString& rModuleId)
{
    if (rCommand.isEmpty())
        return Image();

    sal_Int16 nImageType(ui::ImageType::COLOR_NORMAL | ui::ImageType::SIZE_DEFAULT);
    if (bLarge)
        nImageType |= ui::ImageType::SIZE_LARGE;

    try
    {
        uno::Reference<frame::XController> xController(rFrame->getController());
        uno::Reference<frame::XModel> xModel(xController->getModel());

        uno::Reference<ui::XUIConfigurationManagerSupplier> xSupplier(xModel, uno::UNO_QUERY);
        uno::Reference<ui::XUIConfigurationManager> xDocUICfgMgr(xSupplier->getUIConfigurationManager(), uno::UNO_QUERY);
        uno::Reference<ui::XImageManager> xDocImgMgr(xDocUICfgMgr->getImageManager(), uno::UNO_QUERY);

        uno::Sequence< uno::Reference<graphic::XGraphic> > aGraphicSeq;
        uno::Sequence<OUString> aImageCmdSeq(1);
        aImageCmdSeq[0] = rCommand;

        aGraphicSeq = xDocImgMgr->getImages( nImageType, aImageCmdSeq );
        uno::Reference<graphic::XGraphic> xGraphic = aGraphicSeq[0];
        Image aImage(xGraphic);

        if (!!aImage)
            return aImage;
    }
    catch (uno::Exception&)
    {
    }

    try {
        uno::Reference<ui::XModuleUIConfigurationManagerSupplier> xModuleCfgMgrSupplier(ui::theModuleUIConfigurationManagerSupplier::get(rContext));
        uno::Reference<ui::XUIConfigurationManager> xUICfgMgr(xModuleCfgMgrSupplier->getUIConfigurationManager(rModuleId));

        uno::Sequence< uno::Reference<graphic::XGraphic> > aGraphicSeq;
        uno::Reference<ui::XImageManager> xModuleImageManager(xUICfgMgr->getImageManager(), uno::UNO_QUERY);

        uno::Sequence<OUString> aImageCmdSeq(1);
        aImageCmdSeq[0] = rCommand;

        aGraphicSeq = xModuleImageManager->getImages(nImageType, aImageCmdSeq);

        uno::Reference<graphic::XGraphic> xGraphic(aGraphicSeq[0]);

        return Image(xGraphic);
    }
    catch (uno::Exception&)
    {
    }

    return Image();
}

void VclBuilder::collectPangoAttribute(xmlreader::XmlReader &reader, stringmap &rMap)
{
    xmlreader::Span span;
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index 043d2d3..179d979 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -2470,7 +2470,7 @@ void MenuBar::SetDisplayable( bool bDisplayable )
    }
}

Window* MenuBar::ImplCreate( Window* pParent, Window* pWindow, MenuBar* pMenu )
Window* MenuBar::ImplCreate(Window* pParent, Window* pWindow, MenuBar* pMenu, const css::uno::Reference<css::frame::XFrame> &/*rFrame*/)
{
    MenuBarWindow *pMenuBarWindow = dynamic_cast<MenuBarWindow*>(pWindow);
    if (!pMenuBarWindow)
diff --git a/vcl/source/window/syswin.cxx b/vcl/source/window/syswin.cxx
index 0a2980b..60c8092 100644
--- a/vcl/source/window/syswin.cxx
+++ b/vcl/source/window/syswin.cxx
@@ -879,7 +879,7 @@ OString SystemWindow::GetWindowState( sal_uLong nMask ) const
    return ImplWindowStateToStr(aData);
}

void SystemWindow::SetMenuBar( MenuBar* pMenuBar )
void SystemWindow::SetMenuBar(MenuBar* pMenuBar, const css::uno::Reference<css::frame::XFrame>& rFrame)
{
    if ( mpMenuBar != pMenuBar )
    {
@@ -902,7 +902,7 @@ void SystemWindow::SetMenuBar( MenuBar* pMenuBar )
            if ( pMenuBar )
            {
                DBG_ASSERT( !pMenuBar->pWindow, "SystemWindow::SetMenuBar() - MenuBars can only set in one SystemWindow at time" );
                ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMenuBarWindow( pNewWindow = MenuBar::ImplCreate( mpWindowImpl->mpBorderWindow, pOldWindow, pMenuBar ) );
                ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetMenuBarWindow(pNewWindow = MenuBar::ImplCreate(mpWindowImpl->mpBorderWindow, pOldWindow, pMenuBar, rFrame));
                ImplCallEventListeners( VCLEVENT_WINDOW_MENUBARADDED, (void*) pMenuBar );
            }
            else
diff --git a/vcl/source/window/toolbox2.cxx b/vcl/source/window/toolbox2.cxx
index 864ec63..0f2731f 100644
--- a/vcl/source/window/toolbox2.cxx
+++ b/vcl/source/window/toolbox2.cxx
@@ -41,17 +41,10 @@
#include <unotools/confignode.hxx>

#include <com/sun/star/frame/ModuleManager.hpp>
#include <com/sun/star/frame/theUICommandDescription.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/frame/XModuleManager2.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#include <com/sun/star/ui/ImageType.hpp>
#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
#include <com/sun/star/ui/XImageManager.hpp>
#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
#include <com/sun/star/ui/XUIConfigurationManager.hpp>

using namespace vcl;
using namespace com::sun::star;
@@ -621,108 +614,14 @@ void ToolBox::InsertItem( sal_uInt16 nItemId, const OUString& rText,
    ImplCallEventListeners( VCLEVENT_TOOLBOX_ITEMADDED, reinterpret_cast< void* >( nNewPos ) );
}

// Get label of the command (like of .uno:Save) from the description service
static OUString getCommandLabel(const OUString& rCommand, const uno::Reference<uno::XComponentContext>& rContext, const OUString& rModuleId)
{
    if (rCommand.isEmpty())
        return OUString();

    try
    {
        uno::Reference<container::XNameAccess> xUICommandLabels;
        uno::Reference<container::XNameAccess> xUICommandDescription(frame::theUICommandDescription::get(rContext));

        if ((xUICommandDescription->getByName(rModuleId) >>= xUICommandLabels) && xUICommandLabels.is())
        {
            uno::Sequence<beans::PropertyValue> aProperties;
            if (xUICommandLabels->getByName(rCommand) >>= aProperties)
            {
                for ( sal_Int32 i = 0; i < aProperties.getLength(); i++ )
                {
                    if (aProperties[i].Name == "Label")
                    {
                        OUString aLabel;
                        if (aProperties[i].Value >>= aLabel)
                            return aLabel;
                    }
                }
            }
        }
    }
    catch (uno::Exception&)
    {
    }

    return OUString();
}

// Get label of the command (like of .uno:Save) from the description service
static Image getCommandImage(const OUString& rCommand, bool bLarge,
        const uno::Reference<uno::XComponentContext>& rContext, const uno::Reference<frame::XFrame>& rFrame,
        const OUString& rModuleId)
{
    if (rCommand.isEmpty())
        return Image();

    sal_Int16 nImageType(ui::ImageType::COLOR_NORMAL | ui::ImageType::SIZE_DEFAULT);
    if (bLarge)
        nImageType |= ui::ImageType::SIZE_LARGE;

    try
    {
        uno::Reference<frame::XController> xController(rFrame->getController());
        uno::Reference<frame::XModel> xModel(xController->getModel());

        uno::Reference<ui::XUIConfigurationManagerSupplier> xSupplier(xModel, uno::UNO_QUERY);
        uno::Reference<ui::XUIConfigurationManager> xDocUICfgMgr(xSupplier->getUIConfigurationManager(), uno::UNO_QUERY);
        uno::Reference<ui::XImageManager> xDocImgMgr(xDocUICfgMgr->getImageManager(), uno::UNO_QUERY);

        uno::Sequence< uno::Reference<graphic::XGraphic> > aGraphicSeq;
        uno::Sequence<OUString> aImageCmdSeq(1);
        aImageCmdSeq[0] = rCommand;

        aGraphicSeq = xDocImgMgr->getImages( nImageType, aImageCmdSeq );
        uno::Reference<graphic::XGraphic> xGraphic = aGraphicSeq[0];
        Image aImage(xGraphic);

        if (!!aImage)
            return aImage;
    }
    catch (uno::Exception&)
    {
    }

    try {
        uno::Reference<ui::XModuleUIConfigurationManagerSupplier> xModuleCfgMgrSupplier(ui::theModuleUIConfigurationManagerSupplier::get(rContext));
        uno::Reference<ui::XUIConfigurationManager> xUICfgMgr(xModuleCfgMgrSupplier->getUIConfigurationManager(rModuleId));

        uno::Sequence< uno::Reference<graphic::XGraphic> > aGraphicSeq;
        uno::Reference<ui::XImageManager> xModuleImageManager(xUICfgMgr->getImageManager(), uno::UNO_QUERY);

        uno::Sequence<OUString> aImageCmdSeq(1);
        aImageCmdSeq[0] = rCommand;

        aGraphicSeq = xModuleImageManager->getImages(nImageType, aImageCmdSeq);

        uno::Reference<graphic::XGraphic> xGraphic(aGraphicSeq[0]);

        return Image(xGraphic);
    }
    catch (uno::Exception&)
    {
    }

    return Image();
}

void ToolBox::InsertItem(const OUString& rCommand, const uno::Reference<frame::XFrame>& rFrame, ToolBoxItemBits nBits, const Size& rRequestedSize, sal_uInt16 nPos)
{
    uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
    uno::Reference<frame::XModuleManager2> xModuleManager(frame::ModuleManager::create(xContext));
    OUString aModuleId(xModuleManager->identify(rFrame));

    OUString aLabel(getCommandLabel(rCommand, xContext, aModuleId));
    Image aImage(getCommandImage(rCommand, (GetToolboxButtonSize() == TOOLBOX_BUTTONSIZE_LARGE), xContext, rFrame, aModuleId));
    OUString aLabel(VclBuilder::getCommandLabel(rCommand, xContext, aModuleId));
    Image aImage(VclBuilder::getCommandImage(rCommand, (GetToolboxButtonSize() == TOOLBOX_BUTTONSIZE_LARGE), xContext, rFrame, aModuleId));

    // let's invent an ItemId
    const sal_uInt16 COMMAND_ITEMID_START = 30000;