diff options
author | Björn Milcke <bm@openoffice.org> | 2003-10-06 08:58:36 +0000 |
---|---|---|
committer | Björn Milcke <bm@openoffice.org> | 2003-10-06 08:58:36 +0000 |
commit | 668c6b0245b6076ac8fb3f5d734795117188675e (patch) | |
tree | 363512534f7fae13719bddccb3a365e48ef7a8d3 /chart2/source/controller/main/ChartController.cxx | |
parent | 2ccbe3d78ecfa9aa1527db50d304a277d3cdbe64 (diff) |
initial import
Diffstat (limited to 'chart2/source/controller/main/ChartController.cxx')
-rw-r--r-- | chart2/source/controller/main/ChartController.cxx | 1124 |
1 files changed, 1124 insertions, 0 deletions
diff --git a/chart2/source/controller/main/ChartController.cxx b/chart2/source/controller/main/ChartController.cxx new file mode 100644 index 000000000000..c6b5e19bac43 --- /dev/null +++ b/chart2/source/controller/main/ChartController.cxx @@ -0,0 +1,1124 @@ +/************************************************************************* + * + * $RCSfile: ChartController.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: bm $ $Date: 2003-10-06 09:58:28 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2003 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ +#include "ChartController.hxx" +#include "servicenames.hxx" + +#include "InlineContainer.hxx" +#include "Chart.hrc" +#include "ResId.hxx" +#include "SchSlotIds.hxx" + +#include "chartview/ChartView.hxx" +#include "ChartWindow.hxx" +#include "DrawModelWrapper.hxx" +#include "DrawViewWrapper.hxx" + +#include "macros.hxx" + +#include "chartview/NumberFormatterWrapper.hxx" + +#include "dlg_ChartType.hxx" +#include "ChartTypeItemConverter.hxx" + +//for SID_CHARMAP: +#ifndef _SVX_SVXIDS_HRC +#include <svx/svxids.hrc> +#endif + +#ifndef _DRAFTS_COM_SUN_STAR_CHART2_XCHARTDOCUMENT_HPP_ +#include <drafts/com/sun/star/chart2/XChartDocument.hpp> +#endif +#ifndef _DRAFTS_COM_SUN_STAR_CHART2_XSTACKABLESCALEGROUP_HPP_ +#include <drafts/com/sun/star/chart2/XStackableScaleGroup.hpp> +#endif + +//------- +// header for define RET_OK +#ifndef _SV_MSGBOX_HXX +#include <vcl/msgbox.hxx> +#endif +//------- + +//------- +#ifndef _TOOLKIT_AWT_VCLXWINDOW_HXX_ +#include <toolkit/awt/vclxwindow.hxx> +#endif +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/helper/vclunohelper.hxx> +#endif +#ifndef _VOS_MUTEX_HXX_ +#include <vos/mutex.hxx> +#endif +//------- +#ifndef _COMPHELPER_PROCESSFACTORY_HXX_ +#include <comphelper/processfactory.hxx> +#endif +#ifndef _COM_SUN_STAR_UTIL_XURLTRANSFORMER_HPP_ +#include <com/sun/star/util/XURLTransformer.hpp> +#endif + +//............................................................................. +namespace chart +{ +//............................................................................. + +using namespace ::com::sun::star; +using namespace ::drafts::com::sun::star::chart2; + +//----------------------------------------------------------------- +// ChartController Constructor and Destructor +//----------------------------------------------------------------- + +ChartController::ChartController(uno::Reference<uno::XComponentContext> const & xContext) + : m_aLifeTimeManager( NULL ) + , m_xFrame( NULL ) + , m_aModelMutex() + , m_aModel( NULL, m_aModelMutex ) + , m_bSuspended( sal_False ) + , m_bCanClose( sal_True ) + , m_pChartWindow( NULL ) + , m_xViewWindow( NULL ) + , m_pChartView( NULL ) + , m_pDrawModelWrapper( NULL ) + , m_pDrawViewWrapper(NULL) + , m_xCC(xContext) //@todo is it allowed to hold this context?? + , m_bViewDirty( false ) + , m_pNumberFormatterWrapper(NULL) +{ + + //@todo + m_pNumberFormatterWrapper = new NumberFormatterWrapper(); +} + +ChartController::~ChartController() +{ + impl_deleteView(); + //m_pChartWindow is deleted via UNO by Window hierarchy or Framework + if(m_pNumberFormatterWrapper) + delete m_pNumberFormatterWrapper; + + //@todo ? +} + +//----------------------------------------------------------------- + +ChartController::RefCountable::RefCountable() : m_nRefCount(0) +{ +} + +ChartController::RefCountable::~RefCountable() +{ +} +void ChartController::RefCountable::acquire() +{ + m_nRefCount++; +} +void ChartController::RefCountable::release() +{ + m_nRefCount--; + if(!m_nRefCount) + delete this; +} + +//----------------------------------------------------------------- + +ChartController::TheModel::TheModel( const uno::Reference< frame::XModel > & xModel ) + : m_xModel( xModel ) + , m_xCloseable( NULL ) + , m_bOwnership( sal_True ) + , m_bOwnershipIsWellKnown( sal_False ) +{ + m_xCloseable = + uno::Reference< util::XCloseable >( xModel, uno::UNO_QUERY ); +} + +ChartController::TheModel::~TheModel() +{ +} + +void ChartController::TheModel::SetOwnerShip( sal_Bool bGetsOwnership ) +{ + m_bOwnership = bGetsOwnership; + m_bOwnershipIsWellKnown = sal_True; +} + +void ChartController::TheModel::addListener( ChartController* pController ) +{ + if(m_xCloseable.is()) + { + //if you need to be able to veto against the destruction of the model + // you must add as a close listener + + //otherwise you 'can' add as closelistener or 'must' add as dispose event listener + + m_xCloseable->addCloseListener( + static_cast<util::XCloseListener*>(pController) ); + } + else if( m_xModel.is() ) + { + //we need to add as dispose event listener + m_xModel->addEventListener( + static_cast<lang::XEventListener*>(pController) ); + } + +} + +void ChartController::TheModel::removeListener( ChartController* pController ) +{ + if(m_xCloseable.is()) + m_xCloseable->removeCloseListener( + static_cast<util::XCloseListener*>(pController) ); + + else if( m_xModel.is() ) + m_xModel->removeEventListener( + static_cast<lang::XEventListener*>(pController) ); +} + +void ChartController::TheModel::tryTermination() +{ + if(!m_bOwnership) + return; + + try + { + if(m_xCloseable.is()) + { + try + { + //@todo ? are we allowed to use sal_True here if we have the explicit ownership? + //I think yes, because there might be other closelistners later in the list which might be interested still + //but make sure that we do not throw the CloseVetoException here ourselfs + //so stop listening before trying to terminate or check the source of queryclosing event + m_xCloseable->close(sal_True); + + m_bOwnership = false; + m_bOwnershipIsWellKnown = sal_True; + } + catch( util::CloseVetoException& ) + { + //since we have indicated to give up the ownership with paramter true in close call + //the one who has thrown the CloseVetoException is the new owner + + OSL_ENSURE( !m_bOwnership, + "INFO: a well known owner has catched a CloseVetoException after calling close(true)" ); + + m_bOwnership = false; + m_bOwnershipIsWellKnown = sal_True; + return; + } + + } + else if( m_xModel.is() ) + { + //@todo correct?? + m_xModel->dispose(); + return; + } + } + catch( uno::Exception& ex) + { + OSL_ENSURE( sal_False, ( rtl::OString("Termination of model failed: ") + + rtl::OUStringToOString( ex.Message, RTL_TEXTENCODING_ASCII_US ) ).getStr() ); + } +} + +//----------------------------------------------------------------- + +ChartController::TheModelRef::TheModelRef( TheModel* pTheModel, ::osl::Mutex& rMutex ) + : m_pTheModel(pTheModel), m_rModelMutex(rMutex) +{ + ::osl::Guard< ::osl::Mutex > aGuard( m_rModelMutex ); + if(m_pTheModel) + m_pTheModel->acquire(); +} +ChartController::TheModelRef::TheModelRef( const TheModelRef& rTheModel, ::osl::Mutex& rMutex ) + : m_rModelMutex(rMutex) +{ + ::osl::Guard< ::osl::Mutex > aGuard( m_rModelMutex ); + m_pTheModel=rTheModel.operator->(); + if(m_pTheModel) + m_pTheModel->acquire(); +} +ChartController::TheModelRef& ChartController::TheModelRef::operator=(TheModel* pTheModel) +{ + ::osl::Guard< ::osl::Mutex > aGuard( m_rModelMutex ); + if(m_pTheModel==pTheModel) + return *this; + if(m_pTheModel) + m_pTheModel->release(); + m_pTheModel=pTheModel; + if(m_pTheModel) + m_pTheModel->acquire(); + return *this; +} +ChartController::TheModelRef& ChartController::TheModelRef::operator=(const TheModelRef& rTheModel) +{ + ::osl::Guard< ::osl::Mutex > aGuard( m_rModelMutex ); + TheModel* pNew=rTheModel.operator->(); + if(m_pTheModel==pNew) + return *this; + if(m_pTheModel) + m_pTheModel->release(); + m_pTheModel=pNew; + if(m_pTheModel) + m_pTheModel->acquire(); + return *this; +} +ChartController::TheModelRef::~TheModelRef() +{ + ::osl::Guard< ::osl::Mutex > aGuard( m_rModelMutex ); + if(m_pTheModel) + m_pTheModel->release(); +} +sal_Bool ChartController::TheModelRef::is() const +{ + return (m_pTheModel != 0); +} + + +//----------------------------------------------------------------- +// private methods +//----------------------------------------------------------------- + + sal_Bool ChartController +::impl_isDisposedOrSuspended() +{ + if( m_aLifeTimeManager.impl_isDisposed() ) + return sal_True; + + if( m_bSuspended ) + { + OSL_ENSURE( sal_False, "This Controller is suspended" ); + return sal_True; + } + return sal_False; +} + +//----------------------------------------------------------------- +// lang::XServiceInfo +//----------------------------------------------------------------- + +APPHELPER_XSERVICEINFO_IMPL(ChartController,CHART_CONTROLLER_SERVICE_IMPLEMENTATION_NAME) + + uno::Sequence< rtl::OUString > ChartController +::getSupportedServiceNames_Static() +{ + uno::Sequence< rtl::OUString > aSNS( 2 ); + aSNS.getArray()[ 0 ] = CHART_CONTROLLER_SERVICE_NAME; + aSNS.getArray()[ 1 ] = ::rtl::OUString::createFromAscii("com.sun.star.frame.Controller"); + //// @todo : add additional services if you support any further + return aSNS; +} + +//----------------------------------------------------------------- +// XController +//----------------------------------------------------------------- + + void SAL_CALL ChartController +::attachFrame( const uno::Reference<frame::XFrame>& xFrame ) + throw(uno::RuntimeException) +{ + osl::Guard< osl::Mutex > aGuard( m_aControllerMutex ); + + if( impl_isDisposedOrSuspended() ) //@todo? allow attaching the frame while suspended? + return; //behave passive if already disposed or suspended + + if(m_xFrame.is()) //what happens, if we do have a Frame already?? + { + //@todo? throw exception? + OSL_ENSURE( sal_False, "there is already a frame attached to the controller" ); + return; + } + + //--attach frame + m_xFrame = xFrame; //the frameloader is responsible to call xFrame->setComponent + + //add as disposelistener to the frame (due to persistent reference) ??...: + + //the frame is considered to be owner of this controller and will live longer than we do + //the frame or the disposer of the frame has the duty to call suspend and dispose on this object + //so we do not need to add as lang::XEventListener for DisposingEvents right? + + //@todo nothing right??? + + + + //-------------------------------------------------- + //create view @todo is this the correct place here?? + + Window* pParent = NULL; + //get the window parent from the frame to use as parent for our new window + if(xFrame.is()) + { + uno::Reference< awt::XWindow > xContainerWindow = xFrame->getContainerWindow(); + VCLXWindow* pParentComponent = VCLXWindow::GetImplementation(xContainerWindow); + pParentComponent->setVisible(sal_True); + + pParent = VCLUnoHelper::GetWindow( xContainerWindow ); + } + + if(m_pChartWindow) + { + //@todo delete ... + } + { + // calls to VCL + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + m_pChartWindow = new ChartWindow(this,pParent,pParent?pParent->GetStyle():0); + m_xViewWindow = uno::Reference< awt::XWindow >( m_pChartWindow->GetComponentInterface(), uno::UNO_QUERY ); + m_pChartWindow->Show(); + } + + impl_tryInitializeView(); + + {//create the menu + util::URL aURL( SchResId(RID_MENU).getURL() ); + + uno::Reference< lang::XMultiServiceFactory > xMgr = comphelper::getProcessServiceFactory(); + uno::Reference< util::XURLTransformer > xTrans( + xMgr->createInstance( ::rtl::OUString::createFromAscii( + "com.sun.star.util.URLTransformer") ), uno::UNO_QUERY ); + if( xTrans.is() ) + { + // Datei laden + xTrans->parseStrict( aURL ); + + uno::Reference< frame::XDispatchProvider > xProv( xFrame, uno::UNO_QUERY ); + if ( xProv.is() ) + { + uno::Reference< frame::XDispatch > aDisp = + xProv->queryDispatch( aURL, + ::rtl::OUString::createFromAscii("_menubar"), 12 ); + if ( aDisp.is() ) + aDisp->dispatch( aURL, uno::Sequence<beans::PropertyValue>() ); + } + } + } +} + +void SAL_CALL ChartController +::impl_rebuildView() + throw(uno::RuntimeException) +{ + m_bViewDirty = false; + impl_deleteView(); + impl_tryInitializeView(); + if( m_aSelectedObjectCID.getLength() ) + { + //@todo reselect object + m_aSelectedObjectCID = C2U(""); + } +} + +void SAL_CALL ChartController +::impl_deleteView() + throw(uno::RuntimeException) +{ + delete m_pChartView; m_pChartView = NULL; + delete m_pDrawViewWrapper; m_pDrawViewWrapper = NULL; + delete m_pDrawModelWrapper; m_pDrawModelWrapper = NULL; +} + + sal_Bool SAL_CALL ChartController +::impl_tryInitializeView() + throw(uno::RuntimeException) +{ + osl::ClearableGuard< osl::Mutex > aGuard( m_aControllerMutex ); + if(!m_pChartWindow || !m_aModel.is() ) + return sal_False; + + m_pDrawModelWrapper = new DrawModelWrapper(m_xCC + ,wrapper::ItemConverter::CreateSchItemPool()); + + uno::Reference< frame::XModel > xDrawModel = m_pDrawModelWrapper->getUnoModel(); + if( xDrawModel.is()) + xDrawModel->lockControllers(); + + m_pChartView = ChartView::createView( m_xCC, m_aModel->getModel() + , uno::Reference<drawing::XDrawPagesSupplier>::query( xDrawModel ) + , m_pNumberFormatterWrapper ); + //OutputDevice* pOutDev = m_pDrawViewWrapper->GetWin(0); + Size aPageSize = m_pChartWindow->GetOutputSize(); + m_pChartView->create( awt::Size( aPageSize.Width(), aPageSize.Height() ) ); +// m_pChartWindow->SetChartView(m_pChartView);//enable event flow from window to View (Window knows View) + + //create draw view: + m_pDrawViewWrapper = new DrawViewWrapper(&m_pDrawModelWrapper->getSdrModel(),m_pChartWindow); + //test: + //Rectangle aTest = m_pDrawViewWrapper->GetWorkArea(); + //m_pDrawViewWrapper->SetWorkArea(pOutDev->PixelToLogic(Rectangle(rOfs, rSize))); + + if( xDrawModel.is()) + { + xDrawModel->unlockControllers(); + m_pChartWindow->Invalidate(); + } + return sal_True; +} + + sal_Bool SAL_CALL ChartController +::attachModel( const uno::Reference< frame::XModel > & xModel ) + throw(uno::RuntimeException) +{ + //is called to attach the controller to a new model. + //return true if attach was successfully, false otherwise (e.g. if you do not work with a model) + + osl::ClearableGuard< osl::Mutex > aGuard( m_aControllerMutex ); + if( impl_isDisposedOrSuspended() ) //@todo? allow attaching a new model while suspended? + return sal_False; //behave passive if already disposed or suspended + aGuard.clear(); + + + TheModelRef aNewModelRef( new TheModel( xModel), m_aModelMutex); + TheModelRef aOldModelRef(m_aModel,m_aModelMutex); + m_aModel = aNewModelRef; + + //--handle relations to the old model if any + if( aOldModelRef.is() ) + { + aOldModelRef->removeListener( this ); + //@todo?? termination correct? + aOldModelRef->tryTermination(); + } + + //--handle relations to the new model + aNewModelRef->addListener( this ); + + //the frameloader is responsible to call xModel->connectController + + { + // Indirect calls to VCL + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + impl_tryInitializeView(); + } + + return sal_True; +} + + uno::Reference< frame::XFrame > SAL_CALL ChartController +::getFrame() throw(uno::RuntimeException) +{ + //provides access to owner frame of this controller + //return the frame containing this controller + + return m_xFrame; +} + + uno::Reference< frame::XModel > SAL_CALL ChartController +::getModel() throw(uno::RuntimeException) +{ + //provides access to currently attached model + //returns the currently attached model + + //return nothing, if you do not have a model + TheModelRef aModelRef( m_aModel, m_aModelMutex); + if(aModelRef.is()) + return aModelRef->getModel(); + + return uno::Reference< frame::XModel > (); +} + + uno::Any SAL_CALL ChartController +::getViewData() throw(uno::RuntimeException) +{ + //provides access to current view status + //set of data that can be used to restore the current view status at later time + // by using XController::restoreViewData() + + osl::ResettableGuard< osl::Mutex > aGuard( m_aControllerMutex ); + if( impl_isDisposedOrSuspended() ) + return uno::Any(); //behave passive if already disposed or suspended //@todo? or throw an exception?? + + //-- collect current view state + uno::Any aRet; + //// @todo integrate specialized implementation + + return aRet; +} + + void SAL_CALL ChartController +::restoreViewData( const uno::Any& Value ) + throw(uno::RuntimeException) +{ + //restores the view status using the data gotten from a previous call to XController::getViewData() + + osl::ResettableGuard< osl::Mutex > aGuard( m_aControllerMutex ); + if( impl_isDisposedOrSuspended() ) + return; //behave passive if already disposed or suspended //@todo? or throw an exception?? + + //// @todo integrate specialized implementation +} + + sal_Bool SAL_CALL ChartController +::suspend( sal_Bool bSuspend ) + throw(uno::RuntimeException) +{ + //is called to prepare the controller for closing the view + //bSuspend==true: force the controller to suspend his work + //bSuspend==false try to reactivate the controller + //returns true if request was accepted and of course successfully finished, false otherwise + + //we may show dialogs here to ask the user for saving changes ... @todo? + + osl::ResettableGuard< osl::Mutex > aGuard( m_aControllerMutex ); + if( m_aLifeTimeManager.impl_isDisposed() ) + return sal_False; //behave passive if already disposed, return false because request was not accepted //@todo? correct + + if(bSuspend==m_bSuspended) + { + OSL_ENSURE( sal_False, "new suspend mode equals old suspend mode" ); + //@todo ??? or return true in this case? + return sal_False; + } + + //change suspend mode + if(bSuspend) + { + //aGuard.clear(); + //@todo ??? try to stop all what may prevent me from becoming disposed + //aGuard.reset(); + + m_bSuspended = bSuspend; + return sal_True; + } + else + { + //aGuard.clear(); + //@todo ??? redo what was made in section bSuspend==true + //aGuard.reset(); + + m_bSuspended = bSuspend; + return sal_True; + } + + + /* + if ( bSuspend ) + getFrame()->removeFrameActionListener( pImp ); + else + getFrame()->addFrameActionListener( pImp ); + */ + return sal_True; +} + +//----------------------------------------------------------------- +// XComponent (base of XController) +//----------------------------------------------------------------- + + void SAL_CALL ChartController +::dispose() throw(uno::RuntimeException) +{ + //This object should release all resources and references in the + //easiest possible manner + //This object must notify all registered listeners using the method + //<member>XEventListener::disposing</member> + + //hold no mutex + if( !m_aLifeTimeManager.dispose() ) + return; + + OSL_ENSURE( m_bSuspended, "dispose was called but controller is not suspended" ); + + //--release all resources and references + + impl_deleteView(); + m_pChartWindow = NULL;//m_pChartWindow is deleted via UNO by Window hierarchy or Framework + + m_xFrame = NULL; + TheModelRef aModelRef( m_aModel, m_aModelMutex); + m_aModel = NULL; + + if(aModelRef.is()) + { + aModelRef->removeListener( this ); + aModelRef->tryTermination(); + } + + //// @todo integrate specialized implementation + //e.g. release further resources and references + } + + void SAL_CALL ChartController +::addEventListener( const uno::Reference<lang::XEventListener>& xListener ) + throw(uno::RuntimeException) +{ + osl::Guard< osl::Mutex > aGuard( m_aControllerMutex ); + if( impl_isDisposedOrSuspended() )//@todo? allow adding of listeners in suspend mode? + return; //behave passive if already disposed or suspended + + //--add listener + m_aLifeTimeManager.m_aListenerContainer.addInterface( ::getCppuType((const uno::Reference< lang::XEventListener >*)0), xListener ); +} + + void SAL_CALL ChartController +::removeEventListener( const uno::Reference< + lang::XEventListener>& xListener ) + throw(uno::RuntimeException) +{ + osl::Guard< osl::Mutex > aGuard( m_aControllerMutex ); + if( impl_isDisposedOrSuspended() ) //@todo? allow removing of listeners in suspend mode? + return; //behave passive if already disposed or suspended + + //--remove listener + m_aLifeTimeManager.m_aListenerContainer.removeInterface( ::getCppuType((const uno::Reference< lang::XEventListener >*)0), xListener ); +} + + +//----------------------------------------------------------------- +// util::XCloseListener +//----------------------------------------------------------------- + void SAL_CALL ChartController +::queryClosing( const lang::EventObject& rSource, sal_Bool bGetsOwnership ) + throw(util::CloseVetoException, uno::RuntimeException) +{ + //do not use the m_aControllerMutex here because this call is not allowed to block + + TheModelRef aModelRef( m_aModel, m_aModelMutex); + + if( !aModelRef.is() ) + return; + + if( !(aModelRef->getModel() == rSource.Source) ) + { + OSL_ENSURE( sal_False, "queryClosing was called on a controller from an unknown source" ); + return; + } + + if( !m_bCanClose )//@todo tryaqcuire mutex + { + if( bGetsOwnership ) + { + aModelRef->SetOwnerShip( bGetsOwnership ); + } + + throw util::CloseVetoException(); + } + else + { + //@ todo prepare to to closing model -> don't start any further hindering actions + } +} + + void SAL_CALL ChartController +::notifyClosing( const lang::EventObject& rSource ) + throw(uno::RuntimeException) +{ + //Listener should deregister himself and relaese all references to the closing object. + + TheModelRef aModelRef( 0, m_aModelMutex); + bool bReleaseModel = sal_False; + { + ::osl::Guard< ::osl::Mutex > aGuard( m_aModelMutex ); + aModelRef = m_aModel; + if( aModelRef.is() && aModelRef->getModel() == rSource.Source ) + { + m_aModel = NULL; + bReleaseModel = sal_True; + } + } + //@todo ?? why remove the listener??? this could be handled by the closing object + if( bReleaseModel ) + { + //--stop listening to the closing model + aModelRef->removeListener( this ); + } +} + +//----------------------------------------------------------------- +// util::XEventListener (base of XCloseListener) +//----------------------------------------------------------------- + void SAL_CALL ChartController +::disposing( const lang::EventObject& rSource ) + throw(uno::RuntimeException) +{ + notifyClosing(rSource); +} + +//----------------------------------------------------------------- +// XDispatchProvider (required interface) +//----------------------------------------------------------------- + +bool isFormatObjectSID( sal_Int32 nSlotID ) +{ + if((sal_Int32)SID_DIAGRAM_TITLE_MAIN == nSlotID + || (sal_Int32)SID_DIAGRAM_TITLE_SUB == nSlotID + || (sal_Int32)SID_DIAGRAM_TITLE_X == nSlotID + || (sal_Int32)SID_DIAGRAM_TITLE_Y == nSlotID + || (sal_Int32)SID_DIAGRAM_TITLE_Z == nSlotID + || (sal_Int32)SID_DIAGRAM_TITLE_ALL == nSlotID + || (sal_Int32)SID_LEGEND == nSlotID + || (sal_Int32)SID_DIAGRAM_AXIS_X == nSlotID + || (sal_Int32)SID_DIAGRAM_AXIS_Y == nSlotID + || (sal_Int32)SID_DIAGRAM_AXIS_Z == nSlotID + || (sal_Int32)SID_DIAGRAM_AXIS_A == nSlotID //secondary x axis + || (sal_Int32)SID_DIAGRAM_AXIS_B == nSlotID + || (sal_Int32)SID_DIAGRAM_AXIS_ALL == nSlotID + || (sal_Int32)SID_DIAGRAM_GRID_X_MAIN == nSlotID + || (sal_Int32)SID_DIAGRAM_GRID_Y_MAIN == nSlotID + || (sal_Int32)SID_DIAGRAM_GRID_Z_MAIN == nSlotID + || (sal_Int32)SID_DIAGRAM_GRID_X_HELP == nSlotID + || (sal_Int32)SID_DIAGRAM_GRID_Y_HELP == nSlotID + || (sal_Int32)SID_DIAGRAM_GRID_Z_HELP == nSlotID + || (sal_Int32)SID_DIAGRAM_GRID_ALL == nSlotID + || (sal_Int32)SID_DIAGRAM_WALL == nSlotID + || (sal_Int32)SID_DIAGRAM_FLOOR == nSlotID + || (sal_Int32)SID_DIAGRAM_AREA == nSlotID + ) + return true; + return false; +} + + uno::Reference<frame::XDispatch> SAL_CALL ChartController +::queryDispatch( const util::URL& rURL + , const rtl::OUString& rTargetFrameName + , sal_Int32 nSearchFlags) + throw(uno::RuntimeException) +{ + //// @todo integrate specialized implementation + //decide which commands you can handle + + if ( !m_aLifeTimeManager.impl_isDisposed() ) + { + //@todo avoid OString (see Mathias mail on bug #104387#) + rtl::OString aCommand( rtl::OUStringToOString( rURL.Path, RTL_TEXTENCODING_ASCII_US ) ); + if( aCommand.equals("Save") + || aCommand.equals("SaveAs") + || aCommand.equals("SaveAll") + + || aCommand.equals("Undo") + || aCommand.equals("Cut") + || aCommand.equals("Copy") + || aCommand.equals("Paste") + || aCommand.equals("SelectAll") + || aCommand.equals("Close") + || aCommand.equals("TESTTEST") + || aCommand.equals("slot:23") + //|| aCommand.copy(0,4).EqualsAscii("Bib/") + //|| aURL.Complete.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("slot:5503")) + ) + { + //@todo create a seperate dispatcher object or implement XDispatch interface by yourself + //to return it here + return static_cast< frame::XDispatch* >( this ); + } + else if(rURL.Protocol.equalsIgnoreAsciiCase( C2U("slot:") ) ) + { + sal_Int32 nSlotID = rURL.Path.toInt32(); + if( (sal_Int32)SID_DIAGRAM_OBJECTS == nSlotID + || (sal_Int32)SID_DIAGRAM_TYPE == nSlotID + || (sal_Int32)SID_INSERT_TITLE == nSlotID + || (sal_Int32)SID_INSERT_CHART_LEGEND == nSlotID + || (sal_Int32)SID_INSERT_DESCRIPTION == nSlotID + || (sal_Int32)SID_INSERT_AXIS == nSlotID + || (sal_Int32)SID_INSERT_GRIDS == nSlotID + || (sal_Int32)SID_INSERT_STATISTICS == nSlotID + || (sal_Int32)SID_CHARMAP == nSlotID + || isFormatObjectSID(nSlotID) + ) + { + return static_cast< frame::XDispatch* >( this ); + } + } + } + return uno::Reference< frame::XDispatch > (); +} +/* +typedef ::std::map< sal_Int32, ::rtl::OUString > tSlotIdCommandMap; +typedef ::comphelper::MakeMap< sal_Int32, ::rtl::OUString > tMakeSlotIdCommandMap; +tMakeSlotIdCommandMap m_aSlotIdCommandMap = + tMakeSlotIdCommandMap + ( (sal_Int32)SID_DIAGRAM_TITLE_MAIN, C2U( "slot:" )+=rtl::OUString::valueOf( (sal_Int32)SID_DIAGRAM_TITLE_MAIN ) ) + ; +*/ + uno::Sequence<uno::Reference<frame::XDispatch > > ChartController +::queryDispatches( const uno::Sequence< + frame::DispatchDescriptor>& xDescripts) + throw(uno::RuntimeException) +{ + sal_Int32 nCount = xDescripts.getLength(); + + if( !nCount ) + return uno::Sequence<uno::Reference<frame::XDispatch > > (); + + uno::Sequence<uno::Reference<frame::XDispatch > > aRet( nCount ); + for( sal_Int32 nPos = 0; nPos<nCount; ++nPos ) + { + aRet[ nPos ] = queryDispatch( + xDescripts[nPos].FeatureURL + , xDescripts[nPos].FrameName + , xDescripts[nPos].SearchFlags ); + } + return aRet; +} + +//----------------------------------------------------------------- +// frame::XDispatch +//----------------------------------------------------------------- + + void SAL_CALL ChartController +::dispatch( const util::URL& rURL + , const uno::Sequence< beans::PropertyValue >& rArgs ) + throw (uno::RuntimeException) +{ + //@todo avoid OString (see Mathias mail on bug #104387#) + rtl::OString aCommand( rtl::OUStringToOString( rURL.Path, RTL_TEXTENCODING_ASCII_US ) ); + //test only + if(aCommand.equals("TESTTEST") + || aCommand.equals("Undo") ) + { + Window* pWindow = m_pChartWindow; + Rectangle aRect( Point(0,0), pWindow->GetOutputSize() ); + Region aRegion( aRect ); + m_pDrawViewWrapper->InitRedraw(pWindow, aRegion ); + + /* + INVALIDATE_CHILDREN + INVALIDATE_NOCHILDREN + INVALIDATE_NOERASE + INVALIDATE_UPDATE + INVALIDATE_TRANSPARENT + INVALIDATE_NOTRANSPARENT + INVALIDATE_NOCLIPCHILDREN + */ + //Invalidate(INVALIDATE_UPDATE); + } + + else if(aCommand.equals("Save")) + { + //only test: + impl_rebuildView(); + } + else if(aCommand.equals("SaveAs")) + { + //only test: + this->executeDispatch_ObjectToDefault(); + } + //---------------------------------- + else if(rURL.Protocol.equalsIgnoreAsciiCase( C2U("slot:") ) ) + { + sal_Int32 nSlotID = rURL.Path.toInt32(); + if((sal_Int32)SID_DIAGRAM_OBJECTS == nSlotID) + { + this->executeDispatch_ObjectProperties(); + } + else if((sal_Int32)SID_DIAGRAM_TYPE == nSlotID) + { + this->executeDispatch_ChartType(); + } + else if((sal_Int32)SID_INSERT_TITLE == nSlotID) + { + this->executeDispatch_InsertTitle(); + } + else if((sal_Int32)SID_INSERT_CHART_LEGEND == nSlotID) + { + this->executeDispatch_InsertLegend(); + } + else if((sal_Int32)SID_INSERT_DESCRIPTION == nSlotID) + { + this->executeDispatch_InsertDataLabel(); + } + else if((sal_Int32)SID_INSERT_AXIS == nSlotID) + { + this->executeDispatch_InsertAxis(); + } + else if((sal_Int32)SID_INSERT_GRIDS == nSlotID) + { + this->executeDispatch_InsertGrid(); + } + else if((sal_Int32)SID_INSERT_STATISTICS == nSlotID) + { + this->executeDispatch_InsertStatistic(); + } + else if((sal_Int32)SID_CHARMAP == nSlotID) + { + this->executeDispatch_InsertSpecialCharacter(); + } + else if( isFormatObjectSID(nSlotID) ) + { + this->executeDispatch_FormatObject(nSlotID); + } + } + else if(aCommand.equals("SaveAll")) + { + if( m_aModel.is()) + { + uno::Reference< ::drafts::com::sun::star::chart2::XChartDocument > xDoc( + m_aModel->getModel(), uno::UNO_QUERY ); + OSL_ASSERT( xDoc.is()); + + uno::Reference< ::drafts::com::sun::star::chart2::XDataProvider > xDataProvider( + m_xCC->getServiceManager()->createInstanceWithContext( + C2U( "com.sun.star.comp.chart.FileDataProvider" ), + m_xCC ), uno::UNO_QUERY ); + OSL_ASSERT( xDataProvider.is()); + + ::rtl::OUString aFileName( +#if defined WNT + RTL_CONSTASCII_USTRINGPARAM( "file:///D:/files/data.chd" ) +#else + RTL_CONSTASCII_USTRINGPARAM( "file:///work/data/data.chd" ) +#endif + ); + + xDoc->attachDataProvider( xDataProvider ); + xDoc->setRangeRepresentation( aFileName ); + impl_rebuildView(); + } + } +} + + void SAL_CALL ChartController +::addStatusListener( const uno::Reference<frame::XStatusListener >& xControl + , const util::URL& aURL ) + throw (uno::RuntimeException) +{ +} + + void SAL_CALL ChartController +::removeStatusListener( const uno::Reference<frame::XStatusListener >& xControl + , const util::URL& aURL ) + throw (uno::RuntimeException) +{ +} + +//----------------------------------------------------------------- +// XContextMenuInterception (optional interface) +//----------------------------------------------------------------- + void SAL_CALL ChartController +::registerContextMenuInterceptor( const uno::Reference< + ui::XContextMenuInterceptor > & xInterceptor) + throw(uno::RuntimeException) +{ + //@todo +} + + void SAL_CALL ChartController +::releaseContextMenuInterceptor( const uno::Reference< + ui::XContextMenuInterceptor > & xInterceptor) + throw(uno::RuntimeException) +{ + //@todo +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +void SAL_CALL ChartController::executeDispatch_ChartType() +{ + bool bChanged = false; + + //------------------------------------------------------------- + //convert properties to ItemSet + uno::Reference< beans::XPropertySet > xProp; + uno::Reference< XChartDocument > xChartDoc( m_aModel->getModel(), uno::UNO_QUERY ); + if( xChartDoc.is()) + xProp.set( xChartDoc->getChartTypeManager(), uno::UNO_QUERY ); + DBG_ASSERT( xProp.is(), "Invalid ChartTypeManager" ); + + { + wrapper::ChartTypeItemConverter aItemConverter( xProp, m_pDrawModelWrapper->GetItemPool() ); + SfxItemSet aItemSet = aItemConverter.CreateEmptyItemSet();//creates only an empty itemset + aItemConverter.FillItemSet( aItemSet ); + //------------------------------------------------------------- + //prepare and open dialog + Window* pParent( NULL ); + SchDiagramTypeDlg aDlg( pParent, aItemSet ); + if( aDlg.Execute() == RET_OK ) + { + SfxItemSet aOutItemSet = aItemConverter.CreateEmptyItemSet(); + aDlg.GetAttr( aOutItemSet ); + + bChanged = aItemConverter.ApplyItemSet( aOutItemSet );//model should be changed now + } + } + + try + { + //make sure that all objects using m_pDrawModelWrapper or m_pChartView are already deleted + if(bChanged && + xChartDoc.is()) + { + uno::Reference< lang::XMultiServiceFactory > xFact( xProp, uno::UNO_QUERY ); + if( xFact.is() ) + { + ::rtl::OUString aServiceName; + if( xProp->getPropertyValue( C2U( "ChartStyleTemplateServiceName" )) >>= aServiceName ) + { + uno::Reference< XChartTypeTemplate > xTemplate( + xFact->createInstance( aServiceName ), uno::UNO_QUERY ); + xChartDoc->setChartTypeTemplate( xTemplate ); + if( xTemplate.is()) + xTemplate->changeDiagram( xChartDoc->getDiagram() ); + impl_rebuildView(); + } + } + } + } + catch( uno::RuntimeException& e) + { + e; + } +} + +//............................................................................. +} //namespace chart +//............................................................................. |