Files
loongoffice/sd/source/ui/framework/factories/BasicViewFactory.cxx
Noel Grandin 827c46e7d7 fdo#82577: Handle Window
Put the VCL Window class in the vcl namespace. Avoids clash with the X11
Window typedef.

Change-Id: Ib1beb7ab4ad75562a42aeb252732a073d25eff1a
2014-09-23 14:11:39 +03:00

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