blob: 9144d814fe4bfdc012a6b3466057ee405a6c4c58 [file] [log] [blame]
/**************************************************************
*
* 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_sd.hxx"
#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 <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 ::rtl::OUString;
using ::sd::framework::FrameworkHelper;
namespace sd { namespace framework {
Reference<XInterface> SAL_CALL BasicViewFactory_createInstance (
const Reference<XComponentContext>& rxContext)
{
return Reference<XInterface>(static_cast<XWeak*>(new BasicViewFactory(rxContext)));
}
::rtl::OUString BasicViewFactory_getImplementationName (void) throw(RuntimeException)
{
return ::rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.framework.BasicViewFactory"));
}
Sequence<rtl::OUString> SAL_CALL BasicViewFactory_getSupportedServiceNames (void)
throw (RuntimeException)
{
static const ::rtl::OUString sServiceName(
::rtl::OUString::createFromAscii("com.sun.star.drawing.framework.BasicViewFactory"));
return Sequence<rtl::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)
{
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.
::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)
{
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)
{
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,
::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());
pDescriptor->mpWrapper = new ViewShellWrapper(
pDescriptor->mpViewShell,
rxViewId,
rxPane->getWindow());
pDescriptor->mxView.set( pDescriptor->mpWrapper->queryInterface( XResource::static_type() ), UNO_QUERY_THROW );
}
return pDescriptor;
}
::boost::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell (
const Reference<XResourceId>& rxViewId,
SfxViewFrame& rFrame,
::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(pHelper->CreateResourceId(
FrameworkHelper::msSlideSorterURL, FrameworkHelper::msLeftDrawPaneURL));
maCacheableResources.push_back(pHelper->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);
Reference<XResource> xNewAnchor (rxPane, UNO_QUERY);
if (xResource.is() && xNewAnchor.is())
{
if (xResource->relocateToAnchor(xNewAnchor))
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(sal_True);
mpBase->GetDrawController().SetSubController(
rpDescriptor->mpViewShell->CreateSubController());
}
} } // end of namespace sd::framework