forked from amazingfate/loongoffice
Put the VCL Window class in the vcl namespace. Avoids clash with the X11 Window typedef. Change-Id: Ib1beb7ab4ad75562a42aeb252732a073d25eff1a
554 lines
18 KiB
C++
554 lines
18 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 "BasicViewFactory.hxx"
|
|
|
|
#include "framework/ViewShellWrapper.hxx"
|
|
#include "framework/FrameworkHelper.hxx"
|
|
#include <com/sun/star/drawing/framework/XControllerManager.hpp>
|
|
#include <com/sun/star/lang/IllegalArgumentException.hpp>
|
|
#include "framework/Pane.hxx"
|
|
#include "DrawController.hxx"
|
|
#include "DrawSubController.hxx"
|
|
#include "ViewShellBase.hxx"
|
|
#include "ViewShellManager.hxx"
|
|
#include "DrawDocShell.hxx"
|
|
#include "DrawViewShell.hxx"
|
|
#include "GraphicViewShell.hxx"
|
|
#include "OutlineViewShell.hxx"
|
|
#include "PresentationViewShell.hxx"
|
|
#include "SlideSorterViewShell.hxx"
|
|
#include "FrameView.hxx"
|
|
#include "facreg.hxx"
|
|
|
|
#include <sfx2/viewfrm.hxx>
|
|
#include <vcl/wrkwin.hxx>
|
|
#include <toolkit/helper/vclunohelper.hxx>
|
|
|
|
#include <boost/bind.hpp>
|
|
|
|
using namespace ::com::sun::star;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::lang;
|
|
using namespace ::com::sun::star::drawing::framework;
|
|
|
|
using ::sd::framework::FrameworkHelper;
|
|
|
|
namespace sd { namespace framework {
|
|
|
|
Reference<XInterface> SAL_CALL BasicViewFactory_createInstance (
|
|
const Reference<XComponentContext>& rxContext) throw (css::uno::Exception)
|
|
{
|
|
return Reference<XInterface>(static_cast<XWeak*>(new BasicViewFactory(rxContext)));
|
|
}
|
|
|
|
OUString BasicViewFactory_getImplementationName (void) throw(RuntimeException)
|
|
{
|
|
return OUString("com.sun.star.comp.Draw.framework.BasicViewFactory");
|
|
}
|
|
|
|
Sequence<OUString> SAL_CALL BasicViewFactory_getSupportedServiceNames (void)
|
|
throw (RuntimeException)
|
|
{
|
|
static const OUString sServiceName("com.sun.star.drawing.framework.BasicViewFactory");
|
|
return Sequence<OUString>(&sServiceName, 1);
|
|
}
|
|
|
|
//===== ViewDescriptor ========================================================
|
|
|
|
class BasicViewFactory::ViewDescriptor
|
|
{
|
|
public:
|
|
Reference<XResource> mxView;
|
|
::boost::shared_ptr<sd::ViewShell> mpViewShell;
|
|
ViewShellWrapper* mpWrapper;
|
|
Reference<XResourceId> mxViewId;
|
|
static bool CompareView (const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor,
|
|
const Reference<XResource>& rxView)
|
|
{ return rpDescriptor->mxView.get() == rxView.get(); }
|
|
};
|
|
|
|
//===== BasicViewFactory::ViewShellContainer ==================================
|
|
|
|
class BasicViewFactory::ViewShellContainer
|
|
: public ::std::vector<boost::shared_ptr<ViewDescriptor> >
|
|
{
|
|
public:
|
|
ViewShellContainer (void) {};
|
|
};
|
|
|
|
class BasicViewFactory::ViewCache
|
|
: public ::std::vector<boost::shared_ptr<ViewDescriptor> >
|
|
{
|
|
public:
|
|
ViewCache (void) {};
|
|
};
|
|
|
|
//===== ViewFactory ===========================================================
|
|
|
|
BasicViewFactory::BasicViewFactory (
|
|
const Reference<XComponentContext>& rxContext)
|
|
: BasicViewFactoryInterfaceBase(MutexOwner::maMutex),
|
|
mxConfigurationController(),
|
|
mpViewShellContainer(new ViewShellContainer()),
|
|
mpBase(NULL),
|
|
mpFrameView(NULL),
|
|
mpWindow(new WorkWindow(NULL,WB_STDWORK)),
|
|
mpViewCache(new ViewCache()),
|
|
mxLocalPane(new Pane(Reference<XResourceId>(), mpWindow.get()))
|
|
{
|
|
(void)rxContext;
|
|
}
|
|
|
|
BasicViewFactory::~BasicViewFactory (void)
|
|
{
|
|
}
|
|
|
|
void SAL_CALL BasicViewFactory::disposing (void)
|
|
{
|
|
// Disconnect from the frame view.
|
|
if (mpFrameView != NULL)
|
|
{
|
|
mpFrameView->Disconnect();
|
|
mpFrameView = NULL;
|
|
}
|
|
|
|
// Relase the view cache.
|
|
ViewShellContainer::const_iterator iView;
|
|
for (iView=mpViewCache->begin(); iView!=mpViewCache->end(); ++iView)
|
|
{
|
|
ReleaseView(*iView, true);
|
|
}
|
|
|
|
// Release the view shell container. At this point no one other than us
|
|
// should hold references to the view shells (at the moment this is a
|
|
// trivial requirement, because no one other then us holds a shared
|
|
// pointer).
|
|
// ViewShellContainer::const_iterator iView;
|
|
for (iView=mpViewShellContainer->begin(); iView!=mpViewShellContainer->end(); ++iView)
|
|
{
|
|
OSL_ASSERT((*iView)->mpViewShell.unique());
|
|
}
|
|
mpViewShellContainer.reset();
|
|
}
|
|
|
|
Reference<XResource> SAL_CALL BasicViewFactory::createResource (
|
|
const Reference<XResourceId>& rxViewId)
|
|
throw(RuntimeException, IllegalArgumentException, WrappedTargetException, std::exception)
|
|
{
|
|
Reference<XResource> xView;
|
|
const bool bIsCenterPane (
|
|
rxViewId->isBoundToURL(FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT));
|
|
|
|
// Get the pane for the anchor URL.
|
|
Reference<XPane> xPane;
|
|
if (mxConfigurationController.is())
|
|
xPane = Reference<XPane>(mxConfigurationController->getResource(rxViewId->getAnchor()),
|
|
UNO_QUERY);
|
|
|
|
// For main views use the frame view of the last main view.
|
|
::sd::FrameView* pFrameView = NULL;
|
|
if (xPane.is() && bIsCenterPane)
|
|
{
|
|
pFrameView = mpFrameView;
|
|
}
|
|
|
|
// Get Window pointer for XWindow of the pane.
|
|
vcl::Window* pWindow = NULL;
|
|
if (xPane.is())
|
|
pWindow = VCLUnoHelper::GetWindow(xPane->getWindow());
|
|
|
|
// Get the view frame.
|
|
SfxViewFrame* pFrame = NULL;
|
|
if (mpBase != NULL)
|
|
pFrame = mpBase->GetViewFrame();
|
|
|
|
if (pFrame != NULL && mpBase!=NULL && pWindow!=NULL)
|
|
{
|
|
// Try to get the view from the cache.
|
|
::boost::shared_ptr<ViewDescriptor> pDescriptor (GetViewFromCache(rxViewId, xPane));
|
|
|
|
// When the requested view is not in the cache then create a new view.
|
|
if (pDescriptor.get() == NULL)
|
|
{
|
|
pDescriptor = CreateView(rxViewId, *pFrame, *pWindow, xPane, pFrameView, bIsCenterPane);
|
|
}
|
|
|
|
if (pDescriptor.get() != NULL)
|
|
xView = pDescriptor->mxView;
|
|
|
|
mpViewShellContainer->push_back(pDescriptor);
|
|
|
|
if (bIsCenterPane)
|
|
ActivateCenterView(pDescriptor);
|
|
else
|
|
pWindow->Resize();
|
|
}
|
|
|
|
return xView;
|
|
}
|
|
|
|
void SAL_CALL BasicViewFactory::releaseResource (const Reference<XResource>& rxView)
|
|
throw(RuntimeException, std::exception)
|
|
{
|
|
if ( ! rxView.is())
|
|
throw lang::IllegalArgumentException();
|
|
|
|
if (rxView.is() && mpBase!=NULL)
|
|
{
|
|
ViewShellContainer::iterator iViewShell (
|
|
::std::find_if(
|
|
mpViewShellContainer->begin(),
|
|
mpViewShellContainer->end(),
|
|
::boost::bind(&ViewDescriptor::CompareView, _1, rxView)));
|
|
if (iViewShell != mpViewShellContainer->end())
|
|
{
|
|
::boost::shared_ptr<ViewShell> pViewShell ((*iViewShell)->mpViewShell);
|
|
|
|
if ((*iViewShell)->mxViewId->isBoundToURL(
|
|
FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT))
|
|
{
|
|
// Obtain a pointer to and connect to the frame view of the
|
|
// view. The next view, that is created, will be
|
|
// initialized with this frame view.
|
|
if (mpFrameView == NULL)
|
|
{
|
|
mpFrameView = pViewShell->GetFrameView();
|
|
if (mpFrameView)
|
|
mpFrameView->Connect();
|
|
}
|
|
|
|
// With the view in the center pane the sub controller is
|
|
// released, too.
|
|
mpBase->GetDrawController().SetSubController(
|
|
Reference<drawing::XDrawSubController>());
|
|
|
|
SfxViewShell* pSfxViewShell = pViewShell->GetViewShell();
|
|
if (pSfxViewShell != NULL)
|
|
pSfxViewShell->DisconnectAllClients();
|
|
}
|
|
|
|
ReleaseView(*iViewShell);
|
|
|
|
mpViewShellContainer->erase(iViewShell);
|
|
}
|
|
else
|
|
{
|
|
throw lang::IllegalArgumentException();
|
|
}
|
|
}
|
|
}
|
|
|
|
void SAL_CALL BasicViewFactory::initialize (const Sequence<Any>& aArguments)
|
|
throw (Exception, RuntimeException, std::exception)
|
|
{
|
|
if (aArguments.getLength() > 0)
|
|
{
|
|
Reference<XConfigurationController> xCC;
|
|
try
|
|
{
|
|
// Get the XController from the first argument.
|
|
Reference<frame::XController> xController (aArguments[0], UNO_QUERY_THROW);
|
|
|
|
// Tunnel through the controller to obtain a ViewShellBase.
|
|
Reference<lang::XUnoTunnel> xTunnel (xController, UNO_QUERY_THROW);
|
|
::sd::DrawController* pController = reinterpret_cast<sd::DrawController*>(
|
|
xTunnel->getSomething(sd::DrawController::getUnoTunnelId()));
|
|
if (pController != NULL)
|
|
mpBase = pController->GetViewShellBase();
|
|
|
|
// Register the factory for its supported views.
|
|
Reference<XControllerManager> xCM (xController,UNO_QUERY_THROW);
|
|
mxConfigurationController = xCM->getConfigurationController();
|
|
if ( ! mxConfigurationController.is())
|
|
throw RuntimeException();
|
|
mxConfigurationController->addResourceFactory(FrameworkHelper::msImpressViewURL, this);
|
|
mxConfigurationController->addResourceFactory(FrameworkHelper::msDrawViewURL, this);
|
|
mxConfigurationController->addResourceFactory(FrameworkHelper::msOutlineViewURL, this);
|
|
mxConfigurationController->addResourceFactory(FrameworkHelper::msNotesViewURL, this);
|
|
mxConfigurationController->addResourceFactory(FrameworkHelper::msHandoutViewURL, this);
|
|
mxConfigurationController->addResourceFactory(FrameworkHelper::msPresentationViewURL, this);
|
|
mxConfigurationController->addResourceFactory(FrameworkHelper::msSlideSorterURL, this);
|
|
}
|
|
catch (RuntimeException&)
|
|
{
|
|
mpBase = NULL;
|
|
if (mxConfigurationController.is())
|
|
mxConfigurationController->removeResourceFactoryForReference(this);
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
|
|
::boost::shared_ptr<BasicViewFactory::ViewDescriptor> BasicViewFactory::CreateView (
|
|
const Reference<XResourceId>& rxViewId,
|
|
SfxViewFrame& rFrame,
|
|
vcl::Window& rWindow,
|
|
const Reference<XPane>& rxPane,
|
|
FrameView* pFrameView,
|
|
const bool bIsCenterPane)
|
|
{
|
|
::boost::shared_ptr<ViewDescriptor> pDescriptor (new ViewDescriptor());
|
|
|
|
pDescriptor->mpViewShell = CreateViewShell(
|
|
rxViewId,
|
|
rFrame,
|
|
rWindow,
|
|
pFrameView,
|
|
bIsCenterPane);
|
|
pDescriptor->mxViewId = rxViewId;
|
|
|
|
if (pDescriptor->mpViewShell.get() != NULL)
|
|
{
|
|
pDescriptor->mpViewShell->Init(bIsCenterPane);
|
|
mpBase->GetViewShellManager()->ActivateViewShell(pDescriptor->mpViewShell.get());
|
|
|
|
Reference<awt::XWindow> xWindow(rxPane->getWindow());
|
|
pDescriptor->mpWrapper = new ViewShellWrapper(
|
|
pDescriptor->mpViewShell,
|
|
rxViewId,
|
|
xWindow);
|
|
|
|
// register ViewShellWrapper on pane window
|
|
if (xWindow.is())
|
|
{
|
|
xWindow->addWindowListener(pDescriptor->mpWrapper);
|
|
if (pDescriptor->mpViewShell != 0)
|
|
{
|
|
pDescriptor->mpViewShell->Resize();
|
|
}
|
|
}
|
|
|
|
pDescriptor->mxView.set( pDescriptor->mpWrapper->queryInterface( cppu::UnoType<XResource>::get() ), UNO_QUERY_THROW );
|
|
}
|
|
|
|
return pDescriptor;
|
|
}
|
|
|
|
::boost::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell (
|
|
const Reference<XResourceId>& rxViewId,
|
|
SfxViewFrame& rFrame,
|
|
vcl::Window& rWindow,
|
|
FrameView* pFrameView,
|
|
const bool bIsCenterPane)
|
|
{
|
|
::boost::shared_ptr<ViewShell> pViewShell;
|
|
const OUString& rsViewURL (rxViewId->getResourceURL());
|
|
if (rsViewURL.equals(FrameworkHelper::msImpressViewURL))
|
|
{
|
|
pViewShell.reset(
|
|
new DrawViewShell(
|
|
&rFrame,
|
|
*mpBase,
|
|
&rWindow,
|
|
PK_STANDARD,
|
|
pFrameView));
|
|
}
|
|
else if (rsViewURL.equals(FrameworkHelper::msDrawViewURL))
|
|
{
|
|
pViewShell.reset(
|
|
new GraphicViewShell (
|
|
&rFrame,
|
|
*mpBase,
|
|
&rWindow,
|
|
pFrameView));
|
|
}
|
|
else if (rsViewURL.equals(FrameworkHelper::msOutlineViewURL))
|
|
{
|
|
pViewShell.reset(
|
|
new OutlineViewShell (
|
|
&rFrame,
|
|
*mpBase,
|
|
&rWindow,
|
|
pFrameView));
|
|
}
|
|
else if (rsViewURL.equals(FrameworkHelper::msNotesViewURL))
|
|
{
|
|
pViewShell.reset(
|
|
new DrawViewShell(
|
|
&rFrame,
|
|
*mpBase,
|
|
&rWindow,
|
|
PK_NOTES,
|
|
pFrameView));
|
|
}
|
|
else if (rsViewURL.equals(FrameworkHelper::msHandoutViewURL))
|
|
{
|
|
pViewShell.reset(
|
|
new DrawViewShell(
|
|
&rFrame,
|
|
*mpBase,
|
|
&rWindow,
|
|
PK_HANDOUT,
|
|
pFrameView));
|
|
}
|
|
else if (rsViewURL.equals(FrameworkHelper::msPresentationViewURL))
|
|
{
|
|
pViewShell.reset(
|
|
new PresentationViewShell(
|
|
&rFrame,
|
|
*mpBase,
|
|
&rWindow,
|
|
pFrameView));
|
|
}
|
|
else if (rsViewURL.equals(FrameworkHelper::msSlideSorterURL))
|
|
{
|
|
pViewShell = ::sd::slidesorter::SlideSorterViewShell::Create (
|
|
&rFrame,
|
|
*mpBase,
|
|
&rWindow,
|
|
pFrameView,
|
|
bIsCenterPane);
|
|
}
|
|
|
|
return pViewShell;
|
|
}
|
|
|
|
void BasicViewFactory::ReleaseView (
|
|
const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor,
|
|
bool bDoNotCache)
|
|
{
|
|
bool bIsCacheable (!bDoNotCache && IsCacheable(rpDescriptor));
|
|
|
|
if (bIsCacheable)
|
|
{
|
|
Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY);
|
|
if (xResource.is())
|
|
{
|
|
Reference<XResource> xNewAnchor (mxLocalPane, UNO_QUERY);
|
|
if (xNewAnchor.is())
|
|
if (xResource->relocateToAnchor(xNewAnchor))
|
|
mpViewCache->push_back(rpDescriptor);
|
|
else
|
|
bIsCacheable = false;
|
|
else
|
|
bIsCacheable = false;
|
|
}
|
|
else
|
|
{
|
|
bIsCacheable = false;
|
|
}
|
|
}
|
|
|
|
if ( ! bIsCacheable)
|
|
{
|
|
// Shut down the current view shell.
|
|
rpDescriptor->mpViewShell->Shutdown ();
|
|
mpBase->GetDocShell()->Disconnect(rpDescriptor->mpViewShell.get());
|
|
mpBase->GetViewShellManager()->DeactivateViewShell(rpDescriptor->mpViewShell.get());
|
|
|
|
Reference<XComponent> xComponent (rpDescriptor->mxView, UNO_QUERY);
|
|
if (xComponent.is())
|
|
xComponent->dispose();
|
|
}
|
|
}
|
|
|
|
bool BasicViewFactory::IsCacheable (const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor)
|
|
{
|
|
bool bIsCacheable (false);
|
|
|
|
Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY);
|
|
if (xResource.is())
|
|
{
|
|
static ::std::vector<Reference<XResourceId> > maCacheableResources;
|
|
if (maCacheableResources.empty() )
|
|
{
|
|
::boost::shared_ptr<FrameworkHelper> pHelper (FrameworkHelper::Instance(*mpBase));
|
|
|
|
// The slide sorter and the task panel are cacheable and relocatable.
|
|
maCacheableResources.push_back(FrameworkHelper::CreateResourceId(
|
|
FrameworkHelper::msSlideSorterURL, FrameworkHelper::msLeftDrawPaneURL));
|
|
maCacheableResources.push_back(FrameworkHelper::CreateResourceId(
|
|
FrameworkHelper::msSlideSorterURL, FrameworkHelper::msLeftImpressPaneURL));
|
|
}
|
|
|
|
::std::vector<Reference<XResourceId> >::const_iterator iId;
|
|
for (iId=maCacheableResources.begin(); iId!=maCacheableResources.end(); ++iId)
|
|
{
|
|
if ((*iId)->compareTo(rpDescriptor->mxViewId) == 0)
|
|
{
|
|
bIsCacheable = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bIsCacheable;
|
|
}
|
|
|
|
::boost::shared_ptr<BasicViewFactory::ViewDescriptor> BasicViewFactory::GetViewFromCache (
|
|
const Reference<XResourceId>& rxViewId,
|
|
const Reference<XPane>& rxPane)
|
|
{
|
|
::boost::shared_ptr<ViewDescriptor> pDescriptor;
|
|
|
|
// Search for the requested view in the cache.
|
|
ViewCache::iterator iEntry;
|
|
for (iEntry=mpViewCache->begin(); iEntry!=mpViewCache->end(); ++iEntry)
|
|
{
|
|
if ((*iEntry)->mxViewId->compareTo(rxViewId) == 0)
|
|
{
|
|
pDescriptor = *iEntry;
|
|
mpViewCache->erase(iEntry);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// When the view has been found then relocate it to the given pane and
|
|
// remove it from the cache.
|
|
if (pDescriptor.get() != NULL)
|
|
{
|
|
bool bRelocationSuccessfull (false);
|
|
Reference<XRelocatableResource> xResource (pDescriptor->mxView, UNO_QUERY);
|
|
if (xResource.is() && rxPane.is())
|
|
{
|
|
if (xResource->relocateToAnchor(rxPane))
|
|
bRelocationSuccessfull = true;
|
|
}
|
|
|
|
if ( ! bRelocationSuccessfull)
|
|
{
|
|
ReleaseView(pDescriptor, true);
|
|
pDescriptor.reset();
|
|
}
|
|
}
|
|
|
|
return pDescriptor;
|
|
}
|
|
|
|
void BasicViewFactory::ActivateCenterView (
|
|
const ::boost::shared_ptr<ViewDescriptor>& rpDescriptor)
|
|
{
|
|
mpBase->GetDocShell()->Connect(rpDescriptor->mpViewShell.get());
|
|
|
|
// During the creation of the new sub-shell, resize requests were not
|
|
// forwarded to it because it was not yet registered. Therefore, we
|
|
// have to request a resize now.
|
|
rpDescriptor->mpViewShell->UIFeatureChanged();
|
|
if (mpBase->GetDocShell()->IsInPlaceActive())
|
|
mpBase->GetViewFrame()->Resize(true);
|
|
|
|
mpBase->GetDrawController().SetSubController(
|
|
rpDescriptor->mpViewShell->CreateSubController());
|
|
}
|
|
|
|
} } // end of namespace sd::framework
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|