/**************************************************************
 *
 * 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
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



#include "precompiled_sfx2.hxx"

#include "SidebarController.hxx"
#include "Deck.hxx"
#include "DeckTitleBar.hxx"
#include "Panel.hxx"
#include "PanelTitleBar.hxx"
#include "SidebarPanel.hxx"
#include "SidebarResource.hxx"
#include "TabBar.hxx"
#include "sfx2/sidebar/Theme.hxx"
#include "sfx2/sidebar/SidebarChildWindow.hxx"
#include "sfx2/sidebar/Tools.hxx"
#include "SidebarDockingWindow.hxx"
#include "Context.hxx"

#include "sfxresid.hxx"
#include "sfx2/sfxsids.hrc"
#include "sfx2/titledockwin.hxx"
#include "sfxlocal.hrc"
#include <vcl/floatwin.hxx>
#include <vcl/fixed.hxx>
#include "splitwin.hxx"
#include <svl/smplhint.hxx>
#include <tools/link.hxx>
#include <toolkit/helper/vclunohelper.hxx>

#include <comphelper/componentfactory.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/componentcontext.hxx>
#include <comphelper/namedvaluecollection.hxx>

#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/ui/ContextChangeEventMultiplexer.hpp>
#include <com/sun/star/ui/ContextChangeEventObject.hpp>
#include <com/sun/star/ui/XUIElementFactory.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>
#include <com/sun/star/util/URL.hpp>
#include <com/sun/star/rendering/XSpriteCanvas.hpp>

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/scoped_array.hpp>


using namespace css;
using namespace cssu;
using ::rtl::OUString;


#undef VERBOSE

namespace
{
    const static OUString gsReadOnlyCommandName (A2S(".uno:EditDoc"));
    const static sal_Int32 gnMaximumSidebarWidth (400);
    const static sal_Int32 gnWidthCloseThreshold (70);
    const static sal_Int32 gnWidthOpenThreshold (40);
}


namespace sfx2 { namespace sidebar {

SidebarController::SidebarControllerContainer SidebarController::maSidebarControllerContainer;

namespace {
    enum MenuId
    {
        MID_UNLOCK_TASK_PANEL = 1,
        MID_LOCK_TASK_PANEL,
        MID_CUSTOMIZATION,
        MID_RESTORE_DEFAULT,
        MID_FIRST_PANEL,
        MID_FIRST_HIDE = 1000
    };

    /** When in doubt, show this deck.
    */
    static const ::rtl::OUString gsDefaultDeckId(A2S("PropertyDeck"));
}


SidebarController::SidebarController (
    SidebarDockingWindow* pParentWindow,
    const cssu::Reference<css::frame::XFrame>& rxFrame)
    : SidebarControllerInterfaceBase(m_aMutex),
      mpCurrentDeck(),
      mpParentWindow(pParentWindow),
      mpTabBar(new TabBar(
              mpParentWindow,
              rxFrame,
              ::boost::bind(&SidebarController::OpenThenSwitchToDeck, this, _1),
              ::boost::bind(&SidebarController::ShowPopupMenu, this, _1,_2))),
      mxFrame(rxFrame),
      maCurrentContext(OUString(), OUString()),
      maRequestedContext(),
      mnRequestedForceFlags(SwitchFlag_NoForce),
      msCurrentDeckId(gsDefaultDeckId),
      msCurrentDeckTitle(),
      maPropertyChangeForwarder(::boost::bind(&SidebarController::BroadcastPropertyChange, this)),
      maContextChangeUpdate(::boost::bind(&SidebarController::UpdateConfigurations, this)),
      maAsynchronousDeckSwitch(),
      mbIsDeckRequestedOpen(),
      mbIsDeckOpen(),
      mbCanDeckBeOpened(true),
      mnSavedSidebarWidth(pParentWindow->GetSizePixel().Width()),
      maFocusManager(::boost::bind(&SidebarController::ShowPanel, this, _1)),
      mxReadOnlyModeDispatch(),
      mbIsDocumentReadOnly(false),
      mpSplitWindow(NULL),
      mnWidthOnSplitterButtonDown(0),
      mpCloseIndicator()
{
    if (pParentWindow == NULL)
    {
        OSL_ASSERT(pParentWindow!=NULL);
            return;
    }

    // Listen for context change events.
    cssu::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer (
        css::ui::ContextChangeEventMultiplexer::get(
            ::comphelper::getProcessComponentContext()));
    if (xMultiplexer.is())
        xMultiplexer->addContextChangeEventListener(
            static_cast<css::ui::XContextChangeEventListener*>(this),
            mxFrame->getController());

    // Listen for window events.
    mpParentWindow->AddEventListener(LINK(this, SidebarController, WindowEventHandler));

    // Listen for theme property changes.
    Theme::GetPropertySet()->addPropertyChangeListener(
        A2S(""),
        static_cast<css::beans::XPropertyChangeListener*>(this));

    // Get the dispatch object as preparation to listen for changes of
    // the read-only state.
    const util::URL aURL (Tools::GetURL(gsReadOnlyCommandName));
    mxReadOnlyModeDispatch = Tools::GetDispatch(mxFrame, aURL);
    if (mxReadOnlyModeDispatch.is())
        mxReadOnlyModeDispatch->addStatusListener(this, aURL);

    SwitchToDeck(A2S("default"));

    WeakReference<SidebarController> xWeakController (this);
    maSidebarControllerContainer.insert(
        SidebarControllerContainer::value_type(
            rxFrame,
            xWeakController));
}




SidebarController::~SidebarController (void)
{
}




SidebarController* SidebarController::GetSidebarControllerForFrame (
    const cssu::Reference<css::frame::XFrame>& rxFrame)
{
    SidebarControllerContainer::iterator iEntry (maSidebarControllerContainer.find(rxFrame));
    if (iEntry == maSidebarControllerContainer.end())
        return NULL;

    cssu::Reference<XInterface> xController (iEntry->second.get());
    if ( ! xController.is())
        return NULL;

    return dynamic_cast<SidebarController*>(xController.get());
}




void SAL_CALL SidebarController::disposing (void)
{
    SidebarControllerContainer::iterator iEntry (maSidebarControllerContainer.find(mxFrame));
    if (iEntry != maSidebarControllerContainer.end())
        maSidebarControllerContainer.erase(iEntry);

    maFocusManager.Clear();

    cssu::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer (
        css::ui::ContextChangeEventMultiplexer::get(
            ::comphelper::getProcessComponentContext()));
    if (xMultiplexer.is())
        xMultiplexer->removeAllContextChangeEventListeners(
            static_cast<css::ui::XContextChangeEventListener*>(this));

    if (mxReadOnlyModeDispatch.is())
        mxReadOnlyModeDispatch->removeStatusListener(this, Tools::GetURL(gsReadOnlyCommandName));
    if (mpSplitWindow != NULL)
    {
        mpSplitWindow->RemoveEventListener(LINK(this, SidebarController, WindowEventHandler));
        mpSplitWindow = NULL;
    }

    if (mpParentWindow != NULL)
    {
        mpParentWindow->RemoveEventListener(LINK(this, SidebarController, WindowEventHandler));
        mpParentWindow = NULL;
    }

    if (mpCurrentDeck)
    {
        mpCurrentDeck->Dispose();
        mpCurrentDeck->PrintWindowTree();
        mpCurrentDeck.reset();
    }

    mpTabBar.reset();

    Theme::GetPropertySet()->removePropertyChangeListener(
        A2S(""),
        static_cast<css::beans::XPropertyChangeListener*>(this));

    maContextChangeUpdate.CancelRequest();
    maAsynchronousDeckSwitch.CancelRequest();
}




void SAL_CALL SidebarController::notifyContextChangeEvent (const css::ui::ContextChangeEventObject& rEvent)
    throw(cssu::RuntimeException)
{
    // Update to the requested new context asynchronously to avoid
    // subtle errors caused by SFX2 which in rare cases can not
    // properly handle a synchronous update.
    maRequestedContext = Context(
        rEvent.ApplicationName,
        rEvent.ContextName);
    if (maRequestedContext != maCurrentContext)
    {
        maAsynchronousDeckSwitch.CancelRequest();
        maContextChangeUpdate.RequestCall();
    }
}




void SAL_CALL SidebarController::disposing (const css::lang::EventObject& rEventObject)
    throw(cssu::RuntimeException)
{
    (void)rEventObject;

    dispose();
}




void SAL_CALL SidebarController::propertyChange (const css::beans::PropertyChangeEvent& rEvent)
    throw(cssu::RuntimeException)
{
    (void)rEvent;

    maPropertyChangeForwarder.RequestCall();
}




void SAL_CALL SidebarController::statusChanged (const css::frame::FeatureStateEvent& rEvent)
    throw(cssu::RuntimeException)
{
    bool bIsReadWrite (true);
    if (rEvent.IsEnabled)
        rEvent.State >>= bIsReadWrite;

    if (mbIsDocumentReadOnly != !bIsReadWrite)
    {
        mbIsDocumentReadOnly = !bIsReadWrite;

        // Force the current deck to update its panel list.
        if ( ! mbIsDocumentReadOnly)
            msCurrentDeckId = gsDefaultDeckId;
        mnRequestedForceFlags |= SwitchFlag_ForceSwitch;
        maAsynchronousDeckSwitch.CancelRequest();
        maContextChangeUpdate.RequestCall();
    }
}




void SAL_CALL SidebarController::requestLayout (void)
    throw(cssu::RuntimeException)
{
    if (mpCurrentDeck)
        mpCurrentDeck->RequestLayout();
    RestrictWidth();
}




void SidebarController::BroadcastPropertyChange (void)
{
    DataChangedEvent aEvent (DATACHANGED_USER);
    mpParentWindow->NotifyAllChilds(aEvent);
    mpParentWindow->Invalidate(INVALIDATE_CHILDREN);
}




void SidebarController::NotifyResize (void)
{
    if( !bool(mpTabBar))
    {
        OSL_ASSERT( bool(mpTabBar));
        return;
    }

    Window* pParentWindow = mpTabBar->GetParent();

    const sal_Int32 nWidth (pParentWindow->GetSizePixel().Width());
    const sal_Int32 nHeight (pParentWindow->GetSizePixel().Height());

    mbIsDeckOpen = (nWidth > TabBar::GetDefaultWidth());

    if (mnSavedSidebarWidth <= 0)
        mnSavedSidebarWidth = nWidth;

    bool bIsDeckVisible;
    if (mbCanDeckBeOpened)
    {
        const bool bIsOpening (nWidth > mnWidthOnSplitterButtonDown);
        if (bIsOpening)
            bIsDeckVisible = nWidth >= TabBar::GetDefaultWidth() + gnWidthOpenThreshold;
        else
            bIsDeckVisible = nWidth >= TabBar::GetDefaultWidth() + gnWidthCloseThreshold;
        mbIsDeckRequestedOpen = bIsDeckVisible;
        UpdateCloseIndicator(!bIsDeckVisible);
    }
    else
        bIsDeckVisible = false;

    // Place the deck.
    if (mpCurrentDeck)
    {
        if (bIsDeckVisible)
        {
            mpCurrentDeck->SetPosSizePixel(0,0, nWidth-TabBar::GetDefaultWidth(), nHeight);
            mpCurrentDeck->Show();
            mpCurrentDeck->RequestLayout();
        }
        else
            mpCurrentDeck->Hide();
    }

    // Place the tab bar.
    mpTabBar->SetPosSizePixel(nWidth-TabBar::GetDefaultWidth(),0,TabBar::GetDefaultWidth(),nHeight);
    mpTabBar->Show();

    // Determine if the closer of the deck can be shown.
    if (mpCurrentDeck)
    {
        DeckTitleBar* pTitleBar = mpCurrentDeck->GetTitleBar();
        if (pTitleBar != NULL && pTitleBar->IsVisible())
            pTitleBar->SetCloserVisible(CanModifyChildWindowWidth());
    }

    RestrictWidth();
}




void SidebarController::ProcessNewWidth (const sal_Int32 nNewWidth)
{
    if ( ! mbIsDeckRequestedOpen)
        return;

    if (mbIsDeckRequestedOpen.get())
     {
        // Deck became large enough to be shown. Show it.
        mnSavedSidebarWidth = nNewWidth;
        RequestOpenDeck();
    }
    else
    {
        // Deck became too small. Close it completely.
        // If window is wider than the tab bar then mark the deck as being visible, even when it's not.
        // This is to trigger an adjustment of the width to the width of the tab bar.
        mbIsDeckOpen = true;
        RequestCloseDeck();

        if (mnWidthOnSplitterButtonDown > TabBar::GetDefaultWidth())
            mnSavedSidebarWidth = mnWidthOnSplitterButtonDown;
    }
}




void SidebarController::UpdateConfigurations (void)
{
    if (maCurrentContext != maRequestedContext
        || mnRequestedForceFlags!=SwitchFlag_NoForce)
    {
        maCurrentContext = maRequestedContext;

        // Find the set of decks that could be displayed for the new context.
        ResourceManager::DeckContextDescriptorContainer aDecks;
        ResourceManager::Instance().GetMatchingDecks (
            aDecks,
            maCurrentContext,
            mbIsDocumentReadOnly,
            mxFrame);

        // Notify the tab bar about the updated set of decks.
        mpTabBar->SetDecks(aDecks);

        // Find the new deck. By default that is the same as the old
        // one. If that is not set or not enabled, then choose the
        // first enabled deck.
        OUString sNewDeckId;
        for (ResourceManager::DeckContextDescriptorContainer::const_iterator
                 iDeck(aDecks.begin()),
                 iEnd(aDecks.end());
             iDeck!=iEnd;
             ++iDeck)
        {
            if (iDeck->mbIsEnabled)
            {
                if (iDeck->msId.equals(msCurrentDeckId))
                {
                    sNewDeckId = msCurrentDeckId;
                    break;
                }
                else if (sNewDeckId.getLength() == 0)
                    sNewDeckId = iDeck->msId;
            }
        }

        if (sNewDeckId.getLength() == 0)
        {
            // We did not find a valid deck.
            RequestCloseDeck();
            return;
        }

        // Tell the tab bar to highlight the button associated
        // with the deck.
        mpTabBar->HighlightDeck(sNewDeckId);

        SwitchToDeck(
            *ResourceManager::Instance().GetDeckDescriptor(sNewDeckId),
            maCurrentContext);
    }
}




void SidebarController::OpenThenSwitchToDeck (
    const ::rtl::OUString& rsDeckId)
{
    RequestOpenDeck();
    SwitchToDeck(rsDeckId);
    mpTabBar->Invalidate();
}




void SidebarController::RequestSwitchToDeck (
    const ::rtl::OUString& rsDeckId)
{
    maContextChangeUpdate.CancelRequest();
    maAsynchronousDeckSwitch.RequestCall(
        ::boost::bind(&SidebarController::OpenThenSwitchToDeck, this, rsDeckId));
}




void SidebarController::SwitchToDeck (
    const ::rtl::OUString& rsDeckId)
{
    if ( ! msCurrentDeckId.equals(rsDeckId)
        || ! mbIsDeckOpen
        || mnRequestedForceFlags!=SwitchFlag_NoForce)
    {
        const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(rsDeckId);
        if (pDeckDescriptor != NULL)
            SwitchToDeck(*pDeckDescriptor, maCurrentContext);
    }
}




void SidebarController::SwitchToDeck (
    const DeckDescriptor& rDeckDescriptor,
    const Context& rContext)
{
    maFocusManager.Clear();

    const bool bForceNewDeck ((mnRequestedForceFlags&SwitchFlag_ForceNewDeck)!=0);
    const bool bForceNewPanels ((mnRequestedForceFlags&SwitchFlag_ForceNewPanels)!=0);
    mnRequestedForceFlags = SwitchFlag_NoForce;

    if ( ! msCurrentDeckId.equals(rDeckDescriptor.msId)
        || bForceNewDeck)
    {
        // When the deck changes then destroy the deck and all panels
        // and create everything new.
        if (mpCurrentDeck)
        {
            mpCurrentDeck->Dispose();
            mpCurrentDeck.reset();
        }

        msCurrentDeckId = rDeckDescriptor.msId;
    }
    mpTabBar->HighlightDeck(msCurrentDeckId);

    // Determine the panels to display in the deck.
    ResourceManager::PanelContextDescriptorContainer aPanelContextDescriptors;
    ResourceManager::Instance().GetMatchingPanels(
        aPanelContextDescriptors,
        rContext,
        rDeckDescriptor.msId,
        mxFrame);

    if (aPanelContextDescriptors.empty())
    {
        // There are no panels to be displayed in the current context.
        if (EnumContext::GetContextEnum(rContext.msContext) != EnumContext::Context_Empty)
        {
            // Switch to the "empty" context and try again.
            SwitchToDeck(
                rDeckDescriptor,
                Context(
                    rContext.msApplication,
                    EnumContext::GetContextName(EnumContext::Context_Empty)));
            return;
        }
        else
        {
            // This is already the "empty" context. Looks like we have
            // to live with an empty deck.
        }
    }

    // Provide a configuration and Deck object.
    if ( ! mpCurrentDeck)
    {
        mpCurrentDeck.reset(
            new Deck(
                rDeckDescriptor,
                mpParentWindow,
                ::boost::bind(&SidebarController::RequestCloseDeck, this)));
        msCurrentDeckTitle = rDeckDescriptor.msTitle;

    }
    if ( ! mpCurrentDeck)
        return;

#ifdef DEBUG
    // Show the context name in the deck title bar.
    DeckTitleBar* pTitleBar = mpCurrentDeck->GetTitleBar();
    if (pTitleBar != NULL)
        pTitleBar->SetTitle(rDeckDescriptor.msTitle+A2S(" (")+maCurrentContext.msContext+A2S(")"));
#endif

    // Update the panel list.
    const sal_Int32 nNewPanelCount (aPanelContextDescriptors.size());
    SharedPanelContainer aNewPanels;
    const SharedPanelContainer& rCurrentPanels (mpCurrentDeck->GetPanels());
    aNewPanels.resize(nNewPanelCount);
    sal_Int32 nWriteIndex (0);
    bool bHasPanelSetChanged (false);
    for (sal_Int32 nReadIndex=0; nReadIndex<nNewPanelCount; ++nReadIndex)
    {
        const ResourceManager::PanelContextDescriptor& rPanelContexDescriptor (
            aPanelContextDescriptors[nReadIndex]);

        // Determine if the panel can be displayed.
        const bool bIsPanelVisible (!mbIsDocumentReadOnly || rPanelContexDescriptor.mbShowForReadOnlyDocuments);
        if ( ! bIsPanelVisible)
            continue;

        // Find the corresponding panel among the currently active
        // panels.
        SharedPanelContainer::const_iterator iPanel;
        if (bForceNewPanels)
        {
            // All panels have to be created in any case. There is no
            // point in searching already existing panels.
            iPanel = rCurrentPanels.end();
        }
        else
        {
            iPanel = ::std::find_if(
                rCurrentPanels.begin(),
                rCurrentPanels.end(),
                ::boost::bind(&Panel::HasIdPredicate, _1, ::boost::cref(rPanelContexDescriptor.msId)));
        }
        if (iPanel != rCurrentPanels.end())
        {
            // Panel already exists in current deck. Reuse it.
            aNewPanels[nWriteIndex] = *iPanel;
            aNewPanels[nWriteIndex]->SetExpanded(rPanelContexDescriptor.mbIsInitiallyVisible);
        }
        else
        {
            // Panel does not yet exist or creation of new panels is forced.
            // Create it.
            aNewPanels[nWriteIndex] = CreatePanel(
                rPanelContexDescriptor.msId,
                mpCurrentDeck->GetPanelParentWindow(),
                rPanelContexDescriptor.mbIsInitiallyVisible,
                rContext);
            bHasPanelSetChanged = true;
        }
        if( bool(aNewPanels[nWriteIndex]))
        {
            // Depending on the context we have to change the command
            // for the "more options" dialog.
            PanelTitleBar* pTitleBar = aNewPanels[nWriteIndex]->GetTitleBar();
            if (pTitleBar != NULL)
            {
                pTitleBar->SetMoreOptionsCommand(
                    rPanelContexDescriptor.msMenuCommand,
                    mxFrame);
            }

            ++nWriteIndex;
        }

    }
    aNewPanels.resize(nWriteIndex);

    // Activate the deck and the new set of panels.
    mpCurrentDeck->SetPosSizePixel(
        0,
        0,
        mpParentWindow->GetSizePixel().Width()-TabBar::GetDefaultWidth(),
        mpParentWindow->GetSizePixel().Height());
    mpCurrentDeck->SetPanels(aNewPanels);
    mpCurrentDeck->Show();

    mpParentWindow->SetText(rDeckDescriptor.msTitle);

    if (bHasPanelSetChanged)
        NotifyResize();

    // Tell the focus manager about the new panels and tab bar
    // buttons.
    maFocusManager.SetDeckTitle(mpCurrentDeck->GetTitleBar());
    maFocusManager.SetPanels(aNewPanels);
    mpTabBar->UpdateFocusManager(maFocusManager);
    UpdateTitleBarIcons();
}




SharedPanel SidebarController::CreatePanel (
    const OUString& rsPanelId,
    ::Window* pParentWindow,
    const bool bIsInitiallyExpanded,
    const Context& rContext)
{
    const PanelDescriptor* pPanelDescriptor = ResourceManager::Instance().GetPanelDescriptor(rsPanelId);
    if (pPanelDescriptor == NULL)
        return SharedPanel();

    // Create the panel which is the parent window of the UIElement.
    SharedPanel pPanel (new Panel(
        *pPanelDescriptor,
        pParentWindow,
        bIsInitiallyExpanded,
        ::boost::bind(&Deck::RequestLayout, mpCurrentDeck.get()),
        ::boost::bind(&SidebarController::GetCurrentContext, this)));

    // Create the XUIElement.
    Reference<ui::XUIElement> xUIElement (CreateUIElement(
            pPanel->GetComponentInterface(),
            pPanelDescriptor->msImplementationURL,
            pPanelDescriptor->mbWantsCanvas,
            rContext));
    if (xUIElement.is())
    {
        // Initialize the panel and add it to the active deck.
        pPanel->SetUIElement(xUIElement);
    }
    else
    {
        pPanel.reset();
    }

    return pPanel;
}




Reference<ui::XUIElement> SidebarController::CreateUIElement (
    const Reference<awt::XWindowPeer>& rxWindow,
    const ::rtl::OUString& rsImplementationURL,
    const bool bWantsCanvas,
    const Context& rContext)
{
    try
    {
        const ::comphelper::ComponentContext aComponentContext (::comphelper::getProcessServiceFactory());
        const Reference<ui::XUIElementFactory> xUIElementFactory (
            aComponentContext.createComponent("com.sun.star.ui.UIElementFactoryManager"),
            UNO_QUERY_THROW);

       // Create the XUIElement.
        ::comphelper::NamedValueCollection aCreationArguments;
        aCreationArguments.put("Frame", makeAny(mxFrame));
        aCreationArguments.put("ParentWindow", makeAny(rxWindow));
        SfxDockingWindow* pSfxDockingWindow = dynamic_cast<SfxDockingWindow*>(mpParentWindow);
        if (pSfxDockingWindow != NULL)
            aCreationArguments.put("SfxBindings", makeAny(sal_uInt64(&pSfxDockingWindow->GetBindings())));
        aCreationArguments.put("Theme", Theme::GetPropertySet());
        aCreationArguments.put("Sidebar", makeAny(Reference<ui::XSidebar>(static_cast<ui::XSidebar*>(this))));
        if (bWantsCanvas)
        {
            Reference<rendering::XSpriteCanvas> xCanvas (VCLUnoHelper::GetWindow(rxWindow)->GetSpriteCanvas());
            aCreationArguments.put("Canvas", makeAny(xCanvas));
        }
        aCreationArguments.put("ApplicationName", makeAny(rContext.msApplication));
        aCreationArguments.put("ContextName", makeAny(rContext.msContext));

        Reference<ui::XUIElement> xUIElement(
            xUIElementFactory->createUIElement(
                rsImplementationURL,
                Sequence<beans::PropertyValue>(aCreationArguments.getPropertyValues())),
            UNO_QUERY_THROW);

        return xUIElement;
    }
    catch(Exception& rException)
    {
        OSL_TRACE("caught exception: %s",
            OUStringToOString(rException.Message, RTL_TEXTENCODING_ASCII_US).getStr());
        // For some reason we can not create the actual panel.
        // Probably because its factory was not properly registered.
        // TODO: provide feedback to developer to better pinpoint the
        // source of the error.

        return NULL;
    }
}




IMPL_LINK(SidebarController, WindowEventHandler, VclWindowEvent*, pEvent)
{
    if (pEvent==NULL)
        return sal_False;

    if (pEvent->GetWindow() == mpParentWindow)
    {
        switch (pEvent->GetId())
        {
            case VCLEVENT_WINDOW_SHOW:
            case VCLEVENT_WINDOW_RESIZE:
                NotifyResize();
                break;

            case VCLEVENT_WINDOW_DATACHANGED:
                // Force an update of deck and tab bar to reflect
                // changes in theme (high contrast mode).
                Theme::HandleDataChange();
                UpdateTitleBarIcons();
                mpParentWindow->Invalidate();
                mnRequestedForceFlags |= SwitchFlag_ForceNewDeck | SwitchFlag_ForceNewPanels;
                maAsynchronousDeckSwitch.CancelRequest();
                maContextChangeUpdate.RequestCall();
                break;

            case SFX_HINT_DYING:
                dispose();
                break;

            case VCLEVENT_WINDOW_PAINT:
                OSL_TRACE("Paint");
                break;

            default:
                break;
        }
    }
    else if (pEvent->GetWindow()==mpSplitWindow && mpSplitWindow!=NULL)
    {
        switch (pEvent->GetId())
        {
            case VCLEVENT_WINDOW_MOUSEBUTTONDOWN:
                mnWidthOnSplitterButtonDown = mpParentWindow->GetSizePixel().Width();
                break;

            case VCLEVENT_WINDOW_MOUSEBUTTONUP:
            {
                ProcessNewWidth(mpParentWindow->GetSizePixel().Width());
                mnWidthOnSplitterButtonDown = 0;
                break;
            }

            case SFX_HINT_DYING:
                dispose();
                break;
         }
    }

    return sal_True;
}




void SidebarController::ShowPopupMenu (
    const Rectangle& rButtonBox,
    const ::std::vector<TabBar::DeckMenuData>& rMenuData) const
{
    ::boost::shared_ptr<PopupMenu> pMenu = CreatePopupMenu(rMenuData);
    pMenu->SetSelectHdl(LINK(this, SidebarController, OnMenuItemSelected));

    // pass toolbox button rect so the menu can stay open on button up
    Rectangle aBox (rButtonBox);
    aBox.Move(mpTabBar->GetPosPixel().X(), 0);
    pMenu->Execute(mpParentWindow, aBox, POPUPMENU_EXECUTE_DOWN);
}




void SidebarController::ShowDetailMenu (const ::rtl::OUString& rsMenuCommand) const
{
    try
    {
        const util::URL aURL (Tools::GetURL(rsMenuCommand));
        Reference<frame::XDispatch> xDispatch (Tools::GetDispatch(mxFrame, aURL));
        if (xDispatch.is())
            xDispatch->dispatch(aURL, Sequence<beans::PropertyValue>());
    }
    catch(Exception& rException)
    {
        OSL_TRACE("caught exception: %s",
            OUStringToOString(rException.Message, RTL_TEXTENCODING_ASCII_US).getStr());
    }
}




::boost::shared_ptr<PopupMenu> SidebarController::CreatePopupMenu (
    const ::std::vector<TabBar::DeckMenuData>& rMenuData) const
{
    // Create the top level popup menu.
    ::boost::shared_ptr<PopupMenu> pMenu (new PopupMenu());
    FloatingWindow* pMenuWindow = dynamic_cast<FloatingWindow*>(pMenu->GetWindow());
    if (pMenuWindow != NULL)
    {
        pMenuWindow->SetPopupModeFlags(pMenuWindow->GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE);
    }

    // Create sub menu for customization (hiding of deck tabs.)
    PopupMenu* pCustomizationMenu = new PopupMenu();

    SidebarResource aLocalResource;

    // Add one entry for every tool panel element to individually make
    // them visible or hide them.
    sal_Int32 nIndex (0);
    for(::std::vector<TabBar::DeckMenuData>::const_iterator
            iItem(rMenuData.begin()),
            iEnd(rMenuData.end());
        iItem!=iEnd;
        ++iItem,++nIndex)
    {
        const sal_Int32 nMenuIndex (nIndex+MID_FIRST_PANEL);
        pMenu->InsertItem(nMenuIndex, iItem->msDisplayName, MIB_RADIOCHECK);
        pMenu->CheckItem(nMenuIndex, iItem->mbIsCurrentDeck ? sal_True : sal_False);
        pMenu->EnableItem(nMenuIndex, (iItem->mbIsEnabled&&iItem->mbIsActive) ? sal_True : sal_False);

        const sal_Int32 nSubMenuIndex (nIndex+MID_FIRST_HIDE);
        if (iItem->mbIsCurrentDeck)
        {
            // Don't allow the currently visible deck to be disabled.
            pCustomizationMenu->InsertItem(nSubMenuIndex, iItem->msDisplayName, MIB_RADIOCHECK);
            pCustomizationMenu->CheckItem(nSubMenuIndex, sal_True);
        }
        else
        {
            pCustomizationMenu->InsertItem(nSubMenuIndex, iItem->msDisplayName, MIB_CHECKABLE);
            pCustomizationMenu->CheckItem(nSubMenuIndex, iItem->mbIsActive ? sal_True : sal_False);
        }
    }

    pMenu->InsertSeparator();

    // Add entry for docking or un-docking the tool panel.
    if (mpParentWindow->IsFloatingMode())
        pMenu->InsertItem(MID_LOCK_TASK_PANEL, String(SfxResId(STR_SFX_DOCK)));
    else
        pMenu->InsertItem(MID_UNLOCK_TASK_PANEL, String(SfxResId(STR_SFX_UNDOCK)));

    pCustomizationMenu->InsertSeparator();
    pCustomizationMenu->InsertItem(MID_RESTORE_DEFAULT, String(SfxResId(STRING_RESTORE)));

    pMenu->InsertItem(MID_CUSTOMIZATION, String(SfxResId(STRING_CUSTOMIZATION)));
    pMenu->SetPopupMenu(MID_CUSTOMIZATION, pCustomizationMenu);

    pMenu->RemoveDisabledEntries(sal_False, sal_False);

    return pMenu;
}




IMPL_LINK(SidebarController, OnMenuItemSelected, Menu*, pMenu)
{
    if (pMenu == NULL)
    {
        OSL_ENSURE(pMenu!=NULL, "sfx2::sidebar::SidebarController::OnMenuItemSelected: illegal menu!");
        return 0;
    }

    pMenu->Deactivate();
    const sal_Int32 nIndex (pMenu->GetCurItemId());
    switch (nIndex)
    {
        case MID_UNLOCK_TASK_PANEL:
            mpParentWindow->SetFloatingMode(sal_True);
            break;

        case MID_LOCK_TASK_PANEL:
            mpParentWindow->SetFloatingMode(sal_False);
            break;

        case MID_RESTORE_DEFAULT:
            mpTabBar->RestoreHideFlags();
            break;

        default:
        {
            try
            {
                if (nIndex >= MID_FIRST_PANEL && nIndex<MID_FIRST_HIDE)
                    SwitchToDeck(mpTabBar->GetDeckIdForIndex(nIndex - MID_FIRST_PANEL));
                else if (nIndex >=MID_FIRST_HIDE)
                    if (pMenu->GetItemBits(nIndex) == MIB_CHECKABLE)
                        mpTabBar->ToggleHideFlag(nIndex-MID_FIRST_HIDE);
            }
            catch (RuntimeException&)
            {
            }
        }
        break;
    }

    return 1;
}




void SidebarController::RequestCloseDeck (void)
{
    mbIsDeckRequestedOpen = false;
    UpdateDeckOpenState();
}




void SidebarController::RequestOpenDeck (void)
{
    mbIsDeckRequestedOpen = true;
    UpdateDeckOpenState();
}




void SidebarController::UpdateDeckOpenState (void)
{
    if ( ! mbIsDeckRequestedOpen)
        // No state requested.
        return;

    // Update (change) the open state when it either has not yet been initialized
    // or when its value differs from the requested state.
    if ( ! mbIsDeckOpen
        || mbIsDeckOpen.get() != mbIsDeckRequestedOpen.get())
    {
        if (mbIsDeckRequestedOpen.get())
        {
            if (mnSavedSidebarWidth <= TabBar::GetDefaultWidth())
                SetChildWindowWidth(SidebarChildWindow::GetDefaultWidth(mpParentWindow));
            else
                SetChildWindowWidth(mnSavedSidebarWidth);
        }
        else
        {
            if ( ! mpParentWindow->IsFloatingMode())
                mnSavedSidebarWidth = SetChildWindowWidth(TabBar::GetDefaultWidth());
            if (mnWidthOnSplitterButtonDown > TabBar::GetDefaultWidth())
                mnSavedSidebarWidth = mnWidthOnSplitterButtonDown;
            mpParentWindow->SetStyle(mpParentWindow->GetStyle() & ~WB_SIZEABLE);
        }

        mbIsDeckOpen = mbIsDeckRequestedOpen.get();
        if (mbIsDeckOpen.get() && mpCurrentDeck)
            mpCurrentDeck->Show(mbIsDeckOpen.get());
        NotifyResize();
    }
}




FocusManager& SidebarController::GetFocusManager (void)
{
    return maFocusManager;
}




bool SidebarController::CanModifyChildWindowWidth (void)
{
    SfxSplitWindow* pSplitWindow = GetSplitWindow();
    if (pSplitWindow == NULL)
        return false;

    sal_uInt16 nRow (0xffff);
    sal_uInt16 nColumn (0xffff);
    if (pSplitWindow->GetWindowPos(mpParentWindow, nColumn, nRow))
    {
        sal_uInt16 nRowCount (pSplitWindow->GetWindowCount(nColumn));
        return nRowCount==1;
    }
    else
        return false;
}




sal_Int32 SidebarController::SetChildWindowWidth (const sal_Int32 nNewWidth)
{
    SfxSplitWindow* pSplitWindow = GetSplitWindow();
    if (pSplitWindow == NULL)
        return 0;

    sal_uInt16 nRow (0xffff);
    sal_uInt16 nColumn (0xffff);
    pSplitWindow->GetWindowPos(mpParentWindow, nColumn, nRow);
    const long nColumnWidth (pSplitWindow->GetLineSize(nColumn));

    Window* pWindow = mpParentWindow;
    const Point aWindowPosition (pWindow->GetPosPixel());
    const Size aWindowSize (pWindow->GetSizePixel());

    pSplitWindow->MoveWindow(
        mpParentWindow,
        Size(nNewWidth, aWindowSize.Height()),
        nColumn,
        nRow);
    static_cast<SplitWindow*>(pSplitWindow)->Split();

    return static_cast<sal_Int32>(nColumnWidth);
}




void SidebarController::RestrictWidth (void)
{
    SfxSplitWindow* pSplitWindow = GetSplitWindow();
    if (pSplitWindow != NULL)
    {
        const sal_uInt16 nId (pSplitWindow->GetItemId(mpParentWindow));
        const sal_uInt16 nSetId (pSplitWindow->GetSet(nId));
        pSplitWindow->SetItemSizeRange(
            nSetId,
            Range(TabBar::GetDefaultWidth(), gnMaximumSidebarWidth));
    }
}




SfxSplitWindow* SidebarController::GetSplitWindow (void)
{
    if (mpParentWindow != NULL)
    {
        SfxSplitWindow* pSplitWindow = dynamic_cast<SfxSplitWindow*>(mpParentWindow->GetParent());
        if (pSplitWindow != mpSplitWindow)
        {
            if (mpSplitWindow != NULL)
                mpSplitWindow->RemoveEventListener(LINK(this, SidebarController, WindowEventHandler));

            mpSplitWindow = pSplitWindow;

            if (mpSplitWindow != NULL)
                mpSplitWindow->AddEventListener(LINK(this, SidebarController, WindowEventHandler));
        }
        return mpSplitWindow;
    }
    else
        return NULL;
}




void SidebarController::UpdateCloseIndicator (const bool bCloseAfterDrag)
{
    if (mpParentWindow == NULL)
        return;

    if (bCloseAfterDrag)
    {
        // Make sure that the indicator exists.
        if ( ! mpCloseIndicator)
        {
            mpCloseIndicator.reset(new FixedImage(mpParentWindow));
            FixedImage* pFixedImage = static_cast<FixedImage*>(mpCloseIndicator.get());
            const Image aImage (Theme::GetImage(Theme::Image_CloseIndicator));
            pFixedImage->SetImage(aImage);
            pFixedImage->SetSizePixel(aImage.GetSizePixel());
            pFixedImage->SetBackground(Theme::GetWallpaper(Theme::Paint_DeckBackground));
        }

        // Place and show the indicator.
        const Size aWindowSize (mpParentWindow->GetSizePixel());
        const Size aImageSize (mpCloseIndicator->GetSizePixel());
        mpCloseIndicator->SetPosPixel(
            Point(
                aWindowSize.Width() - TabBar::GetDefaultWidth() - aImageSize.Width(),
                (aWindowSize.Height() - aImageSize.Height())/2));
        mpCloseIndicator->Show();
    }
    else
    {
        // Hide but don't delete the indicator.
        if (mpCloseIndicator)
            mpCloseIndicator->Hide();
    }
}




void SidebarController::UpdateTitleBarIcons (void)
{
    if ( ! mpCurrentDeck)
        return;

    const bool bIsHighContrastModeActive (Theme::IsHighContrastMode());
    const ResourceManager& rResourceManager (ResourceManager::Instance());

    // Update the deck icon.
    const DeckDescriptor* pDeckDescriptor = rResourceManager.GetDeckDescriptor(mpCurrentDeck->GetId());
    if (pDeckDescriptor != NULL && mpCurrentDeck->GetTitleBar())
    {
        const OUString sIconURL(
            bIsHighContrastModeActive
                ? pDeckDescriptor->msHighContrastTitleBarIconURL
                : pDeckDescriptor->msTitleBarIconURL);
        mpCurrentDeck->GetTitleBar()->SetIcon(Tools::GetImage(sIconURL, mxFrame));
    }

    // Update the panel icons.
    const SharedPanelContainer& rPanels (mpCurrentDeck->GetPanels());
    for (SharedPanelContainer::const_iterator
             iPanel(rPanels.begin()), iEnd(rPanels.end());
             iPanel!=iEnd;
             ++iPanel)
    {
        if ( ! *iPanel)
            continue;
        if ((*iPanel)->GetTitleBar() == NULL)
            continue;
        const PanelDescriptor* pPanelDescriptor = rResourceManager.GetPanelDescriptor((*iPanel)->GetId());
        if (pPanelDescriptor == NULL)
            continue;
        const OUString sIconURL (
            bIsHighContrastModeActive
               ? pPanelDescriptor->msHighContrastTitleBarIconURL
               : pPanelDescriptor->msTitleBarIconURL);
        (*iPanel)->GetTitleBar()->SetIcon(Tools::GetImage(sIconURL, mxFrame));
    }
}




void SidebarController::ShowPanel (const Panel& rPanel)
{
    if (mpCurrentDeck)
        mpCurrentDeck->ShowPanel(rPanel);
}




Context SidebarController::GetCurrentContext (void) const
{
    return maCurrentContext;
}


} } // end of namespace sfx2::sidebar
