diff options
Diffstat (limited to 'chart2/source/controller/main')
56 files changed, 18144 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..bf8afc65e78f --- /dev/null +++ b/chart2/source/controller/main/ChartController.cxx @@ -0,0 +1,1603 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" +#include "ChartController.hxx" +#include "servicenames.hxx" +#include "ResId.hxx" +#include "dlg_DataSource.hxx" +#include "ChartModelHelper.hxx" +#include "ControllerCommandDispatch.hxx" +#include "Strings.hrc" +#include "chartview/ExplicitValueProvider.hxx" +#include "ChartViewHelper.hxx" + +#include "ChartWindow.hxx" +#include "chartview/DrawModelWrapper.hxx" +#include "DrawViewWrapper.hxx" +#include "ObjectIdentifier.hxx" +#include "DiagramHelper.hxx" +#include "ControllerLockGuard.hxx" +#include "UndoGuard.hxx" +#include "ChartDropTargetHelper.hxx" + +#include "macros.hxx" +#include "dlg_CreationWizard.hxx" +#include "dlg_ChartType.hxx" +//#include "svx/ActionDescriptionProvider.hxx" +#include "AccessibleChartView.hxx" +#include "DrawCommandDispatch.hxx" +#include "ShapeController.hxx" +#include "UndoManager.hxx" + +#include <comphelper/InlineContainer.hxx> + +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XUndoSupplier.hpp> +#include <com/sun/star/chart2/data/XDataReceiver.hpp> +#include <com/sun/star/frame/XLoadable.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/embed/XEmbeddedClient.hpp> +#include <com/sun/star/util/XModeChangeBroadcaster.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> +#include <com/sun/star/frame/LayoutManagerEvents.hpp> + +//------- +// header for define RET_OK +#include <vcl/msgbox.hxx> +//------- + +//------- +#include <toolkit/awt/vclxwindow.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> +//------- +#include <com/sun/star/frame/XLayoutManager.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> + +// this is needed to properly destroy the auto_ptr to the AcceleratorExecute +// object in the DTOR +#include <svtools/acceleratorexecute.hxx> +#include <svx/ActionDescriptionProvider.hxx> + +// enable the following define to let the controller listen to model changes and +// react on this by rebuilding the view +#define TEST_ENABLE_MODIFY_LISTENER + +/* +#include <vcl/svapp.hxx> +*/ + +//............................................................................. +namespace chart +{ +//............................................................................. + +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; +using namespace ::com::sun::star::chart2; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +DBG_NAME(ChartController) +//----------------------------------------------------------------- +// ChartController Constructor and Destructor +//----------------------------------------------------------------- + +ChartController::ChartController(uno::Reference<uno::XComponentContext> const & xContext) + : m_aLifeTimeManager( NULL ) + , m_bSuspended( sal_False ) + , m_bCanClose( sal_True ) + , m_xCC(xContext) //@todo is it allowed to hold this context?? + , m_xFrame( NULL ) + , m_aModelMutex() + , m_aModel( NULL, m_aModelMutex ) + , m_pChartWindow( NULL ) + , m_xViewWindow() + , m_xChartView() + , m_pDrawModelWrapper() + , m_pDrawViewWrapper(NULL) + , m_eDragMode(SDRDRAG_MOVE) + , m_bWaitingForDoubleClick(false) + , m_bWaitingForMouseUp(false) + , m_bConnectingToView(false) + , m_xUndoManager( 0 ) + , m_aDispatchContainer( m_xCC, this ) + , m_eDrawMode( CHARTDRAW_SELECT ) +{ + DBG_CTOR(ChartController,NULL); +// m_aDispatchContainer.setUndoManager( m_xUndoManager ); + m_aDoubleClickTimer.SetTimeoutHdl( LINK( this, ChartController, DoubleClickWaitingHdl ) ); +} + +ChartController::~ChartController() +{ + DBG_DTOR(ChartController,NULL); + stopDoubleClickWaiting(); +} + +//----------------------------------------------------------------- + +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<util::XCloseListener*>(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<util::XCloseListener*>(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 + +#if OSL_DEBUG_LEVEL > 2 + OSL_ENSURE( !m_bOwnership, + "INFO: a well known owner has catched a CloseVetoException after calling close(true)" ); +#endif + + m_bOwnership = false; + m_bOwnershipIsWellKnown = sal_True; + return; + } + + } + else if( m_xModel.is() ) + { + //@todo correct?? + m_xModel->dispose(); + return; + } + } + catch( uno::Exception& ex) + { + (void)(ex); // no warning in non-debug builds + 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() const +{ + 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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex()); + + 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 ... + m_pChartWindow->clear(); + m_apDropTargetHelper.reset(); + } + { + awt::Size aPageSize( ChartModelHelper::getPageSize(getModel()) ); + + // calls to VCL + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + m_pChartWindow = new ChartWindow(this,pParent,pParent?pParent->GetStyle():0); + m_pChartWindow->SetBackground();//no Background + m_xViewWindow = uno::Reference< awt::XWindow >( m_pChartWindow->GetComponentInterface(), uno::UNO_QUERY ); + m_pChartWindow->Show(); + m_apDropTargetHelper.reset( + new ChartDropTargetHelper( m_pChartWindow->GetDropTarget(), + uno::Reference< chart2::XChartDocument >( getModel(), uno::UNO_QUERY ))); + + impl_createDrawViewController(); + } + + //create the menu + { + uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY ); + if( xPropSet.is() ) + { + try + { + uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager; + xPropSet->getPropertyValue( C2U( "LayoutManager" ) ) >>= xLayoutManager; + if ( xLayoutManager.is() ) + { + xLayoutManager->lock(); + xLayoutManager->requestElement( C2U( "private:resource/menubar/menubar" ) ); + //@todo: createElement should become unnecessary, remove when #i79198# is fixed + xLayoutManager->createElement( C2U( "private:resource/toolbar/standardbar" ) ); + xLayoutManager->requestElement( C2U( "private:resource/toolbar/standardbar" ) ); + //@todo: createElement should become unnecessary, remove when #i79198# is fixed + xLayoutManager->createElement( C2U( "private:resource/toolbar/toolbar" ) ); + xLayoutManager->requestElement( C2U( "private:resource/toolbar/toolbar" ) ); + + // #i12587# support for shapes in chart + xLayoutManager->createElement( C2U( "private:resource/toolbar/drawbar" ) ); + xLayoutManager->requestElement( C2U( "private:resource/toolbar/drawbar" ) ); + + xLayoutManager->requestElement( C2U( "private:resource/statusbar/statusbar" ) ); + xLayoutManager->unlock(); + + // add as listener to get notified when + m_xLayoutManagerEventBroadcaster.set( xLayoutManager, uno::UNO_QUERY ); + if( m_xLayoutManagerEventBroadcaster.is()) + m_xLayoutManagerEventBroadcaster->addLayoutManagerEventListener( this ); + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + } +} + +//XModeChangeListener +void SAL_CALL ChartController::modeChanged( const util::ModeChangeEvent& rEvent ) + throw ( uno::RuntimeException ) +{ + //adjust controller to view status changes + + if( rEvent.NewMode.equals(C2U("dirty")) ) + { + //the view has become dirty, we should repaint it if we have a window + if( m_pChartWindow ) + m_pChartWindow->ForceInvalidate(); + } + else if( rEvent.NewMode.equals(C2U("invalid")) ) + { + //the view is about to become invalid so end all actions on it + impl_invalidateAccessible(); + ::vos::OGuard aGuard( Application::GetSolarMutex()); + if( m_pDrawViewWrapper && m_pDrawViewWrapper->IsTextEdit() ) + this->EndTextEdit(); + if( m_pDrawViewWrapper ) + { + m_pDrawViewWrapper->UnmarkAll(); + //m_pDrawViewWrapper->hideMarkHandles(); todo?? + m_pDrawViewWrapper->HideSdrPage(); + } + } + else + { + //the view was rebuild so we can start some actions on it again + if( !m_bConnectingToView ) + { + if(m_pChartWindow && m_aModel.is() ) + { + m_bConnectingToView = true; + + GetDrawModelWrapper(); + if(m_pDrawModelWrapper) + { + { + ::vos::OGuard aGuard( Application::GetSolarMutex()); + if( m_pDrawViewWrapper ) + m_pDrawViewWrapper->ReInit(); + } + + //reselect object + if( m_aSelection.hasSelection() ) + this->impl_selectObjectAndNotiy(); + else + ChartModelHelper::triggerRangeHighlighting( getModel() ); + + impl_initializeAccessible(); + + if( m_pChartWindow ) + m_pChartWindow->Invalidate(); + } + + m_bConnectingToView = false; + } + } + } +} + + sal_Bool SAL_CALL ChartController +::attachModel( const uno::Reference< frame::XModel > & xModel ) + throw(uno::RuntimeException) +{ + impl_invalidateAccessible(); + + //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) + + ::vos::OClearableGuard aGuard( Application::GetSolarMutex()); + 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() ) + { + uno::Reference< util::XModeChangeBroadcaster > xViewBroadcaster( m_xChartView, uno::UNO_QUERY ); + if( xViewBroadcaster.is() ) + xViewBroadcaster->removeModeChangeListener(this); + m_pDrawModelWrapper.reset(); + + aOldModelRef->removeListener( this ); + //@todo?? termination correct? +// aOldModelRef->tryTermination(); +#ifdef TEST_ENABLE_MODIFY_LISTENER + uno::Reference< util::XModifyBroadcaster > xMBroadcaster( aOldModelRef->getModel(),uno::UNO_QUERY ); + if( xMBroadcaster.is()) + xMBroadcaster->removeModifyListener( this ); +#endif + } + + //--handle relations to the new model + aNewModelRef->addListener( this ); + + // set new model at dispatchers + m_aDispatchContainer.setModel( aNewModelRef->getModel()); + ControllerCommandDispatch * pDispatch = new ControllerCommandDispatch( m_xCC, this, &m_aDispatchContainer ); + pDispatch->initialize(); + + // the dispatch container will return "this" for all commands returned by + // impl_getAvailableCommands(). That means, for those commands dispatch() + // is called here at the ChartController. + m_aDispatchContainer.setChartDispatch( pDispatch, impl_getAvailableCommands() ); + + DrawCommandDispatch* pDrawDispatch = new DrawCommandDispatch( m_xCC, this ); + if ( pDrawDispatch ) + { + pDrawDispatch->initialize(); + m_aDispatchContainer.setDrawCommandDispatch( pDrawDispatch ); + } + + ShapeController* pShapeController = new ShapeController( m_xCC, this ); + if ( pShapeController ) + { + pShapeController->initialize(); + m_aDispatchContainer.setShapeController( pShapeController ); + } + +#ifdef TEST_ENABLE_MODIFY_LISTENER + uno::Reference< util::XModifyBroadcaster > xMBroadcaster( aNewModelRef->getModel(),uno::UNO_QUERY ); + if( xMBroadcaster.is()) + xMBroadcaster->addModifyListener( this ); +#endif + + //select chart area per default: + select( uno::makeAny( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, rtl::OUString() ) ) ); + + uno::Reference< lang::XMultiServiceFactory > xFact( getModel(), uno::UNO_QUERY ); + if( xFact.is()) + { + m_xChartView = xFact->createInstance( CHART_VIEW_SERVICE_NAME ); + GetDrawModelWrapper(); + uno::Reference< util::XModeChangeBroadcaster > xViewBroadcaster( m_xChartView, uno::UNO_QUERY ); + if( xViewBroadcaster.is() ) + xViewBroadcaster->addModeChangeListener(this); + } + + //the frameloader is responsible to call xModel->connectController + if( m_pChartWindow ) + m_pChartWindow->Invalidate(); + + uno::Reference< chart2::XUndoSupplier > xUndoSupplier( getModel(), uno::UNO_QUERY ); + if( xUndoSupplier.is()) + m_xUndoManager.set( xUndoSupplier->getUndoManager()); + + 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() + + ::vos::OGuard aGuard( Application::GetSolarMutex()); + 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() + + ::vos::OGuard aGuard( Application::GetSolarMutex()); + 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? + + ::vos::OGuard aGuard( Application::GetSolarMutex()); + 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" ); + return sal_True; + } + + //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 ); + */ +} + + +void ChartController::impl_createDrawViewController() +{ + ::vos::OGuard aGuard( Application::GetSolarMutex()); + if(!m_pDrawViewWrapper) + { + if( m_pDrawModelWrapper ) + { + m_pDrawViewWrapper = new DrawViewWrapper(&m_pDrawModelWrapper->getSdrModel(),m_pChartWindow,true); + m_pDrawViewWrapper->attachParentReferenceDevice( getModel() ); + } + } +} +void ChartController::impl_deleteDrawViewController() +{ + if( m_pDrawViewWrapper ) + { + ::vos::OGuard aGuard( Application::GetSolarMutex()); + if( m_pDrawViewWrapper->IsTextEdit() ) + this->EndTextEdit(); + DELETEZ( m_pDrawViewWrapper ); + } +} + +//----------------------------------------------------------------- +// XComponent (base of XController) +//----------------------------------------------------------------- + + void SAL_CALL ChartController +::dispose() throw(uno::RuntimeException) +{ + try + { + //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" ); + + this->stopDoubleClickWaiting(); + + //end range highlighting + if( m_aModel.is()) + { + uno::Reference< view::XSelectionChangeListener > xSelectionChangeListener; + uno::Reference< chart2::data::XDataReceiver > xDataReceiver( getModel(), uno::UNO_QUERY ); + if( xDataReceiver.is() ) + xSelectionChangeListener = uno::Reference< view::XSelectionChangeListener >( xDataReceiver->getRangeHighlighter(), uno::UNO_QUERY ); + if( xSelectionChangeListener.is() ) + { + uno::Reference< frame::XController > xController( this ); + uno::Reference< lang::XComponent > xComp( xController, uno::UNO_QUERY ); + //lang::EventObject aEvent( static_cast< lang::XComponent* >( this ) ); + lang::EventObject aEvent( xComp ); + xSelectionChangeListener->disposing( aEvent ); + } + } + + //--release all resources and references + { + uno::Reference< util::XModeChangeBroadcaster > xViewBroadcaster( m_xChartView, uno::UNO_QUERY ); + if( xViewBroadcaster.is() ) + xViewBroadcaster->removeModeChangeListener(this); + // /-- + impl_invalidateAccessible(); + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + impl_deleteDrawViewController(); + m_pDrawModelWrapper.reset(); + + m_apDropTargetHelper.reset(); + + //the accessible view is disposed within window destructor of m_pChartWindow + m_pChartWindow->clear(); + m_pChartWindow = NULL;//m_pChartWindow is deleted via UNO due to dispose of m_xViewWindow (trigerred by Framework (Controller pretends to be XWindow also)) + m_xViewWindow->dispose(); + m_xChartView.clear(); + // \-- + } + + // remove as listener to layout manager events + if( m_xLayoutManagerEventBroadcaster.is()) + { + m_xLayoutManagerEventBroadcaster->removeLayoutManagerEventListener( this ); + m_xLayoutManagerEventBroadcaster.set( 0 ); + } + + m_xFrame.clear(); + m_xUndoManager.clear(); + + TheModelRef aModelRef( m_aModel, m_aModelMutex); + m_aModel = NULL; + + if( aModelRef.is()) + { + uno::Reference< frame::XModel > xModel( aModelRef->getModel() ); + if(xModel.is()) + xModel->disconnectController( uno::Reference< frame::XController >( this )); + + aModelRef->removeListener( this ); +#ifdef TEST_ENABLE_MODIFY_LISTENER + try + { + uno::Reference< util::XModifyBroadcaster > xMBroadcaster( aModelRef->getModel(),uno::UNO_QUERY ); + if( xMBroadcaster.is()) + xMBroadcaster->removeModifyListener( this ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +#endif + aModelRef->tryTermination(); + } + + //// @todo integrate specialized implementation + //e.g. release further resources and references + + m_aDispatchContainer.DisposeAndClear(); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + + void SAL_CALL ChartController +::addEventListener( const uno::Reference<lang::XEventListener>& xListener ) + throw(uno::RuntimeException) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex()); + 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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex()); + if( m_aLifeTimeManager.impl_isDisposed(false) ) + 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( m_aModel, m_aModelMutex); + if( impl_releaseThisModel( rSource.Source ) ) + { + //--stop listening to the closing model + aModelRef->removeListener( this ); + + // #i79087# If the model using this controller is closed, the frame is + // expected to be closed as well + Reference< util::XCloseable > xFrameCloseable( m_xFrame, uno::UNO_QUERY ); + if( xFrameCloseable.is()) + { + try + { + xFrameCloseable->close( sal_False /* DeliverOwnership */ ); + m_xFrame.clear(); + } + catch( util::CloseVetoException & ) + { + // closing was vetoed + } + } + } +} + +bool ChartController::impl_releaseThisModel( const uno::Reference< uno::XInterface > & xModel ) +{ + bool bReleaseModel = sal_False; + { + ::osl::Guard< ::osl::Mutex > aGuard( m_aModelMutex ); + if( m_aModel.is() && m_aModel->getModel() == xModel ) + { + m_aModel = NULL; + m_xUndoManager.clear(); + bReleaseModel = true; + } + } + if( bReleaseModel ) + m_aDispatchContainer.setModel( 0 ); + return bReleaseModel; +} + +//----------------------------------------------------------------- +// util::XEventListener (base of XCloseListener) +//----------------------------------------------------------------- + void SAL_CALL ChartController +::disposing( const lang::EventObject& rSource ) + throw(uno::RuntimeException) +{ + if( !impl_releaseThisModel( rSource.Source )) + { + if( rSource.Source == m_xLayoutManagerEventBroadcaster ) + m_xLayoutManagerEventBroadcaster.set( 0 ); + } +} + +void SAL_CALL ChartController::layoutEvent( const lang::EventObject& aSource, ::sal_Int16 eLayoutEvent, const uno::Any& /* aInfo */ ) + throw (uno::RuntimeException) +{ + if( eLayoutEvent == frame::LayoutManagerEvents::MERGEDMENUBAR ) + { + Reference< frame::XLayoutManager > xLM( aSource.Source, uno::UNO_QUERY ); + if( xLM.is()) + { + xLM->createElement( C2U("private:resource/statusbar/statusbar")); + xLM->requestElement( C2U("private:resource/statusbar/statusbar")); + } + } +} + + +//----------------------------------------------------------------- +// XDispatchProvider (required interface) +//----------------------------------------------------------------- + +namespace +{ +bool lcl_isFormatObjectCommand( const rtl::OString& aCommand ) +{ + if( aCommand.equals("MainTitle") + || aCommand.equals("SubTitle") + || aCommand.equals("XTitle") + || aCommand.equals("YTitle") + || aCommand.equals("ZTitle") + || aCommand.equals("SecondaryXTitle") + || aCommand.equals("SecondaryYTitle") + || aCommand.equals("AllTitles") + || aCommand.equals("DiagramAxisX") + || aCommand.equals("DiagramAxisY") + || aCommand.equals("DiagramAxisZ") + || aCommand.equals("DiagramAxisA") + || aCommand.equals("DiagramAxisB") + || aCommand.equals("DiagramAxisAll") + || aCommand.equals("DiagramGridXMain") + || aCommand.equals("DiagramGridYMain") + || aCommand.equals("DiagramGridZMain") + || aCommand.equals("DiagramGridXHelp") + || aCommand.equals("DiagramGridYHelp") + || aCommand.equals("DiagramGridZHelp") + || aCommand.equals("DiagramGridAll") + + || aCommand.equals("DiagramWall") + || aCommand.equals("DiagramFloor") + || aCommand.equals("DiagramArea") + || aCommand.equals("Legend") + + || aCommand.equals("FormatWall") + || aCommand.equals("FormatFloor") + || aCommand.equals("FormatChartArea") + || aCommand.equals("FormatLegend") + + || aCommand.equals("FormatTitle") + || aCommand.equals("FormatAxis") + || aCommand.equals("FormatDataSeries") + || aCommand.equals("FormatDataPoint") + || aCommand.equals("FormatDataLabels") + || aCommand.equals("FormatDataLabel") + || aCommand.equals("FormatYErrorBars") + || aCommand.equals("FormatMeanValue") + || aCommand.equals("FormatTrendline") + || aCommand.equals("FormatTrendlineEquation") + || aCommand.equals("FormatStockLoss") + || aCommand.equals("FormatStockGain") + || aCommand.equals("FormatMajorGrid") + || aCommand.equals("FormatMinorGrid") + ) + return true; + + // else + return false; +} +} // anonymous namespace + + uno::Reference<frame::XDispatch> SAL_CALL ChartController +::queryDispatch( const util::URL& rURL + , const rtl::OUString& rTargetFrameName + , sal_Int32 /* nSearchFlags */) + throw(uno::RuntimeException) +{ + if ( !m_aLifeTimeManager.impl_isDisposed() && getModel().is() ) + { + if( rTargetFrameName.getLength() && + rTargetFrameName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("_self"))) + return m_aDispatchContainer.getDispatchForURL( rURL ); + } + return uno::Reference< frame::XDispatch > (); +} + + uno::Sequence<uno::Reference<frame::XDispatch > > ChartController +::queryDispatches( const uno::Sequence< + frame::DispatchDescriptor>& xDescripts) + throw(uno::RuntimeException) +{ + if ( !m_aLifeTimeManager.impl_isDisposed() ) + { + return m_aDispatchContainer.getDispatchesForURLs( xDescripts ); + } + return uno::Sequence<uno::Reference<frame::XDispatch > > (); +} + +//----------------------------------------------------------------- +// 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 ) ); + + if(aCommand.equals("Paste")) + this->executeDispatch_Paste(); + else if(aCommand.equals("Copy")) + this->executeDispatch_Copy(); + else if(aCommand.equals("Cut")) + this->executeDispatch_Cut(); + else if(aCommand.equals("DataRanges")) + this->executeDispatch_SourceData(); + //---------------------------------- + else if(aCommand.equals("Update")) //Update Chart + { + ChartViewHelper::setViewToDirtyState( getModel() ); + if( m_pChartWindow ) + m_pChartWindow->Invalidate(); + } + else if(aCommand.equals("DiagramData")) + this->executeDispatch_EditData(); + //insert objects + else if( aCommand.equals("InsertTitles") + || aCommand.equals("InsertMenuTitles") ) + this->executeDispatch_InsertTitles(); + else if( aCommand.equals("InsertMenuLegend") ) + this->executeDispatch_OpenLegendDialog(); + else if( aCommand.equals("InsertLegend") ) + this->executeDispatch_InsertLegend(); + else if( aCommand.equals("DeleteLegend") ) + this->executeDispatch_DeleteLegend(); + else if( aCommand.equals("InsertMenuDataLabels")) + this->executeDispatch_InsertMenu_DataLabels(); + else if( aCommand.equals("InsertMenuAxes") + || aCommand.equals("InsertRemoveAxes") ) + this->executeDispatch_InsertAxes(); + else if( aCommand.equals("InsertMenuGrids")) + this->executeDispatch_InsertGrid(); + else if( aCommand.equals("InsertMenuTrendlines")) + this->executeDispatch_InsertMenu_Trendlines(); + else if( aCommand.equals("InsertMenuMeanValues")) + this->executeDispatch_InsertMenu_MeanValues(); + else if( aCommand.equals("InsertMenuYErrorBars")) + this->executeDispatch_InsertMenu_YErrorBars(); + else if( aCommand.equals("InsertSymbol")) + this->executeDispatch_InsertSpecialCharacter(); + else if( aCommand.equals("InsertTrendline")) + this->executeDispatch_InsertTrendline(); + else if( aCommand.equals("DeleteTrendline")) + this->executeDispatch_DeleteTrendline(); + else if( aCommand.equals("InsertMeanValue")) + this->executeDispatch_InsertMeanValue(); + else if( aCommand.equals("DeleteMeanValue")) + this->executeDispatch_DeleteMeanValue(); + else if( aCommand.equals("InsertYErrorBars")) + this->executeDispatch_InsertYErrorBars(); + else if( aCommand.equals("DeleteYErrorBars")) + this->executeDispatch_DeleteYErrorBars(); + else if( aCommand.equals("InsertTrendlineEquation")) + this->executeDispatch_InsertTrendlineEquation(); + else if( aCommand.equals("DeleteTrendlineEquation")) + this->executeDispatch_DeleteTrendlineEquation(); + else if( aCommand.equals("InsertTrendlineEquationAndR2")) + this->executeDispatch_InsertTrendlineEquation( true ); + else if( aCommand.equals("InsertR2Value")) + this->executeDispatch_InsertR2Value(); + else if( aCommand.equals("DeleteR2Value")) + this->executeDispatch_DeleteR2Value(); + else if( aCommand.equals("InsertDataLabels") ) + this->executeDispatch_InsertDataLabels(); + else if( aCommand.equals("InsertDataLabel") ) + this->executeDispatch_InsertDataLabel(); + else if( aCommand.equals("DeleteDataLabels") ) + this->executeDispatch_DeleteDataLabels(); + else if( aCommand.equals("DeleteDataLabel") ) + this->executeDispatch_DeleteDataLabel(); + else if( aCommand.equals("ResetAllDataPoints") ) + this->executeDispatch_ResetAllDataPoints(); + else if( aCommand.equals("ResetDataPoint") ) + this->executeDispatch_ResetDataPoint(); + else if( aCommand.equals("InsertAxis") ) + this->executeDispatch_InsertAxis(); + else if( aCommand.equals("InsertMajorGrid") ) + this->executeDispatch_InsertMajorGrid(); + else if( aCommand.equals("InsertMinorGrid") ) + this->executeDispatch_InsertMinorGrid(); + else if( aCommand.equals("InsertAxisTitle") ) + this->executeDispatch_InsertAxisTitle(); + else if( aCommand.equals("DeleteAxis") ) + this->executeDispatch_DeleteAxis(); + else if( aCommand.equals("DeleteMajorGrid") ) + this->executeDispatch_DeleteMajorGrid(); + else if( aCommand.equals("DeleteMinorGrid") ) + this->executeDispatch_DeleteMinorGrid(); + //format objects + else if( aCommand.equals("FormatSelection") ) + this->executeDispatch_ObjectProperties(); + else if( aCommand.equals("TransformDialog")) + { + if ( isShapeContext() ) + { + this->impl_ShapeControllerDispatch( rURL, rArgs ); + } + else + { + this->executeDispatch_PositionAndSize(); + } + } + else if( lcl_isFormatObjectCommand(aCommand) ) + this->executeDispatch_FormatObject(rURL.Path); + //more format +//MENUCHANGE else if(aCommand.equals("SelectSourceRanges")) +//MENUCHANGE this->executeDispatch_SourceData(); + else if( aCommand.equals("DiagramType")) + this->executeDispatch_ChartType(); + else if( aCommand.equals("View3D")) + this->executeDispatch_View3D(); + else if ( aCommand.equals( "Forward" ) ) + { + if ( isShapeContext() ) + { + this->impl_ShapeControllerDispatch( rURL, rArgs ); + } + else + { + this->executeDispatch_MoveSeries( sal_True ); + } + } + else if ( aCommand.equals( "Backward" ) ) + { + if ( isShapeContext() ) + { + this->impl_ShapeControllerDispatch( rURL, rArgs ); + } + else + { + this->executeDispatch_MoveSeries( sal_False ); + } + } + else if( aCommand.equals("NewArrangement")) + this->executeDispatch_NewArrangement(); + else if( aCommand.equals("ToggleLegend")) + this->executeDispatch_ToggleLegend(); + else if( aCommand.equals("ToggleGridHorizontal")) + this->executeDispatch_ToggleGridHorizontal(); + else if( aCommand.equals("ScaleText")) + this->executeDispatch_ScaleText(); + else if( aCommand.equals("StatusBarVisible")) + { + // workaround: this should not be necessary. + uno::Reference< beans::XPropertySet > xPropSet( m_xFrame, uno::UNO_QUERY ); + if( xPropSet.is() ) + { + uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager; + xPropSet->getPropertyValue( C2U( "LayoutManager" ) ) >>= xLayoutManager; + if ( xLayoutManager.is() ) + { + bool bIsVisible( xLayoutManager->isElementVisible( C2U("private:resource/statusbar/statusbar"))); + if( bIsVisible ) + { + xLayoutManager->hideElement( C2U( "private:resource/statusbar/statusbar")); + xLayoutManager->destroyElement( C2U( "private:resource/statusbar/statusbar")); + } + else + { + xLayoutManager->createElement( C2U( "private:resource/statusbar/statusbar")); + xLayoutManager->showElement( C2U( "private:resource/statusbar/statusbar")); + } + // @todo: update menu state (checkmark next to "Statusbar"). + } + } + } + + /* + case SID_TEXTEDIT: + this->executeDispatch_EditText(); + */ +} + + void SAL_CALL ChartController +::addStatusListener( const uno::Reference<frame::XStatusListener >& /* xControl */ + , const util::URL& /* aURL */ ) + throw (uno::RuntimeException) +{ +// // TODO: add listener by URL ! +// ::vos::OGuard aGuard( Application::GetSolarMutex()); +// 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( & xControl ), xControl ); +} + + void SAL_CALL ChartController +::removeStatusListener( const uno::Reference<frame::XStatusListener >& /* xControl */ + , const util::URL& /* aURL */ ) + throw (uno::RuntimeException) +{ +// // TODO: remove listener by URL ! +// ::vos::OGuard aGuard( Application::GetSolarMutex()); +// if( m_aLifeTimeManager.impl_isDisposed() ) +// return; //behave passive if already disposed or suspended + +// //--remove listener +// m_aLifeTimeManager.m_aListenerContainer.removeInterface( ::getCppuType( & xControl ), xControl ); +} + +//----------------------------------------------------------------- +// 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 +} + +// ____ XEmbeddedClient ____ +// implementation see: ChartController_EditData.cxx + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +void SAL_CALL ChartController::executeDispatch_ChartType() +{ + // using assignment for broken gcc 3.3 + UndoLiveUpdateGuard aUndoGuard = UndoLiveUpdateGuard( + ::rtl::OUString( String( SchResId( STR_ACTION_EDIT_CHARTTYPE ))), m_xUndoManager, getModel() ); + + // /-- + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + //prepare and open dialog + ChartTypeDialog aDlg( m_pChartWindow, getModel(), m_xCC ); + if( aDlg.Execute() == RET_OK ) + { + impl_adaptDataSeriesAutoResize(); + aUndoGuard.commitAction(); + } + // \-- +} + +void SAL_CALL ChartController::executeDispatch_SourceData() +{ + //------------------------------------------------------------- + //convert properties to ItemSet + uno::Reference< XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY ); + DBG_ASSERT( xChartDoc.is(), "Invalid XChartDocument" ); + if( !xChartDoc.is()) + return; + + // using assignment for broken gcc 3.3 + UndoLiveUpdateGuard aUndoGuard = UndoLiveUpdateGuard( + ::rtl::OUString( String( SchResId( STR_ACTION_EDIT_DATA_RANGES ))), m_xUndoManager, getModel() ); + if( xChartDoc.is()) + { + // /-- + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + ::chart::DataSourceDialog aDlg( m_pChartWindow, xChartDoc, m_xCC ); + if( aDlg.Execute() == RET_OK ) + { + impl_adaptDataSeriesAutoResize(); + aUndoGuard.commitAction(); + } + // \-- + } +} + +void SAL_CALL ChartController::executeDispatch_MoveSeries( sal_Bool bForward ) +{ + ControllerLockGuard aCLGuard( getModel() ); + + //get selected series + ::rtl::OUString aObjectCID(m_aSelection.getSelectedCID()); + uno::Reference< XDataSeries > xGivenDataSeries( ObjectIdentifier::getDataSeriesForCID( //yyy todo also legendentries and labels? + aObjectCID, getModel() ) ); + + UndoGuardWithSelection aUndoGuard( + ActionDescriptionProvider::createDescription( + (bForward ? ActionDescriptionProvider::MOVE_TOTOP : ActionDescriptionProvider::MOVE_TOBOTTOM), + ::rtl::OUString( String( SchResId( STR_OBJECT_DATASERIES )))), + m_xUndoManager, getModel()); + + bool bChanged = DiagramHelper::moveSeries( ChartModelHelper::findDiagram( getModel() ), xGivenDataSeries, bForward ); + if( bChanged ) + { + m_aSelection.setSelection( ObjectIdentifier::getMovedSeriesCID( aObjectCID, bForward ) ); + aUndoGuard.commitAction(); + } +} + +// ____ XMultiServiceFactory ____ +uno::Reference< uno::XInterface > SAL_CALL + ChartController::createInstance( const ::rtl::OUString& aServiceSpecifier ) + throw (uno::Exception, + uno::RuntimeException) +{ + uno::Reference< uno::XInterface > xResult; + + if( aServiceSpecifier.equals( CHART_ACCESSIBLE_TEXT_SERVICE_NAME )) + xResult.set( impl_createAccessibleTextContext()); + return xResult; +} + +uno::Reference< uno::XInterface > SAL_CALL + ChartController::createInstanceWithArguments( const ::rtl::OUString& ServiceSpecifier, + const uno::Sequence< uno::Any >& /* Arguments */ ) + throw (uno::Exception, + uno::RuntimeException) +{ + // ignore Arguments + return createInstance( ServiceSpecifier ); +} + +uno::Sequence< ::rtl::OUString > SAL_CALL + ChartController::getAvailableServiceNames() + throw (uno::RuntimeException) +{ + static uno::Sequence< ::rtl::OUString > aServiceNames; + + if( aServiceNames.getLength() == 0 ) + { + aServiceNames.realloc(1); + aServiceNames[0] = CHART_ACCESSIBLE_TEXT_SERVICE_NAME; + } + + return aServiceNames; +} + +// ____ XModifyListener ____ +void SAL_CALL ChartController::modified( const lang::EventObject& /* aEvent */ ) + throw (uno::RuntimeException) +{ + // the source can also be a subobject of the ChartModel + // @todo: change the source in ChartModel to always be the model itself ? +// if( getModel() == aEvent.Source ) + + + //todo? update menu states ? +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +IMPL_LINK( ChartController, NotifyUndoActionHdl, SdrUndoAction*, pUndoAction ) +{ + ::rtl::OUString aObjectCID = m_aSelection.getSelectedCID(); + if ( aObjectCID.getLength() == 0 ) + { + UndoManager* pUndoManager = UndoManager::getImplementation( m_xUndoManager ); + if ( pUndoManager ) + { + pUndoManager->addShapeUndoAction( pUndoAction ); + } + } + return 0L; +} + +DrawModelWrapper* ChartController::GetDrawModelWrapper() +{ + if( !m_pDrawModelWrapper.get() ) + { + ExplicitValueProvider* pProvider = ExplicitValueProvider::getExplicitValueProvider( m_xChartView ); + if( pProvider ) + m_pDrawModelWrapper = pProvider->getDrawModelWrapper(); + if ( m_pDrawModelWrapper.get() ) + { + m_pDrawModelWrapper->getSdrModel().SetNotifyUndoActionHdl( LINK( this, ChartController, NotifyUndoActionHdl ) ); + } + } + return m_pDrawModelWrapper.get(); +} + +DrawViewWrapper* ChartController::GetDrawViewWrapper() +{ + if ( !m_pDrawViewWrapper ) + { + impl_createDrawViewController(); + } + return m_pDrawViewWrapper; +} + +uno::Reference< XAccessible > ChartController::CreateAccessible() +{ + uno::Reference< XAccessible > xResult = new AccessibleChartView( m_xCC, GetDrawViewWrapper() ); + impl_initializeAccessible( uno::Reference< lang::XInitialization >( xResult, uno::UNO_QUERY ) ); + return xResult; +} + +void ChartController::impl_invalidateAccessible() +{ + if( m_pChartWindow ) + { + Reference< lang::XInitialization > xInit( m_pChartWindow->GetAccessible(false), uno::UNO_QUERY ); + if(xInit.is()) + { + uno::Sequence< uno::Any > aArguments(3);//empty arguments -> invalid accessible + xInit->initialize(aArguments); + } + } +} +void ChartController::impl_initializeAccessible() +{ + if( m_pChartWindow ) + this->impl_initializeAccessible( Reference< lang::XInitialization >( m_pChartWindow->GetAccessible(false), uno::UNO_QUERY ) ); +} +void ChartController::impl_initializeAccessible( const uno::Reference< lang::XInitialization >& xInit ) +{ + if(xInit.is()) + { + uno::Sequence< uno::Any > aArguments(5); + uno::Reference<view::XSelectionSupplier> xSelectionSupplier(this); + aArguments[0]=uno::makeAny(xSelectionSupplier); + uno::Reference<frame::XModel> xModel(getModel()); + aArguments[1]=uno::makeAny(xModel); + aArguments[2]=uno::makeAny(m_xChartView); + uno::Reference< XAccessible > xParent; + if( m_pChartWindow ) + { + Window* pParentWin( m_pChartWindow->GetAccessibleParentWindow()); + if( pParentWin ) + xParent.set( pParentWin->GetAccessible()); + } + aArguments[3]=uno::makeAny(xParent); + aArguments[4]=uno::makeAny(m_xViewWindow); + + xInit->initialize(aArguments); + } +} + +::std::set< ::rtl::OUString > ChartController::impl_getAvailableCommands() +{ + return ::comphelper::MakeSet< ::rtl::OUString > + // commands for container forward + ( C2U("AddDirect")) ( C2U("NewDoc")) ( C2U("Open")) + ( C2U("Save")) ( C2U("SaveAs")) ( C2U("SendMail")) + ( C2U("EditDoc")) ( C2U("ExportDirectToPDF")) ( C2U("PrintDefault")) + + // own commands + ( C2U("Cut") ) ( C2U("Copy") ) ( C2U("Paste") ) + ( C2U("DataRanges") ) ( C2U("DiagramData") ) + // insert objects + ( C2U("InsertMenuTitles") ) ( C2U("InsertTitles") ) + ( C2U("InsertMenuLegend") ) ( C2U("InsertLegend") ) ( C2U("DeleteLegend") ) + ( C2U("InsertMenuDataLabels") ) + ( C2U("InsertMenuAxes") ) ( C2U("InsertRemoveAxes") ) ( C2U("InsertMenuGrids") ) + ( C2U("InsertSymbol") ) + ( C2U("InsertTrendlineEquation") ) ( C2U("InsertTrendlineEquationAndR2") ) + ( C2U("InsertR2Value") ) ( C2U("DeleteR2Value") ) + ( C2U("InsertMenuTrendlines") ) ( C2U("InsertTrendline") ) + ( C2U("InsertMenuMeanValues") ) ( C2U("InsertMeanValue") ) + ( C2U("InsertMenuYErrorBars") ) ( C2U("InsertYErrorBars") ) + ( C2U("InsertDataLabels") ) ( C2U("InsertDataLabel") ) + ( C2U("DeleteTrendline") ) ( C2U("DeleteMeanValue") ) ( C2U("DeleteTrendlineEquation") ) + ( C2U("DeleteYErrorBars") ) + ( C2U("DeleteDataLabels") ) ( C2U("DeleteDataLabel") ) + //format objects +//MENUCHANGE ( C2U("SelectSourceRanges") ) + ( C2U("FormatSelection") ) ( C2U("TransformDialog") ) + ( C2U("DiagramType") ) ( C2U("View3D") ) + ( C2U("Forward") ) ( C2U("Backward") ) + ( C2U("MainTitle") ) ( C2U("SubTitle") ) + ( C2U("XTitle") ) ( C2U("YTitle") ) ( C2U("ZTitle") ) + ( C2U("SecondaryXTitle") ) ( C2U("SecondaryYTitle") ) + ( C2U("AllTitles") ) ( C2U("Legend") ) + ( C2U("DiagramAxisX") ) ( C2U("DiagramAxisY") ) ( C2U("DiagramAxisZ") ) + ( C2U("DiagramAxisA") ) ( C2U("DiagramAxisB") ) ( C2U("DiagramAxisAll") ) + ( C2U("DiagramGridXMain") ) ( C2U("DiagramGridYMain") ) ( C2U("DiagramGridZMain") ) + ( C2U("DiagramGridXHelp") ) ( C2U("DiagramGridYHelp") ) ( C2U("DiagramGridZHelp") ) + ( C2U("DiagramGridAll") ) + ( C2U("DiagramWall") ) ( C2U("DiagramFloor") ) ( C2U("DiagramArea") ) + + //context menu - format objects entries + ( C2U("FormatWall") ) ( C2U("FormatFloor") ) ( C2U("FormatChartArea") ) + ( C2U("FormatLegend") ) + + ( C2U("FormatAxis") ) ( C2U("FormatTitle") ) + ( C2U("FormatDataSeries") ) ( C2U("FormatDataPoint") ) + ( C2U("ResetAllDataPoints") ) ( C2U("ResetDataPoint") ) + ( C2U("FormatDataLabels") ) ( C2U("FormatDataLabel") ) + ( C2U("FormatMeanValue") ) ( C2U("FormatTrendline") ) ( C2U("FormatTrendlineEquation") ) + ( C2U("FormatYErrorBars") ) + ( C2U("FormatStockLoss") ) ( C2U("FormatStockGain") ) + + ( C2U("FormatMajorGrid") ) ( C2U("InsertMajorGrid") ) ( C2U("DeleteMajorGrid") ) + ( C2U("FormatMinorGrid") ) ( C2U("InsertMinorGrid") ) ( C2U("DeleteMinorGrid") ) + ( C2U("InsertAxis") ) ( C2U("DeleteAxis") ) ( C2U("InsertAxisTitle") ) + + // toolbar commands + ( C2U("ToggleGridHorizontal"))( C2U("ToggleLegend") ) ( C2U("ScaleText") ) + ( C2U("NewArrangement") ) ( C2U("Update") ) + ( C2U("DefaultColors") ) ( C2U("BarWidth") ) ( C2U("NumberOfLines") ) + ( C2U("ArrangeRow") ) + ( C2U("StatusBarVisible") ) + ( C2U("ChartElementSelector") ) + ; +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/ChartController.hxx b/chart2/source/controller/main/ChartController.hxx new file mode 100644 index 000000000000..f2b64eb7a9c5 --- /dev/null +++ b/chart2/source/controller/main/ChartController.hxx @@ -0,0 +1,737 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _CHART_CONTROLLER_HXX +#define _CHART_CONTROLLER_HXX + +#include "LifeTime.hxx" +#include "ServiceMacros.hxx" +#include "CommandDispatchContainer.hxx" +#include "SelectionHelper.hxx" + +// header for enum SdrDragMode +#include <svx/svdtypes.hxx> +// header for class Timer +#include <vcl/timer.hxx> +// header for class MouseEvent +#include <vcl/event.hxx> + +#include <cppuhelper/implbase12.hxx> + +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/chart2/XUndoManager.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <com/sun/star/ui/XContextMenuInterception.hpp> +#include <com/sun/star/uno/XWeak.hpp> +#include <com/sun/star/util/XCloseListener.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/util/XModifyListener.hpp> +#include <com/sun/star/util/XModeChangeListener.hpp> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XLayoutManagerListener.hpp> +#include <com/sun/star/frame/XLayoutManagerEventBroadcaster.hpp> + +#include <memory> +#include <boost/shared_ptr.hpp> +#include <set> + + +class SdrModel; + +namespace svt +{ + class AcceleratorExecute; +} + +class DropTargetHelper; + +namespace com { namespace sun { namespace star { +namespace graphic { + class XGraphic; +} +}}} + + +//............................................................................. +namespace chart +{ +//............................................................................. + +enum ChartDrawMode { CHARTDRAW_INSERT, CHARTDRAW_SELECT }; + +class WindowController +{ +public: + virtual ~WindowController() {}; + + virtual void PrePaint()=0; + virtual void execute_Paint( const Rectangle& rRect )=0; + virtual void execute_MouseButtonDown( const MouseEvent& rMEvt )=0; + virtual void execute_MouseMove( const MouseEvent& rMEvt )=0; + virtual void execute_Tracking( const TrackingEvent& rTEvt )=0; + virtual void execute_MouseButtonUp( const MouseEvent& rMEvt )=0; + virtual void execute_Resize()=0; + virtual void execute_Activate()=0; + virtual void execute_Deactivate()=0; + virtual void execute_GetFocus()=0; + virtual void execute_LoseFocus()=0; + virtual void execute_Command( const CommandEvent& rCEvt )=0; + virtual bool execute_KeyInput( const KeyEvent& rKEvt )=0; + + /** get help text to be shown in a quick help + + @param aAtLogicPosition the position in logic coordinates (of the + window) of the mouse cursor to determine for + which object help is requested. + + @param bIsBalloonHelp determines whether to return the long text version + (balloon help) or the shorter one (quick help). + + @param rOutQuickHelpText is filled with the quick help text + + @param rOutEqualRect is filled with a rectangle that denotes the region + in which the quick help does not change. + + @return </TRUE>, if a quick help should be shown. + */ + virtual bool requestQuickHelp( + ::Point aAtLogicPosition, bool bIsBalloonHelp, + ::rtl::OUString & rOutQuickHelpText, ::com::sun::star::awt::Rectangle & rOutEqualRect ) = 0; + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible() = 0; +}; + +class ChartWindow; +class DrawModelWrapper; +class DrawViewWrapper; +class ViewElementListProvider; +class ReferenceSizeProvider; + +class ChartController : public ::cppu::WeakImplHelper12 < + ::com::sun::star::frame::XController //comprehends XComponent (required interface) + ,::com::sun::star::frame::XDispatchProvider //(required interface) + ,::com::sun::star::view::XSelectionSupplier //(optional interface) + ,::com::sun::star::ui::XContextMenuInterception //(optional interface) + ,::com::sun::star::util::XCloseListener //(needed for communication with XModel) + ,::com::sun::star::lang::XServiceInfo + // ,public ::com::sun::star::uno::XWeak // implemented by WeakImplHelper(optional interface) + // ,public ::com::sun::star::uno::XInterface // implemented by WeakImplHelper(optional interface) + // ,public ::com::sun::star::lang::XTypeProvider // implemented by WeakImplHelper + ,::com::sun::star::frame::XDispatch + ,::com::sun::star::awt::XWindow //this is the Window Controller part of this Controller, that will be given to a Frame via setComponent + ,::com::sun::star::lang::XMultiServiceFactory + ,::com::sun::star::util::XModifyListener + ,::com::sun::star::util::XModeChangeListener + ,::com::sun::star::frame::XLayoutManagerListener + > + , public WindowController +{ + friend class DrawCommandDispatch; + friend class ShapeController; + +public: + //no default constructor + ChartController(::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > const & xContext); + virtual ~ChartController(); + + //----------------------------------------------------------------- + // ::com::sun::star::lang::XServiceInfo + //----------------------------------------------------------------- + + APPHELPER_XSERVICEINFO_DECL() + APPHELPER_SERVICE_FACTORY_HELPER(ChartController) + + //----------------------------------------------------------------- + // ::com::sun::star::frame::XController (required interface) + //----------------------------------------------------------------- + virtual void SAL_CALL + attachFrame( const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XFrame > & xFrame ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + attachModel( const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > SAL_CALL + getFrame() throw (::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > SAL_CALL + getModel() throw (::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Any SAL_CALL + getViewData() throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + restoreViewData( const ::com::sun::star::uno::Any& rValue ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + suspend( sal_Bool bSuspend ) + throw (::com::sun::star::uno::RuntimeException); + + //----------------------------------------------------------------- + // ::com::sun::star::lang::XComponent (base of XController) + //----------------------------------------------------------------- + virtual void SAL_CALL + dispose() throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + addEventListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XEventListener > & xListener ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + removeEventListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XEventListener > & xListener ) + throw (::com::sun::star::uno::RuntimeException); + + //----------------------------------------------------------------- + // ::com::sun::star::frame::XDispatchProvider (required interface) + //----------------------------------------------------------------- + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XDispatch> SAL_CALL + queryDispatch( const ::com::sun::star::util::URL& rURL + , const rtl::OUString& rTargetFrameName + , sal_Int32 nSearchFlags) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XDispatch > > SAL_CALL + queryDispatches( const ::com::sun::star::uno::Sequence< + ::com::sun::star::frame::DispatchDescriptor > & xDescripts) + throw (::com::sun::star::uno::RuntimeException); + + //----------------------------------------------------------------- + // ::com::sun::star::view::XSelectionSupplier (optional interface) + //----------------------------------------------------------------- + virtual sal_Bool SAL_CALL + select( const ::com::sun::star::uno::Any& rSelection ) + throw ( com::sun::star::lang::IllegalArgumentException ); + + virtual ::com::sun::star::uno::Any SAL_CALL + getSelection() throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + addSelectionChangeListener( const ::com::sun::star::uno::Reference< + com::sun::star::view::XSelectionChangeListener > & xListener ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + removeSelectionChangeListener( const ::com::sun::star::uno::Reference< + com::sun::star::view::XSelectionChangeListener > & xListener ) + throw (::com::sun::star::uno::RuntimeException); + + //----------------------------------------------------------------- + // ::com::sun::star::ui::XContextMenuInterception (optional interface) + //----------------------------------------------------------------- + virtual void SAL_CALL + registerContextMenuInterceptor( const ::com::sun::star::uno::Reference< + ::com::sun::star::ui::XContextMenuInterceptor > & xInterceptor) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + releaseContextMenuInterceptor( const ::com::sun::star::uno::Reference< + ::com::sun::star::ui::XContextMenuInterceptor > & xInterceptor) + throw (::com::sun::star::uno::RuntimeException); + + + //----------------------------------------------------------------- + //----------------------------------------------------------------- + //additional interfaces + + //----------------------------------------------------------------- + // ::com::sun::star::util::XCloseListener + //----------------------------------------------------------------- + virtual void SAL_CALL + queryClosing( const ::com::sun::star::lang::EventObject& Source + , sal_Bool GetsOwnership ) + throw (::com::sun::star::util::CloseVetoException + , ::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + notifyClosing( const ::com::sun::star::lang::EventObject& Source ) + throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------- + // ::com::sun::star::util::XEventListener (base of XCloseListener and XModifyListener) + //------------------------------------------------------------------------------------- + virtual void SAL_CALL + disposing( const ::com::sun::star::lang::EventObject& Source ) + throw (::com::sun::star::uno::RuntimeException); + + //----------------------------------------------------------------- + // ::com::sun::star::frame::XDispatch + //----------------------------------------------------------------- + + virtual void SAL_CALL + dispatch( const ::com::sun::star::util::URL& aURL + , const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& aArgs ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + addStatusListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XStatusListener >& xControl + , const ::com::sun::star::util::URL& aURL ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + removeStatusListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XStatusListener >& xControl + , const ::com::sun::star::util::URL& aURL ) + throw (::com::sun::star::uno::RuntimeException); + + //----------------------------------------------------------------- + // ::com::sun::star::awt::XWindow + //----------------------------------------------------------------- + virtual void SAL_CALL + setPosSize( sal_Int32 X, sal_Int32 Y + , sal_Int32 Width, sal_Int32 Height, sal_Int16 Flags ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::awt::Rectangle SAL_CALL + getPosSize() + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + setVisible( sal_Bool Visible ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + setEnable( sal_Bool Enable ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + setFocus() throw (::com::sun::star::uno::RuntimeException); + + //---------------- + virtual void SAL_CALL + addWindowListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XWindowListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + removeWindowListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XWindowListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + addFocusListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XFocusListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + removeFocusListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XFocusListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + addKeyListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XKeyListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + removeKeyListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XKeyListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + addMouseListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XMouseListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + removeMouseListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XMouseListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + addMouseMotionListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XMouseMotionListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + removeMouseMotionListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XMouseMotionListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + addPaintListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XPaintListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + removePaintListener( const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XPaintListener >& xListener ) + throw (::com::sun::star::uno::RuntimeException); + + //----------------------------------------------------------------- + // ::com::sun::star::lang XMultiServiceFactory + //----------------------------------------------------------------- + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL + createInstance( const ::rtl::OUString& aServiceSpecifier ) + throw (::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL + createInstanceWithArguments( const ::rtl::OUString& ServiceSpecifier, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Any >& Arguments ) + throw (::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getAvailableServiceNames() + throw (::com::sun::star::uno::RuntimeException); + + //----------------------------------------------------------------- + // ::com::sun::star::util::XModifyListener + //----------------------------------------------------------------- + virtual void SAL_CALL modified( + const ::com::sun::star::lang::EventObject& aEvent ) + throw (::com::sun::star::uno::RuntimeException); + + //----------------------------------------------------------------- + // ::com::sun::star::util::XModeChangeListener + //----------------------------------------------------------------- + virtual void SAL_CALL modeChanged( + const ::com::sun::star::util::ModeChangeEvent& _rSource ) + throw (::com::sun::star::uno::RuntimeException); + + //----------------------------------------------------------------- + // ::com::sun::star::frame::XLayoutManagerListener + //----------------------------------------------------------------- + virtual void SAL_CALL layoutEvent( + const ::com::sun::star::lang::EventObject& aSource, + ::sal_Int16 eLayoutEvent, + const ::com::sun::star::uno::Any& aInfo ) + throw (::com::sun::star::uno::RuntimeException); + + //----------------------------------------------------------------- + // chart2::WindowController + //----------------------------------------------------------------- + virtual void PrePaint(); + virtual void execute_Paint( const Rectangle& rRect ); + virtual void execute_MouseButtonDown( const MouseEvent& rMEvt ); + virtual void execute_MouseMove( const MouseEvent& rMEvt ); + virtual void execute_Tracking( const TrackingEvent& rTEvt ); + virtual void execute_MouseButtonUp( const MouseEvent& rMEvt ); + virtual void execute_Resize(); + virtual void execute_Activate(); + virtual void execute_Deactivate(); + virtual void execute_GetFocus(); + virtual void execute_LoseFocus(); + virtual void execute_Command( const CommandEvent& rCEvt ); + virtual bool execute_KeyInput( const KeyEvent& rKEvt ); + + virtual bool requestQuickHelp( + ::Point aAtLogicPosition, bool bIsBalloonHelp, + ::rtl::OUString & rOutQuickHelpText, ::com::sun::star::awt::Rectangle & rOutEqualRect ); + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible(); + + //----------------------------------------------------------------- + //----------------------------------------------------------------- + + static bool isObjectDeleteable( const ::com::sun::star::uno::Any& rSelection ); + + void setDrawMode( ChartDrawMode eMode ) { m_eDrawMode = eMode; } + ChartDrawMode getDrawMode() const { return m_eDrawMode; } + + bool isShapeContext() const; + + DECL_LINK( NotifyUndoActionHdl, SdrUndoAction* ); + +public: + //----------------------------------------------------------------- + //----------------------------------------------------------------- + //----------------------------------------------------------------- + //----------------------------------------------------------------- + //private + //----------------------------------------------------------------- + //----------------------------------------------------------------- + //----------------------------------------------------------------- + //----------------------------------------------------------------- + + +private: + DrawModelWrapper* GetDrawModelWrapper(); + DrawViewWrapper* GetDrawViewWrapper(); + +private: + class TheModelRef; + friend class ChartController::TheModelRef; + class RefCountable + { + public: + RefCountable(); + virtual ~RefCountable(); + void acquire(); + void release(); + private: + sal_Int32 volatile m_nRefCount; + }; + class TheModel : public RefCountable + { + public: + TheModel( const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel ); + + virtual ~TheModel(); + + void SetOwnerShip( sal_Bool bGetsOwnership ); + void addListener( ChartController* pController ); + void removeListener( ChartController* pController ); + void tryTermination(); + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > + getModel() { return m_xModel;} + + private: + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > m_xModel; + ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloseable > m_xCloseable; + + //the ownership between model and controller is not clear at first + //each controller might consider himself as owner of the model first + sal_Bool volatile m_bOwnership; + //with a XCloseable::close call and during XCloseListener::queryClosing + //the ownership can be regulated more explicit, + //if so the ownership is considered to be well known + sal_Bool volatile m_bOwnershipIsWellKnown; + }; + class TheModelRef + { + public: + TheModelRef( TheModel* pTheModel, ::osl::Mutex& rMutex ); + TheModelRef( const TheModelRef& rTheModel, ::osl::Mutex& rMutex ); + TheModelRef& operator=(ChartController::TheModel* pTheModel); + TheModelRef& operator=(const TheModelRef& rTheModel); + virtual ~TheModelRef(); + sal_Bool is() const; + TheModel* operator->() const { return m_pTheModel; } + private: + TheModel* m_pTheModel; + mutable ::osl::Mutex& m_rModelMutex; + }; + +private: + mutable ::apphelper::LifeTimeManager m_aLifeTimeManager; + + mutable ::osl::Mutex m_aControllerMutex; + sal_Bool volatile m_bSuspended; + sal_Bool volatile m_bCanClose; + + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> m_xCC; + + //model + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > m_xFrame; + mutable ::osl::Mutex m_aModelMutex; + TheModelRef m_aModel; + + //view + ChartWindow* m_pChartWindow; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > m_xViewWindow; + ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XInterface > m_xChartView; + ::boost::shared_ptr< DrawModelWrapper > m_pDrawModelWrapper; + DrawViewWrapper* m_pDrawViewWrapper; + + Selection m_aSelection; + SdrDragMode m_eDragMode; + + Timer m_aDoubleClickTimer; + bool volatile m_bWaitingForDoubleClick; + bool volatile m_bWaitingForMouseUp; + + bool volatile m_bConnectingToView; + + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XUndoManager > m_xUndoManager; + /// needed for dispatching URLs in FeatureStateEvents + mutable ::com::sun::star::uno::Reference< ::com::sun::star::util::XURLTransformer > m_xURLTransformer; + + ::std::auto_ptr< ::svt::AcceleratorExecute > m_apAccelExecute; + + CommandDispatchContainer m_aDispatchContainer; + + ::std::auto_ptr< DropTargetHelper > m_apDropTargetHelper; + ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XLayoutManagerEventBroadcaster > + m_xLayoutManagerEventBroadcaster; + + ChartDrawMode m_eDrawMode; + +private: + //private methods + + sal_Bool impl_isDisposedOrSuspended() const; + ::std::auto_ptr< ReferenceSizeProvider > impl_createReferenceSizeProvider(); + void impl_adaptDataSeriesAutoResize(); + + void impl_createDrawViewController(); + void impl_deleteDrawViewController(); + + //executeDispatch methods + void SAL_CALL executeDispatch_ObjectProperties(); + void SAL_CALL executeDispatch_FormatObject( const ::rtl::OUString& rDispatchCommand ); + void SAL_CALL executeDlg_ObjectProperties( const ::rtl::OUString& rObjectCID ); + bool executeDlg_ObjectProperties_withoutUndoGuard( const ::rtl::OUString& rObjectCID, bool bOkClickOnUnchangedDialogSouldBeRatedAsSuccessAlso ); + + void SAL_CALL executeDispatch_ChartType(); + + void executeDispatch_InsertTitles(); + void executeDispatch_InsertLegend(); + void executeDispatch_DeleteLegend(); + void executeDispatch_OpenLegendDialog(); + void executeDispatch_InsertAxes(); + void executeDispatch_InsertGrid(); + + void executeDispatch_InsertMenu_DataLabels(); + void executeDispatch_InsertMenu_YErrorBars(); + void executeDispatch_InsertMenu_Trendlines(); + void executeDispatch_InsertMenu_MeanValues(); + + void executeDispatch_InsertMeanValue(); + void executeDispatch_InsertTrendline(); + void executeDispatch_InsertTrendlineEquation( bool bInsertR2=false ); + void executeDispatch_InsertYErrorBars(); + + void executeDispatch_InsertR2Value(); + void executeDispatch_DeleteR2Value(); + + void executeDispatch_DeleteMeanValue(); + void executeDispatch_DeleteTrendline(); + void executeDispatch_DeleteTrendlineEquation(); + void executeDispatch_DeleteYErrorBars(); + + void executeDispatch_InsertDataLabels(); + void executeDispatch_InsertDataLabel(); + void executeDispatch_DeleteDataLabels(); + void executeDispatch_DeleteDataLabel(); + + void executeDispatch_ResetAllDataPoints(); + void executeDispatch_ResetDataPoint(); + + void executeDispatch_InsertAxis(); + void executeDispatch_InsertAxisTitle(); + void executeDispatch_InsertMajorGrid(); + void executeDispatch_InsertMinorGrid(); + void executeDispatch_DeleteAxis(); + void executeDispatch_DeleteMajorGrid(); + void executeDispatch_DeleteMinorGrid(); + + void SAL_CALL executeDispatch_InsertSpecialCharacter(); + void SAL_CALL executeDispatch_EditText( const Point* pMousePixel = NULL ); + void SAL_CALL executeDispatch_SourceData(); + void SAL_CALL executeDispatch_MoveSeries( sal_Bool bForward ); + + void StartTextEdit( const Point* pMousePixel = NULL ); + bool EndTextEdit(); + + void SAL_CALL executeDispatch_View3D(); + void SAL_CALL executeDispatch_PositionAndSize(); + + void executeDispatch_EditData(); + + void executeDispatch_NewArrangement(); + void executeDispatch_ScaleText(); + + void executeDispatch_Paste(); + void executeDispatch_Copy(); + void executeDispatch_Cut(); + bool executeDispatch_Delete(); + void executeDispatch_ToggleLegend(); + void executeDispatch_ToggleGridHorizontal(); + + void impl_ShapeControllerDispatch( const ::com::sun::star::util::URL& rURL, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rArgs ); + + // + DECL_LINK( DoubleClickWaitingHdl, void* ); + void execute_DoubleClick( const Point* pMousePixel = NULL ); + void startDoubleClickWaiting(); + void stopDoubleClickWaiting(); + + void impl_selectObjectAndNotiy(); + void impl_notifySelectionChangeListeners(); + void impl_invalidateAccessible(); + void impl_initializeAccessible(); + void impl_initializeAccessible( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XInitialization >& xInit ); + + //sets the model member to null if it equals the parameter + //returns true if successful + bool impl_releaseThisModel( const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XInterface > & xModel ); + + enum eMoveOrResizeType + { + MOVE_OBJECT, + CENTERED_RESIZE_OBJECT + }; + /// @return </TRUE>, if resize/move was successful + bool impl_moveOrResizeObject( + const ::rtl::OUString & rCID, eMoveOrResizeType eType, double fAmountLogicX, double fAmountLogicY ); + bool impl_DragDataPoint( const ::rtl::OUString & rCID, double fOffset ); + + ::std::set< ::rtl::OUString > impl_getAvailableCommands(); + + /** Creates a helper accesibility class that must be initialized via XInitialization. For + parameters see + + The returned object should not be used directly. Instead a proxy object + should use this helper to retrieve its children and add them to its own + children. + */ + ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessibleContext > + impl_createAccessibleTextContext(); + + void impl_PasteGraphic( ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > & xGraphic, + const ::Point & aPosition ); + void impl_PasteShapes( SdrModel* pModel ); + void impl_PasteStringAsTextShape( const ::rtl::OUString& rString, const ::com::sun::star::awt::Point& rPosition ); + void impl_SetMousePointer( const MouseEvent & rEvent ); + + void impl_ClearSelection(); + + void impl_switchDiagramPositioningToExcludingPositioning(); +}; + +//............................................................................. +} // namespace chart +//............................................................................. + +#endif + diff --git a/chart2/source/controller/main/ChartController_EditData.cxx b/chart2/source/controller/main/ChartController_EditData.cxx new file mode 100644 index 000000000000..0248732a63a7 --- /dev/null +++ b/chart2/source/controller/main/ChartController_EditData.cxx @@ -0,0 +1,80 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" +#include "ChartController.hxx" +#include "macros.hxx" + +#include "dlg_DataEditor.hxx" +#include "DataSourceHelper.hxx" +#include "DiagramHelper.hxx" +#include "ControllerLockGuard.hxx" +#include "UndoGuard.hxx" +#include "ResId.hxx" +#include "Strings.hrc" + +// for RET_OK +#include <vcl/msgbox.hxx> +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> +#include <com/sun/star/chart2/XChartDocument.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +void ChartController::executeDispatch_EditData() +{ + Reference< chart2::XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY ); + if( xChartDoc.is()) + { + Window* pParent( NULL ); + + Reference< ::com::sun::star::chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider()); + + { + // /-- + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + // using assignment for broken gcc 3.3 + UndoLiveUpdateGuardWithData aUndoGuard = UndoLiveUpdateGuardWithData( + ::rtl::OUString( String( SchResId( STR_ACTION_EDIT_CHART_DATA ))), + m_xUndoManager, getModel() ); + DataEditor aDataEditorDialog( pParent, xChartDoc, m_xCC ); + // the dialog has no OK/Cancel + aDataEditorDialog.Execute(); + aUndoGuard.commitAction(); + // \-- + } + } +} + +} // namespace chart diff --git a/chart2/source/controller/main/ChartController_Insert.cxx b/chart2/source/controller/main/ChartController_Insert.cxx new file mode 100644 index 000000000000..0a7a4057ef9a --- /dev/null +++ b/chart2/source/controller/main/ChartController_Insert.cxx @@ -0,0 +1,946 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" +#include "ChartController.hxx" + +#include "dlg_InsertAxis_Grid.hxx" +#include "dlg_InsertDataLabel.hxx" +#include "dlg_InsertLegend.hxx" +#include "dlg_InsertTrendline.hxx" +#include "dlg_InsertErrorBars.hxx" +#include "dlg_InsertTitle.hxx" +#include "dlg_ObjectProperties.hxx" + +#include "ChartWindow.hxx" +#include "ChartModelHelper.hxx" +#include "AxisHelper.hxx" +#include "TitleHelper.hxx" +#include "DiagramHelper.hxx" +#include "macros.hxx" +#include "chartview/DrawModelWrapper.hxx" +#include "chartview/NumberFormatterWrapper.hxx" +#include "ViewElementListProvider.hxx" +#include "MultipleChartConverters.hxx" +#include "ControllerLockGuard.hxx" +#include "UndoGuard.hxx" +#include "ResId.hxx" +#include "Strings.hrc" +#include "ReferenceSizeProvider.hxx" +#include "ObjectIdentifier.hxx" +#include "RegressionCurveHelper.hxx" +#include "RegressionCurveItemConverter.hxx" +#include "StatisticsHelper.hxx" +#include "ErrorBarItemConverter.hxx" +#include "MultipleItemConverter.hxx" +#include "DataSeriesHelper.hxx" +#include "ObjectNameProvider.hxx" +#include "LegendHelper.hxx" + +#include <com/sun/star/chart2/XRegressionCurve.hpp> +#include <com/sun/star/chart/ErrorBarStyle.hpp> +#include <svx/ActionDescriptionProvider.hxx> + +//-------------------------------------- + +// header for define RET_OK +#include <vcl/msgbox.hxx> +// header for class OUStringBuffer +#include <rtl/ustrbuf.hxx> +// header for class Application +#include <vcl/svapp.hxx> +// header for class ::vos::OGuard +#include <vos/mutex.hxx> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +//............................................................................. + +namespace +{ +struct lcl_InsertMeanValueLine +{ +public: + lcl_InsertMeanValueLine( const uno::Reference< uno::XComponentContext > & xContext ) : + m_xContext( xContext ) + {} + + void operator()( const uno::Reference< chart2::XDataSeries > & xSeries ) + { + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( + xSeries, uno::UNO_QUERY ); + if( xRegCurveCnt.is()) + { + ::chart::RegressionCurveHelper::addMeanValueLine( + xRegCurveCnt, m_xContext, uno::Reference< beans::XPropertySet >( xSeries, uno::UNO_QUERY )); + } + } + +private: + uno::Reference< uno::XComponentContext > m_xContext; +}; + +} // anonymous namespace + +//............................................................................. +namespace chart +{ +//............................................................................. + +void ChartController::executeDispatch_InsertAxes() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_AXES )))), + m_xUndoManager, getModel() ); + + try + { + InsertAxisOrGridDialogData aDialogInput; + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram(getModel()); + AxisHelper::getAxisOrGridExcistence( aDialogInput.aExistenceList, xDiagram, sal_True ); + AxisHelper::getAxisOrGridPossibilities( aDialogInput.aPossibilityList, xDiagram, sal_True ); + + ::vos::OGuard aGuard( Application::GetSolarMutex()); + SchAxisDlg aDlg( m_pChartWindow, aDialogInput ); + if( aDlg.Execute() == RET_OK ) + { + // lock controllers till end of block + ControllerLockGuard aCLGuard( getModel() ); + + InsertAxisOrGridDialogData aDialogOutput; + aDlg.getResult( aDialogOutput ); + ::std::auto_ptr< ReferenceSizeProvider > mpRefSizeProvider( + impl_createReferenceSizeProvider()); + bool bChanged = AxisHelper::changeVisibilityOfAxes( xDiagram + , aDialogInput.aExistenceList, aDialogOutput.aExistenceList, m_xCC + , mpRefSizeProvider.get() ); + if( bChanged ) + aUndoGuard.commitAction(); + } + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } +} + +void ChartController::executeDispatch_InsertGrid() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_GRIDS )))), + m_xUndoManager, getModel() ); + + try + { + InsertAxisOrGridDialogData aDialogInput; + uno::Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram(getModel()); + AxisHelper::getAxisOrGridExcistence( aDialogInput.aExistenceList, xDiagram, sal_False ); + AxisHelper::getAxisOrGridPossibilities( aDialogInput.aPossibilityList, xDiagram, sal_False ); + + ::vos::OGuard aGuard( Application::GetSolarMutex()); + SchGridDlg aDlg( m_pChartWindow, aDialogInput );//aItemSet, b3D, bNet, bSecondaryX, bSecondaryY ); + if( aDlg.Execute() == RET_OK ) + { + // lock controllers till end of block + ControllerLockGuard aCLGuard( getModel() ); + InsertAxisOrGridDialogData aDialogOutput; + aDlg.getResult( aDialogOutput ); + bool bChanged = AxisHelper::changeVisibilityOfGrids( xDiagram + , aDialogInput.aExistenceList, aDialogOutput.aExistenceList, m_xCC ); + if( bChanged ) + aUndoGuard.commitAction(); + } + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +void ChartController::executeDispatch_InsertTitles() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_TITLES )))), + m_xUndoManager, getModel() ); + + try + { + TitleDialogData aDialogInput; + aDialogInput.readFromModel( getModel() ); + + ::vos::OGuard aGuard( Application::GetSolarMutex()); + SchTitleDlg aDlg( m_pChartWindow, aDialogInput ); + if( aDlg.Execute() == RET_OK ) + { + // lock controllers till end of block + ControllerLockGuard aCLGuard( getModel() ); + TitleDialogData aDialogOutput( impl_createReferenceSizeProvider()); + aDlg.getResult( aDialogOutput ); + bool bChanged = aDialogOutput.writeDifferenceToModel( getModel(), m_xCC, &aDialogInput ); + if( bChanged ) + aUndoGuard.commitAction(); + } + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } +} + +void ChartController::executeDispatch_DeleteLegend() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( SchResId( STR_OBJECT_LEGEND )))), + m_xUndoManager, getModel() ); + + LegendHelper::hideLegend( getModel() ); + aUndoGuard.commitAction(); +} + +void ChartController::executeDispatch_InsertLegend() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_LEGEND )))), + m_xUndoManager, getModel() ); + + Reference< chart2::XLegend > xLegend = LegendHelper::showLegend( getModel(), m_xCC ); + aUndoGuard.commitAction(); +} + +void ChartController::executeDispatch_OpenLegendDialog() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_LEGEND )))), + m_xUndoManager, getModel() ); + + try + { + //prepare and open dialog + ::vos::OGuard aGuard( Application::GetSolarMutex()); + SchLegendDlg aDlg( m_pChartWindow, m_xCC ); + aDlg.init( getModel() ); + if( aDlg.Execute() == RET_OK ) + { + // lock controllers till end of block + ControllerLockGuard aCLGuard( getModel() ); + bool bChanged = aDlg.writeToModel( getModel() ); + if( bChanged ) + aUndoGuard.commitAction(); + } + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +void ChartController::executeDispatch_InsertMenu_DataLabels() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_DATALABELS )))), + m_xUndoManager, getModel() ); + + //if a series is selected insert labels for that series only: + uno::Reference< chart2::XDataSeries > xSeries( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel()), uno::UNO_QUERY ); + if( xSeries.is() ) + { + // add labels + DataSeriesHelper::insertDataLabelsToSeriesAndAllPoints( xSeries ); + + rtl::OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) ); + aChildParticle+=(C2U("=")); + rtl::OUString aObjectCID = ObjectIdentifier::createClassifiedIdentifierForParticles( + ObjectIdentifier::getSeriesParticleFromCID(m_aSelection.getSelectedCID()), aChildParticle ); + + bool bSuccess = ChartController::executeDlg_ObjectProperties_withoutUndoGuard( aObjectCID, true ); + if( bSuccess ) + aUndoGuard.commitAction(); + return; + } + + try + { + wrapper::AllDataLabelItemConverter aItemConverter( + getModel(), + m_pDrawModelWrapper->GetItemPool(), + m_pDrawModelWrapper->getSdrModel(), + uno::Reference< lang::XMultiServiceFactory >( getModel(), uno::UNO_QUERY )); + SfxItemSet aItemSet = aItemConverter.CreateEmptyItemSet(); + aItemConverter.FillItemSet( aItemSet ); + + //prepare and open dialog + ::vos::OGuard aGuard( Application::GetSolarMutex()); + + //get number formatter + uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( getModel(), uno::UNO_QUERY ); + NumberFormatterWrapper aNumberFormatterWrapper( xNumberFormatsSupplier ); + SvNumberFormatter* pNumberFormatter = aNumberFormatterWrapper.getSvNumberFormatter(); + + DataLabelsDialog aDlg( m_pChartWindow, aItemSet, pNumberFormatter); + + if( aDlg.Execute() == RET_OK ) + { + SfxItemSet aOutItemSet = aItemConverter.CreateEmptyItemSet(); + aDlg.FillItemSet( aOutItemSet ); + // lock controllers till end of block + ControllerLockGuard aCLGuard( getModel() ); + bool bChanged = aItemConverter.ApplyItemSet( aOutItemSet );//model should be changed now + if( bChanged ) + aUndoGuard.commitAction(); + } + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } +} + +void ChartController::executeDispatch_InsertMenu_YErrorBars() +{ + //if a series is selected insert error bars for that series only: + uno::Reference< chart2::XDataSeries > xSeries( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + if( xSeries.is()) + { + executeDispatch_InsertYErrorBars(); + return; + } + + //if no series is selected insert error bars for all series + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ObjectNameProvider::getName_ObjectForAllSeries( OBJECTTYPE_DATA_ERRORS ) ), + m_xUndoManager, getModel() ); + + try + { + wrapper::AllSeriesStatisticsConverter aItemConverter( + getModel(), m_pDrawModelWrapper->GetItemPool() ); + SfxItemSet aItemSet = aItemConverter.CreateEmptyItemSet(); + aItemConverter.FillItemSet( aItemSet ); + + //prepare and open dialog + ::vos::OGuard aGuard( Application::GetSolarMutex()); + InsertErrorBarsDialog aDlg( + m_pChartWindow, aItemSet, + uno::Reference< chart2::XChartDocument >( getModel(), uno::UNO_QUERY )); + aDlg.SetAxisMinorStepWidthForErrorBarDecimals( + InsertErrorBarsDialog::getAxisMinorStepWidthForErrorBarDecimals( getModel(), m_xChartView, rtl::OUString() ) ); + + if( aDlg.Execute() == RET_OK ) + { + SfxItemSet aOutItemSet = aItemConverter.CreateEmptyItemSet(); + aDlg.FillItemSet( aOutItemSet ); + + // lock controllers till end of block + ControllerLockGuard aCLGuard( getModel() ); + bool bChanged = aItemConverter.ApplyItemSet( aOutItemSet );//model should be changed now + if( bChanged ) + aUndoGuard.commitAction(); + } + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } +} + +void ChartController::executeDispatch_InsertMeanValue() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_AVERAGE_LINE )))), + m_xUndoManager, getModel() ); + lcl_InsertMeanValueLine( m_xCC ).operator()( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() )); + aUndoGuard.commitAction(); +} + +void ChartController::executeDispatch_InsertMenu_MeanValues() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_AVERAGE_LINE )))), + m_xUndoManager, getModel() ); + + uno::Reference< chart2::XDataSeries > xSeries( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + if( xSeries.is() ) + { + //if a series is selected insert mean value only for that series: + lcl_InsertMeanValueLine( m_xCC ).operator()(xSeries); + } + else + { + ::std::vector< uno::Reference< chart2::XDataSeries > > aSeries( + DiagramHelper::getDataSeriesFromDiagram( ChartModelHelper::findDiagram( getModel() ))); + ::std::for_each( aSeries.begin(), aSeries.end(), lcl_InsertMeanValueLine( m_xCC )); + } + aUndoGuard.commitAction(); +} + +void ChartController::executeDispatch_InsertMenu_Trendlines() +{ + //if a series is selected insert only for that series: + uno::Reference< chart2::XDataSeries > xSeries( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + if( xSeries.is()) + { + executeDispatch_InsertTrendline(); + return; + } + + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ObjectNameProvider::getName_ObjectForAllSeries( OBJECTTYPE_DATA_CURVE ) ), + m_xUndoManager, getModel() ); + + try + { + wrapper::AllSeriesStatisticsConverter aItemConverter( + getModel(), m_pDrawModelWrapper->GetItemPool() ); + SfxItemSet aItemSet = aItemConverter.CreateEmptyItemSet(); + aItemConverter.FillItemSet( aItemSet ); + + //prepare and open dialog + ::vos::OGuard aGuard( Application::GetSolarMutex()); + InsertTrendlineDialog aDlg( m_pChartWindow, aItemSet ); + aDlg.adjustSize(); + + if( aDlg.Execute() == RET_OK ) + { + SfxItemSet aOutItemSet = aItemConverter.CreateEmptyItemSet(); + aDlg.FillItemSet( aOutItemSet ); + + // lock controllers till end of block + ControllerLockGuard aCLGuard( getModel() ); + bool bChanged = aItemConverter.ApplyItemSet( aOutItemSet );//model should be changed now + if( bChanged ) + aUndoGuard.commitAction(); + } + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } +} + +void ChartController::executeDispatch_InsertTrendline() +{ + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel()), uno::UNO_QUERY ); + if( xRegCurveCnt.is()) + { + UndoLiveUpdateGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_CURVE )))), + m_xUndoManager, getModel() ); + + // add a linear curve + RegressionCurveHelper::addRegressionCurve( + RegressionCurveHelper::REGRESSION_TYPE_LINEAR, xRegCurveCnt, m_xCC ); + + // get an appropriate item converter + uno::Reference< chart2::XRegressionCurve > xCurve( + RegressionCurveHelper::getFirstCurveNotMeanValueLine( xRegCurveCnt )); + uno::Reference< beans::XPropertySet > xCurveProp( xCurve, uno::UNO_QUERY ); + if( !xCurveProp.is()) + return; + wrapper::RegressionCurveItemConverter aItemConverter( + xCurveProp, xRegCurveCnt, m_pDrawModelWrapper->getSdrModel().GetItemPool(), + m_pDrawModelWrapper->getSdrModel(), + uno::Reference< lang::XMultiServiceFactory >( getModel(), uno::UNO_QUERY )); + + // open dialog + SfxItemSet aItemSet = aItemConverter.CreateEmptyItemSet(); + aItemConverter.FillItemSet( aItemSet ); + ObjectPropertiesDialogParameter aDialogParameter = ObjectPropertiesDialogParameter( + ObjectIdentifier::createDataCurveCID( + ObjectIdentifier::getSeriesParticleFromCID( m_aSelection.getSelectedCID()), + RegressionCurveHelper::getRegressionCurveIndex( xRegCurveCnt, xCurve ), false )); + aDialogParameter.init( getModel() ); + ViewElementListProvider aViewElementListProvider( m_pDrawModelWrapper.get()); + ::vos::OGuard aGuard( Application::GetSolarMutex()); + SchAttribTabDlg aDlg( m_pChartWindow, &aItemSet, &aDialogParameter, &aViewElementListProvider, + uno::Reference< util::XNumberFormatsSupplier >( getModel(), uno::UNO_QUERY )); + + // note: when a user pressed "OK" but didn't change any settings in the + // dialog, the SfxTabDialog returns "Cancel" + if( aDlg.Execute() == RET_OK || aDlg.DialogWasClosedWithOK()) + { + const SfxItemSet* pOutItemSet = aDlg.GetOutputItemSet(); + if( pOutItemSet ) + { + ControllerLockGuard aCLGuard( getModel() ); + aItemConverter.ApplyItemSet( *pOutItemSet ); + } + aUndoGuard.commitAction(); + } + } +} + +void ChartController::executeDispatch_InsertYErrorBars() +{ + uno::Reference< chart2::XDataSeries > xSeries( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + if( xSeries.is()) + { + UndoLiveUpdateGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_ERROR_BARS )))), + m_xUndoManager, getModel() ); + + // add error bars with standard deviation + uno::Reference< beans::XPropertySet > xErrorBarProp( + StatisticsHelper::addErrorBars( xSeries, m_xCC, ::com::sun::star::chart::ErrorBarStyle::STANDARD_DEVIATION )); + + // get an appropriate item converter + wrapper::ErrorBarItemConverter aItemConverter( + getModel(), xErrorBarProp, m_pDrawModelWrapper->getSdrModel().GetItemPool(), + m_pDrawModelWrapper->getSdrModel(), + uno::Reference< lang::XMultiServiceFactory >( getModel(), uno::UNO_QUERY )); + + // open dialog + SfxItemSet aItemSet = aItemConverter.CreateEmptyItemSet(); + aItemConverter.FillItemSet( aItemSet ); + ObjectPropertiesDialogParameter aDialogParameter = ObjectPropertiesDialogParameter( + ObjectIdentifier::createClassifiedIdentifierWithParent( + OBJECTTYPE_DATA_ERRORS, ::rtl::OUString(), m_aSelection.getSelectedCID())); + aDialogParameter.init( getModel() ); + ViewElementListProvider aViewElementListProvider( m_pDrawModelWrapper.get()); + ::vos::OGuard aGuard( Application::GetSolarMutex()); + SchAttribTabDlg aDlg( m_pChartWindow, &aItemSet, &aDialogParameter, &aViewElementListProvider, + uno::Reference< util::XNumberFormatsSupplier >( getModel(), uno::UNO_QUERY )); + aDlg.SetAxisMinorStepWidthForErrorBarDecimals( + InsertErrorBarsDialog::getAxisMinorStepWidthForErrorBarDecimals( getModel(), m_xChartView, m_aSelection.getSelectedCID())); + + // note: when a user pressed "OK" but didn't change any settings in the + // dialog, the SfxTabDialog returns "Cancel" + if( aDlg.Execute() == RET_OK || aDlg.DialogWasClosedWithOK()) + { + const SfxItemSet* pOutItemSet = aDlg.GetOutputItemSet(); + if( pOutItemSet ) + { + ControllerLockGuard aCLGuard( getModel() ); + aItemConverter.ApplyItemSet( *pOutItemSet ); + } + aUndoGuard.commitAction(); + } + } +} + +void ChartController::executeDispatch_InsertTrendlineEquation( bool bInsertR2 ) +{ + uno::Reference< chart2::XRegressionCurve > xRegCurve( + ObjectIdentifier::getObjectPropertySet( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + if( !xRegCurve.is() ) + { + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + xRegCurve.set( RegressionCurveHelper::getFirstCurveNotMeanValueLine( xRegCurveCnt ) ); + } + if( xRegCurve.is()) + { + uno::Reference< beans::XPropertySet > xEqProp( xRegCurve->getEquationProperties()); + if( xEqProp.is()) + { + // using assignment for broken gcc 3.3 + UndoGuard aUndoGuard = UndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_CURVE_EQUATION )))), + m_xUndoManager, getModel() ); + xEqProp->setPropertyValue( C2U("ShowEquation"), uno::makeAny( true )); + xEqProp->setPropertyValue( C2U("ShowCorrelationCoefficient"), uno::makeAny( bInsertR2 )); + aUndoGuard.commitAction(); + } + } +} + +void ChartController::executeDispatch_InsertR2Value() +{ + uno::Reference< beans::XPropertySet > xEqProp( + ObjectIdentifier::getObjectPropertySet( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + if( xEqProp.is()) + { + UndoGuard aUndoGuard = UndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_CURVE_EQUATION )))), + m_xUndoManager, getModel() ); + xEqProp->setPropertyValue( C2U("ShowCorrelationCoefficient"), uno::makeAny( true )); + aUndoGuard.commitAction(); + } +} + +void ChartController::executeDispatch_DeleteR2Value() +{ + uno::Reference< beans::XPropertySet > xEqProp( + ObjectIdentifier::getObjectPropertySet( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + if( xEqProp.is()) + { + UndoGuard aUndoGuard = UndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_CURVE_EQUATION )))), + m_xUndoManager, getModel() ); + xEqProp->setPropertyValue( C2U("ShowCorrelationCoefficient"), uno::makeAny( false )); + aUndoGuard.commitAction(); + } +} + +void ChartController::executeDispatch_DeleteMeanValue() +{ + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + if( xRegCurveCnt.is()) + { + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( SchResId( STR_OBJECT_AVERAGE_LINE )))), + m_xUndoManager, getModel() ); + RegressionCurveHelper::removeMeanValueLine( xRegCurveCnt ); + aUndoGuard.commitAction(); + } +} + +void ChartController::executeDispatch_DeleteTrendline() +{ + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + if( xRegCurveCnt.is()) + { + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( SchResId( STR_OBJECT_CURVE )))), + m_xUndoManager, getModel() ); + RegressionCurveHelper::removeAllExceptMeanValueLine( xRegCurveCnt ); + aUndoGuard.commitAction(); + } +} + +void ChartController::executeDispatch_DeleteTrendlineEquation() +{ + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + if( xRegCurveCnt.is()) + { + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( SchResId( STR_OBJECT_CURVE_EQUATION )))), + m_xUndoManager, getModel() ); + RegressionCurveHelper::removeEquations( xRegCurveCnt ); + aUndoGuard.commitAction(); + } +} + +void ChartController::executeDispatch_DeleteYErrorBars() +{ + uno::Reference< chart2::XDataSeries > xDataSeries( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() )); + if( xDataSeries.is()) + { + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( SchResId( STR_OBJECT_CURVE )))), + m_xUndoManager, getModel() ); + StatisticsHelper::removeErrorBars( xDataSeries ); + aUndoGuard.commitAction(); + } +} + +void ChartController::executeDispatch_InsertDataLabels() +{ + uno::Reference< chart2::XDataSeries > xSeries( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + if( xSeries.is() ) + { + UndoGuard aUndoGuard = UndoGuard( ActionDescriptionProvider::createDescription( ActionDescriptionProvider::INSERT, + ::rtl::OUString( String( SchResId( STR_OBJECT_DATALABELS )))), + m_xUndoManager, getModel() ); + DataSeriesHelper::insertDataLabelsToSeriesAndAllPoints( xSeries ); + aUndoGuard.commitAction(); + } +} + +void ChartController::executeDispatch_InsertDataLabel() +{ + UndoGuard aUndoGuard = UndoGuard( ActionDescriptionProvider::createDescription( ActionDescriptionProvider::INSERT, + ::rtl::OUString( String( SchResId( STR_OBJECT_LABEL )))), + m_xUndoManager, getModel() ); + DataSeriesHelper::insertDataLabelToPoint( ObjectIdentifier::getObjectPropertySet( m_aSelection.getSelectedCID(), getModel() ) ); + aUndoGuard.commitAction(); +} + +void ChartController::executeDispatch_DeleteDataLabels() +{ + uno::Reference< chart2::XDataSeries > xSeries( + ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + if( xSeries.is() ) + { + UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( ActionDescriptionProvider::DELETE, + ::rtl::OUString( String( SchResId( STR_OBJECT_DATALABELS )))), + m_xUndoManager, getModel() ); + DataSeriesHelper::deleteDataLabelsFromSeriesAndAllPoints( xSeries ); + aUndoGuard.commitAction(); + } +} + +void ChartController::executeDispatch_DeleteDataLabel() +{ + UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( ActionDescriptionProvider::DELETE, + ::rtl::OUString( String( SchResId( STR_OBJECT_LABEL )))), + m_xUndoManager, getModel() ); + DataSeriesHelper::deleteDataLabelsFromPoint( ObjectIdentifier::getObjectPropertySet( m_aSelection.getSelectedCID(), getModel() ) ); + aUndoGuard.commitAction(); +} + +void ChartController::executeDispatch_ResetAllDataPoints() +{ + UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( ActionDescriptionProvider::FORMAT, + ::rtl::OUString( String( SchResId( STR_OBJECT_DATAPOINTS )))), + m_xUndoManager, getModel() ); + uno::Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + if( xSeries.is() ) + xSeries->resetAllDataPoints(); + aUndoGuard.commitAction(); +} +void ChartController::executeDispatch_ResetDataPoint() +{ + UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( ActionDescriptionProvider::FORMAT, + ::rtl::OUString( String( SchResId( STR_OBJECT_DATAPOINT )))), + m_xUndoManager, getModel() ); + uno::Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ), uno::UNO_QUERY ); + if( xSeries.is() ) + { + sal_Int32 nPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( m_aSelection.getSelectedCID() ); + xSeries->resetDataPoint( nPointIndex ); + } + aUndoGuard.commitAction(); +} + +void ChartController::executeDispatch_InsertAxisTitle() +{ + try + { + uno::Reference< XTitle > xTitle; + { + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_TITLE )))), + m_xUndoManager, getModel() ); + + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + sal_Int32 nDimensionIndex = -1; + sal_Int32 nCooSysIndex = -1; + sal_Int32 nAxisIndex = -1; + AxisHelper::getIndicesForAxis( xAxis, ChartModelHelper::findDiagram(getModel()), nCooSysIndex, nDimensionIndex, nAxisIndex ); + + TitleHelper::eTitleType eTitleType = TitleHelper::X_AXIS_TITLE; + if( nDimensionIndex==0 ) + eTitleType = nAxisIndex==0 ? TitleHelper::X_AXIS_TITLE : TitleHelper::SECONDARY_X_AXIS_TITLE; + else if( nDimensionIndex==1 ) + eTitleType = nAxisIndex==0 ? TitleHelper::Y_AXIS_TITLE : TitleHelper::SECONDARY_Y_AXIS_TITLE; + else + eTitleType = TitleHelper::Z_AXIS_TITLE; + + ::std::auto_ptr< ReferenceSizeProvider > apRefSizeProvider( impl_createReferenceSizeProvider()); + xTitle = TitleHelper::createTitle( eTitleType, ObjectNameProvider::getTitleNameByType(eTitleType), getModel(), m_xCC, apRefSizeProvider.get() ); + aUndoGuard.commitAction(); + } + + /* + if( xTitle.is() ) + { + OUString aTitleCID = ObjectIdentifier::createClassifiedIdentifierForObject( xTitle, getModel() ); + select( uno::makeAny(aTitleCID) ); + executeDispatch_EditText(); + } + */ + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } +} + +void ChartController::executeDispatch_InsertAxis() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_AXIS )))), + m_xUndoManager, getModel() ); + + try + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + if( xAxis.is() ) + { + AxisHelper::makeAxisVisible( xAxis ); + aUndoGuard.commitAction(); + } + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } +} + +void ChartController::executeDispatch_DeleteAxis() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( SchResId( STR_OBJECT_AXIS )))), + m_xUndoManager, getModel() ); + + try + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + if( xAxis.is() ) + { + AxisHelper::makeAxisInvisible( xAxis ); + aUndoGuard.commitAction(); + } + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } +} + +void ChartController::executeDispatch_InsertMajorGrid() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_GRID )))), + m_xUndoManager, getModel() ); + + try + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + if( xAxis.is() ) + { + AxisHelper::makeGridVisible( xAxis->getGridProperties() ); + aUndoGuard.commitAction(); + } + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } +} + +void ChartController::executeDispatch_DeleteMajorGrid() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( SchResId( STR_OBJECT_GRID )))), + m_xUndoManager, getModel() ); + + try + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + if( xAxis.is() ) + { + AxisHelper::makeGridInvisible( xAxis->getGridProperties() ); + aUndoGuard.commitAction(); + } + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } +} + +void ChartController::executeDispatch_InsertMinorGrid() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::INSERT, ::rtl::OUString( String( SchResId( STR_OBJECT_GRID )))), + m_xUndoManager, getModel() ); + + try + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + if( xAxis.is() ) + { + Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() ); + for( sal_Int32 nN=0; nN<aSubGrids.getLength(); nN++) + AxisHelper::makeGridVisible( aSubGrids[nN] ); + aUndoGuard.commitAction(); + } + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } +} + +void ChartController::executeDispatch_DeleteMinorGrid() +{ + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( SchResId( STR_OBJECT_GRID )))), + m_xUndoManager, getModel() ); + + try + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + if( xAxis.is() ) + { + Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() ); + for( sal_Int32 nN=0; nN<aSubGrids.getLength(); nN++) + AxisHelper::makeGridInvisible( aSubGrids[nN] ); + aUndoGuard.commitAction(); + } + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/ChartController_Position.cxx b/chart2/source/controller/main/ChartController_Position.cxx new file mode 100644 index 000000000000..619d308ffad2 --- /dev/null +++ b/chart2/source/controller/main/ChartController_Position.cxx @@ -0,0 +1,191 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" +#include "ChartController.hxx" + +#include "macros.hxx" +#include "ChartWindow.hxx" +#include "DrawViewWrapper.hxx" +#include "PositionAndSizeHelper.hxx" +#include "ChartModelHelper.hxx" +#include "UndoGuard.hxx" +#include "Strings.hrc" +#include "ObjectNameProvider.hxx" +#include "chartview/ExplicitValueProvider.hxx" +#include "CommonConverters.hxx" +#include <svx/ActionDescriptionProvider.hxx> + +// header for define RET_OK +#include <vcl/msgbox.hxx> +#include <svx/svxids.hrc> +#include <svx/rectenum.hxx> +#include <svl/aeitem.hxx> +#include <svx/svxdlg.hxx> +#include <svx/dialogs.hrc> +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +void lcl_getPositionAndSizeFromItemSet( const SfxItemSet& rItemSet, Rectangle& rPosAndSize, const awt::Size aOriginalSize ) +{ + long nPosX(0); + long nPosY(0); + long nSizX(0); + long nSizY(0); + + RECT_POINT eRP = (RECT_POINT)RP_LT; + + const SfxPoolItem* pPoolItem=NULL; + //read position + if (SFX_ITEM_SET==rItemSet.GetItemState(SID_ATTR_TRANSFORM_POS_X,TRUE,&pPoolItem)) + nPosX=((const SfxInt32Item*)pPoolItem)->GetValue(); + if (SFX_ITEM_SET==rItemSet.GetItemState(SID_ATTR_TRANSFORM_POS_Y,TRUE,&pPoolItem)) + nPosY=((const SfxInt32Item*)pPoolItem)->GetValue(); + //read size + if (SFX_ITEM_SET==rItemSet.GetItemState(SID_ATTR_TRANSFORM_WIDTH,TRUE,&pPoolItem)) + nSizX=((const SfxUInt32Item*)pPoolItem)->GetValue(); + if (SFX_ITEM_SET==rItemSet.GetItemState(SID_ATTR_TRANSFORM_HEIGHT,TRUE,&pPoolItem)) + nSizY=((const SfxUInt32Item*)pPoolItem)->GetValue(); + if (SFX_ITEM_SET==rItemSet.GetItemState(SID_ATTR_TRANSFORM_SIZE_POINT,TRUE,&pPoolItem)) + eRP=(RECT_POINT)((const SfxAllEnumItem*)pPoolItem)->GetValue(); + + switch( eRP ) + { + case RP_LT: + break; + case RP_MT: + nPosX += ( aOriginalSize.Width - nSizX ) / 2; + break; + case RP_RT: + nPosX += aOriginalSize.Width - nSizX; + break; + case RP_LM: + nPosY += ( aOriginalSize.Height - nSizY ) / 2; + break; + case RP_MM: + nPosX += ( aOriginalSize.Width - nSizX ) / 2; + nPosY += ( aOriginalSize.Height - nSizY ) / 2; + break; + case RP_RM: + nPosX += aOriginalSize.Width - nSizX; + nPosY += ( aOriginalSize.Height - nSizY ) / 2; + break; + case RP_LB: + nPosY += aOriginalSize.Height - nSizY; + break; + case RP_MB: + nPosX += ( aOriginalSize.Width - nSizX ) / 2; + nPosY += aOriginalSize.Height - nSizY; + break; + case RP_RB: + nPosX += aOriginalSize.Width - nSizX; + nPosY += aOriginalSize.Height - nSizY; + break; + default: + break; + } + + rPosAndSize = Rectangle(Point(nPosX,nPosY),Size(nSizX,nSizY)); +} + +void SAL_CALL ChartController::executeDispatch_PositionAndSize() +{ + const ::rtl::OUString aCID( m_aSelection.getSelectedCID() ); + + if( !aCID.getLength() ) + return; + + awt::Size aSelectedSize; + ExplicitValueProvider* pProvider( ExplicitValueProvider::getExplicitValueProvider( m_xChartView ) ); + if( pProvider ) + aSelectedSize = ToSize( ( pProvider->getRectangleOfObject( aCID ) ) ); + + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::POS_SIZE, + ObjectNameProvider::getName( ObjectIdentifier::getObjectType( aCID ))), + m_xUndoManager, getModel() ); + + SfxAbstractTabDialog * pDlg = NULL; + try + { + SfxItemSet aItemSet = m_pDrawViewWrapper->getPositionAndSizeItemSetFromMarkedObject(); + + //prepare and open dialog + SdrView* pSdrView = m_pDrawViewWrapper; + bool bResizePossible = m_aSelection.isResizeableObjectSelected(); + + ::vos::OGuard aGuard( Application::GetSolarMutex()); + SvxAbstractDialogFactory * pFact = SvxAbstractDialogFactory::Create(); + DBG_ASSERT( pFact, "No dialog factory" ); + pDlg = pFact->CreateSchTransformTabDialog( + m_pChartWindow, &aItemSet, pSdrView, RID_SCH_TransformTabDLG_SVXPAGE_ANGLE, bResizePossible ); + DBG_ASSERT( pDlg, "Couldn't create SchTransformTabDialog" ); + + + if( pDlg->Execute() == RET_OK ) + { + const SfxItemSet* pOutItemSet = pDlg->GetOutputItemSet(); + if(pOutItemSet) + { + Rectangle aObjectRect; + aItemSet.Put(*pOutItemSet);//overwrite old values with new values (-> all items are set) + lcl_getPositionAndSizeFromItemSet( aItemSet, aObjectRect, aSelectedSize ); + awt::Size aPageSize( ChartModelHelper::getPageSize( getModel() ) ); + Rectangle aPageRect( 0,0,aPageSize.Width,aPageSize.Height ); + + bool bChanged = PositionAndSizeHelper::moveObject( m_aSelection.getSelectedCID() + , getModel() + , awt::Rectangle(aObjectRect.getX(),aObjectRect.getY(),aObjectRect.getWidth(),aObjectRect.getHeight()) + , awt::Rectangle(aPageRect.getX(),aPageRect.getY(),aPageRect.getWidth(),aPageRect.getHeight()) ); + if( bChanged ) + aUndoGuard.commitAction(); + } + } + delete pDlg; + } + catch( uno::Exception& e) + { + delete pDlg; + ASSERT_EXCEPTION( e ); + } +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/ChartController_Properties.cxx b/chart2/source/controller/main/ChartController_Properties.cxx new file mode 100644 index 000000000000..649b9cb62f9d --- /dev/null +++ b/chart2/source/controller/main/ChartController_Properties.cxx @@ -0,0 +1,860 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" +#include "ChartController.hxx" +#include "ChartWindow.hxx" +#include "chartview/DrawModelWrapper.hxx" +#include "ObjectIdentifier.hxx" +#include "chartview/ExplicitValueProvider.hxx" +#include "macros.hxx" +#include "dlg_ObjectProperties.hxx" +#include "dlg_View3D.hxx" +#include "dlg_InsertErrorBars.hxx" +#include "ViewElementListProvider.hxx" +#include "DataPointItemConverter.hxx" +#include "AxisItemConverter.hxx" +#include "MultipleChartConverters.hxx" +#include "TitleItemConverter.hxx" +#include "LegendItemConverter.hxx" +#include "RegressionCurveItemConverter.hxx" +#include "RegressionEquationItemConverter.hxx" +#include "ErrorBarItemConverter.hxx" +#include "ChartModelHelper.hxx" +#include "AxisHelper.hxx" +#include "TitleHelper.hxx" +#include "LegendHelper.hxx" +#include "ChartTypeHelper.hxx" +#include "ColorPerPointHelper.hxx" +#include "DiagramHelper.hxx" +#include "servicenames_charttypes.hxx" +#include "ControllerLockGuard.hxx" +#include "UndoGuard.hxx" +#include "ObjectNameProvider.hxx" +#include "ResId.hxx" +#include "Strings.hrc" +#include "ReferenceSizeProvider.hxx" +#include "RegressionCurveHelper.hxx" +#include <com/sun/star/chart2/XChartDocument.hpp> + +//for auto_ptr +#include <memory> + +// header for define RET_OK +#include <vcl/msgbox.hxx> +// for SolarMutex +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> +#include <svx/ActionDescriptionProvider.hxx> + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using ::com::sun::star::uno::Reference; +using ::rtl::OUString; + +namespace +{ + +::comphelper::ItemConverter* createItemConverter( + const ::rtl::OUString & aObjectCID + , const uno::Reference< frame::XModel > & xChartModel + , const uno::Reference< uno::XComponentContext > & xContext + , SdrModel & rDrawModel + , NumberFormatterWrapper * pNumberFormatterWrapper = NULL + , ExplicitValueProvider * pExplicitValueProvider = NULL + , ::std::auto_ptr< ReferenceSizeProvider > pRefSizeProvider = + ::std::auto_ptr< ReferenceSizeProvider >() + ) +{ + ::comphelper::ItemConverter* pItemConverter=NULL; + + //------------------------------------------------------------- + //get type of selected object + ObjectType eObjectType = ObjectIdentifier::getObjectType( aObjectCID ); + if( OBJECTTYPE_UNKNOWN==eObjectType ) + { + DBG_ERROR("unknown ObjectType"); + return NULL; + } + //-- + rtl::OUString aParticleID = ObjectIdentifier::getParticleID( aObjectCID ); + bool bAffectsMultipleObjects = aParticleID.equals(C2U("ALLELEMENTS")); + //------------------------------------------------------------- + if( !bAffectsMultipleObjects ) + { + uno::Reference< beans::XPropertySet > xObjectProperties = + ObjectIdentifier::getObjectPropertySet( aObjectCID, xChartModel ); + if(!xObjectProperties.is()) + return NULL; + //create itemconverter for a single object + switch(eObjectType) + { + case OBJECTTYPE_PAGE: + pItemConverter = new wrapper::GraphicPropertyItemConverter( + xObjectProperties, rDrawModel.GetItemPool(), + rDrawModel, uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY ), + wrapper::GraphicPropertyItemConverter::LINE_AND_FILL_PROPERTIES ); + break; + case OBJECTTYPE_TITLE: + { + ::std::auto_ptr< awt::Size > pRefSize; + if( pRefSizeProvider.get() ) + pRefSize.reset( new awt::Size( pRefSizeProvider->getPageSize())); + + pItemConverter = new wrapper::TitleItemConverter( xObjectProperties, + rDrawModel.GetItemPool(), rDrawModel, + uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY ), + pRefSize ); + } + break; + case OBJECTTYPE_LEGEND: + { + ::std::auto_ptr< awt::Size > pRefSize; + if( pRefSizeProvider.get() ) + pRefSize.reset( new awt::Size( pRefSizeProvider->getPageSize())); + + pItemConverter = new wrapper::LegendItemConverter( xObjectProperties, + rDrawModel.GetItemPool(), rDrawModel, + uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY ), + pRefSize ); + } + break; + case OBJECTTYPE_LEGEND_ENTRY: + break; + case OBJECTTYPE_DIAGRAM: + break; + case OBJECTTYPE_DIAGRAM_WALL: + case OBJECTTYPE_DIAGRAM_FLOOR: + pItemConverter = new wrapper::GraphicPropertyItemConverter( + xObjectProperties, rDrawModel.GetItemPool(), + rDrawModel, uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY ), + wrapper::GraphicPropertyItemConverter::LINE_AND_FILL_PROPERTIES ); + break; + case OBJECTTYPE_AXIS: + { + ::std::auto_ptr< awt::Size > pRefSize; + if( pRefSizeProvider.get() ) + pRefSize.reset( new awt::Size( pRefSizeProvider->getPageSize())); + + uno::Reference< beans::XPropertySet > xDiaProp; + xDiaProp.set( ChartModelHelper::findDiagram( xChartModel ), uno::UNO_QUERY ); + + // the second property set contains the property CoordinateOrigin + // nOriginIndex is the index of the corresponding index of the + // origin (x=0, y=1, z=2) + + ExplicitScaleData aExplicitScale; + ExplicitIncrementData aExplicitIncrement; + if( pExplicitValueProvider ) + pExplicitValueProvider->getExplicitValuesForAxis( + uno::Reference< XAxis >( xObjectProperties, uno::UNO_QUERY ), + aExplicitScale, aExplicitIncrement ); + + pItemConverter = new wrapper::AxisItemConverter( + xObjectProperties, rDrawModel.GetItemPool(), + rDrawModel, + uno::Reference< chart2::XChartDocument >( xChartModel, uno::UNO_QUERY ), + &aExplicitScale, &aExplicitIncrement, + pRefSize ); + } + break; + case OBJECTTYPE_AXIS_UNITLABEL: + break; + case OBJECTTYPE_DATA_LABELS: + case OBJECTTYPE_DATA_SERIES: + case OBJECTTYPE_DATA_LABEL: + case OBJECTTYPE_DATA_POINT: + { + ::std::auto_ptr< awt::Size > pRefSize; + if( pRefSizeProvider.get() ) + pRefSize.reset( new awt::Size( pRefSizeProvider->getPageSize())); + + wrapper::GraphicPropertyItemConverter::eGraphicObjectType eMapTo = + wrapper::GraphicPropertyItemConverter::FILLED_DATA_POINT; + + uno::Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( aObjectCID, xChartModel ); + uno::Reference< XChartType > xChartType = ChartModelHelper::getChartTypeOfSeries( xChartModel, xSeries ); + + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + if( !ChartTypeHelper::isSupportingAreaProperties( xChartType, nDimensionCount ) ) + eMapTo = wrapper::GraphicPropertyItemConverter::LINE_DATA_POINT; + /* + FILLED_DATA_POINT, + LINE_DATA_POINT, + LINE_PROPERTIES, + FILL_PROPERTIES, + LINE_AND_FILL_PROPERTIES + */ + bool bDataSeries = ( eObjectType == OBJECTTYPE_DATA_SERIES || eObjectType == OBJECTTYPE_DATA_LABELS ); + + //special color for pie chart: + bool bUseSpecialFillColor = false; + sal_Int32 nSpecialFillColor =0; + sal_Int32 nPointIndex = -1; /*-1 for whole series*/ + if(!bDataSeries) + { + nPointIndex = aParticleID.toInt32(); + uno::Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY ); + bool bVaryColorsByPoint = false; + if( xSeriesProp.is() && + (xSeriesProp->getPropertyValue(C2U("VaryColorsByPoint")) >>= bVaryColorsByPoint) && + bVaryColorsByPoint ) + { + if( !ColorPerPointHelper::hasPointOwnColor( xSeriesProp, nPointIndex, xObjectProperties ) ) + { + bUseSpecialFillColor = true; + OSL_ASSERT( xDiagram.is()); + uno::Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme() ); + if( xColorScheme.is()) + nSpecialFillColor = xColorScheme->getColorByIndex( nPointIndex ); + } + } + } + sal_Int32 nNumberFormat=ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel( xObjectProperties, xSeries, nPointIndex, xDiagram ); + sal_Int32 nPercentNumberFormat=ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel( + xObjectProperties,uno::Reference< util::XNumberFormatsSupplier >(xChartModel, uno::UNO_QUERY)); + + pItemConverter = new wrapper::DataPointItemConverter( xChartModel, xContext, + xObjectProperties, xSeries, rDrawModel.GetItemPool(), rDrawModel, + pNumberFormatterWrapper, + uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY ), + eMapTo, pRefSize, bDataSeries, bUseSpecialFillColor, nSpecialFillColor, false, + nNumberFormat, nPercentNumberFormat ); + break; + } + case OBJECTTYPE_GRID: + case OBJECTTYPE_SUBGRID: + case OBJECTTYPE_DATA_AVERAGE_LINE: + pItemConverter = new wrapper::GraphicPropertyItemConverter( + xObjectProperties, rDrawModel.GetItemPool(), + rDrawModel, uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY ), + wrapper::GraphicPropertyItemConverter::LINE_PROPERTIES ); + break; + + case OBJECTTYPE_DATA_ERRORS: + pItemConverter = new wrapper::ErrorBarItemConverter( + xChartModel, xObjectProperties, rDrawModel.GetItemPool(), + rDrawModel, uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY )); + break; + + case OBJECTTYPE_DATA_CURVE: + pItemConverter = new wrapper::RegressionCurveItemConverter( + xObjectProperties, uno::Reference< chart2::XRegressionCurveContainer >( + ObjectIdentifier::getDataSeriesForCID( aObjectCID, xChartModel ), uno::UNO_QUERY ), + rDrawModel.GetItemPool(), rDrawModel, + uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY )); + break; + case OBJECTTYPE_DATA_CURVE_EQUATION: + { + ::std::auto_ptr< awt::Size > pRefSize; + if( pRefSizeProvider.get() ) + pRefSize.reset( new awt::Size( pRefSizeProvider->getPageSize())); + + pItemConverter = new wrapper::RegressionEquationItemConverter( + xObjectProperties, rDrawModel.GetItemPool(), rDrawModel, + uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY ), + pRefSize ); + break; + } + case OBJECTTYPE_DATA_ERRORS_X: + break; + case OBJECTTYPE_DATA_ERRORS_Y: + break; + case OBJECTTYPE_DATA_ERRORS_Z: + break; + case OBJECTTYPE_DATA_STOCK_RANGE: + break; + case OBJECTTYPE_DATA_STOCK_LOSS: + case OBJECTTYPE_DATA_STOCK_GAIN: + pItemConverter = new wrapper::GraphicPropertyItemConverter( + xObjectProperties, rDrawModel.GetItemPool(), + rDrawModel, uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY ), + wrapper::GraphicPropertyItemConverter::LINE_AND_FILL_PROPERTIES ); + break; + default: //OBJECTTYPE_UNKNOWN + break; + } + } + else + { + //create itemconverter for a all objects of given type + switch(eObjectType) + { + case OBJECTTYPE_TITLE: + pItemConverter = new wrapper::AllTitleItemConverter( xChartModel, rDrawModel.GetItemPool(), + rDrawModel, uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY )); + break; + case OBJECTTYPE_AXIS: + { + ::std::auto_ptr< awt::Size > pRefSize; + if( pRefSizeProvider.get() ) + pRefSize.reset( new awt::Size( pRefSizeProvider->getPageSize())); + + pItemConverter = new wrapper::AllAxisItemConverter( xChartModel, rDrawModel.GetItemPool(), + rDrawModel, uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY ), pRefSize ); + } + break; + case OBJECTTYPE_GRID: + case OBJECTTYPE_SUBGRID: + pItemConverter = new wrapper::AllGridItemConverter( xChartModel, rDrawModel.GetItemPool(), + rDrawModel, uno::Reference< lang::XMultiServiceFactory >( xChartModel, uno::UNO_QUERY )); + break; + default: //for this type it is not supported to change all elements at once + break; + } + + } + return pItemConverter; +} + +rtl::OUString lcl_getTitleCIDForCommand( const ::rtl::OString& rDispatchCommand, const uno::Reference< frame::XModel > & xChartModel ) +{ + if( rDispatchCommand.equals("AllTitles")) + return ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_TITLE, C2U("ALLELEMENTS") ); + + TitleHelper::eTitleType nTitleType( TitleHelper::MAIN_TITLE ); + if( rDispatchCommand.equals("SubTitle") ) + nTitleType = TitleHelper::SUB_TITLE; + else if( rDispatchCommand.equals("XTitle") ) + nTitleType = TitleHelper::X_AXIS_TITLE; + else if( rDispatchCommand.equals("YTitle") ) + nTitleType = TitleHelper::Y_AXIS_TITLE; + else if( rDispatchCommand.equals("ZTitle") ) + nTitleType = TitleHelper::Z_AXIS_TITLE; + else if( rDispatchCommand.equals("SecondaryXTitle") ) + nTitleType = TitleHelper::SECONDARY_X_AXIS_TITLE; + else if( rDispatchCommand.equals("SecondaryYTitle") ) + nTitleType = TitleHelper::SECONDARY_Y_AXIS_TITLE; + + uno::Reference< XTitle > xTitle( TitleHelper::getTitle( nTitleType, xChartModel ) ); + return ObjectIdentifier::createClassifiedIdentifierForObject( xTitle, xChartModel ); +} + +rtl::OUString lcl_getAxisCIDForCommand( const ::rtl::OString& rDispatchCommand, const uno::Reference< frame::XModel >& xChartModel ) +{ + if( rDispatchCommand.equals("DiagramAxisAll")) + return ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_AXIS, C2U("ALLELEMENTS") ); + + sal_Int32 nDimensionIndex=0; + bool bMainAxis=true; + if( rDispatchCommand.equals("DiagramAxisX")) + { + nDimensionIndex=0; bMainAxis=true; + } + else if( rDispatchCommand.equals("DiagramAxisY")) + { + nDimensionIndex=1; bMainAxis=true; + } + else if( rDispatchCommand.equals("DiagramAxisZ")) + { + nDimensionIndex=2; bMainAxis=true; + } + else if( rDispatchCommand.equals("DiagramAxisA")) + { + nDimensionIndex=0; bMainAxis=false; + } + else if( rDispatchCommand.equals("DiagramAxisB")) + { + nDimensionIndex=1; bMainAxis=false; + } + + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + uno::Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) ); + return ObjectIdentifier::createClassifiedIdentifierForObject( xAxis, xChartModel ); +} + +rtl::OUString lcl_getGridCIDForCommand( const ::rtl::OString& rDispatchCommand, const uno::Reference< frame::XModel >& xChartModel ) +{ + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); + + if( rDispatchCommand.equals("DiagramGridAll")) + return ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_GRID, C2U("ALLELEMENTS") ); + + sal_Int32 nDimensionIndex=0; + bool bMainGrid=true; + + //x and y is swapped in the commands + + if( rDispatchCommand.equals("DiagramGridYMain")) + { + nDimensionIndex=0; bMainGrid=true; + } + else if( rDispatchCommand.equals("DiagramGridXMain")) + { + nDimensionIndex=1; bMainGrid=true; + } + else if( rDispatchCommand.equals("DiagramGridZMain")) + { + nDimensionIndex=2; bMainGrid=true; + } + else if( rDispatchCommand.equals("DiagramGridYHelp")) + { + nDimensionIndex=0; bMainGrid=false; + } + else if( rDispatchCommand.equals("DiagramGridXHelp")) + { + nDimensionIndex=1; bMainGrid=false; + } + else if( rDispatchCommand.equals("DiagramGridZHelp")) + { + nDimensionIndex=2; bMainGrid=false; + } + + bool bMainAxis = true; + uno::Reference< XAxis > xAxis( AxisHelper::getAxis( nDimensionIndex, bMainAxis, xDiagram ) ); + + sal_Int32 nSubGridIndex= bMainGrid ? (-1) : 0; + rtl::OUString aCID( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel, nSubGridIndex ) ); + return aCID; +} +rtl::OUString lcl_getObjectCIDForCommand( const ::rtl::OString& rDispatchCommand, const uno::Reference< XChartDocument > & xChartDocument, const rtl::OUString& rSelectedCID ) +{ + ObjectType eObjectType = OBJECTTYPE_UNKNOWN; + rtl::OUString aParticleID; + + uno::Reference< frame::XModel > xChartModel( xChartDocument, uno::UNO_QUERY ); + const ObjectType eSelectedType = ObjectIdentifier::getObjectType( rSelectedCID ); + uno::Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( rSelectedCID, xChartModel ); + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( xSeries, uno::UNO_QUERY ); + + //------------------------------------------------------------------------- + //legend + if( rDispatchCommand.equals("Legend") || rDispatchCommand.equals("FormatLegend") ) + { + eObjectType = OBJECTTYPE_LEGEND; + //@todo set particular aParticleID if we have more than one legend + } + //------------------------------------------------------------------------- + //wall floor area + else if( rDispatchCommand.equals("DiagramWall") || rDispatchCommand.equals("FormatWall") ) + { + //OBJECTTYPE_DIAGRAM; + eObjectType = OBJECTTYPE_DIAGRAM_WALL; + //@todo set particular aParticleID if we have more than one diagram + } + else if( rDispatchCommand.equals("DiagramFloor") || rDispatchCommand.equals("FormatFloor") ) + { + eObjectType = OBJECTTYPE_DIAGRAM_FLOOR; + //@todo set particular aParticleID if we have more than one diagram + } + else if( rDispatchCommand.equals("DiagramArea") || rDispatchCommand.equals("FormatChartArea") ) + { + eObjectType = OBJECTTYPE_PAGE; + } + //------------------------------------------------------------------------- + //title + else if( rDispatchCommand.equals("MainTitle") + || rDispatchCommand.equals("SubTitle") + || rDispatchCommand.equals("XTitle") + || rDispatchCommand.equals("YTitle") + || rDispatchCommand.equals("ZTitle") + || rDispatchCommand.equals("SecondaryXTitle") + || rDispatchCommand.equals("SecondaryYTitle") + || rDispatchCommand.equals("AllTitles") + ) + { + return lcl_getTitleCIDForCommand( rDispatchCommand, xChartModel ); + } + //------------------------------------------------------------------------- + //axis + else if( rDispatchCommand.equals("DiagramAxisX") + || rDispatchCommand.equals("DiagramAxisY") + || rDispatchCommand.equals("DiagramAxisZ") + || rDispatchCommand.equals("DiagramAxisA") + || rDispatchCommand.equals("DiagramAxisB") + || rDispatchCommand.equals("DiagramAxisAll") + ) + { + return lcl_getAxisCIDForCommand( rDispatchCommand, xChartModel ); + } + //------------------------------------------------------------------------- + //grid + else if( rDispatchCommand.equals("DiagramGridYMain") + || rDispatchCommand.equals("DiagramGridXMain") + || rDispatchCommand.equals("DiagramGridZMain") + || rDispatchCommand.equals("DiagramGridYHelp") + || rDispatchCommand.equals("DiagramGridXHelp") + || rDispatchCommand.equals("DiagramGridZHelp") + || rDispatchCommand.equals("DiagramGridAll") + ) + { + return lcl_getGridCIDForCommand( rDispatchCommand, xChartModel ); + } + //------------------------------------------------------------------------- + //data series + else if( rDispatchCommand.equals("FormatDataSeries") ) + { + if( eSelectedType == OBJECTTYPE_DATA_SERIES ) + return rSelectedCID; + else + return ObjectIdentifier::createClassifiedIdentifier( + OBJECTTYPE_DATA_SERIES, ObjectIdentifier::getSeriesParticleFromCID( rSelectedCID ) ); + } + //------------------------------------------------------------------------- + //data point + else if( rDispatchCommand.equals("FormatDataPoint") ) + { + return rSelectedCID; + } + //------------------------------------------------------------------------- + //data labels + else if( rDispatchCommand.equals("FormatDataLabels") ) + { + if( eSelectedType == OBJECTTYPE_DATA_LABELS ) + return rSelectedCID; + else + return ObjectIdentifier::createClassifiedIdentifierWithParent( + OBJECTTYPE_DATA_LABELS, ::rtl::OUString(), rSelectedCID ); + } + //------------------------------------------------------------------------- + //data labels + else if( rDispatchCommand.equals("FormatDataLabel") ) + { + if( eSelectedType == OBJECTTYPE_DATA_LABEL ) + return rSelectedCID; + else + { + sal_Int32 nPointIndex = ObjectIdentifier::getParticleID( rSelectedCID ).toInt32(); + if( nPointIndex>=0 ) + { + OUString aSeriesParticle = ObjectIdentifier::getSeriesParticleFromCID( rSelectedCID ); + OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) ); + aChildParticle+=(C2U("=")); + OUString aLabelsCID = ObjectIdentifier::createClassifiedIdentifierForParticles( aSeriesParticle, aChildParticle ); + OUString aLabelCID_Stub = ObjectIdentifier::createClassifiedIdentifierWithParent( + OBJECTTYPE_DATA_LABEL, ::rtl::OUString(), aLabelsCID ); + + return ObjectIdentifier::createPointCID( aLabelCID_Stub, nPointIndex ); + } + } + } + //------------------------------------------------------------------------- + //mean value line + else if( rDispatchCommand.equals("FormatMeanValue") ) + { + if( eSelectedType == OBJECTTYPE_DATA_AVERAGE_LINE ) + return rSelectedCID; + else + return ObjectIdentifier::createDataCurveCID( + ObjectIdentifier::getSeriesParticleFromCID( rSelectedCID ), + RegressionCurveHelper::getRegressionCurveIndex( xRegCurveCnt, + RegressionCurveHelper::getMeanValueLine( xRegCurveCnt ) ), true ); + } + //------------------------------------------------------------------------- + //trend line + else if( rDispatchCommand.equals("FormatTrendline") ) + { + if( eSelectedType == OBJECTTYPE_DATA_CURVE ) + return rSelectedCID; + else + return ObjectIdentifier::createDataCurveCID( + ObjectIdentifier::getSeriesParticleFromCID( rSelectedCID ), + RegressionCurveHelper::getRegressionCurveIndex( xRegCurveCnt, + RegressionCurveHelper::getFirstCurveNotMeanValueLine( xRegCurveCnt ) ), false ); + } + //------------------------------------------------------------------------- + //trend line equation + else if( rDispatchCommand.equals("FormatTrendlineEquation") ) + { + if( eSelectedType == OBJECTTYPE_DATA_CURVE_EQUATION ) + return rSelectedCID; + else + return ObjectIdentifier::createDataCurveEquationCID( + ObjectIdentifier::getSeriesParticleFromCID( rSelectedCID ), + RegressionCurveHelper::getRegressionCurveIndex( xRegCurveCnt, + RegressionCurveHelper::getFirstCurveNotMeanValueLine( xRegCurveCnt ) ) ); + } + //------------------------------------------------------------------------- + // y error bars + else if( rDispatchCommand.equals("FormatYErrorBars") ) + { + if( eSelectedType == OBJECTTYPE_DATA_ERRORS ) + return rSelectedCID; + else + return ObjectIdentifier::createClassifiedIdentifierWithParent( + OBJECTTYPE_DATA_ERRORS, ::rtl::OUString(), rSelectedCID ); + } + //------------------------------------------------------------------------- + // axis + else if( rDispatchCommand.equals("FormatAxis") ) + { + if( eSelectedType == OBJECTTYPE_AXIS ) + return rSelectedCID; + else + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( rSelectedCID, xChartModel ); + return ObjectIdentifier::createClassifiedIdentifierForObject( xAxis , xChartModel ); + } + } + //------------------------------------------------------------------------- + // major grid + else if( rDispatchCommand.equals("FormatMajorGrid") ) + { + if( eSelectedType == OBJECTTYPE_GRID ) + return rSelectedCID; + else + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( rSelectedCID, xChartModel ); + return ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel ); + } + + } + //------------------------------------------------------------------------- + // minor grid + else if( rDispatchCommand.equals("FormatMinorGrid") ) + { + if( eSelectedType == OBJECTTYPE_SUBGRID ) + return rSelectedCID; + else + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( rSelectedCID, xChartModel ); + return ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel, 0 /*sub grid index*/ ); + } + } + //------------------------------------------------------------------------- + // title + else if( rDispatchCommand.equals("FormatTitle") ) + { + if( eSelectedType == OBJECTTYPE_TITLE ) + return rSelectedCID; + } + //------------------------------------------------------------------------- + // stock loss + else if( rDispatchCommand.equals("FormatStockLoss") ) + { + if( eSelectedType == OBJECTTYPE_DATA_STOCK_LOSS ) + return rSelectedCID; + else + return ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DATA_STOCK_LOSS, rtl::OUString()); + } + //------------------------------------------------------------------------- + // stock gain + else if( rDispatchCommand.equals("FormatStockGain") ) + { + if( eSelectedType == OBJECTTYPE_DATA_STOCK_GAIN ) + return rSelectedCID; + else + return ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DATA_STOCK_GAIN, rtl::OUString() ); + } + + return ObjectIdentifier::createClassifiedIdentifier( + eObjectType, aParticleID ); +} + +} +// anonymous namespace + +void SAL_CALL ChartController::executeDispatch_FormatObject(const ::rtl::OUString& rDispatchCommand) +{ + uno::Reference< XChartDocument > xChartDocument( getModel(), uno::UNO_QUERY ); + rtl::OString aCommand( rtl::OUStringToOString( rDispatchCommand, RTL_TEXTENCODING_ASCII_US ) ); + rtl::OUString rObjectCID = lcl_getObjectCIDForCommand( aCommand, xChartDocument, m_aSelection.getSelectedCID() ); + executeDlg_ObjectProperties( rObjectCID ); +} + +void SAL_CALL ChartController::executeDispatch_ObjectProperties() +{ + executeDlg_ObjectProperties( m_aSelection.getSelectedCID() ); +} + +namespace +{ + +rtl::OUString lcl_getFormatCIDforSelectedCID( const ::rtl::OUString& rSelectedCID ) +{ + ::rtl::OUString aFormatCID(rSelectedCID); + + //get type of selected object + ObjectType eObjectType = ObjectIdentifier::getObjectType( aFormatCID ); + + // some legend entries are handled as if they were data series + if( OBJECTTYPE_LEGEND_ENTRY==eObjectType ) + { + rtl::OUString aParentParticle( ObjectIdentifier::getFullParentParticle( rSelectedCID ) ); + aFormatCID = ObjectIdentifier::createClassifiedIdentifierForParticle( aParentParticle ); + } + + // treat diagram as wall + if( OBJECTTYPE_DIAGRAM==eObjectType ) + aFormatCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ); + + return aFormatCID; +} + +}//end anonymous namespace + +void SAL_CALL ChartController::executeDlg_ObjectProperties( const ::rtl::OUString& rSelectedObjectCID ) +{ + rtl::OUString aObjectCID = lcl_getFormatCIDforSelectedCID( rSelectedObjectCID ); + + UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::FORMAT, + ObjectNameProvider::getName( ObjectIdentifier::getObjectType( aObjectCID ))), + m_xUndoManager, getModel() ); + + bool bSuccess = ChartController::executeDlg_ObjectProperties_withoutUndoGuard( aObjectCID, false ); + if( bSuccess ) + aUndoGuard.commitAction(); +} + +bool ChartController::executeDlg_ObjectProperties_withoutUndoGuard( const ::rtl::OUString& rObjectCID, bool bOkClickOnUnchangedDialogSouldBeRatedAsSuccessAlso ) +{ + //return true if the properties were changed successfully + bool bRet = false; + if( !rObjectCID.getLength() ) + { + //DBG_ERROR("empty ObjectID"); + return bRet; + } + try + { + NumberFormatterWrapper aNumberFormatterWrapper( uno::Reference< util::XNumberFormatsSupplier >(getModel(), uno::UNO_QUERY) ); + + //------------------------------------------------------------- + //get type of object + ObjectType eObjectType = ObjectIdentifier::getObjectType( rObjectCID ); + if( OBJECTTYPE_UNKNOWN==eObjectType ) + { + //DBG_ERROR("unknown ObjectType"); + return bRet; + } + if( OBJECTTYPE_DIAGRAM_WALL==eObjectType || OBJECTTYPE_DIAGRAM_FLOOR==eObjectType ) + { + if( !DiagramHelper::isSupportingFloorAndWall( ChartModelHelper::findDiagram( getModel() ) ) ) + return bRet; + } + + //------------------------------------------------------------- + //convert properties to ItemSet + + awt::Size aPageSize( ChartModelHelper::getPageSize(getModel()) ); + + ::std::auto_ptr< ReferenceSizeProvider > pRefSizeProv( + impl_createReferenceSizeProvider()); + ::std::auto_ptr< ::comphelper::ItemConverter > apItemConverter( + createItemConverter( rObjectCID, getModel(), m_xCC, + m_pDrawModelWrapper->getSdrModel(), + &aNumberFormatterWrapper, + ExplicitValueProvider::getExplicitValueProvider(m_xChartView), + pRefSizeProv )); + if(!apItemConverter.get()) + return bRet; + + SfxItemSet aItemSet = apItemConverter->CreateEmptyItemSet(); + apItemConverter->FillItemSet( aItemSet ); + + //------------------------------------------------------------- + //prepare dialog + ObjectPropertiesDialogParameter aDialogParameter = ObjectPropertiesDialogParameter( rObjectCID ); + aDialogParameter.init( getModel() ); + ViewElementListProvider aViewElementListProvider( m_pDrawModelWrapper.get() ); + + ::vos::OGuard aGuard( Application::GetSolarMutex()); + SchAttribTabDlg aDlg( m_pChartWindow, &aItemSet, &aDialogParameter, &aViewElementListProvider + , uno::Reference< util::XNumberFormatsSupplier >( getModel(), uno::UNO_QUERY ) ); + + if(aDialogParameter.HasSymbolProperties()) + { + SfxItemSet* pSymbolShapeProperties=NULL; + uno::Reference< beans::XPropertySet > xObjectProperties = + ObjectIdentifier::getObjectPropertySet( rObjectCID, getModel() ); + wrapper::DataPointItemConverter aSymbolItemConverter( getModel(), m_xCC + , xObjectProperties, ObjectIdentifier::getDataSeriesForCID( rObjectCID, getModel() ) + , m_pDrawModelWrapper->getSdrModel().GetItemPool() + , m_pDrawModelWrapper->getSdrModel() + , &aNumberFormatterWrapper + , uno::Reference< lang::XMultiServiceFactory >( getModel(), uno::UNO_QUERY ) + , wrapper::GraphicPropertyItemConverter::FILLED_DATA_POINT ); + + pSymbolShapeProperties = new SfxItemSet( aSymbolItemConverter.CreateEmptyItemSet() ); + aSymbolItemConverter.FillItemSet( *pSymbolShapeProperties ); + + sal_Int32 nStandardSymbol=0;//@todo get from somewhere + Graphic* pAutoSymbolGraphic = new Graphic( aViewElementListProvider.GetSymbolGraphic( nStandardSymbol, pSymbolShapeProperties ) ); + // note: the dialog takes the ownership of pSymbolShapeProperties and pAutoSymbolGraphic + aDlg.setSymbolInformation( pSymbolShapeProperties, pAutoSymbolGraphic ); + } + if( aDialogParameter.HasStatisticProperties() ) + { + aDlg.SetAxisMinorStepWidthForErrorBarDecimals( + InsertErrorBarsDialog::getAxisMinorStepWidthForErrorBarDecimals( getModel(), m_xChartView, rObjectCID ) ); + } + + //------------------------------------------------------------- + //open the dialog + if( aDlg.Execute() == RET_OK || (bOkClickOnUnchangedDialogSouldBeRatedAsSuccessAlso && aDlg.DialogWasClosedWithOK()) ) + { + const SfxItemSet* pOutItemSet = aDlg.GetOutputItemSet(); + if(pOutItemSet) + { + ControllerLockGuard aCLGuard( getModel()); + apItemConverter->ApplyItemSet( *pOutItemSet );//model should be changed now + bRet = true; + } + } + } + catch( util::CloseVetoException& ) + { + } + catch( uno::RuntimeException& ) + { + } + return bRet; +} + +void SAL_CALL ChartController::executeDispatch_View3D() +{ + try + { + // using assignment for broken gcc 3.3 + UndoLiveUpdateGuard aUndoGuard = UndoLiveUpdateGuard( + ::rtl::OUString( String( SchResId( STR_ACTION_EDIT_3D_VIEW ))), + m_xUndoManager, getModel()); + + // /-- + //open dialog + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + View3DDialog aDlg( m_pChartWindow, getModel(), m_pDrawModelWrapper->GetColorTable() ); + if( aDlg.Execute() == RET_OK ) + aUndoGuard.commitAction(); + // \-- + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/ChartController_TextEdit.cxx b/chart2/source/controller/main/ChartController_TextEdit.cxx new file mode 100644 index 000000000000..a6e82430d8f6 --- /dev/null +++ b/chart2/source/controller/main/ChartController_TextEdit.cxx @@ -0,0 +1,271 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" +#include "ChartController.hxx" + +#include "DrawViewWrapper.hxx" +#include "ChartWindow.hxx" +#include "TitleHelper.hxx" +#include "ObjectIdentifier.hxx" +#include "macros.hxx" +#include "ControllerLockGuard.hxx" +#include "AccessibleTextHelper.hxx" +#include "chartview/DrawModelWrapper.hxx" + +#include <svx/svdotext.hxx> + +// header for define RET_OK +#include <vcl/msgbox.hxx> +// header for class SdrOutliner +#include <svx/svdoutl.hxx> +#include <svx/svxdlg.hxx> +#ifndef _SVX_DIALOGS_HRC +#include <svx/dialogs.hrc> +#endif +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <svl/stritem.hxx> +#include <editeng/fontitem.hxx> + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +//using namespace ::com::sun::star::chart2; + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +void SAL_CALL ChartController::executeDispatch_EditText( const Point* pMousePixel ) +{ + this->StartTextEdit( pMousePixel ); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +void ChartController::StartTextEdit( const Point* pMousePixel ) +{ + //the first marked object will be edited + + SdrObject* pTextObj = m_pDrawViewWrapper->getTextEditObject(); + if(!pTextObj) + return; + + m_xUndoManager->preAction( getModel()); + SdrOutliner* pOutliner = m_pDrawViewWrapper->getOutliner(); + //pOutliner->SetRefDevice(m_pChartWindow); + //pOutliner->SetStyleSheetPool((SfxStyleSheetPool*)pStyleSheetPool); + //pOutliner->SetDefaultLanguage( eLang ); + //pOutliner->SetHyphenator( xHyphenator ); + + //#i77362 change notification for changes on additional shapes are missing + uno::Reference< beans::XPropertySet > xChartViewProps( m_xChartView, uno::UNO_QUERY ); + if( xChartViewProps.is() ) + xChartViewProps->setPropertyValue( C2U("SdrViewIsInEditMode"), uno::makeAny(sal_True) ); + + sal_Bool bEdit = m_pDrawViewWrapper->SdrBeginTextEdit( pTextObj + , m_pDrawViewWrapper->GetPageView() + , m_pChartWindow + , sal_False //bIsNewObj + , pOutliner + , 0L //pOutlinerView + , sal_True //bDontDeleteOutliner + , sal_True //bOnlyOneView + ); + if(bEdit) + { + // set undo manager at topmost shell ( SdDrawTextObjectBar ) + /* + if( pViewSh ) + pViewSh->GetViewFrame()->GetDispatcher()->GetShell( 0 )-> + SetUndoManager(&pOutliner->GetUndoManager()); + */ + m_pDrawViewWrapper->SetEditMode(); + + // #i12587# support for shapes in chart + if ( pMousePixel ) + { + OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView(); + if ( pOutlinerView ) + { + MouseEvent aEditEvt( *pMousePixel, 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 ); + pOutlinerView->MouseButtonDown( aEditEvt ); + pOutlinerView->MouseButtonUp( aEditEvt ); + } + } + + //we invalidate the outliner region because the outliner has some + //paint problems (some characters are painted twice a little bit shifted) + m_pChartWindow->Invalidate( m_pDrawViewWrapper->GetMarkedObjBoundRect() ); + } +} + +bool ChartController::EndTextEdit() +{ + m_pDrawViewWrapper->SdrEndTextEdit(); + + //#i77362 change notification for changes on additional shapes are missing + uno::Reference< beans::XPropertySet > xChartViewProps( m_xChartView, uno::UNO_QUERY ); + if( xChartViewProps.is() ) + xChartViewProps->setPropertyValue( C2U("SdrViewIsInEditMode"), uno::makeAny(sal_False) ); + + SdrObject* pTextObject = m_pDrawViewWrapper->getTextEditObject(); + if(!pTextObject) + return false; + + SdrOutliner* pOutliner = m_pDrawViewWrapper->getOutliner(); + OutlinerParaObject* pParaObj = pTextObject->GetOutlinerParaObject(); + if( pParaObj && pOutliner ) + { + pOutliner->SetText( *pParaObj ); + + String aString = pOutliner->GetText( + pOutliner->GetParagraph( 0 ), + pOutliner->GetParagraphCount() ); + + ::rtl::OUString aObjectCID = m_aSelection.getSelectedCID(); + if ( aObjectCID.getLength() > 0 ) + { + uno::Reference< beans::XPropertySet > xPropSet = + ObjectIdentifier::getObjectPropertySet( aObjectCID, getModel() ); + + // lock controllers till end of block + ControllerLockGuard aCLGuard( getModel() ); + + TitleHelper::setCompleteString( aString, uno::Reference< + ::com::sun::star::chart2::XTitle >::query( xPropSet ), m_xCC ); + + try + { + m_xUndoManager->postAction( C2U("Edit Text") ); + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } + } + else + { + try + { + m_xUndoManager->cancelAction(); + } + catch ( uno::RuntimeException& e ) + { + ASSERT_EXCEPTION( e ); + } + } + } + return true; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +void SAL_CALL ChartController::executeDispatch_InsertSpecialCharacter() +{ + ::vos::OGuard aGuard( Application::GetSolarMutex()); + + if( m_pDrawViewWrapper && !m_pDrawViewWrapper->IsTextEdit() ) + this->StartTextEdit(); + + SvxAbstractDialogFactory * pFact = SvxAbstractDialogFactory::Create(); + DBG_ASSERT( pFact, "No dialog factory" ); + + SfxAllItemSet aSet( m_pDrawModelWrapper->GetItemPool() ); + aSet.Put( SfxBoolItem( FN_PARAM_1, FALSE ) ); + + //set fixed current font + aSet.Put( SfxBoolItem( FN_PARAM_2, TRUE ) ); //maybe not necessary in future + + Font aCurFont = m_pDrawViewWrapper->getOutliner()->GetRefDevice()->GetFont(); + aSet.Put( SvxFontItem( aCurFont.GetFamily(), aCurFont.GetName(), aCurFont.GetStyleName(), aCurFont.GetPitch(), aCurFont.GetCharSet(), SID_ATTR_CHAR_FONT ) ); + + SfxAbstractDialog * pDlg = pFact->CreateSfxDialog( m_pChartWindow, aSet, getFrame(), RID_SVXDLG_CHARMAP ); + DBG_ASSERT( pDlg, "Couldn't create SvxCharacterMap dialog" ); + if( pDlg->Execute() == RET_OK ) + { + const SfxItemSet* pSet = pDlg->GetOutputItemSet(); + const SfxPoolItem* pItem=0; + String aString; + if ( pSet && pSet->GetItemState( SID_CHARMAP, TRUE, &pItem) == SFX_ITEM_SET && + pItem->ISA(SfxStringItem) ) + aString = dynamic_cast<const SfxStringItem*>(pItem)->GetValue(); + + OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView(); + SdrOutliner* pOutliner = m_pDrawViewWrapper->getOutliner(); + + if(!pOutliner || !pOutlinerView) + return; + + // insert string to outliner + + // prevent flicker + pOutlinerView->HideCursor(); + pOutliner->SetUpdateMode(FALSE); + + // delete current selection by inserting empty String, so current + // attributes become unique (sel. has to be erased anyway) + pOutlinerView->InsertText(String()); + + //SfxUndoManager& rUndoMgr = pOutliner->GetUndoManager(); + //rUndoMgr.EnterListAction( String( SchResId( STR_UNDO_INSERT_SPECCHAR )), String( SchResId( STR_UNDO_INSERT_SPECCHAR ))); + pOutlinerView->InsertText(aString, TRUE); + + ESelection aSel = pOutlinerView->GetSelection(); + aSel.nStartPara = aSel.nEndPara; + aSel.nStartPos = aSel.nEndPos; + pOutlinerView->SetSelection(aSel); + + //rUndoMgr.LeaveListAction(); + + // show changes + pOutliner->SetUpdateMode(TRUE); + pOutlinerView->ShowCursor(); + } + + delete pDlg; +} + +uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > + ChartController::impl_createAccessibleTextContext() +{ + uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > xResult( + new AccessibleTextHelper( m_pDrawViewWrapper )); + + return xResult; +} + + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/ChartController_Tools.cxx b/chart2/source/controller/main/ChartController_Tools.cxx new file mode 100644 index 000000000000..779e3c32f1e7 --- /dev/null +++ b/chart2/source/controller/main/ChartController_Tools.cxx @@ -0,0 +1,919 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "ChartController.hxx" +#include "ChartWindow.hxx" +#include "ChartModelHelper.hxx" +#include "TitleHelper.hxx" +#include "ThreeDHelper.hxx" +#include "DataSeriesHelper.hxx" +#include "UndoGuard.hxx" +#include "ControllerLockGuard.hxx" +#include "macros.hxx" +#include "ResId.hxx" +#include "Strings.hrc" +#include "ObjectIdentifier.hxx" +#include "ReferenceSizeProvider.hxx" +#include "chartview/ExplicitValueProvider.hxx" +#include "chartview/DrawModelWrapper.hxx" +#include "ChartTransferable.hxx" +#include "DrawViewWrapper.hxx" +#include "LegendHelper.hxx" +#include "AxisHelper.hxx" +#include "RegressionCurveHelper.hxx" +#include "ShapeController.hxx" +#include "DiagramHelper.hxx" +#include "ObjectNameProvider.hxx" + +#include <com/sun/star/chart2/DataPointLabel.hpp> +#include <com/sun/star/beans/XPropertyState.hpp> +#include <com/sun/star/drawing/CameraGeometry.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/text/XTextRange.hpp> +#include <com/sun/star/drawing/TextVerticalAdjust.hpp> +#include <com/sun/star/drawing/TextHorizontalAdjust.hpp> +#include <com/sun/star/chart/ErrorBarStyle.hpp> + +#include <svx/ActionDescriptionProvider.hxx> +// for TransferableDataHelper/TransferableHelper +#include <svtools/transfer.hxx> +// for SotStorageStreamRef +#include <sot/storage.hxx> +// for Graphic +#include <vcl/graph.hxx> +// for SvxDrawingLayerImport/SvxUnoDrawingModel +#include <svx/unomodel.hxx> +// for SdrModel +#include <svx/svdmodel.hxx> +// for OInputStreamWrapper +#include <unotools/streamwrap.hxx> +// for SolarMutex +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> +#include <svx/dialmgr.hxx> +#include <svx/dialogs.hrc> +// for OutlinerView +#include <editeng/outliner.hxx> +#include <svx/svditer.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdundo.hxx> +#include <svx/unoapi.hxx> +#include <svx/unopage.hxx> + +#include <boost/scoped_ptr.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace +{ + +bool lcl_deleteDataSeries( + const OUString & rCID, + const Reference< frame::XModel > & xModel, + const Reference< chart2::XUndoManager > & xUndoManager ) +{ + bool bResult = false; + uno::Reference< chart2::XDataSeries > xSeries( ::chart::ObjectIdentifier::getDataSeriesForCID( rCID, xModel )); + uno::Reference< chart2::XChartDocument > xChartDoc( xModel, uno::UNO_QUERY ); + if( xSeries.is() && xChartDoc.is()) + { + uno::Reference< chart2::XChartType > xChartType( + ::chart::DataSeriesHelper::getChartTypeOfSeries( xSeries, xChartDoc->getFirstDiagram())); + if( xChartType.is()) + { + ::chart::UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( ::chart::SchResId( STR_OBJECT_DATASERIES )))), + xUndoManager, xModel ); + + Reference< chart2::XDiagram > xDiagram( ::chart::ChartModelHelper::findDiagram( xModel ) ); + uno::Reference< chart2::XAxis > xAxis( ::chart::DiagramHelper::getAttachedAxis( xSeries, xDiagram ) ); + + ::chart::DataSeriesHelper::deleteSeries( xSeries, xChartType ); + + ::chart::AxisHelper::hideAxisIfNoDataIsAttached( xAxis, xDiagram ); + + bResult = true; + aUndoGuard.commitAction(); + } + } + return bResult; +} + +bool lcl_deleteDataCurve( + const OUString & rCID, + const Reference< frame::XModel > & xModel, + const Reference< chart2::XUndoManager > & xUndoManager ) +{ + bool bResult = false; + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( + ::chart::ObjectIdentifier::getObjectPropertySet( + ::chart::ObjectIdentifier::getSeriesParticleFromCID( rCID ), xModel ), uno::UNO_QUERY ); + if( xRegCurveCnt.is()) + { + ::chart::UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( ::chart::SchResId( STR_OBJECT_CURVE )))), + xUndoManager, xModel ); + ::chart::RegressionCurveHelper::removeAllExceptMeanValueLine( xRegCurveCnt ); + bResult = true; + aUndoGuard.commitAction(); + } + return bResult; +} + +// void lcl_CopyPageContentToPage( +// const Reference< drawing::XDrawPage > & xSourcePage, +// const Reference< drawing::XDrawPage > & xDestPage ) +// { +// try +// { +// Reference< container::XIndexAccess > xSourceIA( xSourcePage, uno::UNO_QUERY_THROW ); +// sal_Int32 nCount( xSourceIA->getCount()); +// for( sal_Int32 i=0; i<nCount; ++i ) +// { +// Reference< drawing::XShape > xShape; +// if( xSourceIA->getByIndex( i ) >>= xShape ) +// xDestPage->add( xShape ); +// } +// } +// catch( const uno::Exception & ex ) +// { +// ASSERT_EXCEPTION( ex ); +// } +// } + +// // copies all shapes on all pages of xSource to the only page of xDestination +// void lcl_CopyShapesToChart( +// const Reference< frame::XModel > & xSource, const Reference< frame::XModel > & xDestination ) +// { +// try +// { +// Reference< drawing::XDrawPageSupplier > xDestPGSupp( xDestination, uno::UNO_QUERY_THROW ); +// Reference< drawing::XDrawPage > xDestPage( xDestPGSupp->getDrawPage()); +// Reference< drawing::XDrawPagesSupplier > xSourcePGsSupp( xSource, uno::UNO_QUERY_THROW ); +// Reference< drawing::XDrawPages > xSourcePages( xSourcePGsSupp->getDrawPages()); + +// sal_Int32 nCount( xSourcePages->getCount()); +// for( sal_Int32 i=0; i<nCount; ++i ) +// { +// Reference< drawing::XDrawPage > xSourcePage( xSourcePages->getByIndex( i ), uno::UNO_QUERY_THROW ); +// lcl_CopyPageContentToPage( xSourcePage, xDestPage ); +// } +// } +// catch( const uno::Exception & ex ) +// { +// ASSERT_EXCEPTION( ex ); +// } +// } + +} // anonymous namespace + + +namespace chart +{ + +::std::auto_ptr< ReferenceSizeProvider > ChartController::impl_createReferenceSizeProvider() +{ + awt::Size aPageSize( ChartModelHelper::getPageSize( getModel() ) ); + + return ::std::auto_ptr< ReferenceSizeProvider >( + new ReferenceSizeProvider( aPageSize, + Reference< chart2::XChartDocument >( getModel(), uno::UNO_QUERY ))); +} + +void ChartController::impl_adaptDataSeriesAutoResize() +{ + ::std::auto_ptr< ReferenceSizeProvider > apRefSizeProvider( + impl_createReferenceSizeProvider()); + if( apRefSizeProvider.get()) + apRefSizeProvider->setValuesAtAllDataSeries(); +} + +void ChartController::executeDispatch_NewArrangement() +{ + // remove manual positions at titles, legend and the diagram, remove manual + // size at the diagram + + try + { + Reference< frame::XModel > xModel( getModel() ); + Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel )); + if( xDiagram.is()) + { + // using assignment for broken gcc 3.3 + UndoGuard aUndoGuard = UndoGuard( + ::rtl::OUString( String( SchResId( STR_ACTION_REARRANGE_CHART ))), + m_xUndoManager, xModel ); + ControllerLockGuard aCtlLockGuard( xModel ); + + // diagram + Reference< beans::XPropertyState > xState( xDiagram, uno::UNO_QUERY_THROW ); + xState->setPropertyToDefault( C2U("RelativeSize")); + xState->setPropertyToDefault( C2U("RelativePosition")); + xState->setPropertyToDefault( C2U("PosSizeExcludeAxes")); + + // 3d rotation + ThreeDHelper::set3DSettingsToDefault( uno::Reference< beans::XPropertySet >( xDiagram, uno::UNO_QUERY ) ); + + // legend + Reference< beans::XPropertyState > xLegendState( xDiagram->getLegend(), uno::UNO_QUERY ); + if( xLegendState.is()) + xLegendState->setPropertyToDefault( C2U("RelativePosition")); + + // titles + for( sal_Int32 eType = TitleHelper::TITLE_BEGIN; + eType < TitleHelper::NORMAL_TITLE_END; + ++eType ) + { + Reference< beans::XPropertyState > xTitleState( + TitleHelper::getTitle( + static_cast< TitleHelper::eTitleType >( eType ), xModel ), uno::UNO_QUERY ); + if( xTitleState.is()) + xTitleState->setPropertyToDefault( C2U("RelativePosition")); + } + + // regression curve equations + ::std::vector< Reference< chart2::XRegressionCurve > > aRegressionCurves( + RegressionCurveHelper::getAllRegressionCurvesNotMeanValueLine( xDiagram )); + ::std::for_each( aRegressionCurves.begin(), aRegressionCurves.end(), + RegressionCurveHelper::resetEquationPosition ); + + aUndoGuard.commitAction(); + } + } + catch( uno::RuntimeException & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void ChartController::executeDispatch_ScaleText() +{ + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + // using assignment for broken gcc 3.3 + UndoGuard aUndoGuard = UndoGuard( + ::rtl::OUString( String( SchResId( STR_ACTION_SCALE_TEXT ))), + m_xUndoManager, getModel() ); + ControllerLockGuard aCtlLockGuard( getModel() ); + ::std::auto_ptr< ReferenceSizeProvider > apRefSizeProv( impl_createReferenceSizeProvider()); + OSL_ASSERT( apRefSizeProv.get()); + if( apRefSizeProv.get()) + apRefSizeProv->toggleAutoResizeState(); + aUndoGuard.commitAction(); +} + +void ChartController::executeDispatch_Paste() +{ + if( m_pChartWindow ) + { + Graphic aGraphic; + // paste location: center of window + Point aPos; + aPos = m_pChartWindow->PixelToLogic( Rectangle( aPos, m_pChartWindow->GetSizePixel()).Center()); + + // handle different formats + TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( m_pChartWindow )); + if( aDataHelper.GetTransferable().is()) + { + if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) ) + { + SotStorageStreamRef xStm; + if ( aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_DRAWING, xStm ) ) + { + xStm->Seek( 0 ); + Reference< io::XInputStream > xInputStream( new utl::OInputStreamWrapper( *xStm ) ); + ::boost::scoped_ptr< SdrModel > spModel( new SdrModel() ); + if ( SvxDrawingLayerImport( spModel.get(), xInputStream ) ) + { + impl_PasteShapes( spModel.get() ); + } + } + } + else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) ) + { + // graphic exchange format (graphic manager bitmap format?) + SotStorageStreamRef xStm; + if( aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_SVXB, xStm )) + (*xStm) >> aGraphic; + } + else if( aDataHelper.HasFormat( FORMAT_GDIMETAFILE )) + { + // meta file + GDIMetaFile aMetafile; + if( aDataHelper.GetGDIMetaFile( FORMAT_GDIMETAFILE, aMetafile )) + aGraphic = Graphic( aMetafile ); + } + else if( aDataHelper.HasFormat( FORMAT_BITMAP )) + { + // bitmap (non-graphic-manager) + Bitmap aBmp; + if( aDataHelper.GetBitmap( FORMAT_BITMAP, aBmp )) + aGraphic = Graphic( aBmp ); + } + else if( aDataHelper.HasFormat( FORMAT_STRING )) + { + OUString aString; + if( aDataHelper.GetString( FORMAT_STRING, aString ) && m_pDrawModelWrapper ) + { + if( m_pDrawViewWrapper ) + { + OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView(); + if( pOutlinerView )//in case of edit mode insert into edited string + pOutlinerView->InsertText( aString ); + else + { + impl_PasteStringAsTextShape( aString, awt::Point( 0, 0 ) ); + } + } + } + } + } + + if( aGraphic.GetType() != GRAPHIC_NONE ) + { + Reference< graphic::XGraphic > xGraphic( aGraphic.GetXGraphic()); + if( xGraphic.is()) + impl_PasteGraphic( xGraphic, aPos ); + } + } +} + +// note: aPosition is ignored for now. The object is always pasted centered to +// the page +void ChartController::impl_PasteGraphic( + uno::Reference< graphic::XGraphic > & xGraphic, + const ::Point & /* aPosition */ ) +{ + // note: the XPropertySet of the model is the old API. Also the property + // "AdditionalShapes" that is used there. + uno::Reference< beans::XPropertySet > xModelProp( getModel(), uno::UNO_QUERY ); + DrawModelWrapper * pDrawModelWrapper( this->GetDrawModelWrapper()); + if( ! (xGraphic.is() && xModelProp.is())) + return; + uno::Reference< lang::XMultiServiceFactory > xFact( pDrawModelWrapper->getShapeFactory()); + uno::Reference< drawing::XShape > xGraphicShape( + xFact->createInstance( C2U( "com.sun.star.drawing.GraphicObjectShape" )), uno::UNO_QUERY ); + uno::Reference< beans::XPropertySet > xGraphicShapeProp( xGraphicShape, uno::UNO_QUERY ); + if( xGraphicShapeProp.is() && xGraphicShape.is()) + { + uno::Reference< drawing::XShapes > xPage( pDrawModelWrapper->getMainDrawPage(), uno::UNO_QUERY ); + if( xPage.is()) + { + xPage->add( xGraphicShape ); + //need to change the model state manually + { + uno::Reference< util::XModifiable > xModifiable( getModel(), uno::UNO_QUERY ); + if( xModifiable.is() ) + xModifiable->setModified( true ); + } + //select new shape + m_aSelection.setSelection( xGraphicShape ); + m_aSelection.applySelection( m_pDrawViewWrapper ); + } + xGraphicShapeProp->setPropertyValue( C2U("Graphic"), uno::makeAny( xGraphic )); + uno::Reference< beans::XPropertySet > xGraphicProp( xGraphic, uno::UNO_QUERY ); + + awt::Size aGraphicSize( 1000, 1000 ); + // first try size in 100th mm, then pixel size + if( ! ( xGraphicProp->getPropertyValue( C2U("Size100thMM")) >>= aGraphicSize ) && + ( ( xGraphicProp->getPropertyValue( C2U("SizePixel")) >>= aGraphicSize ) && m_pChartWindow )) + { + ::Size aVCLSize( m_pChartWindow->PixelToLogic( Size( aGraphicSize.Width, aGraphicSize.Height ))); + aGraphicSize.Width = aVCLSize.getWidth(); + aGraphicSize.Height = aVCLSize.getHeight(); + } + xGraphicShape->setSize( aGraphicSize ); + xGraphicShape->setPosition( awt::Point( 0, 0 ) ); + } +} + +void ChartController::impl_PasteShapes( SdrModel* pModel ) +{ + DrawModelWrapper* pDrawModelWrapper( this->GetDrawModelWrapper() ); + if ( pDrawModelWrapper && m_pDrawViewWrapper ) + { + Reference< drawing::XDrawPage > xDestPage( pDrawModelWrapper->getMainDrawPage() ); + SdrPage* pDestPage = GetSdrPageFromXDrawPage( xDestPage ); + if ( pDestPage ) + { + Reference< drawing::XShape > xSelShape; + m_pDrawViewWrapper->BegUndo( SVX_RESSTR( RID_SVX_3D_UNDO_EXCHANGE_PASTE ) ); + sal_uInt16 nCount = pModel->GetPageCount(); + for ( sal_uInt16 i = 0; i < nCount; ++i ) + { + const SdrPage* pPage = pModel->GetPage( i ); + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + while ( aIter.IsMore() ) + { + SdrObject* pObj = aIter.Next(); + SdrObject* pNewObj = ( pObj ? pObj->Clone() : NULL ); + if ( pNewObj ) + { + pNewObj->SetModel( &pDrawModelWrapper->getSdrModel() ); + pNewObj->SetPage( pDestPage ); + + // set position + Reference< drawing::XShape > xShape( pNewObj->getUnoShape(), uno::UNO_QUERY ); + if ( xShape.is() ) + { + xShape->setPosition( awt::Point( 0, 0 ) ); + } + + pDestPage->InsertObject( pNewObj ); + m_pDrawViewWrapper->AddUndo( new SdrUndoInsertObj( *pNewObj ) ); + xSelShape = xShape; + } + } + } + + Reference< util::XModifiable > xModifiable( getModel(), uno::UNO_QUERY ); + if ( xModifiable.is() ) + { + xModifiable->setModified( true ); + } + + // select last inserted shape + m_aSelection.setSelection( xSelShape ); + m_aSelection.applySelection( m_pDrawViewWrapper ); + + m_pDrawViewWrapper->EndUndo(); + + impl_switchDiagramPositioningToExcludingPositioning(); + } + } +} + +void ChartController::impl_PasteStringAsTextShape( const OUString& rString, const awt::Point& rPosition ) +{ + DrawModelWrapper* pDrawModelWrapper( this->GetDrawModelWrapper() ); + if ( pDrawModelWrapper && m_pDrawViewWrapper ) + { + const Reference< lang::XMultiServiceFactory >& xShapeFactory( pDrawModelWrapper->getShapeFactory() ); + const Reference< drawing::XDrawPage >& xDrawPage( pDrawModelWrapper->getMainDrawPage() ); + OSL_ASSERT( xShapeFactory.is() && xDrawPage.is() ); + + if ( xShapeFactory.is() && xDrawPage.is() ) + { + try + { + Reference< drawing::XShape > xTextShape( + xShapeFactory->createInstance( C2U( "com.sun.star.drawing.TextShape" ) ), uno::UNO_QUERY_THROW ); + xDrawPage->add( xTextShape ); + + Reference< text::XTextRange > xRange( xTextShape, uno::UNO_QUERY_THROW ); + xRange->setString( rString ); + + float fCharHeight = 10.0; + Reference< beans::XPropertySet > xProperties( xTextShape, uno::UNO_QUERY_THROW ); + xProperties->setPropertyValue( C2U( "TextAutoGrowHeight" ), uno::makeAny( true ) ); + xProperties->setPropertyValue( C2U( "TextAutoGrowWidth" ), uno::makeAny( true ) ); + xProperties->setPropertyValue( C2U( "CharHeight" ), uno::makeAny( fCharHeight ) ); + xProperties->setPropertyValue( C2U( "CharHeightAsian" ), uno::makeAny( fCharHeight ) ); + xProperties->setPropertyValue( C2U( "CharHeightComplex" ), uno::makeAny( fCharHeight ) ); + xProperties->setPropertyValue( C2U( "TextVerticalAdjust" ), uno::makeAny( drawing::TextVerticalAdjust_CENTER ) ); + xProperties->setPropertyValue( C2U( "TextHorizontalAdjust" ), uno::makeAny( drawing::TextHorizontalAdjust_CENTER ) ); + xProperties->setPropertyValue( C2U( "CharFontName" ), uno::makeAny( C2U( "Albany" ) ) ); + + xTextShape->setPosition( rPosition ); + + m_aSelection.setSelection( xTextShape ); + m_aSelection.applySelection( m_pDrawViewWrapper ); + + SdrObject* pObj = DrawViewWrapper::getSdrObject( xTextShape ); + if ( pObj ) + { + m_pDrawViewWrapper->BegUndo( SVX_RESSTR( RID_SVX_3D_UNDO_EXCHANGE_PASTE ) ); + m_pDrawViewWrapper->AddUndo( new SdrUndoInsertObj( *pObj ) ); + m_pDrawViewWrapper->EndUndo(); + + impl_switchDiagramPositioningToExcludingPositioning(); + } + } + catch ( const uno::Exception& ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + } +} + +void ChartController::executeDispatch_Copy() +{ + if ( m_pDrawViewWrapper ) + { + OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView(); + if ( pOutlinerView ) + { + pOutlinerView->Copy(); + } + else + { + Reference< datatransfer::XTransferable > xTransferable; + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + SdrObject* pSelectedObj = 0; + if ( m_pDrawModelWrapper ) + { + ObjectIdentifier aSelOID( m_aSelection.getSelectedOID() ); + if ( aSelOID.isAutoGeneratedObject() ) + { + pSelectedObj = m_pDrawModelWrapper->getNamedSdrObject( aSelOID.getObjectCID() ); + } + else if ( aSelOID.isAdditionalShape() ) + { + pSelectedObj = DrawViewWrapper::getSdrObject( aSelOID.getAdditionalShape() ); + } + if ( pSelectedObj ) + { + xTransferable = Reference< datatransfer::XTransferable >( new ChartTransferable( + &m_pDrawModelWrapper->getSdrModel(), pSelectedObj, aSelOID.isAdditionalShape() ) ); + } + } + } + if ( xTransferable.is() ) + { + Reference< datatransfer::clipboard::XClipboard > xClipboard( TransferableHelper::GetSystemClipboard() ); + if ( xClipboard.is() ) + { + xClipboard->setContents( xTransferable, Reference< datatransfer::clipboard::XClipboardOwner >() ); + } + } + } + } +} + +void ChartController::executeDispatch_Cut() +{ + executeDispatch_Copy(); + executeDispatch_Delete(); +} + +//static +bool ChartController::isObjectDeleteable( const uno::Any& rSelection ) +{ + ObjectIdentifier aSelOID( rSelection ); + if ( aSelOID.isAutoGeneratedObject() ) + { + OUString aSelObjCID( aSelOID.getObjectCID() ); + ObjectType aObjectType(ObjectIdentifier::getObjectType( aSelObjCID )); + if( (OBJECTTYPE_TITLE == aObjectType) || (OBJECTTYPE_LEGEND == aObjectType) ) + return true; + if( (OBJECTTYPE_DATA_SERIES == aObjectType) || (OBJECTTYPE_LEGEND_ENTRY == aObjectType) ) + return true; + if( (OBJECTTYPE_DATA_CURVE_EQUATION == aObjectType) || (OBJECTTYPE_DATA_CURVE == aObjectType) || + (OBJECTTYPE_DATA_AVERAGE_LINE == aObjectType) || (OBJECTTYPE_DATA_ERRORS == aObjectType)) + return true; + if( (OBJECTTYPE_DATA_LABELS == aObjectType) || (OBJECTTYPE_DATA_LABEL == aObjectType) ) + return true; + if( (OBJECTTYPE_AXIS == aObjectType) || (OBJECTTYPE_GRID == aObjectType) || (OBJECTTYPE_SUBGRID == aObjectType) ) + return true; + } + else if ( aSelOID.isAdditionalShape() ) + { + return true; + } + + return false; +} + +bool ChartController::isShapeContext() const +{ + if ( m_aSelection.isAdditionalShapeSelected() || + ( m_pDrawViewWrapper && m_pDrawViewWrapper->AreObjectsMarked() && + ( m_pDrawViewWrapper->GetCurrentObjIdentifier() == OBJ_TEXT ) ) ) + { + return true; + } + + return false; +} + +void ChartController::impl_ClearSelection() +{ + if( m_aSelection.hasSelection()) + { + m_aSelection.clearSelection(); + impl_notifySelectionChangeListeners(); + } +} + +bool ChartController::executeDispatch_Delete() +{ + bool bReturn = false; + + // remove the selected object + // + rtl::OUString aCID( m_aSelection.getSelectedCID() ); + if( aCID.getLength() ) + { + if( !isObjectDeleteable( uno::Any( aCID ) ) ) + return false; + + //remove chart object + uno::Reference< chart2::XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY ); + if( !xChartDoc.is() ) + return false; + + ObjectType aObjectType( ObjectIdentifier::getObjectType( aCID )); + switch( aObjectType ) + { + case OBJECTTYPE_TITLE: + { + // using assignment for broken gcc 3.3 + UndoGuard aUndoGuard = UndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( SchResId( STR_OBJECT_TITLE )))), + m_xUndoManager, getModel()); + TitleHelper::removeTitle( + ObjectIdentifier::getTitleTypeForCID( aCID ), getModel() ); + bReturn = true; + aUndoGuard.commitAction(); + break; + } + case OBJECTTYPE_LEGEND: + { + uno::Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram()); + if( xDiagram.is()) + { + uno::Reference< beans::XPropertySet > xLegendProp( xDiagram->getLegend(), uno::UNO_QUERY ); + if( xLegendProp.is()) + { + // using assignment for broken gcc 3.3 + UndoGuard aUndoGuard = UndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( SchResId( STR_OBJECT_LEGEND )))), + m_xUndoManager, getModel() ); + xLegendProp->setPropertyValue( C2U("Show"), uno::makeAny( false )); + bReturn = true; + aUndoGuard.commitAction(); + } + } + break; + } + + case OBJECTTYPE_DATA_SERIES: + bReturn = lcl_deleteDataSeries( aCID, getModel(), m_xUndoManager ); + break; + + case OBJECTTYPE_LEGEND_ENTRY: + { + ObjectType eParentObjectType = ObjectIdentifier::getObjectType( + ObjectIdentifier::getFullParentParticle( aCID )); + if( eParentObjectType == OBJECTTYPE_DATA_SERIES ) + bReturn = lcl_deleteDataSeries( aCID, getModel(), m_xUndoManager ); + else if( eParentObjectType == OBJECTTYPE_DATA_CURVE ) + bReturn = lcl_deleteDataCurve( aCID, getModel(), m_xUndoManager ); + break; + } + + case OBJECTTYPE_DATA_AVERAGE_LINE: + { + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( + ObjectIdentifier::getObjectPropertySet( + ObjectIdentifier::getFullParentParticle( aCID ), getModel()), uno::UNO_QUERY ); + if( xRegCurveCnt.is()) + { + // using assignment for broken gcc 3.3 + UndoGuard aUndoGuard = UndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( SchResId( STR_OBJECT_AVERAGE_LINE )))), + m_xUndoManager, getModel() ); + RegressionCurveHelper::removeMeanValueLine( xRegCurveCnt ); + bReturn = true; + aUndoGuard.commitAction(); + } + break; + } + + case OBJECTTYPE_DATA_CURVE: + bReturn = lcl_deleteDataCurve( aCID, getModel(), m_xUndoManager ); + break; + + case OBJECTTYPE_DATA_CURVE_EQUATION: + { + uno::Reference< beans::XPropertySet > xEqProp( + ObjectIdentifier::getObjectPropertySet( aCID, getModel())); + if( xEqProp.is()) + { + uno::Reference< frame::XModel > xModel( getModel() ); + // using assignment for broken gcc 3.3 + UndoGuard aUndoGuard = UndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( SchResId( STR_OBJECT_CURVE_EQUATION )))), + m_xUndoManager, xModel ); + { + ControllerLockGuard aCtlLockGuard( xModel ); + xEqProp->setPropertyValue( C2U("ShowEquation"), uno::makeAny( false )); + xEqProp->setPropertyValue( C2U("ShowCorrelationCoefficient"), uno::makeAny( false )); + } + bReturn = true; + aUndoGuard.commitAction(); + } + break; + } + + case OBJECTTYPE_DATA_ERRORS: + { + uno::Reference< beans::XPropertySet > xErrorBarProp( + ObjectIdentifier::getObjectPropertySet( aCID, getModel() )); + if( xErrorBarProp.is()) + { + uno::Reference< frame::XModel > xModel( getModel() ); + // using assignment for broken gcc 3.3 + UndoGuard aUndoGuard = UndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( SchResId( STR_OBJECT_ERROR_BARS )))), + m_xUndoManager, xModel ); + { + ControllerLockGuard aCtlLockGuard( xModel ); + xErrorBarProp->setPropertyValue( + C2U("ErrorBarStyle"), + uno::makeAny( ::com::sun::star::chart::ErrorBarStyle::NONE )); + } + bReturn = true; + aUndoGuard.commitAction(); + } + break; + } + + case OBJECTTYPE_DATA_LABELS: + case OBJECTTYPE_DATA_LABEL: + { + uno::Reference< beans::XPropertySet > xObjectProperties = + ObjectIdentifier::getObjectPropertySet( aCID, getModel() ); + if( xObjectProperties.is() ) + { + UndoGuard aUndoGuard = UndoGuard( + ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::DELETE, ::rtl::OUString( String( + SchResId( aObjectType == OBJECTTYPE_DATA_LABEL ? STR_OBJECT_LABEL : STR_OBJECT_DATALABELS )))), + m_xUndoManager, getModel() ); + chart2::DataPointLabel aLabel; + xObjectProperties->getPropertyValue( C2U( "Label" ) ) >>= aLabel; + aLabel.ShowNumber = false; + aLabel.ShowNumberInPercent = false; + aLabel.ShowCategoryName = false; + aLabel.ShowLegendSymbol = false; + if( aObjectType == OBJECTTYPE_DATA_LABELS ) + { + uno::Reference< chart2::XDataSeries > xSeries( ObjectIdentifier::getDataSeriesForCID( aCID, getModel() )); + ::chart::DataSeriesHelper::setPropertyAlsoToAllAttributedDataPoints( xSeries, C2U( "Label" ), uno::makeAny(aLabel) ); + } + else + xObjectProperties->setPropertyValue( C2U( "Label" ), uno::makeAny(aLabel) ); + bReturn = true; + aUndoGuard.commitAction(); + } + break; + } + case OBJECTTYPE_AXIS: + { + executeDispatch_DeleteAxis(); + bReturn = true; + break; + } + case OBJECTTYPE_GRID: + { + executeDispatch_DeleteMajorGrid(); + bReturn = true; + break; + } + case OBJECTTYPE_SUBGRID: + { + executeDispatch_DeleteMinorGrid(); + bReturn = true; + break; + } + + default: + { + break; + } + } + } + else + { + //remove additional shape + impl_ClearSelection(); + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + if ( m_pDrawViewWrapper ) + { + m_pDrawViewWrapper->DeleteMarked(); + bReturn = true; + } + } + } + return bReturn; +} + +void ChartController::executeDispatch_ToggleLegend() +{ + Reference< frame::XModel > xModel( getModel() ); + UndoGuard aUndoGuard = UndoGuard( + ::rtl::OUString( String( SchResId( STR_ACTION_TOGGLE_LEGEND ))), m_xUndoManager, xModel ); + Reference< beans::XPropertySet > xLegendProp( LegendHelper::getLegend( xModel ), uno::UNO_QUERY ); + bool bChanged = false; + if( xLegendProp.is()) + { + try + { + bool bShow = false; + if( xLegendProp->getPropertyValue( C2U("Show")) >>= bShow ) + { + xLegendProp->setPropertyValue( C2U("Show"), uno::makeAny( ! bShow )); + bChanged = true; + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + else + { + xLegendProp.set( LegendHelper::getLegend( xModel, m_xCC, true ), uno::UNO_QUERY ); + if( xLegendProp.is()) + bChanged = true; + } + + if( bChanged ) + aUndoGuard.commitAction(); +} + +void ChartController::executeDispatch_ToggleGridHorizontal() +{ + Reference< frame::XModel > xModel( getModel() ); + UndoGuard aUndoGuard = UndoGuard( + ::rtl::OUString( String( SchResId( STR_ACTION_TOGGLE_GRID_HORZ ))), m_xUndoManager, xModel ); + Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( getModel() )); + if( xDiagram.is()) + { + sal_Int32 nDimensionIndex = 1; + sal_Int32 nCooSysIndex = 0; + bool bIsMainGrid = true; + + bool bHasMainYGrid = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, bIsMainGrid, xDiagram ); + + if( bHasMainYGrid ) + AxisHelper::hideGrid( nDimensionIndex, nCooSysIndex, bIsMainGrid, xDiagram ); + else + AxisHelper::showGrid( nDimensionIndex, nCooSysIndex, bIsMainGrid, xDiagram, m_xCC ); + + aUndoGuard.commitAction(); + } +} + +void ChartController::impl_ShapeControllerDispatch( const util::URL& rURL, const Sequence< beans::PropertyValue >& rArgs ) +{ + Reference< frame::XDispatch > xDispatch( m_aDispatchContainer.getShapeController() ); + if ( xDispatch.is() ) + { + xDispatch->dispatch( rURL, rArgs ); + } +} + +void ChartController::impl_switchDiagramPositioningToExcludingPositioning() +{ + UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( + ActionDescriptionProvider::POS_SIZE, + ObjectNameProvider::getName( OBJECTTYPE_DIAGRAM)), + m_xUndoManager, m_aModel->getModel() ); + if( DiagramHelper::switchDiagramPositioningToExcludingPositioning( m_aModel->getModel(), true, true ) ) + aUndoGuard.commitAction(); +} + +} // namespace chart diff --git a/chart2/source/controller/main/ChartController_Window.cxx b/chart2/source/controller/main/ChartController_Window.cxx new file mode 100644 index 000000000000..56908ac4ef79 --- /dev/null +++ b/chart2/source/controller/main/ChartController_Window.cxx @@ -0,0 +1,2029 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" +#include "ChartController.hxx" +#include "PositionAndSizeHelper.hxx" +#include "ObjectIdentifier.hxx" +#include "ChartWindow.hxx" +#include "ResId.hxx" +#include "CommonConverters.hxx" +#include "ChartModelHelper.hxx" +#include "DiagramHelper.hxx" +#include "TitleHelper.hxx" +#include "UndoGuard.hxx" +#include "ControllerLockGuard.hxx" +#include "ObjectNameProvider.hxx" +#include "Strings.hrc" +#include "SchSlotIds.hxx" +#include "macros.hxx" +#include "DragMethod_PieSegment.hxx" +#include "DragMethod_RotateDiagram.hxx" +#include "ObjectHierarchy.hxx" +#include "chartview/ExplicitValueProvider.hxx" +#include "RelativePositionHelper.hxx" +#include "chartview/DrawModelWrapper.hxx" +#include "RegressionCurveHelper.hxx" +#include "StatisticsHelper.hxx" +#include "DataSeriesHelper.hxx" +#include "ContainerHelper.hxx" +#include "AxisHelper.hxx" +#include "LegendHelper.hxx" +#include "servicenames_charttypes.hxx" +#include "MenuResIds.hrc" +#include "DrawCommandDispatch.hxx" + +#include <com/sun/star/chart2/RelativePosition.hpp> +#include <com/sun/star/chart2/RelativeSize.hpp> +#include <com/sun/star/chart2/XRegressionCurveContainer.hpp> + +#include <com/sun/star/frame/XDispatchHelper.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/util/XUpdatable.hpp> +#include <comphelper/InlineContainer.hxx> + +#include <svtools/contextmenuhelper.hxx> +#include <toolkit/awt/vclxmenu.hxx> + +#include <svx/svxids.hrc> +#include <svx/ActionDescriptionProvider.hxx> + +// header for class E3dObject +#include <svx/obj3d.hxx> +// header for class E3dScene +#include <svx/scene3d.hxx> +// header for class SdrDragMethod +#include <svx/svddrgmt.hxx> +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> + +// for InfoBox +#include <vcl/msgbox.hxx> + +#include <rtl/math.hxx> +#include <svtools/acceleratorexecute.hxx> + +#define DRGPIX 2 // Drag MinMove in Pixel + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using ::com::sun::star::uno::Reference; +using ::rtl::OUString; + +//............................................................................. +namespace chart +{ +//............................................................................. + +namespace +{ +bool lcl_GrowAndShiftLogic( + RelativePosition & rInOutRelPos, + RelativeSize & rInOutRelSize, + const awt::Size & rRefSize, + double fGrowLogicX, + double fGrowLogicY ) +{ + if( rRefSize.Width == 0 || + rRefSize.Height == 0 ) + return false; + + double fRelativeGrowX = fGrowLogicX / rRefSize.Width; + double fRelativeGrowY = fGrowLogicY / rRefSize.Height; + + return ::chart::RelativePositionHelper::centerGrow( + rInOutRelPos, rInOutRelSize, + fRelativeGrowX, fRelativeGrowY, + /* bCheck = */ true ); +} + +bool lcl_MoveObjectLogic( + RelativePosition & rInOutRelPos, + RelativeSize & rObjectSize, + const awt::Size & rRefSize, + double fShiftLogicX, + double fShiftLogicY ) +{ + if( rRefSize.Width == 0 || + rRefSize.Height == 0 ) + return false; + + double fRelativeShiftX = fShiftLogicX / rRefSize.Width; + double fRelativeShiftY = fShiftLogicY / rRefSize.Height; + + return ::chart::RelativePositionHelper::moveObject( + rInOutRelPos, rObjectSize, + fRelativeShiftX, fRelativeShiftY, + /* bCheck = */ true ); +} + +void lcl_insertMenuCommand( + const uno::Reference< awt::XPopupMenu > & xMenu, + const uno::Reference< awt::XMenuExtended > & xMenuEx, + sal_Int16 nId, const ::rtl::OUString & rCommand ) +{ + static ::rtl::OUString aEmptyString; + xMenu->insertItem( nId, aEmptyString, 0, -1 ); + xMenuEx->setCommand( nId, rCommand ); +} + +OUString lcl_getFormatCommandForObjectCID( const OUString& rCID ) +{ + OUString aDispatchCommand( C2U(".uno:FormatSelection") ); + + ObjectType eObjectType = ObjectIdentifier::getObjectType( rCID ); + + switch(eObjectType) + { + case OBJECTTYPE_DIAGRAM: + case OBJECTTYPE_DIAGRAM_WALL: + aDispatchCommand = C2U(".uno:FormatWall"); + break; + case OBJECTTYPE_DIAGRAM_FLOOR: + aDispatchCommand = C2U(".uno:FormatFloor"); + break; + case OBJECTTYPE_PAGE: + aDispatchCommand = C2U(".uno:FormatChartArea"); + break; + case OBJECTTYPE_LEGEND: + aDispatchCommand = C2U(".uno:FormatLegend"); + break; + case OBJECTTYPE_TITLE: + aDispatchCommand = C2U(".uno:FormatTitle"); + break; + case OBJECTTYPE_LEGEND_ENTRY: + aDispatchCommand = C2U(".uno:FormatDataSeries"); + break; + case OBJECTTYPE_AXIS: + case OBJECTTYPE_AXIS_UNITLABEL: + aDispatchCommand = C2U(".uno:FormatAxis"); + break; + case OBJECTTYPE_GRID: + aDispatchCommand = C2U(".uno:FormatMajorGrid"); + break; + case OBJECTTYPE_SUBGRID: + aDispatchCommand = C2U(".uno:FormatMinorGrid"); + break; + case OBJECTTYPE_DATA_LABELS: + aDispatchCommand = C2U(".uno:FormatDataLabels"); + break; + case OBJECTTYPE_DATA_SERIES: + aDispatchCommand = C2U(".uno:FormatDataSeries"); + break; + case OBJECTTYPE_DATA_LABEL: + aDispatchCommand = C2U(".uno:FormatDataLabel"); + break; + case OBJECTTYPE_DATA_POINT: + aDispatchCommand = C2U(".uno:FormatDataPoint"); + break; + case OBJECTTYPE_DATA_AVERAGE_LINE: + aDispatchCommand = C2U(".uno:FormatMeanValue"); + break; + case OBJECTTYPE_DATA_ERRORS: + case OBJECTTYPE_DATA_ERRORS_X: + case OBJECTTYPE_DATA_ERRORS_Y: + case OBJECTTYPE_DATA_ERRORS_Z: + aDispatchCommand = C2U(".uno:FormatYErrorBars"); + break; + case OBJECTTYPE_DATA_CURVE: + aDispatchCommand = C2U(".uno:FormatTrendline"); + break; + case OBJECTTYPE_DATA_CURVE_EQUATION: + aDispatchCommand = C2U(".uno:FormatTrendlineEquation"); + break; + case OBJECTTYPE_DATA_STOCK_RANGE: + aDispatchCommand = C2U(".uno:FormatSelection"); + break; + case OBJECTTYPE_DATA_STOCK_LOSS: + aDispatchCommand = C2U(".uno:FormatStockLoss"); + break; + case OBJECTTYPE_DATA_STOCK_GAIN: + aDispatchCommand = C2U(".uno:FormatStockGain"); + break; + default: //OBJECTTYPE_UNKNOWN + break; + } + return aDispatchCommand; +} + +} // anonymous namespace + +const short HITPIX=2; //hit-tolerance in pixel + +//----------------------------------------------------------------- +// awt::XWindow +//----------------------------------------------------------------- + void SAL_CALL ChartController +::setPosSize( sal_Int32 X, sal_Int32 Y + , sal_Int32 Width, sal_Int32 Height, sal_Int16 Flags ) + throw (uno::RuntimeException) +{ + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + Window* pWindow = m_pChartWindow; + + if(xWindow.is() && pWindow) + { + Size aLogicSize = pWindow->PixelToLogic( Size( Width, Height ), MapMode( MAP_100TH_MM ) ); + + bool bIsEmbedded = true; + //todo: for standalone chart: detect wether we are standalone + if( bIsEmbedded ) + { + //change map mode to fit new size + awt::Size aModelPageSize = ChartModelHelper::getPageSize( getModel() ); + sal_Int32 nScaleXNumerator = aLogicSize.Width(); + sal_Int32 nScaleXDenominator = aModelPageSize.Width; + sal_Int32 nScaleYNumerator = aLogicSize.Height(); + sal_Int32 nScaleYDenominator = aModelPageSize.Height; + MapMode aNewMapMode( MAP_100TH_MM, Point(0,0) + , Fraction(nScaleXNumerator,nScaleXDenominator) + , Fraction(nScaleYNumerator,nScaleYDenominator) ); + pWindow->SetMapMode(aNewMapMode); + pWindow->SetPosSizePixel( X, Y, Width, Height, Flags ); + + //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100% + uno::Reference< beans::XPropertySet > xProp( m_xChartView, uno::UNO_QUERY ); + if( xProp.is() ) + { + uno::Sequence< beans::PropertyValue > aZoomFactors(4); + aZoomFactors[0].Name = C2U("ScaleXNumerator"); + aZoomFactors[0].Value = uno::makeAny( nScaleXNumerator ); + aZoomFactors[1].Name = C2U("ScaleXDenominator"); + aZoomFactors[1].Value = uno::makeAny( nScaleXDenominator ); + aZoomFactors[2].Name = C2U("ScaleYNumerator"); + aZoomFactors[2].Value = uno::makeAny( nScaleYNumerator ); + aZoomFactors[3].Name = C2U("ScaleYDenominator"); + aZoomFactors[3].Value = uno::makeAny( nScaleYDenominator ); + xProp->setPropertyValue( C2U("ZoomFactors"), uno::makeAny( aZoomFactors )); + } + + //a correct work area is at least necessary for correct values in the position and size dialog and for dragging area + if(m_pDrawViewWrapper) + { + Rectangle aRect(Point(0,0), pWindow->GetOutputSize()); + m_pDrawViewWrapper->SetWorkArea( aRect ); + } + } + else + { + //change visarea + ChartModelHelper::setPageSize( awt::Size( aLogicSize.Width(), aLogicSize.Height() ), getModel() ); + pWindow->SetPosSizePixel( X, Y, Width, Height, Flags ); + } + pWindow->Invalidate(); + } +} + + awt::Rectangle SAL_CALL ChartController +::getPosSize() + throw (uno::RuntimeException) +{ + //@todo + awt::Rectangle aRet(0,0,0,0); + + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + if(xWindow.is()) + aRet = xWindow->getPosSize(); + + return aRet; +} + + void SAL_CALL ChartController +::setVisible( sal_Bool Visible ) + throw (uno::RuntimeException) +{ + //@todo + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->setVisible( Visible ); +} + + void SAL_CALL ChartController +::setEnable( sal_Bool Enable ) + throw (uno::RuntimeException) +{ + //@todo + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->setEnable( Enable ); +} + + void SAL_CALL ChartController +::setFocus() throw (uno::RuntimeException) +{ + //@todo + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->setFocus(); +} + + void SAL_CALL ChartController +::addWindowListener( const uno::Reference< + awt::XWindowListener >& xListener ) + throw (uno::RuntimeException) +{ + //@todo + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->addWindowListener( xListener ); +} + + void SAL_CALL ChartController +::removeWindowListener( const uno::Reference< + awt::XWindowListener >& xListener ) + throw (uno::RuntimeException) +{ + //@todo + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->removeWindowListener( xListener ); +} + + void SAL_CALL ChartController +::addFocusListener( const uno::Reference< + awt::XFocusListener >& xListener ) + throw (uno::RuntimeException) +{ + //@todo + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->addFocusListener( xListener ); +} + + void SAL_CALL ChartController +::removeFocusListener( const uno::Reference< + awt::XFocusListener >& xListener ) + throw (uno::RuntimeException) +{ + //@todo + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->removeFocusListener( xListener ); +} + + void SAL_CALL ChartController +::addKeyListener( const uno::Reference< + awt::XKeyListener >& xListener ) + throw (uno::RuntimeException) +{ + //@todo + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->addKeyListener( xListener ); +} + + void SAL_CALL ChartController +::removeKeyListener( const uno::Reference< + awt::XKeyListener >& xListener ) + throw (uno::RuntimeException) +{ + //@todo + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->removeKeyListener( xListener ); +} + + void SAL_CALL ChartController +::addMouseListener( const uno::Reference< + awt::XMouseListener >& xListener ) + throw (uno::RuntimeException) +{ + //@todo + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->addMouseListener( xListener ); +} + + void SAL_CALL ChartController +::removeMouseListener( const uno::Reference< + awt::XMouseListener >& xListener ) + throw (uno::RuntimeException) +{ + //@todo + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->removeMouseListener( xListener ); +} + + void SAL_CALL ChartController +::addMouseMotionListener( const uno::Reference< + awt::XMouseMotionListener >& xListener ) + throw (uno::RuntimeException) +{ + //@todo + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->addMouseMotionListener( xListener ); +} + + void SAL_CALL ChartController +::removeMouseMotionListener( const uno::Reference< + awt::XMouseMotionListener >& xListener ) + throw (uno::RuntimeException) +{ + //@todo + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->removeMouseMotionListener( xListener ); +} + + void SAL_CALL ChartController +::addPaintListener( const uno::Reference< + awt::XPaintListener >& xListener ) + throw (uno::RuntimeException) +{ + //@todo + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->addPaintListener( xListener ); +} + + void SAL_CALL ChartController +::removePaintListener( const uno::Reference< + awt::XPaintListener >& xListener ) + throw (uno::RuntimeException) +{ + //@todo + uno::Reference<awt::XWindow> xWindow = m_xViewWindow; + + if(xWindow.is()) + xWindow->removePaintListener( xListener ); +} + +//----------------------------------------------------------------- +// impl vcl window controller methods +//----------------------------------------------------------------- +void ChartController::PrePaint() +{ + // forward VCLs PrePaint window event to DrawingLayer + DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; + + if(pDrawViewWrapper) + { + pDrawViewWrapper->PrePaint(); + } +} + +void ChartController::execute_Paint( const Rectangle& rRect ) +{ + try + { + uno::Reference< frame::XModel > xModel( getModel() ); + //DBG_ASSERT( xModel.is(), "ChartController::execute_Paint: have no model to paint"); + if( !xModel.is() ) + return; + + //better performance for big data + uno::Reference< beans::XPropertySet > xProp( m_xChartView, uno::UNO_QUERY ); + if( xProp.is() ) + { + awt::Size aResolution(1000,1000); + { + ::vos::OGuard aGuard( Application::GetSolarMutex()); + if( m_pChartWindow ) + { + aResolution.Width = m_pChartWindow->GetSizePixel().Width(); + aResolution.Height = m_pChartWindow->GetSizePixel().Height(); + } + } + xProp->setPropertyValue( C2U("Resolution"), uno::makeAny( aResolution )); + } + // + + uno::Reference< util::XUpdatable > xUpdatable( m_xChartView, uno::UNO_QUERY ); + if( xUpdatable.is() ) + xUpdatable->update(); + + Window* pWindow = m_pChartWindow; + { + ::vos::OGuard aGuard( Application::GetSolarMutex()); + DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; + if(pDrawViewWrapper) + pDrawViewWrapper->CompleteRedraw(pWindow, Region(rRect) ); + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + catch( ... ) + { + } +} + +bool isDoubleClick( const MouseEvent& rMEvt ) +{ + return rMEvt.GetClicks() == 2 && rMEvt.IsLeft() && + !rMEvt.IsMod1() && !rMEvt.IsMod2() && !rMEvt.IsShift(); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +void ChartController::startDoubleClickWaiting() +{ + m_bWaitingForDoubleClick = true; + + ULONG nDblClkTime = 500; + if( m_pChartWindow ) + { + const MouseSettings& rMSettings = m_pChartWindow->GetSettings().GetMouseSettings(); + nDblClkTime = rMSettings.GetDoubleClickTime(); + } + m_aDoubleClickTimer.SetTimeout( nDblClkTime ); + m_aDoubleClickTimer.Start(); +} + +void ChartController::stopDoubleClickWaiting() +{ + m_aDoubleClickTimer.Stop(); + m_bWaitingForDoubleClick = false; +} + +IMPL_LINK( ChartController, DoubleClickWaitingHdl, void*, EMPTYARG ) +{ + m_bWaitingForDoubleClick = false; + + if( !m_bWaitingForMouseUp && m_aSelection.maybeSwitchSelectionAfterSingleClickWasEnsured() ) + { + this->impl_selectObjectAndNotiy(); + if( m_pChartWindow ) + { + Window::PointerState aPointerState( m_pChartWindow->GetPointerState() ); + MouseEvent aMouseEvent( aPointerState.maPos,1/*nClicks*/, + 0/*nMode*/, static_cast< USHORT >( aPointerState.mnState )/*nButtons*/, + 0/*nModifier*/ ); + impl_SetMousePointer( aMouseEvent ); + } + } + + return 0; +} + +//------------------------------------------------------------------------ + +void ChartController::execute_MouseButtonDown( const MouseEvent& rMEvt ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex()); + + m_bWaitingForMouseUp = true; + + if( isDoubleClick(rMEvt) ) + stopDoubleClickWaiting(); + else + startDoubleClickWaiting(); + + m_aSelection.remindSelectionBeforeMouseDown(); + + Window* pWindow = m_pChartWindow; + DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; + if(!pWindow || !pDrawViewWrapper ) + return; + + Point aMPos = pWindow->PixelToLogic(rMEvt.GetPosPixel()); + + if ( MOUSE_LEFT == rMEvt.GetButtons() ) + { + pWindow->GrabFocus(); + pWindow->CaptureMouse(); + } + + if( pDrawViewWrapper->IsTextEdit() ) + { + SdrViewEvent aVEvt; + if ( pDrawViewWrapper->IsTextEditHit( aMPos, HITPIX ) || + // #i12587# support for shapes in chart + ( rMEvt.IsRight() && pDrawViewWrapper->PickAnything( rMEvt, SDRMOUSEBUTTONDOWN, aVEvt ) == SDRHIT_MARKEDOBJECT ) ) + { + pDrawViewWrapper->MouseButtonDown(rMEvt,m_pChartWindow); + return; + } + else + { + this->EndTextEdit(); + } + } + + //abort running action + if( pDrawViewWrapper->IsAction() ) + { + if( rMEvt.IsRight() ) + pDrawViewWrapper->BckAction(); + return; + } + + if( isDoubleClick(rMEvt) ) //do not change selection if double click + return;//double click is handled further in mousebutton up + + SdrHdl* pHitSelectionHdl = 0; + //switch from move to resize if handle is hit on a resizeable object + if( m_aSelection.isResizeableObjectSelected() ) + pHitSelectionHdl = pDrawViewWrapper->PickHandle( aMPos ); + //only change selection if no selection handles are hit + if( !pHitSelectionHdl ) + { + // #i12587# support for shapes in chart + if ( m_eDrawMode == CHARTDRAW_INSERT && + ( !pDrawViewWrapper->IsMarkedHit( aMPos ) || !m_aSelection.isDragableObjectSelected() ) ) + { + if ( m_aSelection.hasSelection() ) + { + m_aSelection.clearSelection(); + } + if ( !pDrawViewWrapper->IsAction() ) + { + if ( pDrawViewWrapper->GetCurrentObjIdentifier() == OBJ_CAPTION ) + { + Size aCaptionSize( 2268, 1134 ); + pDrawViewWrapper->BegCreateCaptionObj( aMPos, aCaptionSize ); + } + else + { + pDrawViewWrapper->BegCreateObj( aMPos); + } + SdrObject* pObj = pDrawViewWrapper->GetCreateObj(); + DrawCommandDispatch* pDrawCommandDispatch = m_aDispatchContainer.getDrawCommandDispatch(); + if ( pObj && m_pDrawModelWrapper && pDrawCommandDispatch ) + { + SfxItemSet aSet( m_pDrawModelWrapper->GetItemPool() ); + pDrawCommandDispatch->setAttributes( pObj ); + pDrawCommandDispatch->setLineEnds( aSet ); + pObj->SetMergedItemSet( aSet ); + } + } + impl_SetMousePointer( rMEvt ); + return; + } + + m_aSelection.adaptSelectionToNewPos( aMPos, pDrawViewWrapper + , rMEvt.IsRight(), m_bWaitingForDoubleClick ); + + if( !m_aSelection.isRotateableObjectSelected( getModel() ) ) + { + m_eDragMode = SDRDRAG_MOVE; + pDrawViewWrapper->SetDragMode(m_eDragMode); + } + + m_aSelection.applySelection(pDrawViewWrapper); + } + if( m_aSelection.isDragableObjectSelected() + && !rMEvt.IsRight() ) + { + //start drag + USHORT nDrgLog = (USHORT)pWindow->PixelToLogic(Size(DRGPIX,0)).Width(); + SdrDragMethod* pDragMethod = NULL; + + //change selection to 3D scene if rotate mode + SdrDragMode eDragMode = pDrawViewWrapper->GetDragMode(); + if( SDRDRAG_ROTATE==eDragMode ) + { + E3dScene* pScene = SelectionHelper::getSceneToRotate( pDrawViewWrapper->getNamedSdrObject( m_aSelection.getSelectedCID() ) ); + if( pScene ) + { + DragMethod_RotateDiagram::RotationDirection eRotationDirection(DragMethod_RotateDiagram::ROTATIONDIRECTION_FREE); + if(pHitSelectionHdl) + { + SdrHdlKind eKind = pHitSelectionHdl->GetKind(); + if( eKind==HDL_UPPER || eKind==HDL_LOWER ) + eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_X; + else if( eKind==HDL_LEFT || eKind==HDL_RIGHT ) + eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_Y; + else if( eKind==HDL_UPLFT || eKind==HDL_UPRGT || eKind==HDL_LWLFT || eKind==HDL_LWRGT ) + eRotationDirection = DragMethod_RotateDiagram::ROTATIONDIRECTION_Z; + } + pDragMethod = new DragMethod_RotateDiagram( *pDrawViewWrapper, m_aSelection.getSelectedCID(), getModel(), eRotationDirection ); + } + } + else + { + rtl::OUString aDragMethodServiceName( ObjectIdentifier::getDragMethodServiceName( m_aSelection.getSelectedCID() ) ); + if( aDragMethodServiceName.equals( ObjectIdentifier::getPieSegmentDragMethodServiceName() ) ) + pDragMethod = new DragMethod_PieSegment( *pDrawViewWrapper, m_aSelection.getSelectedCID(), getModel() ); + } + pDrawViewWrapper->SdrView::BegDragObj(aMPos, NULL, pHitSelectionHdl, nDrgLog, pDragMethod); + } + + impl_SetMousePointer( rMEvt ); +} + +void ChartController::execute_MouseMove( const MouseEvent& rMEvt ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex()); + + Window* pWindow = m_pChartWindow; + DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; + if(!pWindow || !pDrawViewWrapper) + return; + + if( m_pDrawViewWrapper->IsTextEdit() ) + { + if( m_pDrawViewWrapper->MouseMove(rMEvt,m_pChartWindow) ) + return; + } + + if(pDrawViewWrapper->IsAction()) + { + pDrawViewWrapper->MovAction( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); + } + + //?? pDrawViewWrapper->GetPageView()->DragPoly(); + + impl_SetMousePointer( rMEvt ); +} +void ChartController::execute_Tracking( const TrackingEvent& /* rTEvt */ ) +{ +} + +//----------------- + +void ChartController::execute_MouseButtonUp( const MouseEvent& rMEvt ) +{ + ControllerLockGuard aCLGuard( getModel() ); + bool bMouseUpWithoutMouseDown = !m_bWaitingForMouseUp; + m_bWaitingForMouseUp = false; + bool bNotifySelectionChange = false; + { + ::vos::OGuard aGuard( Application::GetSolarMutex()); + + Window* pWindow = m_pChartWindow; + DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; + if(!pWindow || !pDrawViewWrapper) + return; + + Point aMPos = pWindow->PixelToLogic(rMEvt.GetPosPixel()); + + if(pDrawViewWrapper->IsTextEdit()) + { + if( pDrawViewWrapper->MouseButtonUp(rMEvt,m_pChartWindow) ) + return; + } + + // #i12587# support for shapes in chart + if ( m_eDrawMode == CHARTDRAW_INSERT && pDrawViewWrapper->IsCreateObj() ) + { + pDrawViewWrapper->EndCreateObj( SDRCREATE_FORCEEND ); + impl_switchDiagramPositioningToExcludingPositioning(); + if ( pDrawViewWrapper->AreObjectsMarked() ) + { + if ( pDrawViewWrapper->GetCurrentObjIdentifier() == OBJ_TEXT ) + { + executeDispatch_EditText(); + } + else + { + SdrObject* pObj = pDrawViewWrapper->getSelectedObject(); + if ( pObj ) + { + uno::Reference< drawing::XShape > xShape( pObj->getUnoShape(), uno::UNO_QUERY ); + if ( xShape.is() ) + { + m_aSelection.setSelection( xShape ); + m_aSelection.applySelection( pDrawViewWrapper ); + } + } + } + } + else + { + m_aSelection.adaptSelectionToNewPos( aMPos, pDrawViewWrapper, rMEvt.IsRight(), m_bWaitingForDoubleClick ); + m_aSelection.applySelection( pDrawViewWrapper ); + setDrawMode( CHARTDRAW_SELECT ); + } + } + else if ( pDrawViewWrapper->IsDragObj() ) + { + bool bDraggingDone = false; + SdrDragMethod* pDragMethod = pDrawViewWrapper->SdrView::GetDragMethod(); + bool bIsMoveOnly = pDragMethod ? pDragMethod->getMoveOnly() : false; + DragMethod_Base* pChartDragMethod = dynamic_cast< DragMethod_Base* >(pDragMethod); + if( pChartDragMethod ) + { + UndoGuard aUndoGuard( pChartDragMethod->getUndoDescription(), + m_xUndoManager, getModel() ); + + if( pDrawViewWrapper->EndDragObj(false) ) + { + bDraggingDone = true; + aUndoGuard.commitAction(); + } + } + + if( !bDraggingDone && pDrawViewWrapper->EndDragObj(false) ) + { + try + { + //end move or size + SdrObject* pObj = pDrawViewWrapper->getSelectedObject(); + if( pObj ) + { + Rectangle aObjectRect = pObj->GetSnapRect(); + awt::Size aPageSize( ChartModelHelper::getPageSize( getModel() ) ); + Rectangle aPageRect( 0,0,aPageSize.Width,aPageSize.Height ); + + const E3dObject* pE3dObject = dynamic_cast< const E3dObject*>( pObj ); + if( pE3dObject ) + aObjectRect = pE3dObject->GetScene()->GetSnapRect(); + + ActionDescriptionProvider::ActionType eActionType(ActionDescriptionProvider::MOVE); + if( !bIsMoveOnly && m_aSelection.isResizeableObjectSelected() ) + eActionType = ActionDescriptionProvider::RESIZE; + + UndoGuard aUndoGuard( + ActionDescriptionProvider::createDescription( + eActionType, + ObjectNameProvider::getName( ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() ))), + m_xUndoManager, getModel() ); + bool bChanged = PositionAndSizeHelper::moveObject( m_aSelection.getSelectedCID() + , getModel() + , awt::Rectangle(aObjectRect.getX(),aObjectRect.getY(),aObjectRect.getWidth(),aObjectRect.getHeight()) + , awt::Rectangle(aPageRect.getX(),aPageRect.getY(),aPageRect.getWidth(),aPageRect.getHeight()) ); + if( bChanged ) + { + bDraggingDone = true; + aUndoGuard.commitAction(); + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + //all wanted model changes will take effect + //and all unwanted view modifications are cleaned + } + + if( !bDraggingDone ) //mouse wasn't moved while dragging + { + bool bClickedTwiceOnDragableObject = SelectionHelper::isDragableObjectHitTwice( aMPos, m_aSelection.getSelectedCID(), *pDrawViewWrapper ); + bool bIsRotateable = m_aSelection.isRotateableObjectSelected( getModel() ); + + //toggel between move and rotate + if( bIsRotateable && bClickedTwiceOnDragableObject && SDRDRAG_MOVE==m_eDragMode ) + m_eDragMode=SDRDRAG_ROTATE; + else + m_eDragMode=SDRDRAG_MOVE; + + pDrawViewWrapper->SetDragMode(m_eDragMode); + + if( !m_bWaitingForDoubleClick && m_aSelection.maybeSwitchSelectionAfterSingleClickWasEnsured() ) + { + this->impl_selectObjectAndNotiy(); + } + } + else + m_aSelection.resetPossibleSelectionAfterSingleClickWasEnsured(); + } + else if( isDoubleClick(rMEvt) && !bMouseUpWithoutMouseDown /*#i106966#*/ ) + { + Point aMousePixel = rMEvt.GetPosPixel(); + execute_DoubleClick( &aMousePixel ); + } + + //@todo ForcePointer(&rMEvt); + pWindow->ReleaseMouse(); + + if( m_aSelection.isSelectionDifferentFromBeforeMouseDown() ) + bNotifySelectionChange = true; + } + + impl_SetMousePointer( rMEvt ); + + if(bNotifySelectionChange) + impl_notifySelectionChangeListeners(); +} + +void ChartController::execute_DoubleClick( const Point* pMousePixel ) +{ + bool bEditText = false; + if ( m_aSelection.hasSelection() ) + { + ::rtl::OUString aCID( m_aSelection.getSelectedCID() ); + if ( aCID.getLength() ) + { + ObjectType eObjectType = ObjectIdentifier::getObjectType( aCID ); + if ( OBJECTTYPE_TITLE == eObjectType ) + { + bEditText = true; + } + } + else + { + // #i12587# support for shapes in chart + SdrObject* pObj = DrawViewWrapper::getSdrObject( m_aSelection.getSelectedAdditionalShape() ); + if ( pObj && pObj->ISA( SdrTextObj ) ) + { + bEditText = true; + } + } + } + + if ( bEditText ) + { + executeDispatch_EditText( pMousePixel ); + } + else + { + executeDispatch_ObjectProperties(); + } +} + +void ChartController::execute_Resize() +{ + m_pChartWindow->Invalidate(); +} +void ChartController::execute_Activate() +{ + ///// pDrawViewWrapper->SetEditMode(TRUE); +} +void ChartController::execute_Deactivate() +{ + /* + pDrawViewWrapper->SetEditMode(FALSE); + this->ReleaseMouse(); + */ +} +void ChartController::execute_GetFocus() +{ +} +void ChartController::execute_LoseFocus() +{ + //this->ReleaseMouse(); +} + +void ChartController::execute_Command( const CommandEvent& rCEvt ) +{ + Window* pWindow = m_pChartWindow; + + bool bIsAction = false; + { + ::vos::OGuard aGuard( Application::GetSolarMutex()); + DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; + if(!pWindow || !pDrawViewWrapper) + return; + bIsAction = m_pDrawViewWrapper->IsAction(); + } + + // pop-up menu + if(rCEvt.GetCommand() == COMMAND_CONTEXTMENU && !bIsAction) + { + m_pChartWindow->ReleaseMouse(); + + if( m_aSelection.isSelectionDifferentFromBeforeMouseDown() ) + impl_notifySelectionChangeListeners(); + + if ( isShapeContext() ) + { + // #i12587# support for shapes in chart + PopupMenu aContextMenu( SchResId( m_pDrawViewWrapper->IsTextEdit() ? + RID_CONTEXTMENU_SHAPEEDIT : RID_CONTEXTMENU_SHAPE ) ); + ::svt::ContextMenuHelper aContextMenuHelper( m_xFrame ); + Point aPos( rCEvt.GetMousePosPixel() ); + if( !rCEvt.IsMouseEvent() ) + { + aPos = m_pChartWindow->GetPointerState().maPos; + } + aContextMenuHelper.completeAndExecute( aPos, aContextMenu ); + } + else + { + // todo: the context menu should be specified by an xml file in uiconfig + uno::Reference< awt::XPopupMenu > xPopupMenu( + m_xCC->getServiceManager()->createInstanceWithContext( + C2U("com.sun.star.awt.PopupMenu"), m_xCC ), uno::UNO_QUERY ); + uno::Reference< awt::XMenuExtended > xMenuEx( xPopupMenu, uno::UNO_QUERY ); + if( xPopupMenu.is() && xMenuEx.is()) + { + sal_Int16 nUniqueId = 1; + ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() ); + Reference< XDiagram > xDiagram = ChartModelHelper::findDiagram( getModel() ); + + OUString aFormatCommand( lcl_getFormatCommandForObjectCID( m_aSelection.getSelectedCID() ) ); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, aFormatCommand ); + + //some commands for dataseries and points: + //----- + if( OBJECTTYPE_DATA_SERIES == eObjectType || OBJECTTYPE_DATA_POINT == eObjectType ) + { + bool bIsPoint = ( OBJECTTYPE_DATA_POINT == eObjectType ); + uno::Reference< XDataSeries > xSeries = ObjectIdentifier::getDataSeriesForCID( m_aSelection.getSelectedCID(), getModel() ); + uno::Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY ); + Reference< chart2::XRegressionCurve > xTrendline( RegressionCurveHelper::getFirstCurveNotMeanValueLine( xCurveCnt ) ); + bool bHasEquation = RegressionCurveHelper::hasEquation( xTrendline ); + Reference< chart2::XRegressionCurve > xMeanValue( RegressionCurveHelper::getMeanValueLine( xCurveCnt ) ); + bool bHasYErrorBars = StatisticsHelper::hasErrorBars( xSeries, true ); + bool bHasDataLabelsAtSeries = DataSeriesHelper::hasDataLabelsAtSeries( xSeries ); + bool bHasDataLabelsAtPoints = DataSeriesHelper::hasDataLabelsAtPoints( xSeries ); + bool bHasDataLabelAtPoint = false; + sal_Int32 nPointIndex = -1; + if( bIsPoint ) + { + nPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( m_aSelection.getSelectedCID() ); + bHasDataLabelAtPoint = DataSeriesHelper::hasDataLabelAtPoint( xSeries, nPointIndex ); + } + bool bSelectedPointIsFormatted = false; + bool bHasFormattedDataPointsOtherThanSelected = false; + + Reference< beans::XPropertySet > xSeriesProperties( xSeries, uno::UNO_QUERY ); + if( xSeriesProperties.is() ) + { + uno::Sequence< sal_Int32 > aAttributedDataPointIndexList; + if( xSeriesProperties->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList ) + { + if( aAttributedDataPointIndexList.hasElements() ) + { + if( bIsPoint ) + { + ::std::vector< sal_Int32 > aIndices( ContainerHelper::SequenceToVector( aAttributedDataPointIndexList ) ); + ::std::vector< sal_Int32 >::iterator aIt = ::std::find( aIndices.begin(), aIndices.end(), nPointIndex ); + if( aIt != aIndices.end()) + bSelectedPointIsFormatted = true; + else + bHasFormattedDataPointsOtherThanSelected = true; + } + else + bHasFormattedDataPointsOtherThanSelected = true; + } + } + } + + //const sal_Int32 nIdBeforeFormat = nUniqueId; + if( bIsPoint ) + { + if( bHasDataLabelAtPoint ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatDataLabel") ); + if( !bHasDataLabelAtPoint ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertDataLabel") ); + else + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteDataLabel") ); + if( bSelectedPointIsFormatted ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:ResetDataPoint")); + + xPopupMenu->insertSeparator( -1 ); + + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatDataSeries") ); + } + + Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries ) ); + if( xChartType->getChartType().equals(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) ) + { + try + { + Reference< beans::XPropertySet > xChartTypeProp( xChartType, uno::UNO_QUERY ); + if( xChartTypeProp.is() ) + { + bool bJapaneseStyle = false; + xChartTypeProp->getPropertyValue( C2U( "Japanese" ) ) >>= bJapaneseStyle; + + if( bJapaneseStyle ) + { + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatStockLoss") ); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatStockGain") ); + } + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + + if( bHasDataLabelsAtSeries ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatDataLabels") ); + if( xTrendline.is() ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatTrendline") ); + if( bHasEquation ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatTrendlineEquation") ); + if( xMeanValue.is() ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatMeanValue") ); + if( bHasYErrorBars ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatYErrorBars") ); + + //if( nIdBeforeFormat != nUniqueId ) + xPopupMenu->insertSeparator( -1 ); + + //const sal_Int32 nIdBeforeInsert = nUniqueId; + + if( !bHasDataLabelsAtSeries ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertDataLabels") ); + if( !xTrendline.is() ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertTrendline") ); + else if( !bHasEquation ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertTrendlineEquation") ); + if( !xMeanValue.is() ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertMeanValue") ); + if( !bHasYErrorBars ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertYErrorBars") ); + + //if( nIdBeforeInsert != nUniqueId ) + // xPopupMenu->insertSeparator( -1 ); + + //const sal_Int32 nIdBeforeDelete = nUniqueId; + + if( bHasDataLabelsAtSeries || ( bHasDataLabelsAtPoints && bHasFormattedDataPointsOtherThanSelected ) ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteDataLabels") ); + if( xTrendline.is() ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteTrendline") ); + if( bHasEquation ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteTrendlineEquation") ); + if( xMeanValue.is() ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteMeanValue") ); + if( bHasYErrorBars ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteYErrorBars") ); + + if( bHasFormattedDataPointsOtherThanSelected ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:ResetAllDataPoints")); + + //if( nIdBeforeDelete != nUniqueId ) + xPopupMenu->insertSeparator( -1 ); + + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId, C2U(".uno:ArrangeRow")); + uno::Reference< awt::XPopupMenu > xArrangePopupMenu( + m_xCC->getServiceManager()->createInstanceWithContext( + C2U("com.sun.star.awt.PopupMenu"), m_xCC ), uno::UNO_QUERY ); + uno::Reference< awt::XMenuExtended > xArrangeMenuEx( xArrangePopupMenu, uno::UNO_QUERY ); + if( xArrangePopupMenu.is() && xArrangeMenuEx.is()) + { + sal_Int16 nSubId = nUniqueId + 1; + lcl_insertMenuCommand( xArrangePopupMenu, xArrangeMenuEx, nSubId++, C2U(".uno:Forward") ); + lcl_insertMenuCommand( xArrangePopupMenu, xArrangeMenuEx, nSubId, C2U(".uno:Backward") ); + xPopupMenu->setPopupMenu( nUniqueId, xArrangePopupMenu ); + nUniqueId = nSubId; + } + ++nUniqueId; + } + else if( OBJECTTYPE_DATA_CURVE == eObjectType ) + { + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatTrendlineEquation") ); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertTrendlineEquation") ); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertTrendlineEquationAndR2") ); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertR2Value") ); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteTrendlineEquation") ); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteR2Value") ); + } + else if( OBJECTTYPE_DATA_CURVE_EQUATION == eObjectType ) + { + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertR2Value") ); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteR2Value") ); + } + + //some commands for axes: and grids + //----- + else if( OBJECTTYPE_AXIS == eObjectType || OBJECTTYPE_GRID == eObjectType || OBJECTTYPE_SUBGRID == eObjectType ) + { + Reference< XAxis > xAxis = ObjectIdentifier::getAxisForCID( m_aSelection.getSelectedCID(), getModel() ); + if( xAxis.is() && xDiagram.is() ) + { + sal_Int32 nDimensionIndex = -1; + sal_Int32 nCooSysIndex = -1; + sal_Int32 nAxisIndex = -1; + AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex ); + bool bIsSecondaryAxis = nAxisIndex!=0; + bool bIsAxisVisible = AxisHelper::isAxisVisible( xAxis ); + bool bIsMajorGridVisible = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, true /*bMainGrid*/, xDiagram ); + bool bIsMinorGridVisible = AxisHelper::isGridShown( nDimensionIndex, nCooSysIndex, false /*bMainGrid*/, xDiagram ); + bool bHasTitle = false; + uno::Reference< XTitled > xTitled( xAxis, uno::UNO_QUERY ); + if( xTitled.is()) + bHasTitle = TitleHelper::getCompleteString( xTitled->getTitleObject() ).getLength()>0; + + if( OBJECTTYPE_AXIS != eObjectType && bIsAxisVisible ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatAxis") ); + if( OBJECTTYPE_GRID != eObjectType && bIsMajorGridVisible && !bIsSecondaryAxis ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatMajorGrid") ); + if( OBJECTTYPE_SUBGRID != eObjectType && bIsMinorGridVisible && !bIsSecondaryAxis ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatMinorGrid") ); + + xPopupMenu->insertSeparator( -1 ); + + if( OBJECTTYPE_AXIS != eObjectType && !bIsAxisVisible ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertAxis") ); + if( OBJECTTYPE_GRID != eObjectType && !bIsMajorGridVisible && !bIsSecondaryAxis ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertMajorGrid") ); + if( OBJECTTYPE_SUBGRID != eObjectType && !bIsMinorGridVisible && !bIsSecondaryAxis ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertMinorGrid") ); + if( !bHasTitle ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertAxisTitle") ); + + if( bIsAxisVisible ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteAxis") ); + if( bIsMajorGridVisible && !bIsSecondaryAxis ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteMajorGrid") ); + if( bIsMinorGridVisible && !bIsSecondaryAxis ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteMinorGrid") ); + } + } + + if( OBJECTTYPE_DATA_STOCK_LOSS == eObjectType ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatStockGain") ); + else if( OBJECTTYPE_DATA_STOCK_GAIN == eObjectType ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:FormatStockLoss") ); + + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:TransformDialog")); + + if( OBJECTTYPE_PAGE == eObjectType || OBJECTTYPE_DIAGRAM == eObjectType + || OBJECTTYPE_DIAGRAM_WALL == eObjectType + || OBJECTTYPE_DIAGRAM_FLOOR == eObjectType + || OBJECTTYPE_UNKNOWN == eObjectType ) + { + if( OBJECTTYPE_UNKNOWN != eObjectType ) + xPopupMenu->insertSeparator( -1 ); + bool bHasLegend = LegendHelper::hasLegend( xDiagram ); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertTitles") ); + if( !bHasLegend ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertLegend") ); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:InsertRemoveAxes") ); + if( bHasLegend ) + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DeleteLegend") ); + } + //----- + + xPopupMenu->insertSeparator( -1 ); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DiagramType")); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DataRanges")); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:DiagramData")); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:View3D")); + xPopupMenu->insertSeparator( -1 ); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:Cut")); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:Copy")); + lcl_insertMenuCommand( xPopupMenu, xMenuEx, nUniqueId++, C2U(".uno:Paste")); + + ::svt::ContextMenuHelper aContextMenuHelper( m_xFrame ); + Point aPos( rCEvt.GetMousePosPixel() ); + if( !rCEvt.IsMouseEvent() ) + aPos = m_pChartWindow->GetPointerState().maPos; + aContextMenuHelper.completeAndExecute( aPos, xPopupMenu ); + } + } + } + else if( ( rCEvt.GetCommand() == COMMAND_STARTEXTTEXTINPUT ) || + ( rCEvt.GetCommand() == COMMAND_EXTTEXTINPUT ) || + ( rCEvt.GetCommand() == COMMAND_ENDEXTTEXTINPUT ) || + ( rCEvt.GetCommand() == COMMAND_INPUTCONTEXTCHANGE ) ) + { + //#i84417# enable editing with IME + if( m_pDrawViewWrapper ) + m_pDrawViewWrapper->Command( rCEvt, m_pChartWindow ); + } +} + +bool ChartController::execute_KeyInput( const KeyEvent& rKEvt ) +{ + bool bReturn=false; + + Window* pWindow = m_pChartWindow; + DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; + if(!pWindow || !pDrawViewWrapper) + return bReturn; + + // handle accelerators + if( ! m_apAccelExecute.get() && m_xFrame.is() && m_xCC.is() && m_xCC->getServiceManager().is() ) + { + m_apAccelExecute.reset( ::svt::AcceleratorExecute::createAcceleratorHelper()); + OSL_ASSERT( m_apAccelExecute.get()); + if( m_apAccelExecute.get() ) + m_apAccelExecute->init( + uno::Reference< lang::XMultiServiceFactory >( m_xCC->getServiceManager(), uno::UNO_QUERY ), m_xFrame ); + } + + KeyCode aKeyCode( rKEvt.GetKeyCode()); + sal_uInt16 nCode = aKeyCode.GetCode(); +// bool bShift = aKeyCode.IsShift(); + bool bAlternate = aKeyCode.IsMod2(); + + if( m_apAccelExecute.get() ) + bReturn = m_apAccelExecute->execute( aKeyCode ); + if( bReturn ) + return bReturn; + + if( pDrawViewWrapper->IsTextEdit() ) + { + if( pDrawViewWrapper->KeyInput(rKEvt,pWindow) ) + { + bReturn = true; + if( nCode == KEY_ESCAPE ) + { + this->EndTextEdit(); + } + } + } + + //if( m_pDrawViewWrapper->IsAction() ); + + // keyboard accessibility + ObjectType eObjectType = ObjectIdentifier::getObjectType( m_aSelection.getSelectedCID() ); + if( ! bReturn ) + { + // Natvigation (Tab/F3/Home/End) + uno::Reference< XChartDocument > xChartDoc( getModel(), uno::UNO_QUERY ); + ObjectKeyNavigation aObjNav( m_aSelection.getSelectedOID(), xChartDoc, ExplicitValueProvider::getExplicitValueProvider( m_xChartView )); + awt::KeyEvent aKeyEvent( ::svt::AcceleratorExecute::st_VCLKey2AWTKey( aKeyCode )); + bReturn = aObjNav.handleKeyEvent( aKeyEvent ); + if( bReturn ) + { + ObjectIdentifier aNewOID = aObjNav.getCurrentSelection(); + uno::Any aNewSelection; + if ( aNewOID.isValid() && !ObjectHierarchy::isRootNode( aNewOID ) ) + { + aNewSelection = aNewOID.getAny(); + } + if ( m_eDragMode == SDRDRAG_ROTATE && !SelectionHelper::isRotateableObject( aNewOID.getObjectCID(), getModel() ) ) + { + m_eDragMode = SDRDRAG_MOVE; + } + bReturn = select( aNewSelection ); + } + } + + // Position and Size (+/-/arrow-keys) or pie segment dragging + if( ! bReturn ) + { + // pie segment dragging + // note: could also be done for data series + if( eObjectType == OBJECTTYPE_DATA_POINT && + ObjectIdentifier::getDragMethodServiceName( m_aSelection.getSelectedCID() ).equals( + ObjectIdentifier::getPieSegmentDragMethodServiceName())) + { + bool bDrag = false; + bool bDragInside = false; + if( nCode == KEY_ADD || + nCode == KEY_SUBTRACT ) + { + bDrag = true; + bDragInside = ( nCode == KEY_SUBTRACT ); + } + else if( + nCode == KEY_LEFT || + nCode == KEY_RIGHT || + nCode == KEY_UP || + nCode == KEY_DOWN ) + { + bDrag = true; + rtl::OUString aParameter( ObjectIdentifier::getDragParameterString( m_aSelection.getSelectedCID() )); + sal_Int32 nOffsetPercentDummy( 0 ); + awt::Point aMinimumPosition( 0, 0 ); + awt::Point aMaximumPosition( 0, 0 ); + ObjectIdentifier::parsePieSegmentDragParameterString( + aParameter, nOffsetPercentDummy, aMinimumPosition, aMaximumPosition ); + aMaximumPosition.Y -= aMinimumPosition.Y; + aMaximumPosition.X -= aMinimumPosition.X; + + bDragInside = + (nCode == KEY_RIGHT && (aMaximumPosition.X < 0)) || + (nCode == KEY_LEFT && (aMaximumPosition.X > 0)) || + (nCode == KEY_DOWN && (aMaximumPosition.Y < 0)) || + (nCode == KEY_UP && (aMaximumPosition.Y > 0)); + } + + if( bDrag ) + { + double fAmount = bAlternate ? 0.01 : 0.05; + if( bDragInside ) + fAmount *= -1.0; + + bReturn = impl_DragDataPoint( m_aSelection.getSelectedCID(), fAmount ); + } + } + else + { + // size + if( nCode == KEY_ADD || + nCode == KEY_SUBTRACT ) + { + if( eObjectType == OBJECTTYPE_DIAGRAM ) + { + // default 1 mm in each direction + double fGrowAmountX = 200.0; + double fGrowAmountY = 200.0; + if( bAlternate && pWindow ) + { + // together with Alt-key: 1 px in each direction + Size aPixelSize = pWindow->PixelToLogic( Size( 2, 2 )); + fGrowAmountX = static_cast< double >( aPixelSize.Width()); + fGrowAmountY = static_cast< double >( aPixelSize.Height()); + } + if( nCode == KEY_SUBTRACT ) + { + fGrowAmountX = -fGrowAmountX; + fGrowAmountY = -fGrowAmountY; + } + bReturn = impl_moveOrResizeObject( + m_aSelection.getSelectedCID(), CENTERED_RESIZE_OBJECT, fGrowAmountX, fGrowAmountY ); + } + } + // position + else if( nCode == KEY_LEFT || + nCode == KEY_RIGHT || + nCode == KEY_UP || + nCode == KEY_DOWN ) + { + if( m_aSelection.isDragableObjectSelected() ) + { + // default 1 mm + double fShiftAmountX = 100.0; + double fShiftAmountY = 100.0; + if( bAlternate && pWindow ) + { + // together with Alt-key: 1 px + Size aPixelSize = pWindow->PixelToLogic( Size( 1, 1 )); + fShiftAmountX = static_cast< double >( aPixelSize.Width()); + fShiftAmountY = static_cast< double >( aPixelSize.Height()); + } + switch( nCode ) + { + case KEY_LEFT: + fShiftAmountX = -fShiftAmountX; + fShiftAmountY = 0.0; + break; + case KEY_RIGHT: + fShiftAmountY = 0.0; + break; + case KEY_UP: + fShiftAmountX = 0.0; + fShiftAmountY = -fShiftAmountY; + break; + case KEY_DOWN: + fShiftAmountX = 0.0; + break; + } + if( m_aSelection.getSelectedCID().getLength() ) + { + //move chart objects + bReturn = impl_moveOrResizeObject( + m_aSelection.getSelectedCID(), MOVE_OBJECT, fShiftAmountX, fShiftAmountY ); + } + else + { + //move additional shapes + uno::Reference< drawing::XShape > xShape( m_aSelection.getSelectedAdditionalShape() ); + if( xShape.is() ) + { + awt::Point aPos( xShape->getPosition() ); + awt::Size aSize( xShape->getSize() ); + awt::Size aPageSize( ChartModelHelper::getPageSize( getModel() ) ); + aPos.X = static_cast< long >( static_cast< double >( aPos.X ) + fShiftAmountX ); + aPos.Y = static_cast< long >( static_cast< double >( aPos.Y ) + fShiftAmountY ); + if( aPos.X + aSize.Width > aPageSize.Width ) + aPos.X = aPageSize.Width - aSize.Width; + if( aPos.X < 0 ) + aPos.X = 0; + if( aPos.Y + aSize.Height > aPageSize.Height ) + aPos.Y = aPageSize.Height - aSize.Height; + if( aPos.Y < 0 ) + aPos.Y = 0; + + xShape->setPosition( aPos ); + } + } + } + } + } + } + + // text edit + if( ! bReturn && + nCode == KEY_F2 ) + { + if( OBJECTTYPE_TITLE == eObjectType ) + { + executeDispatch_EditText(); + bReturn = true; + } + } + + // deactivate inplace mode (this code should be unnecessary, but + // unfortunately is not) + if( ! bReturn && + nCode == KEY_ESCAPE ) + { + uno::Reference< frame::XDispatchHelper > xDispatchHelper( + m_xCC->getServiceManager()->createInstanceWithContext( + C2U("com.sun.star.frame.DispatchHelper"), m_xCC ), uno::UNO_QUERY ); + if( xDispatchHelper.is()) + { + uno::Sequence< beans::PropertyValue > aArgs; + xDispatchHelper->executeDispatch( + uno::Reference< frame::XDispatchProvider >( m_xFrame, uno::UNO_QUERY ), + C2U(".uno:TerminateInplaceActivation"), + C2U("_parent"), + frame::FrameSearchFlag::PARENT, + aArgs ); + bReturn = true; + } + } + + if( ! bReturn && + (nCode == KEY_DELETE || nCode == KEY_BACKSPACE )) + { + bReturn = executeDispatch_Delete(); + if( ! bReturn ) + { + InfoBox( m_pChartWindow, String(SchResId( STR_ACTION_NOTPOSSIBLE ))).Execute(); + } + } + + /* old chart: + // Ctrl-Shift-R: Repaint + if (!bReturn && GetWindow()) + { + KeyCode aKeyCode = rKEvt.GetKeyCode(); + + if (aKeyCode.IsMod1() && aKeyCode.IsShift() + && aKeyCode.GetCode() == KEY_R) + { + // 3D-Kontext wieder zerstoeren + GetWindow()->Invalidate(); + bReturn = TRUE; + } + } + */ + return bReturn; +} + +bool ChartController::requestQuickHelp( + ::Point aAtLogicPosition, + bool bIsBalloonHelp, + ::rtl::OUString & rOutQuickHelpText, + awt::Rectangle & rOutEqualRect ) +{ + uno::Reference< frame::XModel > xChartModel; + if( m_aModel.is()) + xChartModel.set( getModel() ); + if( !xChartModel.is()) + return false; + + // help text + ::rtl::OUString aCID; + if( m_pDrawViewWrapper ) + { + aCID = SelectionHelper::getHitObjectCID( + aAtLogicPosition, *m_pDrawViewWrapper ); + } + bool bResult( aCID.getLength()); + + if( bResult ) + { + // get help text + rOutQuickHelpText = ObjectNameProvider::getHelpText( aCID, xChartModel, bIsBalloonHelp /* bVerbose */ ); + + // set rectangle + ExplicitValueProvider * pValueProvider( + ExplicitValueProvider::getExplicitValueProvider( m_xChartView )); + if( pValueProvider ) + rOutEqualRect = pValueProvider->getRectangleOfObject( aCID, true ); + } + + return bResult; +} + +//----------------------------------------------------------------- +// XSelectionSupplier (optional interface) +//----------------------------------------------------------------- + sal_Bool SAL_CALL ChartController +::select( const uno::Any& rSelection ) + throw( lang::IllegalArgumentException ) +{ + bool bSuccess = false; + + if ( rSelection.hasValue() ) + { + const uno::Type& rType = rSelection.getValueType(); + if ( rType == ::getCppuType( static_cast< const ::rtl::OUString* >( 0 ) ) ) + { + ::rtl::OUString aNewCID; + if ( ( rSelection >>= aNewCID ) && m_aSelection.setSelection( aNewCID ) ) + { + bSuccess = true; + } + } + else if ( rType == ::getCppuType( static_cast< const uno::Reference< drawing::XShape >* >( 0 ) ) ) + { + uno::Reference< drawing::XShape > xShape; + if ( ( rSelection >>= xShape ) && m_aSelection.setSelection( xShape ) ) + { + bSuccess = true; + } + } + } + else + { + if ( m_aSelection.hasSelection() ) + { + m_aSelection.clearSelection(); + bSuccess = true; + } + } + + if ( bSuccess ) + { + this->impl_selectObjectAndNotiy(); + return sal_True; + } + + return sal_False; +} + + uno::Any SAL_CALL ChartController +::getSelection() throw(uno::RuntimeException) +{ + uno::Any aReturn; + if ( m_aSelection.hasSelection() ) + { + ::rtl::OUString aCID( m_aSelection.getSelectedCID() ); + if ( aCID.getLength() ) + { + aReturn = uno::makeAny( aCID ); + } + else + { + // #i12587# support for shapes in chart + aReturn = uno::makeAny( m_aSelection.getSelectedAdditionalShape() ); + } + } + return aReturn; +} + + void SAL_CALL ChartController +::addSelectionChangeListener( const uno::Reference< + view::XSelectionChangeListener > & xListener ) + throw(uno::RuntimeException) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex()); + 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< view::XSelectionChangeListener >*)0), xListener ); +} + + void SAL_CALL ChartController +::removeSelectionChangeListener( const uno::Reference< + view::XSelectionChangeListener > & xListener ) + throw(uno::RuntimeException) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex()); + 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< view::XSelectionChangeListener >*)0), xListener ); +} + + void ChartController +::impl_notifySelectionChangeListeners() +{ + ::cppu::OInterfaceContainerHelper* pIC = m_aLifeTimeManager.m_aListenerContainer + .getContainer( ::getCppuType((const uno::Reference< view::XSelectionChangeListener >*)0) ); + if( pIC ) + { + uno::Reference< view::XSelectionSupplier > xSelectionSupplier(this); + lang::EventObject aEvent( xSelectionSupplier ); + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + uno::Reference< view::XSelectionChangeListener > xListener( aIt.next(), uno::UNO_QUERY ); + if( xListener.is() ) + xListener->selectionChanged( aEvent ); + } + } +} + +void ChartController::impl_selectObjectAndNotiy() +{ + DrawViewWrapper* pDrawViewWrapper = m_pDrawViewWrapper; + if( pDrawViewWrapper ) + { + pDrawViewWrapper->SetDragMode( m_eDragMode ); + m_aSelection.applySelection( m_pDrawViewWrapper ); + } + impl_notifySelectionChangeListeners(); +} + +bool ChartController::impl_moveOrResizeObject( + const ::rtl::OUString & rCID, + eMoveOrResizeType eType, + double fAmountLogicX, + double fAmountLogicY ) +{ + bool bResult = false; + bool bNeedShift = true; + bool bNeedResize = ( eType == CENTERED_RESIZE_OBJECT ); + + uno::Reference< frame::XModel > xChartModel( getModel() ); + uno::Reference< beans::XPropertySet > xObjProp( + ObjectIdentifier::getObjectPropertySet( rCID, xChartModel )); + if( xObjProp.is()) + { + awt::Size aRefSize = ChartModelHelper::getPageSize( xChartModel ); + + chart2::RelativePosition aRelPos; + chart2::RelativeSize aRelSize; + bool bDeterminePos = !(xObjProp->getPropertyValue( C2U("RelativePosition")) >>= aRelPos); + bool bDetermineSize = !bNeedResize || !(xObjProp->getPropertyValue( C2U("RelativeSize")) >>= aRelSize); + + if( ( bDeterminePos || bDetermineSize ) && + ( aRefSize.Width > 0 && aRefSize.Height > 0 ) ) + { + ExplicitValueProvider * pValueProvider( + ExplicitValueProvider::getExplicitValueProvider( m_xChartView )); + if( pValueProvider ) + { + awt::Rectangle aRect( pValueProvider->getRectangleOfObject( rCID )); + double fWidth = static_cast< double >( aRefSize.Width ); + double fHeight = static_cast< double >( aRefSize.Height ); + if( bDetermineSize ) + { + aRelSize.Primary = static_cast< double >( aRect.Width ) / fWidth; + aRelSize.Secondary = static_cast< double >( aRect.Height ) / fHeight; + } + if( bDeterminePos ) + { + if( bNeedResize && aRelSize.Primary > 0.0 && aRelSize.Secondary > 0.0 ) + { + aRelPos.Primary = (static_cast< double >( aRect.X ) / fWidth) + + (aRelSize.Primary / 2.0); + aRelPos.Secondary = (static_cast< double >( aRect.Y ) / fHeight) + + (aRelSize.Secondary / 2.0); + aRelPos.Anchor = drawing::Alignment_CENTER; + } + else + { + aRelPos.Primary = static_cast< double >( aRect.X ) / fWidth; + aRelPos.Secondary = static_cast< double >( aRect.Y ) / fHeight; + aRelPos.Anchor = drawing::Alignment_TOP_LEFT; + } + } + } + } + + if( eType == CENTERED_RESIZE_OBJECT ) + bResult = lcl_GrowAndShiftLogic( aRelPos, aRelSize, aRefSize, fAmountLogicX, fAmountLogicY ); + else if( eType == MOVE_OBJECT ) + bResult = lcl_MoveObjectLogic( aRelPos, aRelSize, aRefSize, fAmountLogicX, fAmountLogicY ); + + if( bResult ) + { + ActionDescriptionProvider::ActionType eActionType(ActionDescriptionProvider::MOVE); + if( bNeedResize ) + eActionType = ActionDescriptionProvider::RESIZE; + + ObjectType eObjectType = ObjectIdentifier::getObjectType( rCID ); + UndoGuard aUndoGuard( ActionDescriptionProvider::createDescription( + eActionType, ObjectNameProvider::getName( eObjectType )), m_xUndoManager, xChartModel ); + { + ControllerLockGuard aCLGuard( xChartModel ); + if( bNeedShift ) + xObjProp->setPropertyValue( C2U("RelativePosition"), uno::makeAny( aRelPos )); + if( bNeedResize || (eObjectType == OBJECTTYPE_DIAGRAM) )//Also set an explicat size at the diagram when an explicit position is set + xObjProp->setPropertyValue( C2U("RelativeSize"), uno::makeAny( aRelSize )); + } + aUndoGuard.commitAction(); + } + } + return bResult; +} + +bool ChartController::impl_DragDataPoint( const ::rtl::OUString & rCID, double fAdditionalOffset ) +{ + bool bResult = false; + if( fAdditionalOffset < -1.0 || fAdditionalOffset > 1.0 || fAdditionalOffset == 0.0 ) + return bResult; + + sal_Int32 nDataPointIndex = ObjectIdentifier::getIndexFromParticleOrCID( rCID ); + uno::Reference< chart2::XDataSeries > xSeries( + ObjectIdentifier::getDataSeriesForCID( rCID, getModel() )); + if( xSeries.is()) + { + try + { + uno::Reference< beans::XPropertySet > xPointProp( xSeries->getDataPointByIndex( nDataPointIndex )); + double fOffset = 0.0; + if( xPointProp.is() && + (xPointProp->getPropertyValue( C2U("Offset" )) >>= fOffset ) && + (( fAdditionalOffset > 0.0 && fOffset < 1.0 ) || (fOffset > 0.0)) ) + { + fOffset += fAdditionalOffset; + if( fOffset > 1.0 ) + fOffset = 1.0; + else if( fOffset < 0.0 ) + fOffset = 0.0; + xPointProp->setPropertyValue( C2U("Offset"), uno::makeAny( fOffset )); + bResult = true; + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + + return bResult; +} + +void ChartController::impl_SetMousePointer( const MouseEvent & rEvent ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex()); + Window* pWindow = m_pChartWindow; + if( m_pDrawViewWrapper && pWindow ) + { + Point aMousePos( pWindow->PixelToLogic( rEvent.GetPosPixel())); + sal_uInt16 nModifier = rEvent.GetModifier(); + BOOL bLeftDown = rEvent.IsLeft(); + + if ( m_pDrawViewWrapper->IsTextEdit() ) + { + if( m_pDrawViewWrapper->IsTextEditHit( aMousePos, HITPIX) ) + { + pWindow->SetPointer( m_pDrawViewWrapper->GetPreferedPointer( + aMousePos, pWindow, nModifier, bLeftDown ) ); + return; + } + } + else if( m_pDrawViewWrapper->IsAction() ) + { + return;//don't change pointer during running action + } + + SdrHdl* pHitSelectionHdl = 0; + if( m_aSelection.isResizeableObjectSelected() ) + pHitSelectionHdl = m_pDrawViewWrapper->PickHandle( aMousePos ); + + if( pHitSelectionHdl ) + { + + Pointer aPointer = m_pDrawViewWrapper->GetPreferedPointer( + aMousePos, pWindow, nModifier, bLeftDown ); + bool bForceArrowPointer = false; + + ObjectIdentifier aOID( m_aSelection.getSelectedOID() ); + + switch( aPointer.GetStyle()) + { + case POINTER_NSIZE: + case POINTER_SSIZE: + case POINTER_WSIZE: + case POINTER_ESIZE: + case POINTER_NWSIZE: + case POINTER_NESIZE: + case POINTER_SWSIZE: + case POINTER_SESIZE: + if( ! m_aSelection.isResizeableObjectSelected() ) + bForceArrowPointer = true; + break; + case POINTER_MOVE: + if ( !aOID.isDragableObject() ) + bForceArrowPointer = true; + break; + case POINTER_MOVEPOINT: + case POINTER_MOVEBEZIERWEIGHT: + // there is no point-editing in a chart + // the POINTER_MOVEBEZIERWEIGHT appears in 3d data points + bForceArrowPointer = true; + break; + default: + break; + } + + if( bForceArrowPointer ) + pWindow->SetPointer( Pointer( POINTER_ARROW )); + else + pWindow->SetPointer( aPointer ); + } + else + { + // #i12587# support for shapes in chart + if ( m_eDrawMode == CHARTDRAW_INSERT && + ( !m_pDrawViewWrapper->IsMarkedHit( aMousePos ) || !m_aSelection.isDragableObjectSelected() ) ) + { + PointerStyle ePointerStyle = POINTER_DRAW_RECT; + SdrObjKind eKind = static_cast< SdrObjKind >( m_pDrawViewWrapper->GetCurrentObjIdentifier() ); + switch ( eKind ) + { + case OBJ_LINE: + { + ePointerStyle = POINTER_DRAW_LINE; + } + break; + case OBJ_RECT: + case OBJ_CUSTOMSHAPE: + { + ePointerStyle = POINTER_DRAW_RECT; + } + break; + case OBJ_CIRC: + { + ePointerStyle = POINTER_DRAW_ELLIPSE; + } + break; + case OBJ_FREELINE: + { + ePointerStyle = POINTER_DRAW_POLYGON; + } + break; + case OBJ_TEXT: + { + ePointerStyle = POINTER_DRAW_TEXT; + } + break; + case OBJ_CAPTION: + { + ePointerStyle = POINTER_DRAW_CAPTION; + } + break; + default: + { + ePointerStyle = POINTER_DRAW_RECT; + } + break; + } + pWindow->SetPointer( Pointer( ePointerStyle ) ); + return; + } + + ::rtl::OUString aHitObjectCID( + SelectionHelper::getHitObjectCID( + aMousePos, *m_pDrawViewWrapper, true /*bGetDiagramInsteadOf_Wall*/ )); + + if( m_pDrawViewWrapper->IsTextEdit() ) + { + if( aHitObjectCID.equals(m_aSelection.getSelectedCID()) ) + { + pWindow->SetPointer( Pointer( POINTER_ARROW )); + return; + } + } + + if( !aHitObjectCID.getLength() ) + { + //additional shape was hit + pWindow->SetPointer( POINTER_MOVE ); + } + else if( ObjectIdentifier::isDragableObject( aHitObjectCID ) ) + { + if( (m_eDragMode == SDRDRAG_ROTATE) + && SelectionHelper::isRotateableObject( aHitObjectCID + , getModel() ) ) + pWindow->SetPointer( Pointer( POINTER_ROTATE ) ); + else + { + ObjectType eHitObjectType = ObjectIdentifier::getObjectType( aHitObjectCID ); + if( eHitObjectType == OBJECTTYPE_DATA_POINT ) + { + if( !ObjectIdentifier::areSiblings(aHitObjectCID,m_aSelection.getSelectedCID()) + && !ObjectIdentifier::areIdenticalObjects(aHitObjectCID,m_aSelection.getSelectedCID()) ) + { + pWindow->SetPointer( Pointer( POINTER_ARROW )); + return; + } + } + pWindow->SetPointer( POINTER_MOVE ); + } + } + else + pWindow->SetPointer( Pointer( POINTER_ARROW )); + } + } +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/ChartDropTargetHelper.cxx b/chart2/source/controller/main/ChartDropTargetHelper.cxx new file mode 100644 index 000000000000..8749ca1bc062 --- /dev/null +++ b/chart2/source/controller/main/ChartDropTargetHelper.cxx @@ -0,0 +1,204 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "ChartDropTargetHelper.hxx" +#include "DiagramHelper.hxx" +#include "DataSourceHelper.hxx" + +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/data/XDataProvider.hpp> +#include <com/sun/star/container/XChild.hpp> + +#include <sot/formats.hxx> +#include <vector> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace +{ + +::std::vector< OUString > lcl_getStringsFromByteSequence( + const Sequence< sal_Int8 > & aByteSequence ) +{ + ::std::vector< OUString > aResult; + const sal_Int32 nLength = aByteSequence.getLength(); + const sal_Char * pBytes( reinterpret_cast< const sal_Char* >( aByteSequence.getConstArray())); + sal_Int32 nStartPos = 0; + for( sal_Int32 nPos=0; nPos<nLength; ++nPos ) + { + if( pBytes[nPos] == '\0' ) + { + aResult.push_back( OUString( pBytes + nStartPos, (nPos - nStartPos), RTL_TEXTENCODING_ASCII_US )); + nStartPos = nPos + 1; + } + } + return aResult; +} + +} // anonymous namespace + +namespace chart +{ + +ChartDropTargetHelper::ChartDropTargetHelper( + const Reference< datatransfer::dnd::XDropTarget >& rxDropTarget, + const Reference< chart2::XChartDocument > & xChartDocument ) : + DropTargetHelper( rxDropTarget ), + m_xChartDocument( xChartDocument ) +{} + +ChartDropTargetHelper::~ChartDropTargetHelper() +{} + +bool ChartDropTargetHelper::satisfiesPrerequisites() const +{ + return ( m_xChartDocument.is() && + ! m_xChartDocument->hasInternalDataProvider()); +} + +sal_Int8 ChartDropTargetHelper::AcceptDrop( const AcceptDropEvent& rEvt ) +{ + sal_Int8 nResult = DND_ACTION_NONE; + + if( ( rEvt.mnAction == DND_ACTION_COPY || + rEvt.mnAction == DND_ACTION_MOVE ) && + satisfiesPrerequisites() && + IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ) + { + // @todo: check if the data is suitable. Is this possible without XTransferable? + nResult = rEvt.mnAction; + } + + return nResult; +} + +sal_Int8 ChartDropTargetHelper::ExecuteDrop( const ExecuteDropEvent& rEvt ) +{ + sal_Int8 nResult = DND_ACTION_NONE; + + if( ( rEvt.mnAction == DND_ACTION_COPY || + rEvt.mnAction == DND_ACTION_MOVE ) && + rEvt.maDropEvent.Transferable.is() && + satisfiesPrerequisites()) + { + TransferableDataHelper aDataHelper( rEvt.maDropEvent.Transferable ); + if( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK )) + { + Sequence< sal_Int8 > aBytes; + if( aDataHelper.GetSequence( SOT_FORMATSTR_ID_LINK, aBytes )) + { + ::std::vector< OUString > aStrings( lcl_getStringsFromByteSequence( aBytes )); + if( aStrings.size() >= 3 && + aStrings[0].equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "soffice" ))) + { + OUString aDocName( aStrings[1] ); + OUString aRangeString( aStrings[2] ); + Reference< container::XChild > xChild( m_xChartDocument, uno::UNO_QUERY ); + if( xChild.is()) + { + Reference< frame::XModel > xParentModel( xChild->getParent(), uno::UNO_QUERY ); + if( xParentModel.is() && + m_xChartDocument.is()) + { + bool bDataComesFromParent = true; + // @todo: get the title somehow and compare it to + // aDocName if successful (the document is the + // parent) + if( bDataComesFromParent ) + { + Reference< chart2::data::XDataProvider > xDataProvider( m_xChartDocument->getDataProvider()); + if( xDataProvider.is() && + DataSourceHelper::allArgumentsForRectRangeDetected( m_xChartDocument )) + { + DiagramHelper::tTemplateWithServiceName aTempWithServ( + DiagramHelper::getTemplateForDiagram( + m_xChartDocument->getFirstDiagram(), + Reference< lang::XMultiServiceFactory >( + m_xChartDocument->getChartTypeManager(), uno::UNO_QUERY ))); + if( aTempWithServ.first.is()) + { + Reference< chart2::data::XDataSource > xDataSource( + DataSourceHelper::pressUsedDataIntoRectangularFormat( m_xChartDocument )); + Sequence< beans::PropertyValue > aArguments( + xDataProvider->detectArguments( xDataSource )); + + OUString aOldRange; + beans::PropertyValue * pCellRange = 0; + for( sal_Int32 i=0; i<aArguments.getLength(); ++i ) + { + if( aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation"))) + { + pCellRange = (aArguments.getArray() + i); + aArguments[i].Value >>= aOldRange; + break; + } + } + if( pCellRange ) + { + // copy means add ranges, move means replace + if( rEvt.mnAction == DND_ACTION_COPY ) + { + // @todo: using implcit knowledge that ranges can be + // merged with ";". This should be done more general + pCellRange->Value <<= (aOldRange + OUString( sal_Unicode(';')) + aRangeString ); + } + // move means replace range + else + { + pCellRange->Value <<= aRangeString; + } + + xDataSource.set( xDataProvider->createDataSource( aArguments )); + aTempWithServ.first->changeDiagramData( + m_xChartDocument->getFirstDiagram(), + xDataSource, + aArguments ); + + // always return copy state to avoid deletion of the + // dragged range + nResult = DND_ACTION_COPY; + } + } + } + } + } + } + } + } + } + } + return nResult; +} + +} // namespace chart diff --git a/chart2/source/controller/main/ChartDropTargetHelper.hxx b/chart2/source/controller/main/ChartDropTargetHelper.hxx new file mode 100644 index 000000000000..2de9c0c72663 --- /dev/null +++ b/chart2/source/controller/main/ChartDropTargetHelper.hxx @@ -0,0 +1,69 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_CHARTDROPTARGETHELPER_HXX +#define CHART2_CHARTDROPTARGETHELPER_HXX + +// for DropTargetHelper +#include <svtools/transfer.hxx> + +namespace com { namespace sun { namespace star { +namespace chart2 { + class XChartDocument; +} +}}} + +namespace chart +{ + +class ChartDropTargetHelper : public DropTargetHelper +{ +public: + explicit ChartDropTargetHelper( + const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::dnd::XDropTarget >& rxDropTarget, + const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartDocument > & xChartDocument ); + virtual ~ChartDropTargetHelper(); + +protected: + + virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt ); + virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt ); + +private: + // not available + ChartDropTargetHelper(); + + bool satisfiesPrerequisites() const; + + + ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XChartDocument > m_xChartDocument; +}; + +} // namespace chart + +// CHART2_CHARTDROPTARGETHELPER_HXX +#endif diff --git a/chart2/source/controller/main/ChartFrameloader.cxx b/chart2/source/controller/main/ChartFrameloader.cxx new file mode 100644 index 000000000000..cab3816d5033 --- /dev/null +++ b/chart2/source/controller/main/ChartFrameloader.cxx @@ -0,0 +1,208 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" +#include "ChartFrameloader.hxx" +#include "servicenames.hxx" +#include "MediaDescriptorHelper.hxx" +#include "macros.hxx" +#include <comphelper/mediadescriptor.hxx> +#include <com/sun/star/document/XImporter.hpp> +#include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/frame/XLoadable.hpp> + +//............................................................................. +namespace chart +{ +//............................................................................. + +using namespace ::com::sun::star; + +ChartFrameLoader::ChartFrameLoader( + uno::Reference<uno::XComponentContext> const & xContext) + : m_bCancelRequired( sal_False ) +{ + m_xCC = xContext; + m_oCancelFinished.reset(); +} + +ChartFrameLoader::~ChartFrameLoader() +{ +} + + sal_Bool ChartFrameLoader +::impl_checkCancel() +{ + if(m_bCancelRequired) + { + m_oCancelFinished.set(); + return sal_True; + } + return sal_False; +} + +//----------------------------------------------------------------- +// lang::XServiceInfo +//----------------------------------------------------------------- + +APPHELPER_XSERVICEINFO_IMPL(ChartFrameLoader,CHART_FRAMELOADER_SERVICE_IMPLEMENTATION_NAME) + + uno::Sequence< rtl::OUString > ChartFrameLoader +::getSupportedServiceNames_Static() +{ + uno::Sequence< rtl::OUString > aSNS( 1 ); + aSNS.getArray()[ 0 ] = CHART_FRAMELOADER_SERVICE_NAME; + return aSNS; +} + +//----------------------------------------------------------------- +// frame::XFrameLoader +//----------------------------------------------------------------- + + sal_Bool SAL_CALL ChartFrameLoader +::load( const uno::Sequence< beans::PropertyValue >& rMediaDescriptor + , const uno::Reference<frame::XFrame >& xFrame ) + throw (uno::RuntimeException) +{ + //@todo ? need to add as terminate listener to desktop? + + uno::Reference< frame::XModel > xModel; + bool bHaveLoadedModel = false; + + comphelper::MediaDescriptor aMediaDescriptor(rMediaDescriptor); + { + comphelper::MediaDescriptor::const_iterator aIt( aMediaDescriptor.find( aMediaDescriptor.PROP_MODEL())); + if( aIt != aMediaDescriptor.end()) + { + xModel.set( (*aIt).second.get< uno::Reference< frame::XModel > >()); + bHaveLoadedModel = true; + } + } + + //create and initialize the model + if( ! xModel.is()) + { + //@todo?? load mechanism to cancel during loading of document + xModel.set( + m_xCC->getServiceManager()->createInstanceWithContext( + CHART_MODEL_SERVICE_IMPLEMENTATION_NAME, m_xCC ) + , uno::UNO_QUERY ); + + if( impl_checkCancel() ) + return sal_False; + } + + //create the controller(+XWindow) + uno::Reference< frame::XController > xController = NULL; + uno::Reference< awt::XWindow > xComponentWindow = NULL; + { + xController = uno::Reference< frame::XController >( + m_xCC->getServiceManager()->createInstanceWithContext( + CHART_CONTROLLER_SERVICE_IMPLEMENTATION_NAME,m_xCC ) + , uno::UNO_QUERY ); + + //!!!it is a special characteristic of the example application + //that the controller simultaniously provides the XWindow controller functionality + xComponentWindow = + uno::Reference< awt::XWindow >( xController, uno::UNO_QUERY ); + + if( impl_checkCancel() ) + return sal_False; + } + + + //connect frame, controller and model one to each other: + if(xController.is()&&xModel.is()) + { + xModel->connectController(xController); + xModel->setCurrentController(xController); + xController->attachModel(xModel); + if(xFrame.is()) + xFrame->setComponent(xComponentWindow,xController); + //creates the view and menu + //for correct menu creation the initialized component must be already set into the frame + xController->attachFrame(xFrame); + } + + // call initNew() or load() at XLoadable + if(!bHaveLoadedModel) + try + { + comphelper::MediaDescriptor::const_iterator aIt( aMediaDescriptor.find( aMediaDescriptor.PROP_URL())); + if( aIt != aMediaDescriptor.end()) + { + ::rtl::OUString aURL( (*aIt).second.get< ::rtl::OUString >()); + if( aURL.matchAsciiL( + RTL_CONSTASCII_STRINGPARAM( "private:factory/schart" ))) + { + // create new file + uno::Reference< frame::XLoadable > xLoadable( xModel, uno::UNO_QUERY_THROW ); + xLoadable->initNew(); + } + else + { + aMediaDescriptor.addInputStream(); + uno::Sequence< beans::PropertyValue > aCompleteMediaDescriptor; + aMediaDescriptor >> aCompleteMediaDescriptor; + apphelper::MediaDescriptorHelper aMDHelper( aCompleteMediaDescriptor ); + + // load file + // @todo: replace: aMediaDescriptorHelper.getReducedForModel() + uno::Reference< frame::XLoadable > xLoadable( xModel, uno::UNO_QUERY_THROW ); + xLoadable->load( aCompleteMediaDescriptor ); + + //resize standalone files to get correct size: + if( xComponentWindow.is() && aMDHelper.ISSET_FilterName && aMDHelper.FilterName.equals( C2U("StarChart 5.0")) ) + { + awt::Rectangle aRect( xComponentWindow->getPosSize() ); + sal_Int16 nFlags=0; + xComponentWindow->setPosSize( aRect.X, aRect.Y, aRect.Width, aRect.Height, nFlags ); + } + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return sal_True; +} + + void SAL_CALL ChartFrameLoader +::cancel() throw (uno::RuntimeException) +{ + m_oCancelFinished.reset(); + m_bCancelRequired = sal_True; + m_oCancelFinished.wait(); + m_bCancelRequired = sal_False; +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/ChartFrameloader.hxx b/chart2/source/controller/main/ChartFrameloader.hxx new file mode 100644 index 000000000000..8b6e1e0a3225 --- /dev/null +++ b/chart2/source/controller/main/ChartFrameloader.hxx @@ -0,0 +1,91 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _CHARTFRAMELOADER_HXX +#define _CHARTFRAMELOADER_HXX + +#include "ServiceMacros.hxx" +#include <osl/conditn.hxx> +#include <com/sun/star/frame/XSynchronousFrameLoader.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase2.hxx> + +//............................................................................. +namespace chart +{ +//............................................................................. + +class ChartFrameLoader : public ::cppu::WeakImplHelper2< + ::com::sun::star::frame::XSynchronousFrameLoader + , ::com::sun::star::lang::XServiceInfo + //comprehends XComponent (required interface) + // ,public ::com::sun::star::uno::XWeak // implemented by WeakImplHelper(optional interface) + // ,public ::com::sun::star::uno::XInterface // implemented by WeakImplHelper(optional interface) + // ,public ::com::sun::star::lang::XTypeProvider // implemented by WeakImplHelper + > +{ +private: + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> m_xCC; + sal_Bool m_bCancelRequired; + ::osl::Condition m_oCancelFinished; + +private: + sal_Bool impl_checkCancel(); + //no default constructor + ChartFrameLoader(){} +public: + ChartFrameLoader(::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > const & xContext); + virtual ~ChartFrameLoader(); + + //----------------------------------------------------------------- + // ::com::sun::star::lang::XServiceInfo + //----------------------------------------------------------------- + + APPHELPER_XSERVICEINFO_DECL() + APPHELPER_SERVICE_FACTORY_HELPER(ChartFrameLoader) + + //----------------------------------------------------------------- + // ::com::sun::star::frame::XFrameLoader + //----------------------------------------------------------------- + + virtual sal_Bool SAL_CALL + load( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& rMediaDescriptor + ,const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XFrame >& xFrame ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + cancel() throw (::com::sun::star::uno::RuntimeException); +}; + +//............................................................................. +} //namespace chart +//............................................................................. + +#endif diff --git a/chart2/source/controller/main/ChartRenderer.cxx b/chart2/source/controller/main/ChartRenderer.cxx new file mode 100644 index 000000000000..3419f7a53bec --- /dev/null +++ b/chart2/source/controller/main/ChartRenderer.cxx @@ -0,0 +1,178 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "ChartRenderer.hxx" +#include "servicenames.hxx" +#include "chartview/ExplicitValueProvider.hxx" +#include "chartview/DrawModelWrapper.hxx" +#include "DrawViewWrapper.hxx" +#include "macros.hxx" +#include "ChartModelHelper.hxx" +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> + +#include <com/sun/star/util/XUpdatable.hpp> + +//............................................................................. +namespace chart +{ +//............................................................................. + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using rtl::OUString; + +ChartRenderer::ChartRenderer( const Reference< frame::XModel >& xChartModel ) + : m_xChartModel( uno::WeakReference< frame::XModel >(xChartModel) ) +{ +} + +ChartRenderer::~ChartRenderer() +{ +} + +// ____ ChartPrettyPainter ___ +bool ChartRenderer::DoPaint(OutputDevice* pOutDev, const Rectangle& rLogicObjectRect /*in given output dev map units*/ ) const +{ + if(!pOutDev) + return false; + + Reference<frame::XModel> xModel(m_xChartModel); + uno::Reference< lang::XMultiServiceFactory > xFact( xModel, uno::UNO_QUERY ); + if( !xFact.is() ) + return false; + + //#i84323# ensure that the size the container has of the chart and size that chart has itself are the same + //maybe remove this workaround somewhere in future again + { + if( MAP_100TH_MM == pOutDev->GetMapMode().GetMapUnit() )//no problem for writer in issue #i84323#; but writer uses twips instead of 100thmm which causes small differences in size always when converting to 100thmm and back + { + awt::Size aChartSize( ChartModelHelper::getPageSize(xModel) ); + awt::Size aContainerChartSize( rLogicObjectRect.GetWidth(), rLogicObjectRect.GetHeight() ); + if( aContainerChartSize.Width != aChartSize.Width + || aContainerChartSize.Height != aChartSize.Height ) + { + DBG_ERROR("chart size does not equal size assumed by the container"); + //correct the state here on the fly -> let the container size win + ChartModelHelper::setPageSize( aContainerChartSize, xModel ); + } + } + } + + // get the chart view + Reference< lang::XUnoTunnel > xChartView( xFact->createInstance( CHART_VIEW_SERVICE_NAME ), uno::UNO_QUERY ); + + try + { + //better performance for big data + uno::Reference< beans::XPropertySet > xProp( xChartView, uno::UNO_QUERY ); + if( xProp.is() ) + { + awt::Size aResolution(1000,1000); + { + ::vos::OGuard aGuard( Application::GetSolarMutex()); + Rectangle aPixelRect( pOutDev->LogicToPixel( rLogicObjectRect ) ); + aResolution.Width = aPixelRect.GetWidth(); + aResolution.Height = aPixelRect.GetHeight(); + } + xProp->setPropertyValue( C2U("Resolution"), uno::makeAny( aResolution )); + } + // + + uno::Reference< util::XUpdatable > xUpdatable( xChartView, uno::UNO_QUERY ); + if( xUpdatable.is() ) + xUpdatable->update(); + + ::vos::OGuard aGuard( Application::GetSolarMutex()); + ExplicitValueProvider* pProvider = ExplicitValueProvider::getExplicitValueProvider( xChartView ); + if( !pProvider ) + return false; + ::boost::shared_ptr< DrawModelWrapper > pDrawModelWrapper = pProvider->getDrawModelWrapper(); + if( !pDrawModelWrapper.get() ) + return false; + ::boost::shared_ptr< DrawViewWrapper > pDrawViewWrapper( new DrawViewWrapper(&pDrawModelWrapper->getSdrModel(),pOutDev,false) ); + pDrawViewWrapper->attachParentReferenceDevice( xModel ); + + MapMode aOldMapMode( pOutDev->GetMapMode() ); + Point aOldOrigin( aOldMapMode.GetOrigin() ); + MapMode aMapMode( aOldMapMode ); + Point aOldOriginMM( OutputDevice::LogicToLogic( aOldOrigin, aOldMapMode.GetMapUnit(), MAP_100TH_MM ) ); + Point aObjectTopLeftMM( OutputDevice::LogicToLogic( rLogicObjectRect.TopLeft(), aOldMapMode.GetMapUnit(), MAP_100TH_MM ) ); + aMapMode.SetOrigin( aOldOriginMM + aObjectTopLeftMM ); + aMapMode.SetMapUnit( MAP_100TH_MM ); + pOutDev->SetMapMode(aMapMode); + + Rectangle aPaintRect( OutputDevice::LogicToLogic( rLogicObjectRect, aOldMapMode, aMapMode ) ); + pDrawViewWrapper->CompleteRedraw(pOutDev, Region(aPaintRect) ); + + pOutDev->SetMapMode(aOldMapMode); + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + catch( ... ) + { + } + + return true; +} + +//----------------------------------------------------------------- +// ____ XUnoTunnel ___ +::sal_Int64 SAL_CALL ChartRenderer::getSomething( const Sequence< ::sal_Int8 >& aIdentifier ) + throw( uno::RuntimeException) +{ + if( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory( + ChartPrettyPainter::getUnoTunnelId().getConstArray(), + aIdentifier.getConstArray(), 16 ) ) + { + ChartPrettyPainter* pPaintableObject = this; + return reinterpret_cast<sal_Int64>(pPaintableObject); + } + return 0; +} + +//----------------------------------------------------------------- +// lang::XServiceInfo + +APPHELPER_XSERVICEINFO_IMPL(ChartRenderer,CHART_RENDERER_SERVICE_IMPLEMENTATION_NAME) + +Sequence< OUString > ChartRenderer::getSupportedServiceNames_Static() +{ + Sequence< OUString > aSNS; + return aSNS; +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/ChartTransferable.cxx b/chart2/source/controller/main/ChartTransferable.cxx new file mode 100644 index 000000000000..80041d4c3818 --- /dev/null +++ b/chart2/source/controller/main/ChartTransferable.cxx @@ -0,0 +1,172 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "ChartTransferable.hxx" + +#include <unotools/streamwrap.hxx> +#include <vcl/graph.hxx> +#include <svl/itempool.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <svx/svditer.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> +#include <svx/unomodel.hxx> + +// header for class SdrView +#include <svx/svdview.hxx> + +#define CHARTTRANSFER_OBJECTTYPE_DRAWMODEL 1 + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace chart +{ + +ChartTransferable::ChartTransferable( SdrModel* pDrawModel, SdrObject* pSelectedObj, bool bDrawing ) + :m_pMarkedObjModel( NULL ) + ,m_bDrawing( bDrawing ) +{ + SdrExchangeView * pExchgView( new SdrView( pDrawModel )); + SdrPageView* pPv = pExchgView->ShowSdrPage( pDrawModel->GetPage( 0 )); + if( pSelectedObj ) + pExchgView->MarkObj( pSelectedObj, pPv ); + else + pExchgView->MarkAllObj( pPv ); + Graphic aGraphic( pExchgView->GetMarkedObjMetaFile( TRUE )); + m_xMetaFileGraphic.set( aGraphic.GetXGraphic()); + if ( m_bDrawing ) + { + m_pMarkedObjModel = ( pExchgView ? pExchgView->GetAllMarkedModel() : NULL ); + } + delete pExchgView; +} + +ChartTransferable::~ChartTransferable() +{} + +void ChartTransferable::AddSupportedFormats() +{ + if ( m_bDrawing ) + { + AddFormat( SOT_FORMATSTR_ID_DRAWING ); + } + AddFormat( SOT_FORMAT_GDIMETAFILE ); + AddFormat( SOT_FORMAT_BITMAP ); +} + +sal_Bool ChartTransferable::GetData( const ::com::sun::star::datatransfer::DataFlavor& rFlavor ) +{ + sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor ); + sal_Bool bResult = sal_False; + + if( HasFormat( nFormat )) + { + if ( nFormat == SOT_FORMATSTR_ID_DRAWING ) + { + bResult = SetObject( m_pMarkedObjModel, CHARTTRANSFER_OBJECTTYPE_DRAWMODEL, rFlavor ); + } + else if ( nFormat == FORMAT_GDIMETAFILE ) + { + Graphic aGraphic( m_xMetaFileGraphic ); + bResult = SetGDIMetaFile( aGraphic.GetGDIMetaFile(), rFlavor ); + } + else if( nFormat == FORMAT_BITMAP ) + { + Graphic aGraphic( m_xMetaFileGraphic ); + bResult = SetBitmap( aGraphic.GetBitmap(), rFlavor ); + } + } + + return bResult; +} + +sal_Bool ChartTransferable::WriteObject( SotStorageStreamRef& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId, + const datatransfer::DataFlavor& /* rFlavor */ ) +{ + // called from SetObject, put data into stream + + sal_Bool bRet = sal_False; + switch ( nUserObjectId ) + { + case CHARTTRANSFER_OBJECTTYPE_DRAWMODEL: + { + SdrModel* pMarkedObjModel = reinterpret_cast< SdrModel* >( pUserObject ); + if ( pMarkedObjModel ) + { + rxOStm->SetBufferSize( 0xff00 ); + + // #108584# + // for the changed pool defaults from drawing layer pool set those + // attributes as hard attributes to preserve them for saving + const SfxItemPool& rItemPool = pMarkedObjModel->GetItemPool(); + const SvxFontHeightItem& rDefaultFontHeight = static_cast< const SvxFontHeightItem& >( + rItemPool.GetDefaultItem( EE_CHAR_FONTHEIGHT ) ); + sal_uInt16 nCount = pMarkedObjModel->GetPageCount(); + for ( sal_uInt16 i = 0; i < nCount; ++i ) + { + const SdrPage* pPage = pMarkedObjModel->GetPage( i ); + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + while ( aIter.IsMore() ) + { + SdrObject* pObj = aIter.Next(); + const SvxFontHeightItem& rItem = static_cast< const SvxFontHeightItem& >( + pObj->GetMergedItem( EE_CHAR_FONTHEIGHT ) ); + if ( rItem.GetHeight() == rDefaultFontHeight.GetHeight() ) + { + pObj->SetMergedItem( rDefaultFontHeight ); + } + } + } + + Reference< io::XOutputStream > xDocOut( new utl::OOutputStreamWrapper( *rxOStm ) ); + if ( SvxDrawingLayerExport( pMarkedObjModel, xDocOut ) ) + { + rxOStm->Commit(); + } + + bRet = ( rxOStm->GetError() == ERRCODE_NONE ); + } + } + break; + default: + { + DBG_ERROR( "ChartTransferable::WriteObject: unknown object id" ); + } + break; + } + return bRet; +} + +} // namespace chart diff --git a/chart2/source/controller/main/ChartTransferable.hxx b/chart2/source/controller/main/ChartTransferable.hxx new file mode 100644 index 000000000000..401f43c6d1ae --- /dev/null +++ b/chart2/source/controller/main/ChartTransferable.hxx @@ -0,0 +1,67 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_CHARTTRANSFERABLE_HXX +#define CHART2_CHARTTRANSFERABLE_HXX + +#include <svtools/transfer.hxx> + +namespace com { namespace sun { namespace star { +namespace graphic { + class XGraphic; +} +}}} + +class SdrModel; +class SdrObject; + +namespace chart +{ + +class ChartTransferable : public TransferableHelper +{ +public: + explicit ChartTransferable( SdrModel* pDrawModel, SdrObject* pSelectedObj, bool bDrawing = false ); + virtual ~ChartTransferable(); + +protected: + + // implementation of TransferableHelper methods + virtual void AddSupportedFormats(); + virtual sal_Bool GetData( const ::com::sun::star::datatransfer::DataFlavor& rFlavor ); + virtual sal_Bool WriteObject( SotStorageStreamRef& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId, + const ::com::sun::star::datatransfer::DataFlavor& rFlavor ); + +private: + ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > m_xMetaFileGraphic; + SdrModel* m_pMarkedObjModel; + bool m_bDrawing; +}; + +} // namespace chart + +// CHART2_CHARTTRANSFERABLE_HXX +#endif diff --git a/chart2/source/controller/main/ChartWindow.cxx b/chart2/source/controller/main/ChartWindow.cxx new file mode 100644 index 000000000000..240b615cf0f6 --- /dev/null +++ b/chart2/source/controller/main/ChartWindow.cxx @@ -0,0 +1,271 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" +#include "ChartWindow.hxx" +#include "ChartController.hxx" +#include "HelpIds.hrc" + +#include <vcl/help.hxx> + +using namespace ::com::sun::star; + +namespace +{ +::Rectangle lcl_AWTRectToVCLRect( const ::com::sun::star::awt::Rectangle & rAWTRect ) +{ + ::Rectangle aResult; + aResult.setX( rAWTRect.X ); + aResult.setY( rAWTRect.Y ); + aResult.setWidth( rAWTRect.Width ); + aResult.setHeight( rAWTRect.Height ); + return aResult; +} +} // anonymous namespace + + +//............................................................................. +namespace chart +{ +//............................................................................. + +ChartWindow::ChartWindow( WindowController* pWindowController, Window* pParent, WinBits nStyle ) + : Window(pParent, nStyle) + , m_pWindowController( pWindowController ) + , m_bInPaint(false) +{ + this->SetSmartHelpId( SmartId( HID_SCH_WIN_DOCUMENT ) ); + this->SetMapMode( MapMode(MAP_100TH_MM) ); + adjustHighContrastMode(); + // chart does not depend on exact pixel painting => enable antialiased drawing + SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW | GetAntialiasing() ); + EnableRTL( FALSE ); + if( pParent ) + pParent->EnableRTL( FALSE );// #i96215# necessary for a correct position of the context menu in rtl mode +} + +ChartWindow::~ChartWindow() +{ +} + +void ChartWindow::clear() +{ + m_pWindowController=0; + this->ReleaseMouse(); +} + +void ChartWindow::PrePaint() +{ + // forward VCLs PrePaint window event to DrawingLayer + if( m_pWindowController ) + { + m_pWindowController->PrePaint(); + } +} + +void ChartWindow::Paint( const Rectangle& rRect ) +{ + m_bInPaint = true; + if( m_pWindowController ) + m_pWindowController->execute_Paint( rRect ); + else + Window::Paint( rRect ); + m_bInPaint = false; +} + +void ChartWindow::MouseButtonDown(const MouseEvent& rMEvt) +{ + if( m_pWindowController ) + m_pWindowController->execute_MouseButtonDown(rMEvt); + else + Window::MouseButtonDown(rMEvt); +} + +void ChartWindow::MouseMove( const MouseEvent& rMEvt ) +{ + if( m_pWindowController ) + m_pWindowController->execute_MouseMove( rMEvt ); + else + Window::MouseMove( rMEvt ); +} + +void ChartWindow::Tracking( const TrackingEvent& rTEvt ) +{ + if( m_pWindowController ) + m_pWindowController->execute_Tracking( rTEvt ); + else + Window::Tracking( rTEvt ); +} + +void ChartWindow::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if( m_pWindowController ) + m_pWindowController->execute_MouseButtonUp( rMEvt ); + else + Window::MouseButtonUp( rMEvt ); +} + +void ChartWindow::Resize() +{ + if( m_pWindowController ) + m_pWindowController->execute_Resize(); + else + Window::Resize(); +} + +void ChartWindow::Activate() +{ + if( m_pWindowController ) + m_pWindowController->execute_Activate(); + else + Window::Activate(); +} +void ChartWindow::Deactivate() +{ + if( m_pWindowController ) + m_pWindowController->execute_Deactivate(); + else + Window::Deactivate(); +} +void ChartWindow::GetFocus() +{ + if( m_pWindowController ) + m_pWindowController->execute_GetFocus(); + else + Window::GetFocus(); +} +void ChartWindow::LoseFocus() +{ + if( m_pWindowController ) + m_pWindowController->execute_LoseFocus(); + else + Window::LoseFocus(); +} + +void ChartWindow::Command( const CommandEvent& rCEvt ) +{ + if( m_pWindowController ) + m_pWindowController->execute_Command( rCEvt ); + else + Window::Command( rCEvt ); +} + +void ChartWindow::KeyInput( const KeyEvent& rKEvt ) +{ + if( m_pWindowController ) + { + if( !m_pWindowController->execute_KeyInput(rKEvt) ) + Window::KeyInput(rKEvt); + } + else + Window::KeyInput( rKEvt ); +} + +uno::Reference< accessibility::XAccessible > ChartWindow::CreateAccessible() +{ + if( m_pWindowController ) + return m_pWindowController->CreateAccessible(); + else + return Window::CreateAccessible(); +} + +void ChartWindow::DataChanged( const DataChangedEvent& rDCEvt ) +{ + ::Window::DataChanged( rDCEvt ); + + if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && + (rDCEvt.GetFlags() & SETTINGS_STYLE) ) + { + adjustHighContrastMode(); + } +} + +void ChartWindow::RequestHelp( const HelpEvent& rHEvt ) +{ + bool bHelpHandled = false; + if( ( rHEvt.GetMode() & HELPMODE_QUICK ) && + m_pWindowController ) + { +// Point aLogicHitPos = PixelToLogic( rHEvt.GetMousePosPixel()); // old chart: GetPointerPosPixel() + Point aLogicHitPos = PixelToLogic( GetPointerPosPixel()); + ::rtl::OUString aQuickHelpText; + awt::Rectangle aHelpRect; + bool bIsBalloonHelp( Help::IsBalloonHelpEnabled() ); + bHelpHandled = m_pWindowController->requestQuickHelp( aLogicHitPos, bIsBalloonHelp, aQuickHelpText, aHelpRect ); + + if( bHelpHandled ) + { + if( bIsBalloonHelp ) + Help::ShowBalloon( + this, rHEvt.GetMousePosPixel(), lcl_AWTRectToVCLRect( aHelpRect ), String( aQuickHelpText )); + else + Help::ShowQuickHelp( + this, lcl_AWTRectToVCLRect( aHelpRect ), String( aQuickHelpText )); + } + } + + if( !bHelpHandled ) + ::Window::RequestHelp( rHEvt ); +} + +void ChartWindow::adjustHighContrastMode() +{ + static const sal_Int32 nContrastMode = + DRAWMODE_SETTINGSLINE | DRAWMODE_SETTINGSFILL | + DRAWMODE_SETTINGSTEXT | DRAWMODE_SETTINGSGRADIENT; + + bool bUseContrast = GetSettings().GetStyleSettings().GetHighContrastMode(); + SetDrawMode( bUseContrast ? nContrastMode : DRAWMODE_DEFAULT ); +} + +void ChartWindow::ForceInvalidate() +{ + ::Window::Invalidate(); +} +void ChartWindow::Invalidate( USHORT nFlags ) +{ + if( m_bInPaint ) // #i101928# superfluous paint calls while entering and editing charts" + return; + ::Window::Invalidate( nFlags ); +} +void ChartWindow::Invalidate( const Rectangle& rRect, USHORT nFlags ) +{ + if( m_bInPaint ) // #i101928# superfluous paint calls while entering and editing charts" + return; + ::Window::Invalidate( rRect, nFlags ); +} +void ChartWindow::Invalidate( const Region& rRegion, USHORT nFlags ) +{ + if( m_bInPaint ) // #i101928# superfluous paint calls while entering and editing charts" + return; + ::Window::Invalidate( rRegion, nFlags ); +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/ChartWindow.hxx b/chart2/source/controller/main/ChartWindow.hxx new file mode 100644 index 000000000000..2325d6be7803 --- /dev/null +++ b/chart2/source/controller/main/ChartWindow.hxx @@ -0,0 +1,88 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _CHARTWINDOW_HXX +#define _CHARTWINDOW_HXX + +#include <vcl/window.hxx> + +//............................................................................. +namespace chart +{ +//............................................................................. + + +class WindowController; + +//----------------------------------------------------------------------------- +/** The ChartWindow collects events from the window and forwards them the to the controller +thus the controller can perform appropriate actions +*/ + +class ChartWindow : public Window +{ +public: + ChartWindow( WindowController* pWindowController, Window* pParent, WinBits nStyle ); + virtual ~ChartWindow(); + + void clear(); + + //from base class Window: + virtual void PrePaint(); + virtual void Paint( const Rectangle& rRect ); + virtual void MouseButtonDown( const MouseEvent& rMEvt ); + virtual void MouseMove( const MouseEvent& rMEvt ); + virtual void Tracking( const TrackingEvent& rTEvt ); + virtual void MouseButtonUp( const MouseEvent& rMEvt ); + virtual void Resize(); + virtual void Activate(); + virtual void Deactivate(); + virtual void GetFocus(); + virtual void LoseFocus(); + virtual void Command( const CommandEvent& rCEvt ); + virtual void KeyInput( const KeyEvent& rKEvt ); + virtual void DataChanged( const DataChangedEvent& rDCEvt ); + virtual void RequestHelp( const HelpEvent& rHEvt ); + + void ForceInvalidate(); + virtual void Invalidate( USHORT nFlags = 0 ); + virtual void Invalidate( const Rectangle& rRect, USHORT nFlags = 0 ); + virtual void Invalidate( const Region& rRegion, USHORT nFlags = 0 ); + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible(); + +private: + WindowController* m_pWindowController; + bool m_bInPaint; + + void adjustHighContrastMode(); +}; + +//............................................................................. +} //namespace chart +//............................................................................. + +#endif diff --git a/chart2/source/controller/main/CommandDispatch.cxx b/chart2/source/controller/main/CommandDispatch.cxx new file mode 100644 index 000000000000..bd040fce8fff --- /dev/null +++ b/chart2/source/controller/main/CommandDispatch.cxx @@ -0,0 +1,211 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "CommandDispatch.hxx" +#include "CommonFunctors.hxx" +#include "macros.hxx" + +#include <algorithm> +#include <functional> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace +{ +template< class Map > + struct lcl_DisposeAndClearAndDeleteMapElement : + public ::std::unary_function< typename Map::value_type, void > + { + lcl_DisposeAndClearAndDeleteMapElement( const Reference< uno::XInterface > & xEventSource ) : + m_aEvent( xEventSource ) + {} + void operator() ( typename Map::value_type & rElement ) + { + if( rElement.second ) + { + rElement.second->disposeAndClear( m_aEvent ); + delete rElement.second; + } + } + private: + lang::EventObject m_aEvent; + }; + +template< class Map > + void lcl_DisposeAndClearAndDeleteAllMapElements( + Map & rMap, + const Reference< uno::XInterface > & xEventSource ) +{ + ::std::for_each( rMap.begin(), rMap.end(), + lcl_DisposeAndClearAndDeleteMapElement< Map >( xEventSource )); +} + +} // anonymous namespace + +namespace chart +{ + +CommandDispatch::CommandDispatch( + const Reference< uno::XComponentContext > & xContext ) : + impl::CommandDispatch_Base( m_aMutex ), + m_xContext( xContext ) +{ +} + +CommandDispatch::~CommandDispatch() +{} + +void CommandDispatch::initialize() +{} + +// ____ WeakComponentImplHelperBase ____ +/// is called when this is disposed +void SAL_CALL CommandDispatch::disposing() +{ + lcl_DisposeAndClearAndDeleteAllMapElements( m_aListeners, static_cast< cppu::OWeakObject* >( this )); + m_aListeners.clear(); +} + +// ____ XDispatch ____ +void SAL_CALL CommandDispatch::dispatch( const util::URL& /* URL */, const Sequence< beans::PropertyValue >& /* Arguments */ ) + throw (uno::RuntimeException) +{} + +void SAL_CALL CommandDispatch::addStatusListener( const Reference< frame::XStatusListener >& Control, const util::URL& URL ) + throw (uno::RuntimeException) +{ + tListenerMap::iterator aIt( m_aListeners.find( URL.Complete )); + if( aIt == m_aListeners.end()) + { + aIt = m_aListeners.insert( + m_aListeners.begin(), + tListenerMap::value_type( URL.Complete, new ::cppu::OInterfaceContainerHelper( m_aMutex ))); + } + OSL_ASSERT( aIt != m_aListeners.end()); + + aIt->second->addInterface( Control ); + fireStatusEvent( URL.Complete, Control ); +} + +void SAL_CALL CommandDispatch::removeStatusListener( const Reference< frame::XStatusListener >& Control, const util::URL& URL ) + throw (uno::RuntimeException) +{ + tListenerMap::iterator aIt( m_aListeners.find( URL.Complete )); + if( aIt != m_aListeners.end()) + (*aIt).second->removeInterface( Control ); +} + +// ____ XModifyListener ____ +void SAL_CALL CommandDispatch::modified( const lang::EventObject& /* aEvent */ ) + throw (uno::RuntimeException) +{ + fireAllStatusEvents( 0 ); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL CommandDispatch::disposing( const lang::EventObject& /* Source */ ) + throw (uno::RuntimeException) +{} + +void CommandDispatch::fireAllStatusEvents( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & xSingleListener ) +{ + fireStatusEvent( OUString(), xSingleListener ); +} + +void CommandDispatch::fireStatusEventForURL( + const OUString & rURL, + const uno::Any & rState, + bool bEnabled, + const Reference< frame::XStatusListener > & xSingleListener, /* = 0 */ + const OUString & rFeatureDescriptor /* = OUString() */ ) +{ + // prepare event to send + util::URL aURL; + aURL.Complete = rURL; + if( !m_xURLTransformer.is()) + { + m_xURLTransformer.set( + m_xContext->getServiceManager()->createInstanceWithContext( + C2U( "com.sun.star.util.URLTransformer" ), + m_xContext ), + uno::UNO_QUERY ); + } + if( m_xURLTransformer.is()) + m_xURLTransformer->parseStrict( aURL ); + + frame::FeatureStateEvent aEventToSend( + static_cast< cppu::OWeakObject* >( this ), // Source + aURL, // FeatureURL + rFeatureDescriptor, // FeatureDescriptor + bEnabled, // IsEnabled + false, // Requery + rState // State + ); + + // send event either to single listener or all registered ones + if( xSingleListener.is()) + xSingleListener->statusChanged( aEventToSend ); + else + { + tListenerMap::iterator aIt( m_aListeners.find( aURL.Complete )); + if( aIt != m_aListeners.end()) + { +// ::cppu::OInterfaceContainerHelper * pCntHlp = rBHelper.getContainer( +// ::getCppuType( reinterpret_cast< Reference< frame::XStatusListener > * >(0))); + if( aIt->second ) + { + ::cppu::OInterfaceIteratorHelper aIntfIt( *((*aIt).second) ); + + while( aIntfIt.hasMoreElements()) + { + Reference< frame::XStatusListener > xListener( aIntfIt.next(), uno::UNO_QUERY ); + try + { + if( xListener.is()) + xListener->statusChanged( aEventToSend ); + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + } + } + } +} + + + +} // namespace chart diff --git a/chart2/source/controller/main/CommandDispatch.hxx b/chart2/source/controller/main/CommandDispatch.hxx new file mode 100644 index 000000000000..08140786ac4e --- /dev/null +++ b/chart2/source/controller/main/CommandDispatch.hxx @@ -0,0 +1,151 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_COMMANDDISPATCH_HXX +#define CHART2_COMMANDDISPATCH_HXX + +#include "MutexContainer.hxx" +#include <cppuhelper/compbase2.hxx> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/util/XModifyListener.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> + +#include <vector> +#include <map> + +namespace chart +{ + +namespace impl +{ +typedef ::cppu::WeakComponentImplHelper2< + ::com::sun::star::frame::XDispatch, + ::com::sun::star::util::XModifyListener > + CommandDispatch_Base; +} + +/** This is the base class for an XDispatch. + */ +class CommandDispatch : + public MutexContainer, + public impl::CommandDispatch_Base +{ +public: + explicit CommandDispatch( + const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > & xContext ); + virtual ~CommandDispatch(); + + // late initialisation, especially for adding as listener + virtual void initialize(); + +protected: + /** sends a status event for a specific command to all registered listeners + or only the one given when set. + + This method should be overloaded. The implementation should call + fireStatusEventForURL and pass the xSingleListener argument to this + method unchanged. + + @param rURL + If empty, all available status events must be fired, otherwise only + the one for the given command. + + @param xSingleListener + If set, the event is only sent to this listener rather than to all + registered ones. Whenever a listener adds itself, this method is + called with this parameter set to give an initial state. + */ + virtual void fireStatusEvent( + const ::rtl::OUString & rURL, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & xSingleListener ) = 0; + + /** calls fireStatusEvent( ::rtl::OUString, xSingleListener ) + */ + void fireAllStatusEvents( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & xSingleListener ); + + /** sends a status event for a specific command to all registered listeners + or only the one given when set. + + @param xSingleListener + If set, the event is only sent to this listener rather than to all + registered ones. Whenever a listener adds itself, this method is + called with this parameter set to give an initial state. + */ + void fireStatusEventForURL( + const ::rtl::OUString & rURL, + const ::com::sun::star::uno::Any & rState, + bool bEnabled, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & xSingleListener = + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >(), + const ::rtl::OUString & rFeatureDescriptor = ::rtl::OUString() ); + + // ____ XDispatch ____ + virtual void SAL_CALL dispatch( + const ::com::sun::star::util::URL& URL, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& Arguments ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addStatusListener( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >& Control, + const ::com::sun::star::util::URL& URL ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeStatusListener( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >& Control, + const ::com::sun::star::util::URL& URL ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ WeakComponentImplHelperBase ____ + /// is called when this is disposed + virtual void SAL_CALL disposing(); + + // ____ XModifyListener ____ + virtual void SAL_CALL modified( + const ::com::sun::star::lang::EventObject& aEvent ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ XEventListener (base of XModifyListener) ____ + virtual void SAL_CALL disposing( + const ::com::sun::star::lang::EventObject& Source ) + throw (::com::sun::star::uno::RuntimeException); + +protected: + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext; + ::com::sun::star::uno::Reference< ::com::sun::star::util::XURLTransformer > m_xURLTransformer; + +private: + typedef ::std::map< ::rtl::OUString, ::cppu::OInterfaceContainerHelper* > + tListenerMap; + + tListenerMap m_aListeners; + +}; + +} // namespace chart + +// CHART2_COMMANDDISPATCH_HXX +#endif diff --git a/chart2/source/controller/main/CommandDispatchContainer.cxx b/chart2/source/controller/main/CommandDispatchContainer.cxx new file mode 100644 index 000000000000..e0d689340760 --- /dev/null +++ b/chart2/source/controller/main/CommandDispatchContainer.cxx @@ -0,0 +1,216 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "CommandDispatchContainer.hxx" +#include "UndoCommandDispatch.hxx" +#include "StatusBarCommandDispatch.hxx" +#include "DisposeHelper.hxx" +#include "macros.hxx" +#include "ChartController.hxx" +#include "DrawCommandDispatch.hxx" +#include "ShapeController.hxx" + +#include <comphelper/InlineContainer.hxx> + +#include <com/sun/star/frame/XDispatchProvider.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace chart +{ + +CommandDispatchContainer::CommandDispatchContainer( + const Reference< uno::XComponentContext > & xContext, ChartController* pController ) + :m_xContext( xContext ) + ,m_pChartController( pController ) + ,m_pDrawCommandDispatch( NULL ) + ,m_pShapeController( NULL ) +{ + m_aContainerDocumentCommands = + ::comphelper::MakeSet< OUString > + ( C2U("AddDirect")) ( C2U("NewDoc")) ( C2U("Open")) + ( C2U("Save")) ( C2U("SaveAs")) ( C2U("SendMail")) + ( C2U("EditDoc")) ( C2U("ExportDirectToPDF")) ( C2U("PrintDefault")) + ; +} + +void CommandDispatchContainer::setModel( + const Reference< frame::XModel > & xModel ) +{ + // remove all existing dispatcher that base on the old model + m_aCachedDispatches.clear(); + DisposeHelper::DisposeAllElements( m_aToBeDisposedDispatches ); + m_aToBeDisposedDispatches.clear(); + m_xModel = xModel; +} + +// void CommandDispatchContainer::setUndoManager( +// const Reference< chart2::XUndoManager > & xUndoManager ) +// { +// m_xUndoManager = xUndoManager; +// } + +void CommandDispatchContainer::setChartDispatch( + const Reference< frame::XDispatch > xChartDispatch, + const ::std::set< OUString > & rChartCommands ) +{ + OSL_ENSURE(xChartDispatch.is(),"Invalid fall back dispatcher!"); + m_xChartDispatcher.set( xChartDispatch ); + m_aChartCommands = rChartCommands; + m_aToBeDisposedDispatches.push_back( m_xChartDispatcher ); +} + +Reference< frame::XDispatch > CommandDispatchContainer::getDispatchForURL( + const util::URL & rURL ) +{ + Reference< frame::XDispatch > xResult; + tDispatchMap::const_iterator aIt( m_aCachedDispatches.find( rURL.Complete )); + if( aIt != m_aCachedDispatches.end()) + { + xResult.set( (*aIt).second ); + } + else + { + uno::Reference< frame::XModel > xModel( m_xModel ); + + if( xModel.is() && (rURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Undo" )) + || rURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Redo" ))) ) + { + CommandDispatch * pDispatch = new UndoCommandDispatch( m_xContext, xModel ); + xResult.set( pDispatch ); + pDispatch->initialize(); + m_aCachedDispatches[ C2U(".uno:Undo") ].set( xResult ); + m_aCachedDispatches[ C2U(".uno:Redo") ].set( xResult ); + m_aToBeDisposedDispatches.push_back( xResult ); + } + else if( xModel.is() && (rURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Context" )) + || rURL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ModifiedStatus" ))) ) + { + Reference< view::XSelectionSupplier > xSelSupp( xModel->getCurrentController(), uno::UNO_QUERY ); + CommandDispatch * pDispatch = new StatusBarCommandDispatch( m_xContext, xModel, xSelSupp ); + xResult.set( pDispatch ); + pDispatch->initialize(); + m_aCachedDispatches[ C2U(".uno:Context") ].set( xResult ); + m_aCachedDispatches[ C2U(".uno:ModifiedStatus") ].set( xResult ); + m_aToBeDisposedDispatches.push_back( xResult ); + } + else if( xModel.is() && + (m_aContainerDocumentCommands.find( rURL.Path ) != m_aContainerDocumentCommands.end()) ) + { + xResult.set( getContainerDispatchForURL( xModel->getCurrentController(), rURL )); + // ToDo: can those dispatches be cached? + m_aCachedDispatches[ rURL.Complete ].set( xResult ); + } + else if( m_xChartDispatcher.is() && + (m_aChartCommands.find( rURL.Path ) != m_aChartCommands.end()) ) + { + xResult.set( m_xChartDispatcher ); + m_aCachedDispatches[ rURL.Complete ].set( xResult ); + } + // #i12587# support for shapes in chart + // Note, that the chart dispatcher must be queried first, because + // the chart dispatcher is the default dispatcher for all context + // sensitive commands. + else if ( m_pDrawCommandDispatch && m_pDrawCommandDispatch->isFeatureSupported( rURL.Complete ) ) + { + xResult.set( m_pDrawCommandDispatch ); + m_aCachedDispatches[ rURL.Complete ].set( xResult ); + } + else if ( m_pShapeController && m_pShapeController->isFeatureSupported( rURL.Complete ) ) + { + xResult.set( m_pShapeController ); + m_aCachedDispatches[ rURL.Complete ].set( xResult ); + } + } + + return xResult; +} + +Sequence< Reference< frame::XDispatch > > CommandDispatchContainer::getDispatchesForURLs( + const Sequence< frame::DispatchDescriptor > & aDescriptors ) +{ + sal_Int32 nCount = aDescriptors.getLength(); + uno::Sequence< uno::Reference< frame::XDispatch > > aRet( nCount ); + + for( sal_Int32 nPos = 0; nPos < nCount; ++nPos ) + { + if( aDescriptors[ nPos ].FrameName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("_self"))) + aRet[ nPos ] = getDispatchForURL( aDescriptors[ nPos ].FeatureURL ); + } + return aRet; +} + +void CommandDispatchContainer::DisposeAndClear() +{ + m_aCachedDispatches.clear(); + DisposeHelper::DisposeAllElements( m_aToBeDisposedDispatches ); + m_aToBeDisposedDispatches.clear(); + m_xChartDispatcher.clear(); + m_aChartCommands.clear(); + m_pChartController = NULL; + m_pDrawCommandDispatch = NULL; + m_pShapeController = NULL; +} + +Reference< frame::XDispatch > CommandDispatchContainer::getContainerDispatchForURL( + const Reference< frame::XController > & xChartController, + const util::URL & rURL ) +{ + Reference< frame::XDispatch > xResult; + if( xChartController.is()) + { + Reference< frame::XFrame > xFrame( xChartController->getFrame()); + if( xFrame.is()) + { + Reference< frame::XDispatchProvider > xDispProv( xFrame->getCreator(), uno::UNO_QUERY ); + if( xDispProv.is()) + xResult.set( xDispProv->queryDispatch( rURL, C2U("_self"), 0 )); + } + } + return xResult; +} + +void CommandDispatchContainer::setDrawCommandDispatch( DrawCommandDispatch* pDispatch ) +{ + m_pDrawCommandDispatch = pDispatch; + m_aToBeDisposedDispatches.push_back( Reference< frame::XDispatch >( pDispatch ) ); +} + +void CommandDispatchContainer::setShapeController( ShapeController* pController ) +{ + m_pShapeController = pController; + m_aToBeDisposedDispatches.push_back( Reference< frame::XDispatch >( pController ) ); +} + +} // namespace chart diff --git a/chart2/source/controller/main/CommandDispatchContainer.hxx b/chart2/source/controller/main/CommandDispatchContainer.hxx new file mode 100644 index 000000000000..1c8769e0a6d9 --- /dev/null +++ b/chart2/source/controller/main/CommandDispatchContainer.hxx @@ -0,0 +1,160 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_COMMANDDISPATCHCONTAINER_HXX +#define CHART2_COMMANDDISPATCHCONTAINER_HXX + +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/chart2/XUndoManager.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/frame/DispatchDescriptor.hpp> + +#include <cppuhelper/weakref.hxx> +#include <cppuhelper/interfacecontainer.hxx> + +#include <set> +#include <map> + +namespace chart +{ + +class ChartController; +class DrawCommandDispatch; +class ShapeController; + +/** @HTML + + Helper class for implementing the <code>XDispatchProvider</code> interface + of the ChartController. This class handles all commands to queryDispatch and + queryDispatches in the following way: + + <ul> + <li>Check if there is a cached <code>XDispatch</code> for a given command. + If so, use it.</li> + <li>Check if the command is handled by this class, e.g. Undo. If so, + return a corresponding <code>XDispatch</code> implementation, and cache + this implementation for later use</li> + <li>Otherwise send the command to the chart dispatch provider, if it + can handle this dispatch (determined by the list of commands given in + <code>setChartDispatch()</code>).</li> + </ul> + + <p>The <code>XDispatch</code>Provider is designed to return different + <code>XDispatch</code> implementations for each command. This class here + decides which implementation to use for which command.</p> + + <p>As most commands need much information of the controller and are + implemented there, the controller handles most of the commands itself (it + also implements <code>XDispatch</code>). Therefore it is set here as + chart dispatch.</p> + */ +class CommandDispatchContainer +{ +public: + // note: the chart dispatcher should be removed when all commands are + // handled by other dispatchers. (Chart is currently the controller + // itself) + explicit CommandDispatchContainer( + const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > & xContext, + ChartController* pController ); + + void setModel( + const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel ); +// void setUndoManager( +// const ::com::sun::star::uno::Reference< +// ::com::sun::star::chart2::XUndoManager > & xUndoManager ); + + /** Set a chart dispatcher that is used for all commands contained in + rChartCommands + */ + void setChartDispatch( + const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XDispatch > xChartDispatch, + const ::std::set< ::rtl::OUString > & rChartCommands ); + + /** Returns the dispatch that is able to do the command given in rURL, if + implemented here. If the URL is not implemented here, it should be + checked whether the command is one of the commands given via + the setChartDispatch() method. If so, call the chart dispatch. + + <p>If all this fails, return an empty dispatch.</p> + */ + ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XDispatch > getDispatchForURL( + const ::com::sun::star::util::URL & rURL ); + + ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XDispatch > > getDispatchesForURLs( + const ::com::sun::star::uno::Sequence< + ::com::sun::star::frame::DispatchDescriptor > & aDescriptors ); + + void DisposeAndClear(); + + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > + getContainerDispatchForURL( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController > & xChartController, + const ::com::sun::star::util::URL & rURL ); + + void setDrawCommandDispatch( DrawCommandDispatch* pDispatch ); + DrawCommandDispatch* getDrawCommandDispatch() { return m_pDrawCommandDispatch; } + void setShapeController( ShapeController* pController ); + ShapeController* getShapeController() { return m_pShapeController; } + +private: + typedef + ::std::map< ::rtl::OUString, + ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XDispatch > > + tDispatchMap; + + typedef + ::std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > > tDisposeVector; + + mutable tDispatchMap m_aCachedDispatches; + mutable tDisposeVector m_aToBeDisposedDispatches; + + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext; + ::com::sun::star::uno::WeakReference< ::com::sun::star::frame::XModel > m_xModel; + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XUndoManager > m_xUndoManager; + + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > m_xChartDispatcher; + ::std::set< ::rtl::OUString > m_aChartCommands; + + ::std::set< ::rtl::OUString > m_aContainerDocumentCommands; + + ChartController* m_pChartController; + DrawCommandDispatch* m_pDrawCommandDispatch; + ShapeController* m_pShapeController; +}; + +} // namespace chart + +// CHART2_COMMANDDISPATCHCONTAINER_HXX +#endif diff --git a/chart2/source/controller/main/ConfigurationAccess.cxx b/chart2/source/controller/main/ConfigurationAccess.cxx new file mode 100644 index 000000000000..bf0bc6e14eec --- /dev/null +++ b/chart2/source/controller/main/ConfigurationAccess.cxx @@ -0,0 +1,120 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "ConfigurationAccess.hxx" +#include "macros.hxx" + +// header for class SvtSysLocale +#include <unotools/syslocale.hxx> +// header for class ConfigItem +#include <unotools/configitem.hxx> +// header for rtl::Static +#include <rtl/instance.hxx> + + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; + +namespace +{ +bool lcl_IsMetric() +{ + SvtSysLocale aSysLocale; + const LocaleDataWrapper* pLocWrapper = aSysLocale.GetLocaleDataPtr(); + MeasurementSystem eSys = pLocWrapper->getMeasurementSystemEnum(); + + return ( eSys == MEASURE_METRIC ); +} +}//end anonymous namespace + +// ---------------------------------------- + +class CalcConfigItem : public ::utl::ConfigItem +{ +public: + CalcConfigItem(); + virtual ~CalcConfigItem(); + + FieldUnit getFieldUnit(); + virtual void Commit(); + virtual void Notify( const uno::Sequence<rtl::OUString>& aPropertyNames); +}; + +CalcConfigItem::CalcConfigItem() + : ConfigItem( ::rtl::OUString( C2U( "Office.Calc/Layout" ))) +{ +} + +CalcConfigItem::~CalcConfigItem() +{ +} + +void CalcConfigItem::Commit() {} +void CalcConfigItem::Notify( const uno::Sequence<rtl::OUString>& ) {} + +FieldUnit CalcConfigItem::getFieldUnit() +{ + FieldUnit eResult( FUNIT_CM ); + + uno::Sequence< ::rtl::OUString > aNames( 1 ); + if( lcl_IsMetric() ) + aNames[ 0 ] = ::rtl::OUString( C2U( "Other/MeasureUnit/Metric" )); + else + aNames[ 0 ] = ::rtl::OUString( C2U( "Other/MeasureUnit/NonMetric" )); + + uno::Sequence< uno::Any > aResult( GetProperties( aNames )); + sal_Int32 nValue = 0; + if( aResult[ 0 ] >>= nValue ) + eResult = static_cast< FieldUnit >( nValue ); + + return eResult; +} + +namespace +{ + //a CalcConfigItem Singleton + struct theCalcConfigItem : public rtl::Static< CalcConfigItem, theCalcConfigItem > {}; +} + +namespace ConfigurationAccess +{ + FieldUnit getFieldUnit() + { + FieldUnit aUnit( theCalcConfigItem::get().getFieldUnit() ); + return aUnit; + } +} //namespace ConfigurationAccess + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/ControllerCommandDispatch.cxx b/chart2/source/controller/main/ControllerCommandDispatch.cxx new file mode 100644 index 000000000000..a01b80bfa22b --- /dev/null +++ b/chart2/source/controller/main/ControllerCommandDispatch.cxx @@ -0,0 +1,805 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "ControllerCommandDispatch.hxx" +#include "ChartModelHelper.hxx" +#include "DiagramHelper.hxx" +#include "AxisHelper.hxx" +#include "TitleHelper.hxx" +#include "LegendHelper.hxx" +#include "ObjectIdentifier.hxx" +#include "macros.hxx" +#include "ChartTypeHelper.hxx" +#include "DiagramHelper.hxx" +#include "ChartController.hxx" +#include "RegressionCurveHelper.hxx" +#include "DataSeriesHelper.hxx" +#include "StatisticsHelper.hxx" +#include "ShapeController.hxx" + +#include <com/sun/star/util/XModifyBroadcaster.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XChartType.hpp> +#include <com/sun/star/chart2/XDataSeries.hpp> +#include <com/sun/star/chart2/XRegressionCurve.hpp> +#include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp> + +// only needed until #i68864# is fixed +#include <com/sun/star/frame/XLayoutManager.hpp> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace +{ +bool lcl_isStatusBarVisible( const Reference< frame::XController > & xController ) +{ + bool bIsStatusBarVisible = false; + // Status-Bar visible, workaround: this should not be necessary. @todo: + // remove when Issue #i68864# is fixed + if( xController.is()) + { + Reference< beans::XPropertySet > xPropSet( xController->getFrame(), uno::UNO_QUERY ); + if( xPropSet.is() ) + { + uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager; + xPropSet->getPropertyValue( C2U( "LayoutManager" ) ) >>= xLayoutManager; + if ( xLayoutManager.is() ) + bIsStatusBarVisible = xLayoutManager->isElementVisible( C2U("private:resource/statusbar/statusbar")); + } + } + return bIsStatusBarVisible; +} + +} // anonymous namespace + +namespace chart +{ + +// ---------------------------------------- + +namespace impl +{ + +/// Constants for moving the series. +enum EnumForward{ + MOVE_SERIES_FORWARD = true, + MOVE_SERIES_BACKWARD = false +}; + +/** Represents the current state of the controller (needed for issue 63017). + + You can set the state by calling update(). After this call the state is + preserved in this class until the next call to update(). + + This is useful, not to say necessary, for enabling and disabling of menu + entries (e.g. format>arrangement). As the status requests are sent very + frequently it would be impossible, from a performance point of view, to + query the current status every time directly at the model. So this class + serves as a cache for the state. +*/ +struct ControllerState +{ + ControllerState(); + + void update( const Reference< frame::XController > & xController, + const Reference< frame::XModel > & xModel ); + + // -- State variables ------- + bool bHasSelectedObject; + bool bIsPositionableObject; + bool bIsTextObject; + bool bIsDeleteableObjectSelected; + bool bIsFormateableObjectSelected; + + // May the selected series be moved forward or backward (cf + // format>arrangement). + bool bMayMoveSeriesForward; + bool bMayMoveSeriesBackward; + + // trendlines + bool bMayAddTrendline; + bool bMayAddTrendlineEquation; + bool bMayAddR2Value; + bool bMayAddMeanValue; + bool bMayAddYErrorBars; + + bool bMayDeleteTrendline; + bool bMayDeleteTrendlineEquation; + bool bMayDeleteR2Value; + bool bMayDeleteMeanValue; + bool bMayDeleteYErrorBars; + + bool bMayFormatTrendline; + bool bMayFormatTrendlineEquation; + bool bMayFormatMeanValue; + bool bMayFormatYErrorBars; +}; + + +ControllerState::ControllerState() : + bHasSelectedObject( false ), + bIsPositionableObject( false ), + bIsTextObject(false), + bIsDeleteableObjectSelected(false), + bIsFormateableObjectSelected(false), + bMayMoveSeriesForward( false ), + bMayMoveSeriesBackward( false ), + bMayAddTrendline( false ), + bMayAddTrendlineEquation( false ), + bMayAddR2Value( false ), + bMayAddMeanValue( false ), + bMayAddYErrorBars( false ), + bMayDeleteTrendline( false ), + bMayDeleteTrendlineEquation( false ), + bMayDeleteR2Value( false ), + bMayDeleteMeanValue( false ), + bMayDeleteYErrorBars( false ), + bMayFormatTrendline( false ), + bMayFormatTrendlineEquation( false ), + bMayFormatMeanValue( false ), + bMayFormatYErrorBars( false ) +{} + +void ControllerState::update( + const Reference< frame::XController > & xController, + const Reference< frame::XModel > & xModel ) +{ + Reference< view::XSelectionSupplier > xSelectionSupplier( + xController, uno::UNO_QUERY ); + + // Update ControllerState variables. + if( xSelectionSupplier.is()) + { + uno::Any aSelObj( xSelectionSupplier->getSelection() ); + ObjectIdentifier aSelOID( aSelObj ); + OUString aSelObjCID( aSelOID.getObjectCID() ); + + bHasSelectedObject = aSelOID.isValid(); + + ObjectType aObjectType(ObjectIdentifier::getObjectType( aSelObjCID )); + + bIsPositionableObject = (OBJECTTYPE_DATA_POINT != aObjectType) && aSelOID.isDragableObject(); + bIsTextObject = OBJECTTYPE_TITLE == aObjectType; + + uno::Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel )); + bIsFormateableObjectSelected = bHasSelectedObject && aSelOID.isAutoGeneratedObject(); + if( OBJECTTYPE_DIAGRAM==aObjectType || OBJECTTYPE_DIAGRAM_WALL==aObjectType || OBJECTTYPE_DIAGRAM_FLOOR==aObjectType ) + bIsFormateableObjectSelected = DiagramHelper::isSupportingFloorAndWall( xDiagram ); + + uno::Reference< chart2::XDataSeries > xGivenDataSeries( + ObjectIdentifier::getDataSeriesForCID( + aSelObjCID, xModel ) ); + + bIsDeleteableObjectSelected = ChartController::isObjectDeleteable( aSelObj ); + + bMayMoveSeriesForward = (OBJECTTYPE_DATA_POINT!=aObjectType) && DiagramHelper::isSeriesMoveable( + ChartModelHelper::findDiagram( xModel ), + xGivenDataSeries, + MOVE_SERIES_FORWARD ); + + bMayMoveSeriesBackward = (OBJECTTYPE_DATA_POINT!=aObjectType) && DiagramHelper::isSeriesMoveable( + ChartModelHelper::findDiagram( xModel ), + xGivenDataSeries, + MOVE_SERIES_BACKWARD ); + + bMayAddTrendline = false; + bMayAddTrendlineEquation = false; + bMayAddR2Value = false; + bMayAddMeanValue = false; + bMayAddYErrorBars = false; + bMayDeleteTrendline = false; + bMayDeleteTrendlineEquation = false; + bMayDeleteR2Value = false; + bMayDeleteMeanValue = false; + bMayDeleteYErrorBars = false; + bMayFormatTrendline = false; + bMayFormatTrendlineEquation = false; + bMayFormatMeanValue = false; + bMayFormatYErrorBars = false; + if( bHasSelectedObject ) + { + if( xGivenDataSeries.is()) + { + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + uno::Reference< chart2::XChartType > xFirstChartType( + DataSeriesHelper::getChartTypeOfSeries( xGivenDataSeries, xDiagram )); + + // trend lines/mean value line + if( (OBJECTTYPE_DATA_SERIES == aObjectType || OBJECTTYPE_DATA_POINT == aObjectType) + && ChartTypeHelper::isSupportingRegressionProperties( xFirstChartType, nDimensionCount )) + { + uno::Reference< chart2::XRegressionCurveContainer > xRegCurveCnt( + xGivenDataSeries, uno::UNO_QUERY ); + if( xRegCurveCnt.is()) + { + uno::Reference< chart2::XRegressionCurve > xRegCurve( RegressionCurveHelper::getFirstCurveNotMeanValueLine( xRegCurveCnt ) ); + bMayFormatTrendline = bMayDeleteTrendline = xRegCurve.is(); + bMayFormatMeanValue = bMayDeleteMeanValue = RegressionCurveHelper::hasMeanValueLine( xRegCurveCnt ); + bMayAddTrendline = ! bMayDeleteTrendline; + bMayAddMeanValue = ! bMayDeleteMeanValue; + bMayFormatTrendlineEquation = bMayDeleteTrendlineEquation = RegressionCurveHelper::hasEquation( xRegCurve ); + bMayAddTrendlineEquation = !bMayDeleteTrendlineEquation; + } + } + + // error bars + if( (OBJECTTYPE_DATA_SERIES == aObjectType || OBJECTTYPE_DATA_POINT == aObjectType) + && ChartTypeHelper::isSupportingStatisticProperties( xFirstChartType, nDimensionCount )) + { + bMayFormatYErrorBars = bMayDeleteYErrorBars = StatisticsHelper::hasErrorBars( xGivenDataSeries ); + bMayAddYErrorBars = ! bMayDeleteYErrorBars; + } + } + + if( aObjectType == OBJECTTYPE_DATA_AVERAGE_LINE ) + bMayFormatMeanValue = true; + + if( aObjectType == OBJECTTYPE_DATA_ERRORS_Y || aObjectType == OBJECTTYPE_DATA_ERRORS ) + bMayFormatYErrorBars = true; + + if( aObjectType == OBJECTTYPE_DATA_CURVE ) + { + bMayFormatTrendline = true; + uno::Reference< chart2::XRegressionCurve > xRegCurve( + ObjectIdentifier::getObjectPropertySet( aSelObjCID, xModel ), uno::UNO_QUERY ); + bMayFormatTrendlineEquation = bMayDeleteTrendlineEquation = RegressionCurveHelper::hasEquation( xRegCurve ); + bMayAddTrendlineEquation = !bMayDeleteTrendlineEquation; + } + else if( aObjectType == OBJECTTYPE_DATA_CURVE_EQUATION ) + { + bMayFormatTrendlineEquation = true; + bool bHasR2Value = false; + try + { + uno::Reference< beans::XPropertySet > xEqProp( + ObjectIdentifier::getObjectPropertySet( aSelObjCID, xModel ), uno::UNO_QUERY ); + if( xEqProp.is()) + xEqProp->getPropertyValue( C2U("ShowCorrelationCoefficient") ) >>= bHasR2Value; + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } + bMayAddR2Value = !bHasR2Value; + bMayDeleteR2Value = bHasR2Value; + } + } + } +} + + +/** Represents the current state of the model. + + You can set the state by calling update(). After this call the state is + preserved in this class until the next call to update(). + + This is useful, not to say necessary, for enabling and disabling of menu + entries and toolbar icons. As the status requests are sent very frequently + it would be impossible, from a performance point of view, to query the + current status every time directly at the model. So this class serves as a + cache for the state. + */ +struct ModelState +{ + ModelState(); + + void update( const Reference< frame::XModel > & xModel ); + + bool HasAnyAxis() const; + bool HasAnyGrid() const; + bool HasAnyTitle() const; + + bool bIsReadOnly; + bool bIsThreeD; + bool bHasOwnData; + + bool bHasMainTitle; + bool bHasSubTitle; + bool bHasXAxisTitle; + bool bHasYAxisTitle; + bool bHasZAxisTitle; + bool bHasSecondaryXAxisTitle; + bool bHasSecondaryYAxisTitle; + + bool bHasXAxis; + bool bHasYAxis; + bool bHasZAxis; + bool bHasAAxis; + bool bHasBAxis; + + bool bHasMainXGrid; + bool bHasMainYGrid; + bool bHasMainZGrid; + bool bHasHelpXGrid; + bool bHasHelpYGrid; + bool bHasHelpZGrid; + + bool bHasAutoScaledText; + bool bHasLegend; + bool bHasWall; + bool bHasFloor; + + bool bSupportsStatistics; + bool bSupportsAxes; +}; + +ModelState::ModelState() : + bIsReadOnly( true ), + bIsThreeD( false ), + bHasOwnData( false ), + bHasMainTitle( false ), + bHasSubTitle( false ), + bHasXAxisTitle( false ), + bHasYAxisTitle( false ), + bHasZAxisTitle( false ), + bHasSecondaryXAxisTitle( false ), + bHasSecondaryYAxisTitle( false ), + bHasXAxis( false ), + bHasYAxis( false ), + bHasZAxis( false ), + bHasAAxis( false ), + bHasBAxis( false ), + bHasMainXGrid( false ), + bHasMainYGrid( false ), + bHasMainZGrid( false ), + bHasHelpXGrid( false ), + bHasHelpYGrid( false ), + bHasHelpZGrid( false ), + bHasAutoScaledText( false ), + bHasLegend( false ), + bHasWall( false ), + bHasFloor( false ), + bSupportsStatistics( false ), + bSupportsAxes( false ) + +{} + +void ModelState::update( const Reference< frame::XModel > & xModel ) +{ + Reference< chart2::XChartDocument > xChartDoc( xModel, uno::UNO_QUERY ); + Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram( xModel )); + + bIsReadOnly = true; + Reference< frame::XStorable > xStorable( xModel, uno::UNO_QUERY ); + if( xStorable.is()) + bIsReadOnly = xStorable->isReadonly(); + + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + + uno::Reference< chart2::XChartType > xFirstChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + bSupportsStatistics = ChartTypeHelper::isSupportingStatisticProperties( xFirstChartType, nDimensionCount ); + bSupportsAxes = ChartTypeHelper::isSupportingMainAxis( xFirstChartType, nDimensionCount, 0 ); + + bIsThreeD = (nDimensionCount == 3); + bHasOwnData = (xChartDoc.is() && xChartDoc->hasInternalDataProvider()); + + bHasMainTitle = TitleHelper::getTitle( TitleHelper::MAIN_TITLE, xModel ).is(); + bHasSubTitle = TitleHelper::getTitle( TitleHelper::SUB_TITLE, xModel ).is(); + bHasXAxisTitle = TitleHelper::getTitle( TitleHelper::X_AXIS_TITLE, xModel ).is(); + bHasYAxisTitle = TitleHelper::getTitle( TitleHelper::Y_AXIS_TITLE, xModel ).is(); + bHasZAxisTitle = TitleHelper::getTitle( TitleHelper::Z_AXIS_TITLE, xModel ).is(); + bHasSecondaryXAxisTitle = TitleHelper::getTitle( TitleHelper::SECONDARY_X_AXIS_TITLE, xModel ).is(); + bHasSecondaryYAxisTitle = TitleHelper::getTitle( TitleHelper::SECONDARY_Y_AXIS_TITLE, xModel ).is(); + + bHasXAxis = bSupportsAxes && AxisHelper::getAxis( 0, true, xDiagram ).is(); + bHasYAxis = bSupportsAxes && AxisHelper::getAxis( 1, true, xDiagram ).is(); + bHasZAxis = bSupportsAxes && AxisHelper::getAxis( 2, true, xDiagram ).is(); + bHasAAxis = bSupportsAxes && AxisHelper::getAxis( 0, false, xDiagram ).is(); + bHasBAxis = bSupportsAxes && AxisHelper::getAxis( 1, false, xDiagram ).is(); + + bHasMainXGrid = bSupportsAxes && AxisHelper::isGridShown( 0, 0, true, xDiagram ); + bHasMainYGrid = bSupportsAxes && AxisHelper::isGridShown( 1, 0, true, xDiagram ); + bHasMainZGrid = bSupportsAxes && AxisHelper::isGridShown( 2, 0, true, xDiagram ); + bHasHelpXGrid = bSupportsAxes && AxisHelper::isGridShown( 0, 0, false, xDiagram ); + bHasHelpYGrid = bSupportsAxes && AxisHelper::isGridShown( 1, 0, false, xDiagram ); + bHasHelpZGrid = bSupportsAxes && AxisHelper::isGridShown( 2, 0, false, xDiagram ); + + bHasAutoScaledText = + (ReferenceSizeProvider::getAutoResizeState( xChartDoc ) == + ReferenceSizeProvider::AUTO_RESIZE_YES); + + bHasLegend = LegendHelper::hasLegend( xDiagram ); + bHasWall = DiagramHelper::isSupportingFloorAndWall( xDiagram ); + bHasFloor = bHasWall && bIsThreeD; +} + +bool ModelState::HasAnyAxis() const +{ + return bHasXAxis || bHasYAxis || bHasZAxis || bHasAAxis || bHasBAxis; +} + +bool ModelState::HasAnyGrid() const +{ + return bHasMainXGrid || bHasMainYGrid || bHasMainZGrid || + bHasHelpXGrid || bHasHelpYGrid || bHasHelpZGrid; +} + +bool ModelState::HasAnyTitle() const +{ + return bHasMainTitle || bHasSubTitle || bHasXAxisTitle || bHasYAxisTitle || bHasZAxisTitle || bHasSecondaryXAxisTitle || bHasSecondaryYAxisTitle; +} + +} // namespace impl + +// ---------------------------------------- +DBG_NAME(ControllerCommandDispatch) + +ControllerCommandDispatch::ControllerCommandDispatch( + const Reference< uno::XComponentContext > & xContext, + ChartController* pController, CommandDispatchContainer* pContainer ) : + impl::ControllerCommandDispatch_Base( xContext ), + m_pChartController( pController ), + m_xController( Reference< frame::XController >( pController ) ), + m_xSelectionSupplier( Reference< view::XSelectionSupplier >( pController ) ), + m_xDispatch( Reference< frame::XDispatch >( pController ) ), + m_apModelState( new impl::ModelState() ), + m_apControllerState( new impl::ControllerState() ), + m_pDispatchContainer( pContainer ) +{ + DBG_CTOR(ControllerCommandDispatch,NULL); +} + +ControllerCommandDispatch::~ControllerCommandDispatch() +{ + + DBG_DTOR(ControllerCommandDispatch,NULL); +} + +void ControllerCommandDispatch::initialize() +{ + if( m_xController.is()) + { + Reference< frame::XModel > xModel( m_xController->getModel()); + Reference< util::XModifyBroadcaster > xModifyBroadcaster( xModel, uno::UNO_QUERY ); + OSL_ASSERT( xModifyBroadcaster.is()); + if( xModifyBroadcaster.is()) + xModifyBroadcaster->addModifyListener( this ); + + // Listen selection modifications (Arrangement feature - issue 63017). + if( m_xSelectionSupplier.is() ) + m_xSelectionSupplier->addSelectionChangeListener( this ); + + if( m_apModelState.get() && xModel.is()) + m_apModelState->update( xModel ); + + if( m_apControllerState.get() && xModel.is()) + m_apControllerState->update( m_xController, xModel ); + + updateCommandAvailability(); + } +} + +void ControllerCommandDispatch::fireStatusEventForURLImpl( + const OUString & rURL, + const Reference< frame::XStatusListener > & xSingleListener ) +{ + ::std::map< OUString, uno::Any >::const_iterator aArgIt( m_aCommandArguments.find( rURL )); + if( aArgIt != m_aCommandArguments.end()) + fireStatusEventForURL( rURL, aArgIt->second, commandAvailable( rURL ), xSingleListener ); + else + fireStatusEventForURL( rURL, uno::Any(), commandAvailable( rURL ), xSingleListener ); +} + +void ControllerCommandDispatch::updateCommandAvailability() +{ + bool bModelStateIsValid = ( m_apModelState.get() != 0 ); + bool bControllerStateIsValid = ( m_apControllerState.get() != 0 ); + // Model and controller states exist. + OSL_ASSERT( bModelStateIsValid ); + OSL_ASSERT( bControllerStateIsValid ); + + // read-only + bool bIsWritable = bModelStateIsValid && (! m_apModelState->bIsReadOnly); + // paste is available + // @todo: determine correctly + bool bHasSuitableClipboardContent = true; + + bool bShapeContext = ( m_pChartController ? m_pChartController->isShapeContext() : false ); + + bool bDisableDataTableDialog = false; + if ( m_xController.is() ) + { + Reference< beans::XPropertySet > xProps( m_xController->getModel(), uno::UNO_QUERY ); + if ( xProps.is() ) + { + try + { + xProps->getPropertyValue( C2U( "DisableDataTableDialog" ) ) >>= bDisableDataTableDialog; + } + catch( uno::Exception& e ) + { + ASSERT_EXCEPTION( e ); + } + } + } + + // edit commands + m_aCommandAvailability[ C2U(".uno:Cut")] = bIsWritable && bControllerStateIsValid && m_apControllerState->bIsDeleteableObjectSelected; + m_aCommandAvailability[ C2U(".uno:Copy")] = bControllerStateIsValid && m_apControllerState->bHasSelectedObject; + m_aCommandAvailability[ C2U(".uno:Paste")] = bIsWritable && bHasSuitableClipboardContent; + + // toolbar commands + m_aCommandAvailability[ C2U(".uno:ToggleGridHorizontal")] = bIsWritable; + m_aCommandArguments[ C2U(".uno:ToggleGridHorizontal")] = uno::makeAny( m_apModelState->bHasMainYGrid ); + + m_aCommandAvailability[ C2U(".uno:ToggleLegend")] = bIsWritable; + m_aCommandArguments[ C2U(".uno:ToggleLegend")] = uno::makeAny( m_apModelState->bHasLegend ); + + m_aCommandAvailability[ C2U(".uno:NewArrangement")] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:Update")] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:DefaultColors")] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:BarWidth")] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:NumberOfLines")] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:ArrangeRow")] = + bShapeContext || ( bIsWritable && bControllerStateIsValid && ( m_apControllerState->bMayMoveSeriesForward || m_apControllerState->bMayMoveSeriesBackward ) ); + + // insert objects + m_aCommandAvailability[ C2U(".uno:InsertTitles")] = m_aCommandAvailability[ C2U(".uno:InsertMenuTitles")] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:InsertLegend")] = m_aCommandAvailability[ C2U(".uno:InsertMenuLegend")] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:DeleteLegend")] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:InsertMenuDataLabels")] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:InsertRemoveAxes")] = m_aCommandAvailability[ C2U(".uno:InsertMenuAxes")] = bIsWritable && m_apModelState->bSupportsAxes; + m_aCommandAvailability[ C2U(".uno:InsertMenuGrids")] = bIsWritable && m_apModelState->bSupportsAxes; + m_aCommandAvailability[ C2U(".uno:InsertMenuTrendlines")] = bIsWritable && m_apModelState->bSupportsStatistics; + m_aCommandAvailability[ C2U(".uno:InsertMenuMeanValues")] = bIsWritable && m_apModelState->bSupportsStatistics; + m_aCommandAvailability[ C2U(".uno:InsertMenuYErrorBars")] = bIsWritable && m_apModelState->bSupportsStatistics; + m_aCommandAvailability[ C2U(".uno:InsertSymbol")] = bIsWritable && m_apControllerState->bIsTextObject; + + // format objects + bool bFormatObjectAvailable = bIsWritable && bControllerStateIsValid && m_apControllerState->bIsFormateableObjectSelected; + m_aCommandAvailability[ C2U(".uno:FormatSelection")] = bFormatObjectAvailable; + m_aCommandAvailability[ C2U(".uno:FormatAxis")] = bFormatObjectAvailable; + m_aCommandAvailability[ C2U(".uno:FormatTitle")] = bFormatObjectAvailable; + m_aCommandAvailability[ C2U(".uno:FormatDataSeries")] = bFormatObjectAvailable; + m_aCommandAvailability[ C2U(".uno:FormatDataPoint")] = bFormatObjectAvailable; + m_aCommandAvailability[ C2U(".uno:FormatDataLabels")] = bFormatObjectAvailable; + m_aCommandAvailability[ C2U(".uno:FormatDataLabel")] = bFormatObjectAvailable; + m_aCommandAvailability[ C2U(".uno:FormatYErrorBars")] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayFormatYErrorBars; + m_aCommandAvailability[ C2U(".uno:FormatMeanValue")] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayFormatMeanValue; + m_aCommandAvailability[ C2U(".uno:FormatTrendline")] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayFormatTrendline; + m_aCommandAvailability[ C2U(".uno:FormatTrendlineEquation")] = bFormatObjectAvailable && bControllerStateIsValid && m_apControllerState->bMayFormatTrendlineEquation; + m_aCommandAvailability[ C2U(".uno:FormatStockLoss")] = bFormatObjectAvailable; + m_aCommandAvailability[ C2U(".uno:FormatStockGain")] = bFormatObjectAvailable; + + m_aCommandAvailability[ C2U(".uno:DiagramType")] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:Legend")] = bIsWritable && m_apModelState->bHasLegend; + m_aCommandAvailability[ C2U(".uno:DiagramWall")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasWall; + m_aCommandAvailability[ C2U(".uno:DiagramArea")] = bIsWritable; + + m_aCommandAvailability[ C2U(".uno:TransformDialog")] = bIsWritable && bControllerStateIsValid && m_apControllerState->bHasSelectedObject && m_apControllerState->bIsPositionableObject; + + // 3d commands + m_aCommandAvailability[ C2U(".uno:View3D")] = bIsWritable && bModelStateIsValid && m_apModelState->bIsThreeD; + m_aCommandAvailability[ C2U(".uno:DiagramFloor")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasFloor; + + //some mor format commands with different ui text + m_aCommandAvailability[ C2U(".uno:FormatWall")] = m_aCommandAvailability[ C2U(".uno:DiagramWall")]; + m_aCommandAvailability[ C2U(".uno:FormatFloor")] = m_aCommandAvailability[ C2U(".uno:DiagramFloor")]; + m_aCommandAvailability[ C2U(".uno:FormatChartArea")] = m_aCommandAvailability[ C2U(".uno:DiagramArea")]; + m_aCommandAvailability[ C2U(".uno:FormatLegend")] = m_aCommandAvailability[ C2U(".uno:Legend")]; + + // depending on own data + m_aCommandAvailability[ C2U(".uno:DataRanges")] = bIsWritable && bModelStateIsValid && (! m_apModelState->bHasOwnData); + m_aCommandAvailability[ C2U(".uno:DiagramData")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasOwnData && !bDisableDataTableDialog; + + // titles + m_aCommandAvailability[ C2U(".uno:MainTitle")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainTitle; + m_aCommandAvailability[ C2U(".uno:SubTitle")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasSubTitle; + m_aCommandAvailability[ C2U(".uno:XTitle")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasXAxisTitle; + m_aCommandAvailability[ C2U(".uno:YTitle")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasYAxisTitle; + m_aCommandAvailability[ C2U(".uno:ZTitle")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasZAxisTitle; + m_aCommandAvailability[ C2U(".uno:SecondaryXTitle")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasSecondaryXAxisTitle; + m_aCommandAvailability[ C2U(".uno:SecondaryYTitle")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasSecondaryYAxisTitle; + m_aCommandAvailability[ C2U(".uno:AllTitles")] = bIsWritable && bModelStateIsValid && m_apModelState->HasAnyTitle(); + + // text + m_aCommandAvailability[ C2U(".uno:ScaleText")] = bIsWritable && bModelStateIsValid ; + m_aCommandArguments[ C2U(".uno:ScaleText")] = uno::makeAny( m_apModelState->bHasAutoScaledText ); + + // axes + m_aCommandAvailability[ C2U(".uno:DiagramAxisX")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasXAxis; + m_aCommandAvailability[ C2U(".uno:DiagramAxisY")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasYAxis; + m_aCommandAvailability[ C2U(".uno:DiagramAxisZ")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasZAxis; + m_aCommandAvailability[ C2U(".uno:DiagramAxisA")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasAAxis; + m_aCommandAvailability[ C2U(".uno:DiagramAxisB")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasBAxis; + m_aCommandAvailability[ C2U(".uno:DiagramAxisAll")] = bIsWritable && bModelStateIsValid && m_apModelState->HasAnyAxis(); + + // grids + // note: x and y are swapped in the commands! + m_aCommandAvailability[ C2U(".uno:DiagramGridYMain")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainXGrid; + m_aCommandAvailability[ C2U(".uno:DiagramGridXMain")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainYGrid; + m_aCommandAvailability[ C2U(".uno:DiagramGridZMain")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasMainZGrid; + m_aCommandAvailability[ C2U(".uno:DiagramGridYHelp")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasHelpXGrid; + m_aCommandAvailability[ C2U(".uno:DiagramGridXHelp")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasHelpYGrid; + m_aCommandAvailability[ C2U(".uno:DiagramGridZHelp")] = bIsWritable && bModelStateIsValid && m_apModelState->bHasHelpZGrid; + m_aCommandAvailability[ C2U(".uno:DiagramGridAll")] = bIsWritable && bModelStateIsValid && m_apModelState->HasAnyGrid(); + + // series arrangement + m_aCommandAvailability[ C2U(".uno:Forward")] = ( bShapeContext ? isShapeControllerCommandAvailable( C2U( ".uno:Forward" ) ) : + ( bIsWritable && bControllerStateIsValid && m_apControllerState->bMayMoveSeriesForward && !bDisableDataTableDialog ) ); + m_aCommandAvailability[ C2U(".uno:Backward")] = ( bShapeContext ? isShapeControllerCommandAvailable( C2U( ".uno:Backward" ) ) : + ( bIsWritable && bControllerStateIsValid && m_apControllerState->bMayMoveSeriesBackward && !bDisableDataTableDialog ) ); + + m_aCommandAvailability[ C2U(".uno:InsertDataLabels")] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:InsertDataLabel")] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:InsertMeanValue")] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddMeanValue; + m_aCommandAvailability[ C2U(".uno:InsertTrendline")] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddTrendline; + m_aCommandAvailability[ C2U(".uno:InsertTrendlineEquation")] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddTrendlineEquation; + m_aCommandAvailability[ C2U(".uno:InsertTrendlineEquationAndR2")] = m_aCommandAvailability[ C2U(".uno:InsertTrendlineEquation")]; + m_aCommandAvailability[ C2U(".uno:InsertR2Value")] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddR2Value; + m_aCommandAvailability[ C2U(".uno:DeleteR2Value")] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteR2Value; + + m_aCommandAvailability[ C2U(".uno:InsertYErrorBars")] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayAddYErrorBars; + + m_aCommandAvailability[ C2U(".uno:DeleteDataLabels")] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:DeleteDataLabel") ] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:DeleteTrendline") ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteTrendline; + m_aCommandAvailability[ C2U(".uno:DeleteTrendlineEquation") ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteTrendlineEquation; + m_aCommandAvailability[ C2U(".uno:DeleteMeanValue") ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteMeanValue; + m_aCommandAvailability[ C2U(".uno:DeleteYErrorBars") ] = bIsWritable && bControllerStateIsValid && m_apControllerState->bMayDeleteYErrorBars; + + m_aCommandAvailability[ C2U(".uno:ResetDataPoint") ] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:ResetAllDataPoints") ] = bIsWritable; + + m_aCommandAvailability[ C2U(".uno:InsertAxis") ] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:DeleteAxis") ] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:InsertAxisTitle") ] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:FormatMajorGrid") ] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:InsertMajorGrid") ] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:DeleteMajorGrid") ] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:FormatMinorGrid") ] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:InsertMinorGrid") ] = bIsWritable; + m_aCommandAvailability[ C2U(".uno:DeleteMinorGrid") ] = bIsWritable; +} + +bool ControllerCommandDispatch::commandAvailable( const OUString & rCommand ) +{ + ::std::map< OUString, bool >::const_iterator aIt( m_aCommandAvailability.find( rCommand )); + if( aIt != m_aCommandAvailability.end()) + return aIt->second; + OSL_ENSURE( false, "commandAvailable: command not in availability map" ); + return false; +} + +bool ControllerCommandDispatch::isShapeControllerCommandAvailable( const ::rtl::OUString& rCommand ) +{ + ShapeController* pShapeController = ( m_pDispatchContainer ? m_pDispatchContainer->getShapeController() : NULL ); + if ( pShapeController ) + { + FeatureState aState( pShapeController->getState( rCommand ) ); + return aState.bEnabled; + } + return false; +} + +void ControllerCommandDispatch::fireStatusEvent( + const OUString & rURL, + const Reference< frame::XStatusListener > & xSingleListener /* = 0 */ ) +{ + bool bIsChartSelectorURL = rURL.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(".uno:ChartElementSelector") ); + if( rURL.getLength() == 0 || bIsChartSelectorURL ) + { + uno::Any aArg; + aArg <<= m_xController; + fireStatusEventForURL( C2U(".uno:ChartElementSelector"), aArg, true, xSingleListener ); + } + + if( rURL.getLength() == 0 ) + for( ::std::map< OUString, bool >::const_iterator aIt( m_aCommandAvailability.begin()); + aIt != m_aCommandAvailability.end(); ++aIt ) + fireStatusEventForURLImpl( aIt->first, xSingleListener ); + else if( !bIsChartSelectorURL ) + fireStatusEventForURLImpl( rURL, xSingleListener ); + + // statusbar. Should be handled by base implementation + // @todo: remove if Issue 68864 is fixed + if( rURL.getLength() == 0 || + rURL.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(".uno:StatusBarVisible"))) + { + bool bIsStatusBarVisible( lcl_isStatusBarVisible( m_xController )); + fireStatusEventForURL( C2U(".uno:StatusBarVisible"), uno::makeAny( bIsStatusBarVisible ), true, xSingleListener ); + } +} + +// ____ XDispatch ____ +void SAL_CALL ControllerCommandDispatch::dispatch( + const util::URL& URL, + const Sequence< beans::PropertyValue >& Arguments ) + throw (uno::RuntimeException) +{ + if( commandAvailable( URL.Complete )) + m_xDispatch->dispatch( URL, Arguments ); +} + +// ____ WeakComponentImplHelperBase ____ +/// is called when this is disposed +void SAL_CALL ControllerCommandDispatch::disposing() +{ + m_xController.clear(); + m_xDispatch.clear(); + m_xSelectionSupplier.clear(); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL ControllerCommandDispatch::disposing( const lang::EventObject& /* Source */ ) + throw (uno::RuntimeException) +{ + m_xController.clear(); + m_xDispatch.clear(); + m_xSelectionSupplier.clear(); +} + +// ____ XModifyListener ____ +void SAL_CALL ControllerCommandDispatch::modified( const lang::EventObject& aEvent ) + throw (uno::RuntimeException) +{ + bool bUpdateCommandAvailability = false; + + // Update the "ModelState" Struct. + if( m_apModelState.get() && m_xController.is()) + { + m_apModelState->update( m_xController->getModel()); + bUpdateCommandAvailability = true; + } + + // Update the "ControllerState" Struct. + if( m_apControllerState.get() && m_xController.is()) + { + m_apControllerState->update( m_xController, m_xController->getModel()); + bUpdateCommandAvailability = true; + } + + if( bUpdateCommandAvailability ) + updateCommandAvailability(); + + CommandDispatch::modified( aEvent ); +} + + +// ____ XSelectionChangeListener ____ +void SAL_CALL ControllerCommandDispatch::selectionChanged( const lang::EventObject& aEvent ) + throw (uno::RuntimeException) +{ + // Update the "ControllerState" Struct. + if( m_apControllerState.get() && m_xController.is()) + { + m_apControllerState->update( m_xController, m_xController->getModel()); + updateCommandAvailability(); + } + + CommandDispatch::modified( aEvent ); +} + +} // namespace chart diff --git a/chart2/source/controller/main/ControllerCommandDispatch.hxx b/chart2/source/controller/main/ControllerCommandDispatch.hxx new file mode 100644 index 000000000000..08d57a0d6cbf --- /dev/null +++ b/chart2/source/controller/main/ControllerCommandDispatch.hxx @@ -0,0 +1,136 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_CONTROLLERCOMMANDDISPATCH_HXX +#define CHART2_CONTROLLERCOMMANDDISPATCH_HXX + +#include "CommandDispatch.hxx" +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <cppuhelper/implbase1.hxx> + +#include <memory> + +namespace chart +{ + +class ChartController; +class CommandDispatchContainer; + +namespace impl +{ +struct ModelState; +struct ControllerState; + +// #i63017# : need to implement the XSelectionChangeListener in order +// to update the ControllerState when the selection changes. +typedef ::cppu::ImplInheritanceHelper1< + CommandDispatch, + ::com::sun::star::view::XSelectionChangeListener > + ControllerCommandDispatch_Base; +} + +/** This class is a CommandDispatch that is responsible for all commands that + the ChartController supports. + + This class determines which commands are currently available (via the model + state) and if an available command is called forwards it to the + ChartController. + */ +class ControllerCommandDispatch : public impl::ControllerCommandDispatch_Base +{ +public: + explicit ControllerCommandDispatch( + const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > & xContext, + ChartController* pController, CommandDispatchContainer* pContainer ); + virtual ~ControllerCommandDispatch(); + + // late initialisation, especially for adding as listener + virtual void initialize(); + +protected: + // ____ XDispatch ____ + virtual void SAL_CALL dispatch( + const ::com::sun::star::util::URL& URL, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& Arguments ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ WeakComponentImplHelperBase ____ + /// is called when this is disposed + virtual void SAL_CALL disposing(); + + // ____ XEventListener (base of XModifyListener) ____ + virtual void SAL_CALL disposing( + const ::com::sun::star::lang::EventObject& Source ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void fireStatusEvent( + const ::rtl::OUString & rURL, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & xSingleListener ); + + // ____ XModifyListener ____ + virtual void SAL_CALL modified( + const ::com::sun::star::lang::EventObject& aEvent ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ XSelectionChangeListener ____ + virtual void SAL_CALL selectionChanged( + const ::com::sun::star::lang::EventObject& aEvent ) + throw (::com::sun::star::uno::RuntimeException); + +private: + void fireStatusEventForURLImpl( + const ::rtl::OUString & rURL, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & xSingleListener ); + + bool commandAvailable( const ::rtl::OUString & rCommand ); + void updateCommandAvailability(); + + bool isShapeControllerCommandAvailable( const ::rtl::OUString& rCommand ); + + ChartController* m_pChartController; + ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XController > m_xController; + ::com::sun::star::uno::Reference< + ::com::sun::star::view::XSelectionSupplier > m_xSelectionSupplier; + ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XDispatch > m_xDispatch; + + ::std::auto_ptr< impl::ModelState > m_apModelState; + ::std::auto_ptr< impl::ControllerState > m_apControllerState; + + mutable ::std::map< ::rtl::OUString, bool > m_aCommandAvailability; + mutable ::std::map< ::rtl::OUString, ::com::sun::star::uno::Any > m_aCommandArguments; + + CommandDispatchContainer* m_pDispatchContainer; +}; + +} // namespace chart + +// CHART2_CONTROLLERCOMMANDDISPATCH_HXX +#endif diff --git a/chart2/source/controller/main/DragMethod_Base.cxx b/chart2/source/controller/main/DragMethod_Base.cxx new file mode 100644 index 000000000000..11ba7b7b8016 --- /dev/null +++ b/chart2/source/controller/main/DragMethod_Base.cxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "DragMethod_Base.hxx" + +#include "Strings.hrc" +#include "ResId.hxx" +#include "macros.hxx" +#include "ObjectNameProvider.hxx" +#include "ObjectIdentifier.hxx" +#include <rtl/math.hxx> +//header for class SdrPageView +#include <svx/svdpagv.hxx> +#include <svx/ActionDescriptionProvider.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> + +//............................................................................. +namespace chart +{ +//............................................................................. + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::WeakReference; + +DragMethod_Base::DragMethod_Base( DrawViewWrapper& rDrawViewWrapper + , const rtl::OUString& rObjectCID + , const Reference< frame::XModel >& xChartModel + , ActionDescriptionProvider::ActionType eActionType ) + : SdrDragMethod( rDrawViewWrapper ) + , m_rDrawViewWrapper(rDrawViewWrapper) + , m_aObjectCID(rObjectCID) + , m_eActionType( eActionType ) + , m_xChartModel( WeakReference< frame::XModel >(xChartModel) ) +{ + setMoveOnly(true); +} +DragMethod_Base::~DragMethod_Base() +{ +} + +Reference< frame::XModel > DragMethod_Base::getChartModel() const +{ + return Reference< frame::XModel >( m_xChartModel );; +} + +rtl::OUString DragMethod_Base::getUndoDescription() const +{ + return ActionDescriptionProvider::createDescription( + m_eActionType, + ObjectNameProvider::getName( ObjectIdentifier::getObjectType( m_aObjectCID ))); +} +void DragMethod_Base::TakeSdrDragComment(String& rStr) const +{ + rStr = String( getUndoDescription() ); +} +Pointer DragMethod_Base::GetSdrDragPointer() const +{ + if( IsDraggingPoints() || IsDraggingGluePoints() ) + return Pointer(POINTER_MOVEPOINT); + else + return Pointer(POINTER_MOVE); +} +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/DragMethod_Base.hxx b/chart2/source/controller/main/DragMethod_Base.hxx new file mode 100644 index 000000000000..dfd5cfa20255 --- /dev/null +++ b/chart2/source/controller/main/DragMethod_Base.hxx @@ -0,0 +1,69 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_DRAGMETHOD_BASE_HXX +#define CHART2_DRAGMETHOD_BASE_HXX + +#include "DrawViewWrapper.hxx" +#include <svx/ActionDescriptionProvider.hxx> +// header for class SdrDragMethod +#include <svx/svddrgmt.hxx> + +// header for class WeakReference +#include <cppuhelper/weakref.hxx> + +namespace chart +{ + +class DragMethod_Base : public SdrDragMethod +{ +public: + DragMethod_Base( DrawViewWrapper& rDrawViewWrapper, const rtl::OUString& rObjectCID + , const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xChartModel + , ActionDescriptionProvider::ActionType eActionType = ActionDescriptionProvider::MOVE ); + virtual ~DragMethod_Base(); + + virtual rtl::OUString getUndoDescription() const; + + virtual void TakeSdrDragComment(String& rStr) const; + virtual Pointer GetSdrDragPointer() const; + +protected: + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > getChartModel() const; + +protected: + DrawViewWrapper& m_rDrawViewWrapper; + rtl::OUString m_aObjectCID; + ActionDescriptionProvider::ActionType m_eActionType; + +private: + ::com::sun::star::uno::WeakReference< ::com::sun::star::frame::XModel > m_xChartModel; +}; + +} // namespace chart + +// CHART2_DRAGMETHOD_BASE_HXX +#endif diff --git a/chart2/source/controller/main/DragMethod_PieSegment.cxx b/chart2/source/controller/main/DragMethod_PieSegment.cxx new file mode 100644 index 000000000000..5074147fa9e2 --- /dev/null +++ b/chart2/source/controller/main/DragMethod_PieSegment.cxx @@ -0,0 +1,163 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "DragMethod_PieSegment.hxx" + +#include "Strings.hrc" +#include "ResId.hxx" +#include "macros.hxx" +#include "ObjectIdentifier.hxx" +#include <rtl/math.hxx> +#include <svx/svdpagv.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <basegfx/matrix/b2dhommatrix.hxx> + +//............................................................................. +namespace chart +{ +//............................................................................. + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; +using ::basegfx::B2DVector; + +DragMethod_PieSegment::DragMethod_PieSegment( DrawViewWrapper& rDrawViewWrapper + , const rtl::OUString& rObjectCID + , const Reference< frame::XModel >& xChartModel ) + : DragMethod_Base( rDrawViewWrapper, rObjectCID, xChartModel ) + , m_aStartVector(100.0,100.0) + , m_fInitialOffset(0.0) + , m_fAdditionalOffset(0.0) + , m_aDragDirection(1000.0,1000.0) + , m_fDragRange( 1.0 ) +{ + rtl::OUString aParameter( ObjectIdentifier::getDragParameterString( m_aObjectCID ) ); + + sal_Int32 nOffsetPercent(0); + awt::Point aMinimumPosition(0,0); + awt::Point aMaximumPosition(0,0); + + ObjectIdentifier::parsePieSegmentDragParameterString( + aParameter, nOffsetPercent, aMinimumPosition, aMaximumPosition ); + + m_fInitialOffset = nOffsetPercent / 100.0; + if( m_fInitialOffset < 0.0 ) + m_fInitialOffset = 0.0; + if( m_fInitialOffset > 1.0 ) + m_fInitialOffset = 1.0; + B2DVector aMinVector( aMinimumPosition.X, aMinimumPosition.Y ); + B2DVector aMaxVector( aMaximumPosition.X, aMaximumPosition.Y ); + m_aDragDirection = aMaxVector - aMinVector; + m_fDragRange = m_aDragDirection.scalar( m_aDragDirection ); + if( ::rtl::math::approxEqual( m_fDragRange, 0.0 ) ) + m_fDragRange = 1.0; +} +DragMethod_PieSegment::~DragMethod_PieSegment() +{ +} +void DragMethod_PieSegment::TakeSdrDragComment(String& rStr) const +{ + rStr = String( SchResId( STR_STATUS_PIE_SEGMENT_EXPLODED ) ); + rStr.SearchAndReplaceAscii( "%PERCENTVALUE", String::CreateFromInt32( static_cast<sal_Int32>((m_fAdditionalOffset+m_fInitialOffset)*100.0) )); +} +bool DragMethod_PieSegment::BeginSdrDrag() +{ + Point aStart( DragStat().GetStart() ); + m_aStartVector = B2DVector( aStart.X(), aStart.Y() ); + Show(); + return true; +} +void DragMethod_PieSegment::MoveSdrDrag(const Point& rPnt) +{ + if( DragStat().CheckMinMoved(rPnt) ) + { + //calculate new offset + B2DVector aShiftVector(( B2DVector( rPnt.X(), rPnt.Y() ) - m_aStartVector )); + m_fAdditionalOffset = m_aDragDirection.scalar( aShiftVector )/m_fDragRange; // projection + + if( m_fAdditionalOffset < -m_fInitialOffset ) + m_fAdditionalOffset = -m_fInitialOffset; + else if( m_fAdditionalOffset > (1.0-m_fInitialOffset) ) + m_fAdditionalOffset = 1.0 - m_fInitialOffset; + + B2DVector aNewPosVector = m_aStartVector + (m_aDragDirection * m_fAdditionalOffset); + Point aNewPos = Point( (long)(aNewPosVector.getX()), (long)(aNewPosVector.getY()) ); + if( aNewPos != DragStat().GetNow() ) + { + Hide(); + DragStat().NextMove( aNewPos ); + Show(); + } + } +} +bool DragMethod_PieSegment::EndSdrDrag(bool /*bCopy*/) +{ + Hide(); + + try + { + Reference< frame::XModel > xChartModel( this->getChartModel() ); + if( xChartModel.is() ) + { + Reference< beans::XPropertySet > xPointProperties( + ObjectIdentifier::getObjectPropertySet( m_aObjectCID, xChartModel ) ); + if( xPointProperties.is() ) + xPointProperties->setPropertyValue( C2U( "Offset" ), uno::makeAny( m_fAdditionalOffset+m_fInitialOffset )); + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return true; +} +basegfx::B2DHomMatrix DragMethod_PieSegment::getCurrentTransformation() +{ + basegfx::B2DHomMatrix aRetval; + + aRetval.translate(DragStat().GetDX(), DragStat().GetDY()); + + return aRetval; +} +void DragMethod_PieSegment::createSdrDragEntries() +{ + SdrObject* pObj = m_rDrawViewWrapper.getSelectedObject(); + SdrPageView* pPV = m_rDrawViewWrapper.GetPageView(); + + if( pObj && pPV ) + { + const basegfx::B2DPolyPolygon aNewPolyPolygon(pObj->TakeXorPoly()); + addSdrDragEntry(new SdrDragEntryPolyPolygon(aNewPolyPolygon)); + } +} +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/DragMethod_PieSegment.hxx b/chart2/source/controller/main/DragMethod_PieSegment.hxx new file mode 100644 index 000000000000..f63af9be3cc4 --- /dev/null +++ b/chart2/source/controller/main/DragMethod_PieSegment.hxx @@ -0,0 +1,64 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_DRAGMETHOD_PIESEGMENT_HXX +#define CHART2_DRAGMETHOD_PIESEGMENT_HXX + +#include "DragMethod_Base.hxx" +#include <basegfx/vector/b2dvector.hxx> + +namespace chart +{ + +class DragMethod_PieSegment : public DragMethod_Base +{ +public: + DragMethod_PieSegment( DrawViewWrapper& rDrawViewWrapper, const rtl::OUString& rObjectCID + , const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xChartModel ); + virtual ~DragMethod_PieSegment(); + + virtual void TakeSdrDragComment(String& rStr) const; + virtual bool BeginSdrDrag(); + virtual void MoveSdrDrag(const Point& rPnt); + virtual bool EndSdrDrag(bool bCopy); + + virtual basegfx::B2DHomMatrix getCurrentTransformation(); + +protected: + virtual void createSdrDragEntries(); + +private: + ::basegfx::B2DVector m_aStartVector; + double m_fInitialOffset; + double m_fAdditionalOffset; + ::basegfx::B2DVector m_aDragDirection; + double m_fDragRange; +}; + +} // namespace chart + +// CHART2_DRAGMETHOD_PIESEGMENT_HXX +#endif diff --git a/chart2/source/controller/main/DragMethod_RotateDiagram.cxx b/chart2/source/controller/main/DragMethod_RotateDiagram.cxx new file mode 100644 index 000000000000..944b44dd25bf --- /dev/null +++ b/chart2/source/controller/main/DragMethod_RotateDiagram.cxx @@ -0,0 +1,237 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" +#include "DragMethod_RotateDiagram.hxx" + +#include "SelectionHelper.hxx" +#include "CommonConverters.hxx" +#include "ChartModelHelper.hxx" +#include "macros.hxx" +#include "DiagramHelper.hxx" +#include "ChartTypeHelper.hxx" +#include "ThreeDHelper.hxx" +#include <svx/sdr/overlay/overlaypolypolygon.hxx> +#include <svx/sdr/overlay/overlaymanager.hxx> + +// header for class E3dScene +#include <svx/scene3d.hxx> +#include <basegfx/matrix/b3dhommatrix.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <svx/sdr/contact/viewcontactofe3dscene.hxx> +#include <drawinglayer/geometry/viewinformation3d.hxx> + +#define FIXED_SIZE_FOR_3D_CHART_VOLUME (10000.0) + +//............................................................................. +namespace chart +{ +//............................................................................. + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; + +DragMethod_RotateDiagram::DragMethod_RotateDiagram( DrawViewWrapper& rDrawViewWrapper + , const rtl::OUString& rObjectCID + , const Reference< frame::XModel >& xChartModel + , RotationDirection eRotationDirection ) + : DragMethod_Base( rDrawViewWrapper, rObjectCID, xChartModel, ActionDescriptionProvider::ROTATE ) + , m_pScene(0) + , m_aReferenceRect(100,100,100,100) + , m_aStartPos(0,0) + , m_aWireframePolyPolygon() + , m_fInitialXAngleRad(0.0) + , m_fInitialYAngleRad(0.0) + , m_fInitialZAngleRad(0.0) + , m_fAdditionalXAngleRad(0.0) + , m_fAdditionalYAngleRad(0.0) + , m_fAdditionalZAngleRad(0.0) + , m_nInitialHorizontalAngleDegree(0) + , m_nInitialVerticalAngleDegree(0) + , m_nAdditionalHorizontalAngleDegree(0) + , m_nAdditionalVerticalAngleDegree(0) + , m_eRotationDirection(eRotationDirection) + , m_bRightAngledAxes(sal_False) +{ + m_pScene = SelectionHelper::getSceneToRotate( rDrawViewWrapper.getNamedSdrObject( rObjectCID ) ); + SdrObject* pObj = rDrawViewWrapper.getSelectedObject(); + if(pObj && m_pScene) + { + m_aReferenceRect = pObj->GetLogicRect(); + Rectangle aTemp = m_pScene->GetLogicRect(); + + m_aWireframePolyPolygon = m_pScene->CreateWireframe(); + + uno::Reference< chart2::XDiagram > xDiagram( ChartModelHelper::findDiagram(this->getChartModel()) ); + uno::Reference< beans::XPropertySet > xDiagramProperties( xDiagram, uno::UNO_QUERY ); + if( xDiagramProperties.is() ) + { + ThreeDHelper::getRotationFromDiagram( xDiagramProperties + , m_nInitialHorizontalAngleDegree, m_nInitialVerticalAngleDegree ); + + ThreeDHelper::getRotationAngleFromDiagram( xDiagramProperties + , m_fInitialXAngleRad, m_fInitialYAngleRad, m_fInitialZAngleRad ); + + if( ChartTypeHelper::isSupportingRightAngledAxes( + DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ) ) + xDiagramProperties->getPropertyValue(C2U( "RightAngledAxes" )) >>= m_bRightAngledAxes; + if(m_bRightAngledAxes) + { + if( m_eRotationDirection==ROTATIONDIRECTION_Z ) + m_eRotationDirection=ROTATIONDIRECTION_FREE; + ThreeDHelper::adaptRadAnglesForRightAngledAxes( m_fInitialXAngleRad, m_fInitialYAngleRad ); + } + } + } +} +DragMethod_RotateDiagram::~DragMethod_RotateDiagram() +{ +} +void DragMethod_RotateDiagram::TakeSdrDragComment(String& /*rStr*/) const +{ +} +bool DragMethod_RotateDiagram::BeginSdrDrag() +{ + m_aStartPos = DragStat().GetStart(); + Show(); + return true; +} +void DragMethod_RotateDiagram::MoveSdrDrag(const Point& rPnt) +{ + if( DragStat().CheckMinMoved(rPnt) ) + { + Hide(); + + //calculate new angle + double fX = F_PI / 2.0 * (double)(rPnt.Y() - m_aStartPos.Y()) + / (double)m_aReferenceRect.GetHeight(); + double fY = F_PI * (double)(rPnt.X() - m_aStartPos.X()) + / (double)m_aReferenceRect.GetWidth(); + + if( m_eRotationDirection != ROTATIONDIRECTION_Y ) + m_fAdditionalYAngleRad = fY; + else + m_fAdditionalYAngleRad = 0.0; + if( m_eRotationDirection != ROTATIONDIRECTION_X ) + m_fAdditionalXAngleRad = fX; + else + m_fAdditionalXAngleRad = 0.0; + m_fAdditionalZAngleRad = 0.0; + + if( m_eRotationDirection == ROTATIONDIRECTION_Z ) + { + m_fAdditionalXAngleRad = 0.0; + m_fAdditionalYAngleRad = 0.0; + + double fCx = m_aReferenceRect.Center().X(); + double fCy = m_aReferenceRect.Center().Y(); + + m_fAdditionalZAngleRad = atan((double)(fCx - m_aStartPos.X())/(m_aStartPos.Y()-fCy)) + + atan((double)(fCx - rPnt.X())/(fCy-rPnt.Y())); + } + + m_nAdditionalHorizontalAngleDegree = static_cast<sal_Int32>(m_fAdditionalXAngleRad*180.0/F_PI); + m_nAdditionalVerticalAngleDegree = -static_cast<sal_Int32>(m_fAdditionalYAngleRad*180.0/F_PI); + + DragStat().NextMove(rPnt); + Show(); + } +} +bool DragMethod_RotateDiagram::EndSdrDrag(bool /*bCopy*/) +{ + Hide(); + + if( m_bRightAngledAxes || m_eRotationDirection==ROTATIONDIRECTION_Z ) + { + double fResultX = m_fInitialXAngleRad + m_fAdditionalXAngleRad; + double fResultY = m_fInitialYAngleRad + m_fAdditionalYAngleRad; + double fResultZ = m_fInitialZAngleRad + m_fAdditionalZAngleRad; + + if(m_bRightAngledAxes) + ThreeDHelper::adaptRadAnglesForRightAngledAxes( fResultX, fResultY ); + + ThreeDHelper::setRotationAngleToDiagram( uno::Reference< beans::XPropertySet >( ChartModelHelper::findDiagram( this->getChartModel() ), uno::UNO_QUERY ) + , fResultX, fResultY, fResultZ ); + } + else + { + ThreeDHelper::setRotationToDiagram( ( uno::Reference< beans::XPropertySet >( ChartModelHelper::findDiagram( this->getChartModel() ), uno::UNO_QUERY ) ) + , m_nInitialHorizontalAngleDegree+m_nAdditionalHorizontalAngleDegree, m_nInitialVerticalAngleDegree+m_nAdditionalVerticalAngleDegree ); + } + + return true; +} +void DragMethod_RotateDiagram::CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlayManager) +{ + ::basegfx::B3DHomMatrix aCurrentTransform; + aCurrentTransform.translate( -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0, + -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0, + -FIXED_SIZE_FOR_3D_CHART_VOLUME/2.0 ); + + double fResultX = m_fInitialXAngleRad + m_fAdditionalXAngleRad; + double fResultY = m_fInitialYAngleRad + m_fAdditionalYAngleRad; + double fResultZ = m_fInitialZAngleRad + m_fAdditionalZAngleRad; + + if(!m_bRightAngledAxes) + { + if( m_eRotationDirection!=ROTATIONDIRECTION_Z ) + { + ThreeDHelper::convertElevationRotationDegToXYZAngleRad( + m_nInitialHorizontalAngleDegree+m_nAdditionalHorizontalAngleDegree, -(m_nInitialVerticalAngleDegree+m_nAdditionalVerticalAngleDegree) + , fResultX, fResultY, fResultZ ); + } + aCurrentTransform.rotate( fResultX, fResultY, fResultZ ); + } + else + { + ThreeDHelper::adaptRadAnglesForRightAngledAxes( fResultX, fResultY ); + aCurrentTransform.shearXY(fResultY,-(fResultX)); + } + + if(m_aWireframePolyPolygon.count() && m_pScene) + { + const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(m_pScene->GetViewContact()); + const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D()); + const basegfx::B3DHomMatrix aWorldToView(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection() * aViewInfo3D.getOrientation()); + const basegfx::B3DHomMatrix aTransform(aWorldToView * aCurrentTransform); + + // transform to relative scene coordinates + basegfx::B2DPolyPolygon aPolyPolygon(basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(m_aWireframePolyPolygon, aTransform)); + + // transform to 2D view coordinates + aPolyPolygon.transform(rVCScene.getObjectTransformation()); + + sdr::overlay::OverlayPolyPolygonStriped* pNew = new ::sdr::overlay::OverlayPolyPolygonStriped(aPolyPolygon); + rOverlayManager.add(*pNew); + addToOverlayObjectList(*pNew); + } +} +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/DragMethod_RotateDiagram.hxx b/chart2/source/controller/main/DragMethod_RotateDiagram.hxx new file mode 100644 index 000000000000..b16e12fe5359 --- /dev/null +++ b/chart2/source/controller/main/DragMethod_RotateDiagram.hxx @@ -0,0 +1,92 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_DRAGMETHOD_ROTATEDIAGRAM_HXX +#define CHART2_DRAGMETHOD_ROTATEDIAGRAM_HXX + +#include "DragMethod_Base.hxx" + +// header for class ::basegfx::B3DPolyPolygon +#include <basegfx/polygon/b3dpolypolygon.hxx> + +namespace chart +{ + +class DragMethod_RotateDiagram : public DragMethod_Base +{ +public: + enum RotationDirection + { + ROTATIONDIRECTION_FREE, + ROTATIONDIRECTION_X, + ROTATIONDIRECTION_Y, + ROTATIONDIRECTION_Z + }; + + DragMethod_RotateDiagram( DrawViewWrapper& rDrawViewWrapper + , const rtl::OUString& rObjectCID + , const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& xChartModel + , RotationDirection eRotationDirection + ); + virtual ~DragMethod_RotateDiagram(); + + virtual void TakeSdrDragComment(String& rStr) const; + + virtual bool BeginSdrDrag(); + virtual void MoveSdrDrag(const Point& rPnt); + virtual bool EndSdrDrag(bool bCopy); + + virtual void CreateOverlayGeometry(sdr::overlay::OverlayManager& rOverlayManager); + +private: + E3dScene* m_pScene; + + Rectangle m_aReferenceRect; + Point m_aStartPos; + basegfx::B3DPolyPolygon m_aWireframePolyPolygon; + + double m_fInitialXAngleRad; + double m_fInitialYAngleRad; + double m_fInitialZAngleRad; + + double m_fAdditionalXAngleRad; + double m_fAdditionalYAngleRad; + double m_fAdditionalZAngleRad; + + sal_Int32 m_nInitialHorizontalAngleDegree; + sal_Int32 m_nInitialVerticalAngleDegree; + + sal_Int32 m_nAdditionalHorizontalAngleDegree; + sal_Int32 m_nAdditionalVerticalAngleDegree; + + RotationDirection m_eRotationDirection; + sal_Bool m_bRightAngledAxes; +}; + +} // namespace chart + +// CHART2_DRAGMETHOD_ROTATEDIAGRAM_HXX +#endif diff --git a/chart2/source/controller/main/DrawCommandDispatch.cxx b/chart2/source/controller/main/DrawCommandDispatch.cxx new file mode 100644 index 000000000000..aa28028c4861 --- /dev/null +++ b/chart2/source/controller/main/DrawCommandDispatch.cxx @@ -0,0 +1,674 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "DrawCommandDispatch.hxx" +#include "DrawCommandDispatch.hrc" +#include "ChartController.hxx" +#include "DrawViewWrapper.hxx" +#include "chartview/DrawModelWrapper.hxx" +#include "macros.hxx" + +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#include <svl/itempool.hxx> +#include <editeng/adjitem.hxx> +#include <svx/dialogs.hrc> +#include <svx/dialmgr.hxx> +#include <svx/fmmodel.hxx> +#include <svx/gallery.hxx> +#include <svx/svdoashp.hxx> +#include <svx/svdocapt.hxx> +#include <svx/svdopath.hxx> +#include <svx/svdpage.hxx> +#include <svx/unoapi.hxx> +#include <svx/xlnedit.hxx> +#include <svx/xlnedwit.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/xtable.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> + +#include <boost/bind.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::frame; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + + +//............................................................................. +namespace +{ +//............................................................................. + + // comparing two PropertyValue instances + struct PropertyValueCompare : public ::std::binary_function< beans::PropertyValue, ::rtl::OUString, bool > + { + bool operator() ( const beans::PropertyValue& rPropValue, const ::rtl::OUString& rName ) const + { + return rPropValue.Name.equals( rName ); + } + bool operator() ( const ::rtl::OUString& rName, const beans::PropertyValue& rPropValue ) const + { + return rName.equals( rPropValue.Name ); + } + }; + +//............................................................................. +} // anonymous namespace +//............................................................................. + + +//............................................................................. +namespace chart +{ +//............................................................................. + +DrawCommandDispatch::DrawCommandDispatch( const Reference< uno::XComponentContext >& rxContext, + ChartController* pController ) + :FeatureCommandDispatchBase( rxContext ) + ,m_pChartController( pController ) +{ +} + +DrawCommandDispatch::~DrawCommandDispatch() +{ +} + +void DrawCommandDispatch::initialize() +{ + FeatureCommandDispatchBase::initialize(); +} + +bool DrawCommandDispatch::isFeatureSupported( const ::rtl::OUString& rCommandURL ) +{ + sal_uInt16 nFeatureId = 0; + ::rtl::OUString aBaseCommand; + ::rtl::OUString aCustomShapeType; + return parseCommandURL( rCommandURL, &nFeatureId, &aBaseCommand, &aCustomShapeType ); +} + +::basegfx::B2DPolyPolygon getPolygon( sal_uInt16 nResId, SdrModel& rModel ) +{ + ::basegfx::B2DPolyPolygon aReturn; + XLineEndList* pLineEndList = rModel.GetLineEndList(); + if ( pLineEndList ) + { + String aName( SVX_RES( nResId ) ); + long nCount = pLineEndList->Count(); + for ( long nIndex = 0; nIndex < nCount; ++nIndex ) + { + XLineEndEntry* pEntry = pLineEndList->GetLineEnd( nIndex ); + if ( pEntry->GetName() == aName ) + { + aReturn = pEntry->GetLineEnd(); + break; + } + } + } + return aReturn; +} + +void DrawCommandDispatch::setAttributes( SdrObject* pObj ) +{ + if ( m_pChartController ) + { + DrawModelWrapper* pDrawModelWrapper = m_pChartController->GetDrawModelWrapper(); + DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper(); + if ( pDrawModelWrapper && pDrawViewWrapper && pDrawViewWrapper->GetCurrentObjIdentifier() == OBJ_CUSTOMSHAPE ) + { + sal_Bool bAttributesAppliedFromGallery = sal_False; + if ( GalleryExplorer::GetSdrObjCount( GALLERY_THEME_POWERPOINT ) ) + { + ::std::vector< ::rtl::OUString > aObjList; + if ( GalleryExplorer::FillObjListTitle( GALLERY_THEME_POWERPOINT, aObjList ) ) + { + for ( sal_uInt16 i = 0; i < aObjList.size(); ++i ) + { + if ( aObjList[ i ].equalsIgnoreAsciiCase( m_aCustomShapeType ) ) + { + FmFormModel aModel; + SfxItemPool& rPool = aModel.GetItemPool(); + rPool.FreezeIdRanges(); + if ( GalleryExplorer::GetSdrObj( GALLERY_THEME_POWERPOINT, i, &aModel ) ) + { + const SdrObject* pSourceObj = aModel.GetPage( 0 )->GetObj( 0 ); + if ( pSourceObj ) + { + const SfxItemSet& rSource = pSourceObj->GetMergedItemSet(); + SfxItemSet aDest( pObj->GetModel()->GetItemPool(), // ranges from SdrAttrObj + SDRATTR_START, SDRATTR_SHADOW_LAST, + SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST, + SDRATTR_TEXTDIRECTION, SDRATTR_TEXTDIRECTION, + // Graphic Attributes + SDRATTR_GRAF_FIRST, SDRATTR_GRAF_LAST, + // 3d Properties + SDRATTR_3D_FIRST, SDRATTR_3D_LAST, + // CustomShape properties + SDRATTR_CUSTOMSHAPE_FIRST, SDRATTR_CUSTOMSHAPE_LAST, + // range from SdrTextObj + EE_ITEMS_START, EE_ITEMS_END, + // end + 0, 0); + aDest.Set( rSource ); + pObj->SetMergedItemSet( aDest ); + sal_Int32 nAngle = pSourceObj->GetRotateAngle(); + if ( nAngle ) + { + double a = nAngle * F_PI18000; + pObj->NbcRotate( pObj->GetSnapRect().Center(), nAngle, sin( a ), cos( a ) ); + } + bAttributesAppliedFromGallery = sal_True; + } + } + break; + } + } + } + } + if ( !bAttributesAppliedFromGallery ) + { + pObj->SetMergedItem( SvxAdjustItem( SVX_ADJUST_CENTER, 0 ) ); + pObj->SetMergedItem( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) ); + pObj->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_BLOCK ) ); + pObj->SetMergedItem( SdrTextAutoGrowHeightItem( sal_False ) ); + ( dynamic_cast< SdrObjCustomShape* >( pObj ) )->MergeDefaultAttributes( &m_aCustomShapeType ); + } + } + } +} + +void DrawCommandDispatch::setLineEnds( SfxItemSet& rAttr ) +{ + if ( m_nFeatureId == COMMAND_ID_LINE_ARROW_END && m_pChartController ) + { + DrawModelWrapper* pDrawModelWrapper = m_pChartController->GetDrawModelWrapper(); + DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper(); + if ( pDrawModelWrapper && pDrawViewWrapper ) + { + ::basegfx::B2DPolyPolygon aArrow( getPolygon( RID_SVXSTR_ARROW, pDrawModelWrapper->getSdrModel() ) ); + if ( !aArrow.count() ) + { + ::basegfx::B2DPolygon aNewArrow; + aNewArrow.append( ::basegfx::B2DPoint( 10.0, 0.0 ) ); + aNewArrow.append( ::basegfx::B2DPoint( 0.0, 30.0) ); + aNewArrow.append( ::basegfx::B2DPoint( 20.0, 30.0 ) ); + aNewArrow.setClosed( true ); + aArrow.append( aNewArrow ); + } + + SfxItemSet aSet( pDrawViewWrapper->GetModel()->GetItemPool() ); + pDrawViewWrapper->GetAttributes( aSet ); + + long nWidth = 300; // (1/100th mm) + if ( aSet.GetItemState( XATTR_LINEWIDTH ) != SFX_ITEM_DONTCARE ) + { + long nValue = ( ( const XLineWidthItem& ) aSet.Get( XATTR_LINEWIDTH ) ).GetValue(); + if ( nValue > 0 ) + { + nWidth = nValue * 3; + } + } + + rAttr.Put( XLineEndItem( SVX_RESSTR( RID_SVXSTR_ARROW ), aArrow ) ); + rAttr.Put( XLineEndWidthItem( nWidth ) ); + } + } +} + +// WeakComponentImplHelperBase +void DrawCommandDispatch::disposing() +{ +} + +// XEventListener +void DrawCommandDispatch::disposing( const lang::EventObject& /* Source */ ) + throw (uno::RuntimeException) +{ +} + +FeatureState DrawCommandDispatch::getState( const ::rtl::OUString& rCommand ) +{ + FeatureState aReturn; + aReturn.bEnabled = false; + aReturn.aState <<= false; + + sal_uInt16 nFeatureId = 0; + ::rtl::OUString aBaseCommand; + ::rtl::OUString aCustomShapeType; + if ( parseCommandURL( rCommand, &nFeatureId, &aBaseCommand, &aCustomShapeType ) ) + { + switch ( nFeatureId ) + { + case COMMAND_ID_OBJECT_SELECT: + case COMMAND_ID_DRAW_LINE: + case COMMAND_ID_LINE_ARROW_END: + case COMMAND_ID_DRAW_RECT: + case COMMAND_ID_DRAW_ELLIPSE: + case COMMAND_ID_DRAW_FREELINE_NOFILL: + case COMMAND_ID_DRAW_TEXT: + case COMMAND_ID_DRAW_CAPTION: + case COMMAND_ID_DRAWTBX_CS_BASIC: + case COMMAND_ID_DRAWTBX_CS_SYMBOL: + case COMMAND_ID_DRAWTBX_CS_ARROW: + case COMMAND_ID_DRAWTBX_CS_FLOWCHART: + case COMMAND_ID_DRAWTBX_CS_CALLOUT: + case COMMAND_ID_DRAWTBX_CS_STAR: + { + aReturn.bEnabled = true; + aReturn.aState <<= false; + } + break; + default: + { + aReturn.bEnabled = false; + aReturn.aState <<= false; + } + break; + } + } + + return aReturn; +} + +void DrawCommandDispatch::execute( const ::rtl::OUString& rCommand, const Sequence< beans::PropertyValue>& rArgs ) +{ + (void)rArgs; + + ChartDrawMode eDrawMode = CHARTDRAW_SELECT; + SdrObjKind eKind = OBJ_NONE; + bool bCreate = false; + + sal_uInt16 nFeatureId = 0; + ::rtl::OUString aBaseCommand; + ::rtl::OUString aCustomShapeType; + if ( parseCommandURL( rCommand, &nFeatureId, &aBaseCommand, &aCustomShapeType ) ) + { + m_nFeatureId = nFeatureId; + m_aCustomShapeType = aCustomShapeType; + + switch ( nFeatureId ) + { + case COMMAND_ID_OBJECT_SELECT: + { + eDrawMode = CHARTDRAW_SELECT; + eKind = OBJ_NONE; + } + break; + case COMMAND_ID_DRAW_LINE: + case COMMAND_ID_LINE_ARROW_END: + { + eDrawMode = CHARTDRAW_INSERT; + eKind = OBJ_LINE; + } + break; + case COMMAND_ID_DRAW_RECT: + { + eDrawMode = CHARTDRAW_INSERT; + eKind = OBJ_RECT; + } + break; + case COMMAND_ID_DRAW_ELLIPSE: + { + eDrawMode = CHARTDRAW_INSERT; + eKind = OBJ_CIRC; + } + break; + case COMMAND_ID_DRAW_FREELINE_NOFILL: + { + eDrawMode = CHARTDRAW_INSERT; + eKind = OBJ_FREELINE; + } + break; + case COMMAND_ID_DRAW_TEXT: + { + eDrawMode = CHARTDRAW_INSERT; + eKind = OBJ_TEXT; + bCreate = true; + } + break; + case COMMAND_ID_DRAW_CAPTION: + { + eDrawMode = CHARTDRAW_INSERT; + eKind = OBJ_CAPTION; + } + break; + case COMMAND_ID_DRAWTBX_CS_BASIC: + case COMMAND_ID_DRAWTBX_CS_SYMBOL: + case COMMAND_ID_DRAWTBX_CS_ARROW: + case COMMAND_ID_DRAWTBX_CS_FLOWCHART: + case COMMAND_ID_DRAWTBX_CS_CALLOUT: + case COMMAND_ID_DRAWTBX_CS_STAR: + { + eDrawMode = CHARTDRAW_INSERT; + eKind = OBJ_CUSTOMSHAPE; + } + break; + default: + { + eDrawMode = CHARTDRAW_SELECT; + eKind = OBJ_NONE; + } + break; + } + + if ( m_pChartController ) + { + DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper(); + if ( pDrawViewWrapper ) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + m_pChartController->setDrawMode( eDrawMode ); + setInsertObj( sal::static_int_cast< USHORT >( eKind ) ); + if ( bCreate ) + { + pDrawViewWrapper->SetCreateMode(); + } + + const ::rtl::OUString sKeyModifier( C2U( "KeyModifier" ) ); + const beans::PropertyValue* pIter = rArgs.getConstArray(); + const beans::PropertyValue* pEnd = pIter + rArgs.getLength(); + const beans::PropertyValue* pKeyModifier = ::std::find_if( + pIter, pEnd, ::std::bind2nd( PropertyValueCompare(), boost::cref( sKeyModifier ) ) ); + sal_Int16 nKeyModifier = 0; + if ( pKeyModifier && ( pKeyModifier->Value >>= nKeyModifier ) && nKeyModifier == KEY_MOD1 ) + { + if ( eDrawMode == CHARTDRAW_INSERT ) + { + SdrObject* pObj = createDefaultObject( nFeatureId ); + if ( pObj ) + { + SdrPageView* pPageView = pDrawViewWrapper->GetSdrPageView(); + pDrawViewWrapper->InsertObjectAtView( pObj, *pPageView ); + Reference< drawing::XShape > xShape( pObj->getUnoShape(), uno::UNO_QUERY ); + if ( xShape.is() ) + { + m_pChartController->m_aSelection.setSelection( xShape ); + m_pChartController->m_aSelection.applySelection( pDrawViewWrapper ); + } + if ( nFeatureId == SID_DRAW_TEXT ) + { + m_pChartController->StartTextEdit(); + } + } + } + } + } + } + } +} + +void DrawCommandDispatch::describeSupportedFeatures() +{ + implDescribeSupportedFeature( ".uno:SelectObject", COMMAND_ID_OBJECT_SELECT, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:Line", COMMAND_ID_DRAW_LINE, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:LineArrowEnd", COMMAND_ID_LINE_ARROW_END, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:Rect", COMMAND_ID_DRAW_RECT, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:Ellipse", COMMAND_ID_DRAW_ELLIPSE, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:Freeline_Unfilled", COMMAND_ID_DRAW_FREELINE_NOFILL, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:DrawText", COMMAND_ID_DRAW_TEXT, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:DrawCaption", COMMAND_ID_DRAW_CAPTION, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:BasicShapes", COMMAND_ID_DRAWTBX_CS_BASIC, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:SymbolShapes", COMMAND_ID_DRAWTBX_CS_SYMBOL, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:ArrowShapes", COMMAND_ID_DRAWTBX_CS_ARROW, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:FlowChartShapes", COMMAND_ID_DRAWTBX_CS_FLOWCHART, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:CalloutShapes", COMMAND_ID_DRAWTBX_CS_CALLOUT, CommandGroup::INSERT ); + implDescribeSupportedFeature( ".uno:StarShapes", COMMAND_ID_DRAWTBX_CS_STAR, CommandGroup::INSERT ); +} + +void DrawCommandDispatch::setInsertObj( USHORT eObj ) +{ + DrawViewWrapper* pDrawViewWrapper = ( m_pChartController ? m_pChartController->GetDrawViewWrapper() : NULL ); + if ( pDrawViewWrapper ) + { + pDrawViewWrapper->SetCurrentObj( eObj /*, Inventor */); + } +} + +SdrObject* DrawCommandDispatch::createDefaultObject( const sal_uInt16 nID ) +{ + SdrObject* pObj = NULL; + DrawViewWrapper* pDrawViewWrapper = ( m_pChartController ? m_pChartController->GetDrawViewWrapper() : NULL ); + DrawModelWrapper* pDrawModelWrapper = ( m_pChartController ? m_pChartController->GetDrawModelWrapper() : NULL ); + + if ( pDrawViewWrapper && pDrawModelWrapper ) + { + Reference< drawing::XDrawPage > xDrawPage( pDrawModelWrapper->getMainDrawPage() ); + SdrPage* pPage = GetSdrPageFromXDrawPage( xDrawPage ); + if ( pPage ) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + pObj = SdrObjFactory::MakeNewObject( pDrawViewWrapper->GetCurrentObjInventor(), + pDrawViewWrapper->GetCurrentObjIdentifier(), pPage ); + if ( pObj ) + { + long nDefaultObjectSizeWidth = 4000; + long nDefaultObjectSizeHeight = 2500; + Size aObjectSize( nDefaultObjectSizeWidth, nDefaultObjectSizeHeight ); + Rectangle aPageRect( Rectangle( Point( 0, 0 ), pPage->GetSize() ) ); + Point aObjectPos = aPageRect.Center(); + aObjectPos.X() -= aObjectSize.Width() / 2; + aObjectPos.Y() -= aObjectSize.Height() / 2; + Rectangle aRect( aObjectPos, aObjectSize ); + + switch ( nID ) + { + case COMMAND_ID_DRAW_LINE: + case COMMAND_ID_LINE_ARROW_END: + { + if ( pObj->ISA( SdrPathObj ) ) + { + Point aStart = aRect.TopLeft(); + Point aEnd = aRect.BottomRight(); + sal_Int32 nYMiddle( ( aRect.Top() + aRect.Bottom() ) / 2 ); + basegfx::B2DPolygon aPoly; + aPoly.append( basegfx::B2DPoint( aStart.X(), nYMiddle ) ); + aPoly.append( basegfx::B2DPoint( aEnd.X(), nYMiddle ) ); + ( dynamic_cast< SdrPathObj* >( pObj ) )->SetPathPoly( basegfx::B2DPolyPolygon( aPoly ) ); + SfxItemSet aSet( pDrawModelWrapper->GetItemPool() ); + setLineEnds( aSet ); + pObj->SetMergedItemSet( aSet ); + } + } + break; + case COMMAND_ID_DRAW_FREELINE_NOFILL: + { + if ( pObj->ISA( SdrPathObj ) ) + { + basegfx::B2DPolygon aInnerPoly; + aInnerPoly.append( basegfx::B2DPoint( aRect.Left(), aRect.Bottom() ) ); + aInnerPoly.appendBezierSegment( + basegfx::B2DPoint( aRect.Left(), aRect.Top() ), + basegfx::B2DPoint( aRect.Center().X(), aRect.Top() ), + basegfx::B2DPoint( aRect.Center().X(), aRect.Center().Y() ) ); + aInnerPoly.appendBezierSegment( + basegfx::B2DPoint( aRect.Center().X(), aRect.Bottom() ), + basegfx::B2DPoint( aRect.Right(), aRect.Bottom() ), + basegfx::B2DPoint( aRect.Right(), aRect.Top() ) ); + basegfx::B2DPolyPolygon aPoly; + aPoly.append( aInnerPoly ); + ( dynamic_cast< SdrPathObj* >( pObj ) )->SetPathPoly( aPoly ); + } + } + break; + case COMMAND_ID_DRAW_TEXT: + case COMMAND_ID_DRAW_TEXT_VERTICAL: + { + if ( pObj->ISA( SdrTextObj ) ) + { + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( pObj ); + if ( pTextObj ) + { + pTextObj->SetLogicRect( aRect ); + BOOL bVertical = ( nID == SID_DRAW_TEXT_VERTICAL ); + pTextObj->SetVerticalWriting( bVertical ); + if ( bVertical ) + { + SfxItemSet aSet( pDrawModelWrapper->GetItemPool() ); + aSet.Put( SdrTextAutoGrowWidthItem( TRUE ) ); + aSet.Put( SdrTextAutoGrowHeightItem( FALSE ) ); + aSet.Put( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_TOP ) ); + aSet.Put( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_RIGHT ) ); + pTextObj->SetMergedItemSet( aSet ); + } + } + } + } + break; + case COMMAND_ID_DRAW_CAPTION: + case COMMAND_ID_DRAW_CAPTION_VERTICAL: + { + if ( pObj->ISA( SdrCaptionObj ) ) + { + sal_Bool bIsVertical( SID_DRAW_CAPTION_VERTICAL == nID ); + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( pObj ); + if ( pTextObj ) + { + pTextObj->SetVerticalWriting( bIsVertical ); + } + if ( bIsVertical ) + { + SfxItemSet aSet( pObj->GetMergedItemSet() ); + aSet.Put( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) ); + aSet.Put( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_RIGHT ) ); + pObj->SetMergedItemSet( aSet ); + } + SdrCaptionObj* pCaptionObj = dynamic_cast< SdrCaptionObj* >( pObj ); + if ( pCaptionObj ) + { + pCaptionObj->SetLogicRect( aRect ); + pCaptionObj->SetTailPos( + aRect.TopLeft() - Point( aRect.GetWidth() / 2, aRect.GetHeight() / 2 ) ); + } + } + } + break; + default: + { + pObj->SetLogicRect( aRect ); + SfxItemSet aSet( pDrawModelWrapper->GetItemPool() ); + setAttributes( pObj ); + pObj->SetMergedItemSet( aSet ); + } + break; + } + } + } + } + + return pObj; +} + +bool DrawCommandDispatch::parseCommandURL( const ::rtl::OUString& rCommandURL, sal_uInt16* pnFeatureId, + ::rtl::OUString* pBaseCommand, ::rtl::OUString* pCustomShapeType ) +{ + bool bFound = true; + sal_uInt16 nFeatureId = 0; + ::rtl::OUString aBaseCommand; + ::rtl::OUString aType; + + sal_Int32 nIndex = 1; + ::rtl::OUString aToken = rCommandURL.getToken( 0, '.', nIndex ); + if ( nIndex == -1 || !aToken.getLength() ) + { + aBaseCommand = rCommandURL; + SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( aBaseCommand ); + if ( aIter != m_aSupportedFeatures.end() ) + { + nFeatureId = aIter->second.nFeatureId; + + switch ( nFeatureId ) + { + case COMMAND_ID_DRAWTBX_CS_BASIC: + { + aType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "diamond" ) ); + } + break; + case COMMAND_ID_DRAWTBX_CS_SYMBOL: + { + aType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "smiley" ) ); + } + break; + case COMMAND_ID_DRAWTBX_CS_ARROW: + { + aType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "left-right-arrow" ) ); + } + break; + case COMMAND_ID_DRAWTBX_CS_FLOWCHART: + { + aType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "flowchart-internal-storage" ) ); + } + break; + case COMMAND_ID_DRAWTBX_CS_CALLOUT: + { + aType = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "round-rectangular-callout" ) ); + } + break; + case COMMAND_ID_DRAWTBX_CS_STAR: + { + aType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "star5" ) ); + } + break; + default: + { + } + break; + } + } + else + { + bFound = false; + } + } + else + { + aBaseCommand = rCommandURL.copy( 0, nIndex - 1 ); + SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( aBaseCommand ); + if ( aIter != m_aSupportedFeatures.end() ) + { + nFeatureId = aIter->second.nFeatureId; + aType = rCommandURL.getToken( 0, '.', nIndex ); + } + else + { + bFound = false; + } + } + + *pnFeatureId = nFeatureId; + *pBaseCommand = aBaseCommand; + *pCustomShapeType = aType; + + return bFound; +} + +//............................................................................. +} // namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/DrawCommandDispatch.hrc b/chart2/source/controller/main/DrawCommandDispatch.hrc new file mode 100644 index 000000000000..4e31fafaaf63 --- /dev/null +++ b/chart2/source/controller/main/DrawCommandDispatch.hrc @@ -0,0 +1,50 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART_DRAWCOMMANDDISPATCH_HRC +#define CHART_DRAWCOMMANDDISPATCH_HRC + +//----------------------------------------------------------------------------- +//Command Ids: +#define COMMAND_ID_OBJECT_SELECT 1 +#define COMMAND_ID_DRAW_LINE 2 +#define COMMAND_ID_LINE_ARROW_END 3 +#define COMMAND_ID_DRAW_RECT 4 +#define COMMAND_ID_DRAW_ELLIPSE 5 +#define COMMAND_ID_DRAW_FREELINE_NOFILL 6 +#define COMMAND_ID_DRAW_TEXT 7 +#define COMMAND_ID_DRAW_TEXT_VERTICAL 8 +#define COMMAND_ID_DRAW_CAPTION 9 +#define COMMAND_ID_DRAW_CAPTION_VERTICAL 10 +#define COMMAND_ID_DRAWTBX_CS_BASIC 11 +#define COMMAND_ID_DRAWTBX_CS_SYMBOL 12 +#define COMMAND_ID_DRAWTBX_CS_ARROW 13 +#define COMMAND_ID_DRAWTBX_CS_FLOWCHART 14 +#define COMMAND_ID_DRAWTBX_CS_CALLOUT 15 +#define COMMAND_ID_DRAWTBX_CS_STAR 16 + +// CHART_DRAWCOMMANDDISPATCH_HRC +#endif diff --git a/chart2/source/controller/main/DrawCommandDispatch.hxx b/chart2/source/controller/main/DrawCommandDispatch.hxx new file mode 100644 index 000000000000..38c886e29abb --- /dev/null +++ b/chart2/source/controller/main/DrawCommandDispatch.hxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_DRAWCOMMANDDISPATCH_HXX +#define CHART2_DRAWCOMMANDDISPATCH_HXX + +#include "FeatureCommandDispatchBase.hxx" + +#include <tools/solar.h> + +class SfxItemSet; +class SdrObject; + +//............................................................................. +namespace chart +{ +//............................................................................. + +class ChartController; + +/** This is a CommandDispatch implementation for drawing objects. + */ +class DrawCommandDispatch: public FeatureCommandDispatchBase +{ +public: + DrawCommandDispatch( const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext >& rxContext, ChartController* pController ); + virtual ~DrawCommandDispatch(); + + // late initialisation, especially for adding as listener + virtual void initialize(); + + virtual bool isFeatureSupported( const ::rtl::OUString& rCommandURL ); + + void setAttributes( SdrObject* pObj ); + void setLineEnds( SfxItemSet& rAttr ); + +protected: + // WeakComponentImplHelperBase + virtual void SAL_CALL disposing(); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) + throw (::com::sun::star::uno::RuntimeException); + + // state of a feature + virtual FeatureState getState( const ::rtl::OUString& rCommand ); + + // execute a feature + virtual void execute( const ::rtl::OUString& rCommand, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue>& rArgs ); + + // all the features which should be handled by this class + virtual void describeSupportedFeatures(); + +private: + void setInsertObj( USHORT eObj ); + SdrObject* createDefaultObject( const sal_uInt16 nID ); + + bool parseCommandURL( const ::rtl::OUString& rCommandURL, sal_uInt16* pnFeatureId, ::rtl::OUString* pBaseCommand, ::rtl::OUString* pCustomShapeType ); + + ChartController* m_pChartController; + ::rtl::OUString m_aCustomShapeType; +}; + +//............................................................................. +} // namespace chart +//............................................................................. + +// CHART2_DRAWCOMMANDDISPATCH_HXX +#endif diff --git a/chart2/source/controller/main/ElementSelector.cxx b/chart2/source/controller/main/ElementSelector.cxx new file mode 100644 index 000000000000..3b41fd1b6b66 --- /dev/null +++ b/chart2/source/controller/main/ElementSelector.cxx @@ -0,0 +1,344 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "ElementSelector.hxx" +#include "macros.hxx" +#include "ObjectNameProvider.hxx" +#include "ObjectHierarchy.hxx" +#include "servicenames.hxx" +#include <chartview/ExplicitValueProvider.hxx> +#include "DrawViewWrapper.hxx" +#include "ResId.hxx" +#include "Strings.hrc" + +#include <toolkit/helper/vclunohelper.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> + +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/frame/XControlNotificationListener.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> + +namespace chart +{ + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace +{ +static const ::rtl::OUString lcl_aServiceName( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart.ElementSelectorToolbarController" )); +} + +//------------------------------------------------------------------------------ + +SelectorListBox::SelectorListBox( Window* pParent, WinBits nStyle ) + : ListBox( pParent, nStyle ) + , m_bReleaseFocus( true ) +{ +} + +SelectorListBox::~SelectorListBox() +{ +} + +void lcl_addObjectsToList( const ObjectHierarchy& rHierarchy, const ObjectHierarchy::tOID & rParent, std::vector< ListBoxEntryData >& rEntries + , const sal_Int32 nHierarchyDepth, const Reference< chart2::XChartDocument >& xChartDoc ) +{ + ObjectHierarchy::tChildContainer aChildren( rHierarchy.getChildren(rParent) ); + ObjectHierarchy::tChildContainer::const_iterator aIt( aChildren.begin()); + while( aIt != aChildren.end() ) + { + ObjectHierarchy::tOID aOID = *aIt; + ::rtl::OUString aCID = aOID.getObjectCID(); + ListBoxEntryData aEntry; + aEntry.OID = aOID; + aEntry.UIName += ObjectNameProvider::getNameForCID( aCID, xChartDoc ); + aEntry.nHierarchyDepth = nHierarchyDepth; + rEntries.push_back(aEntry); + lcl_addObjectsToList( rHierarchy, aOID, rEntries, nHierarchyDepth+1, xChartDoc ); + ++aIt; + } +} + +void SelectorListBox::SetChartController( const Reference< frame::XController >& xChartController ) +{ + m_xChartController = xChartController; +} + +void SelectorListBox::UpdateChartElementsListAndSelection() +{ + Clear(); + m_aEntries.clear(); + + Reference< frame::XController > xChartController( m_xChartController ); + if( xChartController.is() ) + { + Reference< view::XSelectionSupplier > xSelectionSupplier( xChartController, uno::UNO_QUERY); + ObjectHierarchy::tOID aSelectedOID; + rtl::OUString aSelectedCID; + if( xSelectionSupplier.is() ) + { + aSelectedOID = ObjectIdentifier( xSelectionSupplier->getSelection() ); + aSelectedCID = aSelectedOID.getObjectCID(); + } + + Reference< chart2::XChartDocument > xChartDoc( xChartController->getModel(), uno::UNO_QUERY ); + ObjectType eType( aSelectedOID.getObjectType() ); + bool bAddSelectionToList = false; + if ( eType == OBJECTTYPE_DATA_POINT || eType == OBJECTTYPE_DATA_LABEL || eType == OBJECTTYPE_SHAPE ) + bAddSelectionToList = true; + + Reference< uno::XInterface > xChartView; + Reference< lang::XMultiServiceFactory > xFact( xChartController->getModel(), uno::UNO_QUERY ); + if( xFact.is() ) + xChartView = xFact->createInstance( CHART_VIEW_SERVICE_NAME ); + ExplicitValueProvider* pExplicitValueProvider = 0;//ExplicitValueProvider::getExplicitValueProvider(xChartView); dies erzeugt alle sichtbaren datenpinkte, das ist zu viel + ObjectHierarchy aHierarchy( xChartDoc, pExplicitValueProvider, true /*bFlattenDiagram*/, true /*bOrderingForElementSelector*/ ); + lcl_addObjectsToList( aHierarchy, aHierarchy.getRootNodeOID(), m_aEntries, 0, xChartDoc ); + + std::vector< ListBoxEntryData >::iterator aIt( m_aEntries.begin() ); + if( bAddSelectionToList ) + { + if ( aSelectedOID.isAutoGeneratedObject() ) + { + rtl::OUString aSeriesCID = ObjectIdentifier::createClassifiedIdentifierForParticle( ObjectIdentifier::getSeriesParticleFromCID( aSelectedCID ) ); + for( aIt = m_aEntries.begin(); aIt != m_aEntries.end(); ++aIt ) + { + if( aIt->OID.getObjectCID().match( aSeriesCID ) ) + { + ListBoxEntryData aEntry; + aEntry.UIName = ObjectNameProvider::getNameForCID( aSelectedCID, xChartDoc ); + aEntry.OID = aSelectedOID; + ++aIt; + if( aIt != m_aEntries.end() ) + m_aEntries.insert(aIt, aEntry); + else + m_aEntries.push_back( aEntry ); + break; + } + } + } + else if ( aSelectedOID.isAdditionalShape() ) + { + ListBoxEntryData aEntry; + SdrObject* pSelectedObj = DrawViewWrapper::getSdrObject( aSelectedOID.getAdditionalShape() ); + ::rtl::OUString aName( pSelectedObj ? pSelectedObj->GetName() : String() ); + aEntry.UIName = ( aName.getLength() > 0 ? aName : ::rtl::OUString( String( SchResId( STR_OBJECT_SHAPE ) ) ) ); + aEntry.OID = aSelectedOID; + m_aEntries.push_back( aEntry ); + } + } + + USHORT nEntryPosToSelect = 0; bool bSelectionFound = false; + aIt = m_aEntries.begin(); + for( USHORT nN=0; aIt != m_aEntries.end(); ++aIt, ++nN ) + { + InsertEntry( aIt->UIName ); + if ( !bSelectionFound && aSelectedOID == aIt->OID ) + { + nEntryPosToSelect = nN; + bSelectionFound = true; + } + } + + if( bSelectionFound ) + SelectEntryPos(nEntryPosToSelect); + + USHORT nEntryCount = GetEntryCount(); + if( nEntryCount > 100 ) + nEntryCount = 100; + SetDropDownLineCount( nEntryCount ); + } + SaveValue();//remind current selection pos +} + +void SelectorListBox::ReleaseFocus_Impl() +{ + if ( !m_bReleaseFocus ) + { + m_bReleaseFocus = true; + return; + } + + Reference< frame::XController > xController( m_xChartController ); + Reference< frame::XFrame > xFrame( xController->getFrame() ); + if ( xFrame.is() && xFrame->getContainerWindow().is() ) + xFrame->getContainerWindow()->setFocus(); +} + +void SelectorListBox::Select() +{ + ListBox::Select(); + + if ( !IsTravelSelect() ) + { + USHORT nPos = GetSelectEntryPos(); + if( nPos < m_aEntries.size() ) + { + ObjectHierarchy::tOID aOID = m_aEntries[nPos].OID; + Reference< view::XSelectionSupplier > xSelectionSupplier( m_xChartController.get(), uno::UNO_QUERY ); + if( xSelectionSupplier.is() ) + xSelectionSupplier->select( aOID.getAny() ); + } + ReleaseFocus_Impl(); + } +} + +long SelectorListBox::Notify( NotifyEvent& rNEvt ) +{ + long nHandled = 0; + + if ( rNEvt.GetType() == EVENT_KEYINPUT ) + { + USHORT nCode = rNEvt.GetKeyEvent()->GetKeyCode().GetCode(); + + switch ( nCode ) + { + case KEY_RETURN: + case KEY_TAB: + { + if ( KEY_TAB == nCode ) + m_bReleaseFocus = false; + else + nHandled = 1; + Select(); + break; + } + + case KEY_ESCAPE: + SelectEntryPos( GetSavedValue() ); //restore saved selection + ReleaseFocus_Impl(); + break; + } + } + else if ( EVENT_LOSEFOCUS == rNEvt.GetType() ) + { + if ( !HasFocus() ) + SelectEntryPos( GetSavedValue() ); + } + + return nHandled ? nHandled : ListBox::Notify( rNEvt ); +} + +Reference< ::com::sun::star::accessibility::XAccessible > SelectorListBox::CreateAccessible() +{ + UpdateChartElementsListAndSelection(); + return ListBox::CreateAccessible(); +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( ElementSelectorToolbarController, lcl_aServiceName ); + +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString > ElementSelectorToolbarController::getSupportedServiceNames_Static() +{ + Sequence< ::rtl::OUString > aServices(1); + aServices[ 0 ] = C2U( "com.sun.star.frame.ToolbarController" ); + return aServices; +} +// ----------------------------------------------------------------------------- +ElementSelectorToolbarController::ElementSelectorToolbarController( const uno::Reference< uno::XComponentContext > & xContext ) + : m_xCC( xContext ) +{ +} +// ----------------------------------------------------------------------------- +ElementSelectorToolbarController::~ElementSelectorToolbarController() +{ +} +// ----------------------------------------------------------------------------- +// XInterface +Any SAL_CALL ElementSelectorToolbarController::queryInterface( const Type& _rType ) throw (RuntimeException) +{ + Any aReturn = ToolboxController::queryInterface(_rType); + if (!aReturn.hasValue()) + aReturn = ElementSelectorToolbarController_BASE::queryInterface(_rType); + return aReturn; +} +// ----------------------------------------------------------------------------- +void SAL_CALL ElementSelectorToolbarController::acquire() throw () +{ + ToolboxController::acquire(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ElementSelectorToolbarController::release() throw () +{ + ToolboxController::release(); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ElementSelectorToolbarController::initialize( const Sequence< Any >& rArguments ) throw (Exception, RuntimeException) +{ + ToolboxController::initialize(rArguments); +} +// ----------------------------------------------------------------------------- +void SAL_CALL ElementSelectorToolbarController::statusChanged( const frame::FeatureStateEvent& rEvent ) throw ( RuntimeException ) +{ + if( m_apSelectorListBox.get() ) + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + if( rEvent.FeatureURL.Path.equalsAscii( "ChartElementSelector" ) ) + { + Reference< frame::XController > xChartController; + rEvent.State >>= xChartController; + m_apSelectorListBox->SetChartController( xChartController ); + m_apSelectorListBox->UpdateChartElementsListAndSelection(); + } + } +} +// ----------------------------------------------------------------------------- +uno::Reference< awt::XWindow > SAL_CALL ElementSelectorToolbarController::createItemWindow( const uno::Reference< awt::XWindow >& xParent ) + throw (uno::RuntimeException) +{ + uno::Reference< awt::XWindow > xItemWindow; + if( !m_apSelectorListBox.get() ) + { + Window* pParent = VCLUnoHelper::GetWindow( xParent ); + if( pParent ) + { + m_apSelectorListBox = ::std::auto_ptr< SelectorListBox >( new SelectorListBox( pParent, WB_DROPDOWN|WB_AUTOHSCROLL|WB_BORDER ) ); + ::Size aLogicalSize( 95, 160 ); + ::Size aPixelSize = m_apSelectorListBox->LogicToPixel( aLogicalSize, MAP_APPFONT ); + m_apSelectorListBox->SetSizePixel( aPixelSize ); + m_apSelectorListBox->SetDropDownLineCount( 5 ); + } + } + if( m_apSelectorListBox.get() ) + xItemWindow = VCLUnoHelper::GetInterface( m_apSelectorListBox.get() ); + return xItemWindow; +} + +//.......................................................................... +} // chart2 +//.......................................................................... diff --git a/chart2/source/controller/main/ElementSelector.hxx b/chart2/source/controller/main/ElementSelector.hxx new file mode 100644 index 000000000000..d85415d614e2 --- /dev/null +++ b/chart2/source/controller/main/ElementSelector.hxx @@ -0,0 +1,123 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _CHART_ELEMENTSELECTOR_HXX +#define _CHART_ELEMENTSELECTOR_HXX + +#include "ServiceMacros.hxx" +#include "ObjectHierarchy.hxx" +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/implbase1.hxx> +#include <svtools/toolboxcontroller.hxx> + +#include <vcl/lstbox.hxx> +#include <cppuhelper/weakref.hxx> + +#include <memory> + +//............................................................................. +namespace chart +{ +//............................................................................. + +struct ListBoxEntryData +{ + rtl::OUString UIName; + ObjectHierarchy::tOID OID; + sal_Int32 nHierarchyDepth; + + ListBoxEntryData() : nHierarchyDepth(0) + { + } +}; + +class SelectorListBox : public ListBox +{ + public: + SelectorListBox( Window* pParent, WinBits nStyle ); + virtual ~SelectorListBox(); + + virtual void Select(); + virtual long Notify( NotifyEvent& rNEvt ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible(); + + void ReleaseFocus_Impl(); + + void SetChartController( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& xChartController ); + void UpdateChartElementsListAndSelection(); + + private: + ::com::sun::star::uno::WeakReference< + ::com::sun::star::frame::XController > m_xChartController; + + ::std::vector< ListBoxEntryData > m_aEntries; + + bool m_bReleaseFocus; +}; + +// ------------------------------------------------------------------ +// ------------------------------------------------------------------ + +typedef ::cppu::ImplHelper1 < ::com::sun::star::lang::XServiceInfo> ElementSelectorToolbarController_BASE; + +class ElementSelectorToolbarController : public ::svt::ToolboxController + , ElementSelectorToolbarController_BASE +{ +public: + ElementSelectorToolbarController( ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > const & xContext ); + virtual ~ElementSelectorToolbarController(); + + // XServiceInfo + APPHELPER_XSERVICEINFO_DECL() + APPHELPER_SERVICE_FACTORY_HELPER(ElementSelectorToolbarController) + + // XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type& aType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw (); + virtual void SAL_CALL release() throw (); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + // XStatusListener + virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException ); + // XToolbarController + virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL createItemWindow( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >& Parent ) throw (::com::sun::star::uno::RuntimeException); + +private: + //no default constructor + ElementSelectorToolbarController(){} + +private: + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> m_xCC; + ::std::auto_ptr< SelectorListBox > m_apSelectorListBox; +}; + +//............................................................................. +} //namespace chart +//............................................................................. + +#endif diff --git a/chart2/source/controller/main/FeatureCommandDispatchBase.cxx b/chart2/source/controller/main/FeatureCommandDispatchBase.cxx new file mode 100644 index 000000000000..39b4e1d4a171 --- /dev/null +++ b/chart2/source/controller/main/FeatureCommandDispatchBase.cxx @@ -0,0 +1,114 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "FeatureCommandDispatchBase.hxx" + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +FeatureCommandDispatchBase::FeatureCommandDispatchBase( const Reference< uno::XComponentContext >& rxContext ) + :CommandDispatch( rxContext ) + ,m_nFeatureId( 0 ) +{ +} + +FeatureCommandDispatchBase::~FeatureCommandDispatchBase() +{ +} + +void FeatureCommandDispatchBase::initialize() +{ + CommandDispatch::initialize(); + fillSupportedFeatures(); +} + +bool FeatureCommandDispatchBase::isFeatureSupported( const ::rtl::OUString& rCommandURL ) +{ + SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( rCommandURL ); + if ( aIter != m_aSupportedFeatures.end() ) + { + return true; + } + return false; +} + +void FeatureCommandDispatchBase::fireStatusEvent( const ::rtl::OUString& rURL, + const Reference< frame::XStatusListener >& xSingleListener /* = 0 */ ) +{ + if ( rURL.getLength() == 0 ) + { + SupportedFeatures::const_iterator aEnd( m_aSupportedFeatures.end() ); + for ( SupportedFeatures::const_iterator aIter( m_aSupportedFeatures.begin() ); aIter != aEnd; ++aIter ) + { + FeatureState aFeatureState( getState( aIter->first ) ); + fireStatusEventForURL( aIter->first, aFeatureState.aState, aFeatureState.bEnabled, xSingleListener ); + } + } + else + { + FeatureState aFeatureState( getState( rURL ) ); + fireStatusEventForURL( rURL, aFeatureState.aState, aFeatureState.bEnabled, xSingleListener ); + } +} + +// XDispatch +void FeatureCommandDispatchBase::dispatch( const util::URL& URL, + const Sequence< beans::PropertyValue >& Arguments ) + throw (uno::RuntimeException) +{ + ::rtl::OUString aCommand( URL.Complete ); + if ( getState( aCommand ).bEnabled ) + { + execute( aCommand, Arguments ); + } +} + +void FeatureCommandDispatchBase::implDescribeSupportedFeature( const sal_Char* pAsciiCommandURL, + sal_uInt16 nId, sal_Int16 nGroup ) +{ + ControllerFeature aFeature; + aFeature.Command = ::rtl::OUString::createFromAscii( pAsciiCommandURL ); + aFeature.nFeatureId = nId; + aFeature.GroupId = nGroup; + + m_aSupportedFeatures[ aFeature.Command ] = aFeature; +} + +void FeatureCommandDispatchBase::fillSupportedFeatures() +{ + describeSupportedFeatures(); +} + +} // namespace chart diff --git a/chart2/source/controller/main/FeatureCommandDispatchBase.hxx b/chart2/source/controller/main/FeatureCommandDispatchBase.hxx new file mode 100644 index 000000000000..b3e2a568d3b9 --- /dev/null +++ b/chart2/source/controller/main/FeatureCommandDispatchBase.hxx @@ -0,0 +1,115 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_FEATURECOMMANDDISPATCHBASE_HXX +#define CHART2_FEATURECOMMANDDISPATCHBASE_HXX + +#include "CommandDispatch.hxx" + +#include <com/sun/star/frame/CommandGroup.hpp> +#include <com/sun/star/frame/DispatchInformation.hpp> +#include <com/sun/star/util/URL.hpp> + +namespace chart +{ + +struct ControllerFeature: public ::com::sun::star::frame::DispatchInformation +{ + sal_uInt16 nFeatureId; +}; + +typedef ::std::map< ::rtl::OUString, + ControllerFeature, + ::std::less< ::rtl::OUString > > SupportedFeatures; + +struct FeatureState +{ + bool bEnabled; + ::com::sun::star::uno::Any aState; + + FeatureState() : bEnabled( false ) { } +}; + +/** This is a base class for CommandDispatch implementations with feature support. + */ +class FeatureCommandDispatchBase: public CommandDispatch +{ +public: + FeatureCommandDispatchBase( const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext >& rxContext ); + virtual ~FeatureCommandDispatchBase(); + + // late initialisation, especially for adding as listener + virtual void initialize(); + + virtual bool isFeatureSupported( const ::rtl::OUString& rCommandURL ); + +protected: + // XDispatch + virtual void SAL_CALL dispatch( const ::com::sun::star::util::URL& URL, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& Arguments ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void fireStatusEvent( const ::rtl::OUString& rURL, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >& xSingleListener ); + + // state of a feature + virtual FeatureState getState( const ::rtl::OUString& rCommand ) = 0; + + // execute a feature + virtual void execute( const ::rtl::OUString& rCommand, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue>& rArgs ) = 0; + + // all the features which should be handled by this class + virtual void describeSupportedFeatures() = 0; + + /** describes a feature supported by the controller + + Must not be called outside <member>describeSupportedFeatures</member>. + + @param pAsciiCommandURL + the URL of the feature command + @param nId + the id of the feature. Later references to this feature usually happen by id, not by + URL. + @param nGroup + the command group of the feature. This is important for configuring the controller UI + by the user, see also <type scope="com::sun::star::frame">CommandGroup</type>. + */ + void implDescribeSupportedFeature( const sal_Char* pAsciiCommandURL, sal_uInt16 nId, + sal_Int16 nGroup = ::com::sun::star::frame::CommandGroup::INTERNAL ); + + mutable SupportedFeatures m_aSupportedFeatures; + + sal_uInt16 m_nFeatureId; + +private: + void fillSupportedFeatures(); +}; + +} // namespace chart + +// CHART2_FEATURECOMMANDDISPATCHBASE_HXX +#endif diff --git a/chart2/source/controller/main/ImplUndoManager.cxx b/chart2/source/controller/main/ImplUndoManager.cxx new file mode 100644 index 000000000000..57e8e7315334 --- /dev/null +++ b/chart2/source/controller/main/ImplUndoManager.cxx @@ -0,0 +1,505 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "ImplUndoManager.hxx" +#include "DisposeHelper.hxx" +#include "CommonFunctors.hxx" +#include "ControllerLockGuard.hxx" +#include "PropertyHelper.hxx" +#include "DataSourceHelper.hxx" +#include "ChartModelHelper.hxx" + +#include <com/sun/star/chart/XComplexDescriptionAccess.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XInternalDataProvider.hpp> +#include <com/sun/star/chart2/XTitled.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> + +#include <boost/bind.hpp> +#include <algorithm> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; +using ::com::sun::star::chart::XComplexDescriptionAccess; + +namespace chart +{ +namespace impl +{ + +void ImplApplyDataToModel( + Reference< frame::XModel > & xInOutModelToChange, + const Reference< chart2::XInternalDataProvider > & xData ) +{ + Reference< chart2::XChartDocument > xDoc( xInOutModelToChange, uno::UNO_QUERY ); + OSL_ASSERT( xDoc.is() && xDoc->hasInternalDataProvider()); + + // copy data from stored internal data provider + if( xDoc.is() && xDoc->hasInternalDataProvider()) + { + Reference< XComplexDescriptionAccess > xCurrentData( xDoc->getDataProvider(), uno::UNO_QUERY ); + Reference< XComplexDescriptionAccess > xSavedData( xData, uno::UNO_QUERY ); + if( xCurrentData.is() && xSavedData.is()) + { + xCurrentData->setData( xSavedData->getData()); + xCurrentData->setComplexRowDescriptions( xSavedData->getComplexRowDescriptions()); + xCurrentData->setComplexColumnDescriptions( xSavedData->getComplexColumnDescriptions()); + } + } +} + +// ---------------------------------------- + +UndoElement::UndoElement( + const OUString & rActionString, + const Reference< frame::XModel > & xModel ) : + m_aActionString( rActionString ) +{ + initialize( xModel ); +} + +UndoElement::UndoElement( + const Reference< frame::XModel > & xModel ) +{ + initialize( xModel ); +} + +UndoElement::UndoElement( const UndoElement & rOther ) : + m_aActionString( rOther.m_aActionString ) +{ + initialize( rOther.m_xModel ); +} + +UndoElement::~UndoElement() +{} + +void UndoElement::initialize( const Reference< frame::XModel > & xModel ) +{ + if ( xModel.is() ) + { + m_xModel.set( UndoElement::cloneModel( xModel ) ); + } +} + +void UndoElement::dispose() +{ + Reference< lang::XComponent > xComp( m_xModel, uno::UNO_QUERY ); + if( xComp.is()) + xComp->dispose(); + m_xModel.set( 0 ); +} + +void UndoElement::applyToModel( + Reference< frame::XModel > & xInOutModelToChange ) +{ + UndoElement::applyModelContentToModel( xInOutModelToChange, m_xModel ); +} + +UndoElement * UndoElement::createFromModel( + const Reference< frame::XModel > & xModel ) +{ + return new UndoElement( getActionString(), xModel ); +} + +void UndoElement::setActionString( const ::rtl::OUString & rActionString ) +{ + m_aActionString = rActionString; +} + +OUString UndoElement::getActionString() const +{ + return m_aActionString; +} + +// static +Reference< frame::XModel > UndoElement::cloneModel( const Reference< frame::XModel > & xModel ) +{ + Reference< frame::XModel > xResult; + uno::Reference< util::XCloneable > xCloneable( xModel, uno::UNO_QUERY ); + OSL_ENSURE( xCloneable.is(), "Cannot clone model" ); + if( xCloneable.is()) + xResult.set( xCloneable->createClone(), uno::UNO_QUERY ); + + return xResult; +} + +// static +void UndoElement::applyModelContentToModel( + Reference< frame::XModel > & xInOutModelToChange, + const Reference< frame::XModel > & xModelToCopyFrom, + const Reference< chart2::XInternalDataProvider > & xData /* = 0 */ ) +{ + + if( xModelToCopyFrom.is() && xInOutModelToChange.is()) + { + try + { + // /-- loccked controllers of destination + ControllerLockGuard aLockedControllers( xInOutModelToChange ); + Reference< chart2::XChartDocument > xSource( xModelToCopyFrom, uno::UNO_QUERY_THROW ); + Reference< chart2::XChartDocument > xDestination( xInOutModelToChange, uno::UNO_QUERY_THROW ); + + // propagate the correct flag for plotting of hidden values to the data provider and all used sequences + ChartModelHelper::setIncludeHiddenCells( ChartModelHelper::isIncludeHiddenCells( xModelToCopyFrom ) , xInOutModelToChange ); + + // diagram + xDestination->setFirstDiagram( xSource->getFirstDiagram()); + + // main title + Reference< chart2::XTitled > xDestinationTitled( xDestination, uno::UNO_QUERY_THROW ); + Reference< chart2::XTitled > xSourceTitled( xSource, uno::UNO_QUERY_THROW ); + xDestinationTitled->setTitleObject( xSourceTitled->getTitleObject()); + + // page background + comphelper::copyProperties( + xSource->getPageBackground(), + xDestination->getPageBackground() ); + + // apply data (not applied in standard Undo) + if( xData.is()) + ImplApplyDataToModel( xInOutModelToChange, xData ); + + // register all sequences at the internal data provider to get adapted + // indexes when columns are added/removed + if( xDestination->hasInternalDataProvider()) + { + Reference< chart2::XInternalDataProvider > xNewDataProvider( xDestination->getDataProvider(), uno::UNO_QUERY ); + Reference< chart2::data::XDataSource > xUsedData( DataSourceHelper::getUsedData( xInOutModelToChange )); + if( xUsedData.is() && xNewDataProvider.is()) + { + Sequence< Reference< chart2::data::XLabeledDataSequence > > aData( xUsedData->getDataSequences()); + for( sal_Int32 i=0; i<aData.getLength(); ++i ) + { + xNewDataProvider->registerDataSequenceForChanges( aData[i]->getValues()); + xNewDataProvider->registerDataSequenceForChanges( aData[i]->getLabel()); + } + } + } + + // restore modify status + Reference< util::XModifiable > xSourceMod( xSource, uno::UNO_QUERY ); + Reference< util::XModifiable > xDestMod( xDestination, uno::UNO_QUERY ); + if( xSourceMod.is() && xDestMod.is() && + ! xSourceMod->isModified() ) + { + xDestMod->setModified( sal_False ); + } + // \-- loccked controllers of destination + } + catch( uno::Exception & ) + { + } + } +} + +// ---------------------------------------- + +UndoElementWithData::UndoElementWithData( + const OUString & rActionString, + const Reference< frame::XModel > & xModel ) : + UndoElement( rActionString, xModel ) +{ + initializeData(); +} + +UndoElementWithData::UndoElementWithData( + const Reference< frame::XModel > & xModel ) : + UndoElement( xModel ) +{ + initializeData(); +} + + +UndoElementWithData::UndoElementWithData( + const UndoElementWithData & rOther ) : + UndoElement( rOther ) +{ + initializeData(); +} + +UndoElementWithData::~UndoElementWithData() +{} + +void UndoElementWithData::initializeData() +{ + try + { + Reference< chart2::XChartDocument > xChartDoc( m_xModel, uno::UNO_QUERY_THROW ); + OSL_ASSERT( xChartDoc->hasInternalDataProvider()); + if( xChartDoc->hasInternalDataProvider()) + { + Reference< util::XCloneable > xCloneable( xChartDoc->getDataProvider(), uno::UNO_QUERY ); + OSL_ENSURE( xCloneable.is(), "Cannot clone data" ); + if( xCloneable.is()) + m_xData.set( xCloneable->createClone(), uno::UNO_QUERY ); + } + } + catch( uno::Exception & ) + { + } +} + +void UndoElementWithData::dispose() +{ + UndoElement::dispose(); + m_xData.set( 0 ); +} + +void UndoElementWithData::applyToModel( + Reference< frame::XModel > & xInOutModelToChange ) +{ + UndoElement::applyModelContentToModel( xInOutModelToChange, m_xModel, m_xData ); +} + +UndoElement * UndoElementWithData::createFromModel( + const Reference< frame::XModel > & xModel ) +{ + return new UndoElementWithData( getActionString(), xModel ); +} + +// ======================================== + +// ---------------------------------------- + +UndoElementWithSelection::UndoElementWithSelection( + const OUString & rActionString, + const Reference< frame::XModel > & xModel ) : + UndoElement( rActionString, xModel ) +{ + initialize( xModel ); +} + +UndoElementWithSelection::UndoElementWithSelection( + const Reference< frame::XModel > & xModel ) : + UndoElement( xModel ) +{ + initialize( xModel ); +} + +UndoElementWithSelection::UndoElementWithSelection( + const UndoElementWithSelection & rOther ) : + UndoElement( rOther ) +{ + initialize( rOther.m_xModel ); +} + +UndoElementWithSelection::~UndoElementWithSelection() +{} + +void UndoElementWithSelection::initialize( const Reference< frame::XModel > & xModel ) +{ + try + { + uno::Reference< view::XSelectionSupplier > xSelSupp( xModel->getCurrentController(), uno::UNO_QUERY ); + OSL_ASSERT( xSelSupp.is() ); + + if( xSelSupp.is() ) + m_aSelection = xSelSupp->getSelection(); + } + catch( const uno::Exception & ) + { + } +} + +void UndoElementWithSelection::dispose() +{ + UndoElement::dispose(); + m_aSelection.clear(); +} + +void UndoElementWithSelection::applyToModel( + Reference< frame::XModel > & xInOutModelToChange ) +{ + UndoElement::applyModelContentToModel( xInOutModelToChange, m_xModel ); + Reference< view::XSelectionSupplier > xCurrentSelectionSuppl( xInOutModelToChange->getCurrentController(), uno::UNO_QUERY ); + OSL_ASSERT( xCurrentSelectionSuppl.is() ); + + if( xCurrentSelectionSuppl.is()) + xCurrentSelectionSuppl->select( m_aSelection ); +} + +UndoElement * UndoElementWithSelection::createFromModel( + const Reference< frame::XModel > & xModel ) +{ + return new UndoElementWithSelection( getActionString(), xModel ); +} + +// ---------------------------------------- + +ShapeUndoElement::ShapeUndoElement( const OUString& rActionString, SdrUndoAction* pAction ) + :UndoElement( rActionString, Reference< frame::XModel >() ) + ,m_pAction( pAction ) +{ +} + +ShapeUndoElement::ShapeUndoElement( const ShapeUndoElement& rOther ) + :UndoElement( rOther ) + ,m_pAction( rOther.m_pAction ) +{ +} + +ShapeUndoElement::~ShapeUndoElement() +{ +} + +SdrUndoAction* ShapeUndoElement::getSdrUndoAction() +{ + return m_pAction; +} + +// ======================================== + +UndoStack::UndoStack() : + m_nSizeLimit( 1000 ) +{ +} + +UndoStack::~UndoStack() +{ + disposeAndClear(); +} + +void UndoStack::pop() +{ + if( ! empty()) + { + top()->dispose(); + delete top(); + m_aStack.pop_back(); + } +} + +void UndoStack::push( UndoElement * pElement ) +{ + m_aStack.push_back( pElement ); + applyLimitation(); +} + +UndoElement * UndoStack::top() const +{ + return m_aStack.back(); +} + +OUString UndoStack::topUndoString() const +{ + if( ! empty()) + return top()->getActionString(); + return OUString(); +} + +Sequence< OUString > UndoStack::getUndoStrings() const +{ + sal_Int32 nSize( static_cast< sal_Int32 >( m_aStack.size())); + Sequence< OUString > aResult( nSize ); + for( sal_Int32 i=0; i<nSize; ++i ) + aResult[i] = m_aStack[i]->getActionString(); + return aResult; +} + +bool UndoStack::empty() const +{ + return m_aStack.empty(); +} + +void UndoStack::disposeAndClear() +{ + ::std::for_each( m_aStack.begin(), m_aStack.end(), ::boost::mem_fn( & UndoElement::dispose )); + ::std::for_each( m_aStack.begin(), m_aStack.end(), CommonFunctors::DeletePtr< UndoElement >() ); + m_aStack.clear(); +} + +void UndoStack::limitSize( sal_Int32 nMaxSize ) +{ + m_nSizeLimit = nMaxSize; + applyLimitation(); +} + +void UndoStack::applyLimitation() +{ + if( m_aStack.size() > static_cast< sal_uInt32 >( m_nSizeLimit )) + { + tUndoStackType::iterator aBegin( m_aStack.begin()); + tUndoStackType::iterator aEnd( aBegin + (m_aStack.size() - m_nSizeLimit)); + // dispose and remove all undo elements that are over the limit + ::std::for_each( aBegin, aEnd, ::boost::mem_fn( & UndoElement::dispose )); + ::std::for_each( aBegin, aEnd, CommonFunctors::DeletePtr< UndoElement >() ); + m_aStack.erase( aBegin, aEnd ); + } +} + +// ================================================================================ + +namespace +{ +static const OUString aUndoStepsPropName( RTL_CONSTASCII_USTRINGPARAM("Steps")); +} // anonymous namespace + +UndoStepsConfigItem::UndoStepsConfigItem( ConfigItemListener & rListener ) : + ::utl::ConfigItem( OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Common/Undo"))), + m_rListener( rListener ) +{ + EnableNotification( Sequence< OUString >( & aUndoStepsPropName, 1 )); +} + +UndoStepsConfigItem::~UndoStepsConfigItem() +{ +} + +void UndoStepsConfigItem::Notify( const Sequence< OUString > & aPropertyNames ) +{ + for( sal_Int32 nIdx=0; nIdx<aPropertyNames.getLength(); ++nIdx ) + { + if( aPropertyNames[nIdx].equals( aUndoStepsPropName )) + m_rListener.notify( aPropertyNames[nIdx] ); + } +} + +void UndoStepsConfigItem::Commit() +{ +} + +// mtehod is not const, because GetProperties is not const +sal_Int32 UndoStepsConfigItem::getUndoSteps() +{ + sal_Int32 nSteps = -1; + Sequence< uno::Any > aValues( + GetProperties( Sequence< OUString >( & aUndoStepsPropName, 1 ))); + if( aValues.getLength()) + aValues[0] >>= nSteps; + return nSteps; +} + +} // namespace impl +} // namespace chart diff --git a/chart2/source/controller/main/ImplUndoManager.hxx b/chart2/source/controller/main/ImplUndoManager.hxx new file mode 100644 index 000000000000..4dde0bc65719 --- /dev/null +++ b/chart2/source/controller/main/ImplUndoManager.hxx @@ -0,0 +1,227 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_IMPLUNDOMANAGER_HXX +#define CHART2_IMPLUNDOMANAGER_HXX + +#include "ConfigItemListener.hxx" + +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/uno/Sequence.hxx> + +#include <rtl/ustring.hxx> +#include <unotools/configitem.hxx> + +#include <utility> +#include <deque> + + +class SdrUndoAction; + +namespace com { namespace sun { namespace star { +namespace chart2 { + class XInternalDataProvider; +} +}}} + + +namespace chart +{ +namespace impl +{ + +class UndoElement +{ +public: + UndoElement( const ::rtl::OUString & rActionString, + const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel ); + UndoElement( const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel ); + UndoElement( const UndoElement & rOther ); + virtual ~UndoElement(); + + virtual void dispose(); + virtual UndoElement * createFromModel( + const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel ); + + virtual void applyToModel( + ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xInOutModelToChange ); + + void setActionString( const ::rtl::OUString & rActionString ); + ::rtl::OUString getActionString() const; + + static ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > cloneModel( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > & xModel ); + + static void applyModelContentToModel( + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > & xInOutModelToChange, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > & xModelToCopyFrom, + const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XInternalDataProvider > & xData = 0 ); + +protected: + ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > m_xModel; + +private: + void initialize( const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel ); + + ::rtl::OUString m_aActionString; +}; + +class UndoElementWithData : public UndoElement +{ +public: + UndoElementWithData( const ::rtl::OUString & rActionString, + const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel ); + UndoElementWithData( const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel ); + UndoElementWithData( const UndoElementWithData & rOther ); + virtual ~UndoElementWithData(); + + virtual void dispose(); + virtual UndoElement * createFromModel( + const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel ); + + virtual void applyToModel( + ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xInOutModelToChange ); + +private: + void initializeData(); + + ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XInternalDataProvider > m_xData; +}; + +class UndoElementWithSelection : public UndoElement +{ +public: + UndoElementWithSelection( const ::rtl::OUString & rActionString, + const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel ); + UndoElementWithSelection( const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel ); + UndoElementWithSelection( const UndoElementWithSelection & rOther ); + virtual ~UndoElementWithSelection(); + + virtual void dispose(); + virtual UndoElement * createFromModel( + const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel ); + + virtual void applyToModel( + ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xInOutModelToChange ); + +private: + void initialize( const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel ); + + ::com::sun::star::uno::Any m_aSelection; +}; + +class ShapeUndoElement : public UndoElement +{ +public: + ShapeUndoElement( const ::rtl::OUString& rActionString, SdrUndoAction* pAction ); + ShapeUndoElement( const ShapeUndoElement& rOther ); + virtual ~ShapeUndoElement(); + + SdrUndoAction* getSdrUndoAction(); + +private: + SdrUndoAction* m_pAction; +}; + +/** Note that all models that are put into this container are at some point + disposed of inside this class. (At least in the destructor). That means + the models retrieved here should never be used, but instead their content + should be copied to a living model. + */ +class UndoStack +{ +public: + UndoStack(); + // disposes of all models left in the stack + ~UndoStack(); + + // removes he last undo action and disposes of the model + void pop(); + void push( UndoElement * rElement ); + + // precondition: !empty() + UndoElement * top() const; + ::rtl::OUString topUndoString() const; + + ::com::sun::star::uno::Sequence< ::rtl::OUString > getUndoStrings() const; + + bool empty() const; + void disposeAndClear(); + + // removes all actions that have been inserted more than nMaxSize steps ago. + // The models of those actions are disposed of + void limitSize( sal_Int32 nMaxSize ); + +private: + void applyLimitation(); + + typedef ::std::deque< UndoElement * > tUndoStackType; + + tUndoStackType m_aStack; + sal_Int32 m_nSizeLimit; +}; + +// ---------------------------------------- + +class UndoStepsConfigItem : public ::utl::ConfigItem +{ +public: + explicit UndoStepsConfigItem( ConfigItemListener & rListener ); + virtual ~UndoStepsConfigItem(); + + sal_Int32 getUndoSteps(); + +protected: + // ____ ::utl::ConfigItem ____ + virtual void Notify( const ::com::sun::star::uno::Sequence< ::rtl::OUString > & aPropertyNames ); + virtual void Commit(); + +private: + ConfigItemListener & m_rListener; +}; + + +} // namespace impl +} // namespace chart + +// CHART2_IMPLUNDOMANAGER_HXX +#endif diff --git a/chart2/source/controller/main/ObjectHierarchy.cxx b/chart2/source/controller/main/ObjectHierarchy.cxx new file mode 100644 index 000000000000..fe73d15500f5 --- /dev/null +++ b/chart2/source/controller/main/ObjectHierarchy.cxx @@ -0,0 +1,862 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "ObjectHierarchy.hxx" +#include "ObjectIdentifier.hxx" +#include "ChartModelHelper.hxx" +#include "DiagramHelper.hxx" +#include "RegressionCurveHelper.hxx" +#include "AxisHelper.hxx" +#include "chartview/ExplicitValueProvider.hxx" +#include "macros.hxx" +#include "LineProperties.hxx" +#include "ChartTypeHelper.hxx" +#include "DataSeriesHelper.hxx" +#include "LegendHelper.hxx" +#include "chartview/DrawModelWrapper.hxx" + +#include <map> +#include <algorithm> + +#include <com/sun/star/chart2/XTitled.hpp> +#include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> +#include <com/sun/star/chart2/XChartTypeContainer.hpp> +#include <com/sun/star/chart2/XDataSeriesContainer.hpp> +#include <com/sun/star/chart/ErrorBarStyle.hpp> + +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/awt/Key.hpp> +#include <com/sun/star/awt/KeyModifier.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace +{ + +struct lcl_ObjectToOID : public ::std::unary_function< Reference< uno::XInterface >, ::chart::ObjectIdentifier > +{ + explicit lcl_ObjectToOID( const Reference< chart2::XChartDocument > & xChartDoc ) : + m_xModel( xChartDoc, uno::UNO_QUERY ) + {} + + ::chart::ObjectIdentifier operator() ( const Reference< uno::XInterface > & xObj ) + { + return ::chart::ObjectIdentifier( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xObj, m_xModel ) ); + } + +private: + Reference< frame::XModel > m_xModel; +}; + +void lcl_getChildOIDs( + ::chart::ObjectHierarchy::tChildContainer& rOutChildren, + const Reference< container::XIndexAccess >& xShapes ) +{ + if( xShapes.is()) + { + sal_Int32 nCount = xShapes->getCount(); + for( sal_Int32 i=0; i<nCount; ++i) + { + Reference< beans::XPropertySet > xShapeProp( xShapes->getByIndex( i ), uno::UNO_QUERY ); + if( xShapeProp.is()) + { + Reference< beans::XPropertySetInfo > xInfo( xShapeProp->getPropertySetInfo()); + OUString aName; + if( xInfo.is() && + xInfo->hasPropertyByName( C2U("Name")) && + (xShapeProp->getPropertyValue( C2U("Name")) >>= aName ) && + aName.getLength() > 0 && + ::chart::ObjectIdentifier::isCID( aName )) + { + rOutChildren.push_back( ::chart::ObjectIdentifier( aName ) ); + } + Reference< container::XIndexAccess > xNewShapes( xShapeProp, uno::UNO_QUERY ); + if( xNewShapes.is()) + lcl_getChildOIDs( rOutChildren, xNewShapes ); + } + } + } +} + +void lcl_addAxisTitle( const Reference< XAxis >& xAxis, ::chart::ObjectHierarchy::tChildContainer& rContainer, const Reference< frame::XModel >& xChartModel ) +{ + Reference< XTitled > xAxisTitled( xAxis, uno::UNO_QUERY ); + if( xAxisTitled.is()) + { + Reference< XTitle > xAxisTitle( xAxisTitled->getTitleObject()); + if( xAxisTitle.is()) + rContainer.push_back( + ::chart::ObjectIdentifier( ::chart::ObjectIdentifier::createClassifiedIdentifierForObject( xAxisTitle, xChartModel ) ) ); + } +} + +} // anonymous namespace + +namespace chart +{ + +namespace impl +{ + +class ImplObjectHierarchy +{ +public: + explicit ImplObjectHierarchy( + const Reference< XChartDocument >& xChartDocument, + ExplicitValueProvider* pExplicitValueProvider, + bool bFlattenDiagram, bool bOrderingForElementSelector ); + + bool hasChildren( const ObjectHierarchy::tOID& rParent ); + ObjectHierarchy::tChildContainer getChildren( const ObjectHierarchy::tOID& rParent ); + ObjectHierarchy::tChildContainer getSiblings( const ObjectHierarchy::tOID& rNode ); + + ObjectHierarchy::tOID getParent( const ObjectHierarchy::tOID& rOID ); + +private: + void createTree( const Reference< XChartDocument > & xChartDocument ); + void createAxesTree( + ObjectHierarchy::tChildContainer & rContainer, + const Reference< XChartDocument > & xChartDoc, + const Reference< XDiagram > & xDiagram ); + void createDiagramTree( + ObjectHierarchy::tChildContainer& rContainer, + const Reference< XChartDocument >& xChartDoc, + const Reference< XDiagram >& xDiagram ); + void createDataSeriesTree( + ObjectHierarchy::tChildContainer & rOutDiagramSubContainer, + const Reference< XDiagram > & xDiagram ); + void createWallAndFloor( + ObjectHierarchy::tChildContainer & rContainer, + const Reference< XDiagram > & xDiagram ); + void createLegendTree( + ObjectHierarchy::tChildContainer & rContainer, + const Reference< XChartDocument > & xChartDoc, + const Reference< XDiagram > & xDiagram ); + void createAdditionalShapesTree( ObjectHierarchy::tChildContainer& rContainer ); + + ObjectHierarchy::tOID getParentImpl( + const ObjectHierarchy::tOID& rParentOID, + const ObjectHierarchy::tOID& rOID ); + + typedef ::std::map< ObjectHierarchy::tOID, ObjectHierarchy::tChildContainer > + tChildMap; + tChildMap m_aChildMap; + ExplicitValueProvider* m_pExplicitValueProvider; + bool m_bFlattenDiagram; + bool m_bOrderingForElementSelector; +}; + +ImplObjectHierarchy::ImplObjectHierarchy( + const Reference< XChartDocument >& xChartDocument, + ExplicitValueProvider* pExplicitValueProvider, + bool bFlattenDiagram, + bool bOrderingForElementSelector ) : + m_pExplicitValueProvider( pExplicitValueProvider ), + m_bFlattenDiagram( bFlattenDiagram ), + m_bOrderingForElementSelector( bOrderingForElementSelector ) +{ + createTree( xChartDocument ); + // don't remember this helper to avoid access after lifetime + m_pExplicitValueProvider = 0; +} + +void ImplObjectHierarchy::createTree( const Reference< XChartDocument >& xChartDocument ) +{ + m_aChildMap = tChildMap();//clear tree + + if( !xChartDocument.is() ) + return; + + //@todo: change ObjectIdentifier to take an XChartDocument rather than XModel + Reference< frame::XModel > xModel( xChartDocument, uno::UNO_QUERY ); + Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartDocument ) ); + ObjectHierarchy::tOID aDiaOID; + if( xDiagram.is() ) + aDiaOID = ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram, xModel ) ); + ObjectHierarchy::tChildContainer aTopLevelContainer; + + // First Level + + // Chart Area + if( m_bOrderingForElementSelector ) + { + aTopLevelContainer.push_back( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) ) ); + if( xDiagram.is() ) + { + aTopLevelContainer.push_back( aDiaOID ); + createWallAndFloor( aTopLevelContainer, xDiagram ); + createLegendTree( aTopLevelContainer, xChartDocument, xDiagram ); + } + } + + // Main Title + Reference< XTitled > xDocTitled( xChartDocument, uno::UNO_QUERY ); + if( xDocTitled.is()) + { + Reference< XTitle > xMainTitle( xDocTitled->getTitleObject()); + if( xMainTitle.is()) + aTopLevelContainer.push_back( + ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xMainTitle, xModel ) ) ); + } + + if( xDiagram.is()) + { + // Sub Title. Note: This is interpreted of being top level + Reference< XTitled > xDiaTitled( xDiagram, uno::UNO_QUERY ); + if( xDiaTitled.is()) + { + Reference< XTitle > xSubTitle( xDiaTitled->getTitleObject()); + if( xSubTitle.is()) + aTopLevelContainer.push_back( + ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xSubTitle, xModel ) ) ); + } + + if( !m_bOrderingForElementSelector ) + { + // Axis Titles. Note: These are interpreted of being top level + Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram ) ); + for( sal_Int32 i=0; i<aAxes.getLength(); ++i ) + lcl_addAxisTitle( aAxes[i], aTopLevelContainer, xModel ); + + // Diagram + aTopLevelContainer.push_back( aDiaOID ); + } + + if( m_bFlattenDiagram ) + createDiagramTree( aTopLevelContainer, xChartDocument, xDiagram ); + else + { + ObjectHierarchy::tChildContainer aSubContainer; + createDiagramTree( aSubContainer, xChartDocument, xDiagram ); + if( !aSubContainer.empty() ) + m_aChildMap[ aDiaOID ] = aSubContainer; + } + + if( !m_bOrderingForElementSelector ) + createLegendTree( aTopLevelContainer, xChartDocument, xDiagram ); + } + + // #i12587# support for shapes in chart + if ( !m_bOrderingForElementSelector ) + { + createAdditionalShapesTree( aTopLevelContainer ); + } + + // Chart Area + if( !m_bOrderingForElementSelector ) + aTopLevelContainer.push_back( + ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, OUString() ) ) ); + + if( ! aTopLevelContainer.empty()) + m_aChildMap[ ObjectHierarchy::getRootNodeOID() ] = aTopLevelContainer; +} + +void ImplObjectHierarchy::createLegendTree( + ObjectHierarchy::tChildContainer & rContainer, + const Reference< XChartDocument > & xChartDoc, + const Reference< XDiagram > & xDiagram ) +{ + if( xDiagram.is() && LegendHelper::hasLegend( xDiagram ) ) + { + ObjectHierarchy::tOID aLegendOID( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xDiagram->getLegend(), Reference< frame::XModel >( xChartDoc, uno::UNO_QUERY ) ) ) ); + rContainer.push_back( aLegendOID ); + + // iterate over child shapes of legend and search for matching CIDs + if( m_pExplicitValueProvider ) + { + Reference< container::XIndexAccess > xLegendShapeContainer( + m_pExplicitValueProvider->getShapeForCID( aLegendOID.getObjectCID() ), uno::UNO_QUERY ); + ObjectHierarchy::tChildContainer aLegendEntryOIDs; + lcl_getChildOIDs( aLegendEntryOIDs, xLegendShapeContainer ); + + m_aChildMap[ aLegendOID ] = aLegendEntryOIDs; + } + } +} + +void ImplObjectHierarchy::createAxesTree( + ObjectHierarchy::tChildContainer & rContainer, + const Reference< XChartDocument > & xChartDoc, + const Reference< XDiagram > & xDiagram ) +{ + Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW ); + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + uno::Reference< chart2::XChartType > xChartType( DiagramHelper::getChartTypeByIndex( xDiagram, 0 ) ); + bool bSupportsAxesGrids = ChartTypeHelper::isSupportingMainAxis( xChartType, nDimensionCount, 0 ); + if( bSupportsAxesGrids ) + { + Sequence< Reference< XAxis > > aAxes( AxisHelper::getAllAxesOfDiagram( xDiagram, /* bOnlyVisible = */ true ) ); + if( !m_bOrderingForElementSelector ) + ::std::transform( aAxes.getConstArray(), aAxes.getConstArray() + aAxes.getLength(), + ::std::back_inserter( rContainer ), + lcl_ObjectToOID( xChartDoc )); + + // get all axes, also invisible ones + aAxes = AxisHelper::getAllAxesOfDiagram( xDiagram, /* bOnlyVisible = */ false ); + // Grids + Reference< frame::XModel > xChartModel( xChartDoc, uno::UNO_QUERY ); + for( sal_Int32 nA=0; nA<aAxes.getLength(); ++nA ) + { + Reference< XAxis > xAxis( aAxes[nA] ); + if(!xAxis.is()) + continue; + + sal_Int32 nCooSysIndex = 0; + sal_Int32 nDimensionIndex = 0; + sal_Int32 nAxisIndex = 0; + AxisHelper::getIndicesForAxis( xAxis, xDiagram, nCooSysIndex, nDimensionIndex, nAxisIndex ); + if( nAxisIndex>0 && !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount, nDimensionIndex ) ) + continue; + + if( m_bOrderingForElementSelector ) + { + // axis + if( AxisHelper::isAxisVisible( xAxis ) ) + rContainer.push_back( + ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForObject( xAxis, xChartModel ) ) ); + + // axis title + lcl_addAxisTitle( aAxes[nA], rContainer, xChartModel ); + } + + Reference< beans::XPropertySet > xGridProperties( xAxis->getGridProperties() ); + if( AxisHelper::isGridVisible( xGridProperties ) ) + { + //main grid + rContainer.push_back( + ObjectIdentifier( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel ) ) ) ); + } + + Sequence< Reference< beans::XPropertySet > > aSubGrids( xAxis->getSubGridProperties() );; + sal_Int32 nSubGrid = 0; + for( nSubGrid = 0; nSubGrid < aSubGrids.getLength(); ++nSubGrid ) + { + Reference< beans::XPropertySet > xSubGridProperties( aSubGrids[nSubGrid] ); + if( AxisHelper::isGridVisible( xSubGridProperties ) ) + { + //sub grid + rContainer.push_back( + ObjectIdentifier( ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForGrid( xAxis, xChartModel, nSubGrid ) ) ) ); + } + } + } + } +} + +void ImplObjectHierarchy::createWallAndFloor( + ObjectHierarchy::tChildContainer & rContainer, + const Reference< XDiagram > & xDiagram ) +{ + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + bool bIsThreeD = ( nDimensionCount == 3 ); + bool bHasWall = DiagramHelper::isSupportingFloorAndWall( xDiagram ); + if( bHasWall && bIsThreeD ) + { + rContainer.push_back( + ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ) ) ); + + Reference< beans::XPropertySet > xFloor( xDiagram->getFloor()); + if( xFloor.is()) + rContainer.push_back( + ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_FLOOR, rtl::OUString() ) ) ); + } + +} + +void ImplObjectHierarchy::createDiagramTree( + ObjectHierarchy::tChildContainer & rContainer, + const Reference< XChartDocument > & xChartDoc, + const Reference< XDiagram > & xDiagram ) +{ + if( !m_bOrderingForElementSelector ) + { + createDataSeriesTree( rContainer, xDiagram ); + createAxesTree( rContainer, xChartDoc, xDiagram ); + createWallAndFloor( rContainer, xDiagram ); + } + else + { + createAxesTree( rContainer, xChartDoc, xDiagram ); + createDataSeriesTree( rContainer, xDiagram ); + } +} + +void ImplObjectHierarchy::createDataSeriesTree( + ObjectHierarchy::tChildContainer & rOutDiagramSubContainer, + const Reference< XDiagram > & xDiagram ) +{ + Reference< XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW ); + + try + { + sal_Int32 nDiagramIndex = 0; + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + Sequence< Reference< XCoordinateSystem > > aCooSysSeq( + xCooSysCnt->getCoordinateSystems()); + for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx ) + { + Reference< XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW ); + Sequence< Reference< XChartType > > aChartTypeSeq( xCTCnt->getChartTypes()); + for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypeSeq.getLength(); ++nCTIdx ) + { + Reference< XChartType > xChartType( aChartTypeSeq[nCTIdx] ); + Reference< XDataSeriesContainer > xDSCnt( xChartType, uno::UNO_QUERY_THROW ); + Sequence< Reference< XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries() ); + const sal_Int32 nNumberOfSeries = + ChartTypeHelper::getNumberOfDisplayedSeries( xChartType, aSeriesSeq.getLength()); + + for( sal_Int32 nSeriesIdx=0; nSeriesIdx<nNumberOfSeries; ++nSeriesIdx ) + { + OUString aSeriesParticle( + ObjectIdentifier::createParticleForSeries( + nDiagramIndex, nCooSysIdx, nCTIdx, nSeriesIdx )); + ObjectHierarchy::tOID aSeriesOID( + ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForParticle( aSeriesParticle ) ) ); + rOutDiagramSubContainer.push_back( aSeriesOID ); + + ObjectHierarchy::tChildContainer aSeriesSubContainer; + + Reference< chart2::XDataSeries > xSeries( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY ); + + // data lablels + if( DataSeriesHelper::hasDataLabelsAtSeries( xSeries ) ) + { + rtl::OUString aChildParticle( ObjectIdentifier::getStringForType( OBJECTTYPE_DATA_LABELS ) ); + aChildParticle+=(C2U("=")); + aSeriesSubContainer.push_back( + ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierForParticles( aSeriesParticle, aChildParticle ) ) ); + } + + // Statistics + if( ChartTypeHelper::isSupportingStatisticProperties( xChartType, nDimensionCount ) ) + { + Reference< chart2::XRegressionCurveContainer > xCurveCnt( xSeries, uno::UNO_QUERY ); + if( xCurveCnt.is()) + { + Sequence< Reference< chart2::XRegressionCurve > > aCurves( xCurveCnt->getRegressionCurves()); + for( sal_Int32 nCurveIdx=0; nCurveIdx<aCurves.getLength(); ++nCurveIdx ) + { + bool bIsAverageLine = RegressionCurveHelper::isMeanValueLine( aCurves[nCurveIdx] ); + aSeriesSubContainer.push_back( + ObjectIdentifier( ObjectIdentifier::createDataCurveCID( aSeriesParticle, nCurveIdx, bIsAverageLine ) ) ); + if( RegressionCurveHelper::hasEquation( aCurves[nCurveIdx] ) ) + { + aSeriesSubContainer.push_back( + ObjectIdentifier( ObjectIdentifier::createDataCurveEquationCID( aSeriesParticle, nCurveIdx ) ) ); + } + } + Reference< beans::XPropertySet > xSeriesProp( xSeries, uno::UNO_QUERY ); + Reference< beans::XPropertySet > xErrorBarProp; + if( xSeriesProp.is() && + (xSeriesProp->getPropertyValue( C2U("ErrorBarY")) >>= xErrorBarProp) && + xErrorBarProp.is()) + { + sal_Int32 nStyle = ::com::sun::star::chart::ErrorBarStyle::NONE; + if( ( xErrorBarProp->getPropertyValue( C2U("ErrorBarStyle")) >>= nStyle ) && + ( nStyle != ::com::sun::star::chart::ErrorBarStyle::NONE ) ) + { + aSeriesSubContainer.push_back( + ObjectIdentifier( ObjectIdentifier::createClassifiedIdentifierWithParent( + OBJECTTYPE_DATA_ERRORS, OUString(), aSeriesParticle ) ) ); + } + } + } + } + + // Data Points + // iterate over child shapes of legend and search for matching CIDs + if( m_pExplicitValueProvider ) + { + Reference< container::XIndexAccess > xSeriesShapeContainer( + m_pExplicitValueProvider->getShapeForCID( aSeriesOID.getObjectCID() ), uno::UNO_QUERY ); + lcl_getChildOIDs( aSeriesSubContainer, xSeriesShapeContainer ); + } + + if( ! aSeriesSubContainer.empty()) + m_aChildMap[ aSeriesOID ] = aSeriesSubContainer; + } + } + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +void ImplObjectHierarchy::createAdditionalShapesTree( ObjectHierarchy::tChildContainer& rContainer ) +{ + try + { + if ( m_pExplicitValueProvider ) + { + Reference< drawing::XDrawPage > xDrawPage( m_pExplicitValueProvider->getDrawModelWrapper()->getMainDrawPage() ); + Reference< drawing::XShapes > xDrawPageShapes( xDrawPage, uno::UNO_QUERY_THROW ); + Reference< drawing::XShapes > xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) ); + sal_Int32 nCount = xDrawPageShapes->getCount(); + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + Reference< drawing::XShape > xShape; + if ( xDrawPageShapes->getByIndex( i ) >>= xShape ) + { + if ( xShape.is() && xShape != xChartRoot ) + { + rContainer.push_back( ObjectIdentifier( xShape ) ); + } + } + } + } + } + catch ( uno::Exception& ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +bool ImplObjectHierarchy::hasChildren( const ObjectHierarchy::tOID& rParent ) +{ + if ( rParent.isValid() ) + { + tChildMap::const_iterator aIt( m_aChildMap.find( rParent )); + if( aIt != m_aChildMap.end()) + return ! (aIt->second.empty()); + } + return false; +} + +ObjectHierarchy::tChildContainer ImplObjectHierarchy::getChildren( const ObjectHierarchy::tOID& rParent ) +{ + if ( rParent.isValid() ) + { + tChildMap::const_iterator aIt( m_aChildMap.find( rParent )); + if( aIt != m_aChildMap.end()) + return aIt->second; + } + return ObjectHierarchy::tChildContainer(); +} + +ObjectHierarchy::tChildContainer ImplObjectHierarchy::getSiblings( const ObjectHierarchy::tOID& rNode ) +{ + if ( rNode.isValid() && !ObjectHierarchy::isRootNode( rNode ) ) + { + for( tChildMap::const_iterator aIt( m_aChildMap.begin()); + aIt != m_aChildMap.end(); ++aIt ) + { + ObjectHierarchy::tChildContainer::const_iterator aElemIt( + ::std::find( aIt->second.begin(), aIt->second.end(), rNode )); + if( aElemIt != aIt->second.end()) + return aIt->second; + } + } + return ObjectHierarchy::tChildContainer(); +} + +ObjectHierarchy::tOID ImplObjectHierarchy::getParentImpl( + const ObjectHierarchy::tOID & rParentOID, + const ObjectHierarchy::tOID & rOID ) +{ + // search children + ObjectHierarchy::tChildContainer aChildren( getChildren( rParentOID )); + ObjectHierarchy::tChildContainer::const_iterator aIt( + ::std::find( aChildren.begin(), aChildren.end(), rOID )); + // recursion end + if( aIt != aChildren.end()) + return rParentOID; + + for( aIt = aChildren.begin(); aIt != aChildren.end(); ++aIt ) + { + // recursion + ObjectHierarchy::tOID aTempParent( getParentImpl( *aIt, rOID )); + if ( aTempParent.isValid() ) + { + // exit on success + return aTempParent; + } + } + + // exit on fail + return ObjectHierarchy::tOID(); +} + +ObjectHierarchy::tOID ImplObjectHierarchy::getParent( + const ObjectHierarchy::tOID & rOID ) +{ + return getParentImpl( ObjectHierarchy::getRootNodeOID(), rOID ); +} + +} // namespace impl + + +ObjectHierarchy::ObjectHierarchy( + const Reference< XChartDocument > & xChartDocument, + ExplicitValueProvider * pExplicitValueProvider /* = 0 */, + bool bFlattenDiagram /* = false */, + bool bOrderingForElementSelector /* = false */) : + m_apImpl( new impl::ImplObjectHierarchy( xChartDocument, pExplicitValueProvider, bFlattenDiagram, bOrderingForElementSelector )) +{} + +ObjectHierarchy::~ObjectHierarchy() +{} + +// static +ObjectHierarchy::tOID ObjectHierarchy::getRootNodeOID() +{ + return ObjectIdentifier( C2U( "ROOT" ) ); +} + +// static +bool ObjectHierarchy::isRootNode( const ObjectHierarchy::tOID& rOID ) +{ + return ( rOID == ObjectHierarchy::getRootNodeOID() ); +} + +ObjectHierarchy::tChildContainer ObjectHierarchy::getTopLevelChildren() const +{ + return m_apImpl->getChildren( ObjectHierarchy::getRootNodeOID()); +} + +bool ObjectHierarchy::hasChildren( const tOID& rParent ) const +{ + return m_apImpl->hasChildren( rParent ); +} + +ObjectHierarchy::tChildContainer ObjectHierarchy::getChildren( + const ObjectHierarchy::tOID& rParent ) const +{ + if ( rParent.isValid() ) + return m_apImpl->getChildren( rParent ); + + return ObjectHierarchy::tChildContainer(); +} + +ObjectHierarchy::tChildContainer ObjectHierarchy::getSiblings( + const ObjectHierarchy::tOID& rNode ) const +{ + if ( rNode.isValid() && !isRootNode( rNode ) ) + return m_apImpl->getSiblings( rNode ); + + return ObjectHierarchy::tChildContainer(); +} + +ObjectHierarchy::tOID ObjectHierarchy::getParent( + const ObjectHierarchy::tOID& rNode ) const +{ + return m_apImpl->getParent( rNode ); +} + +sal_Int32 ObjectHierarchy::getIndexInParent( + const ObjectHierarchy::tOID& rNode ) const +{ + tOID aParentOID( m_apImpl->getParent( rNode )); + tChildContainer aChildren( m_apImpl->getChildren( aParentOID ) ); + tChildContainer::const_iterator aIt( aChildren.begin() ); + for( sal_Int32 nIndex = 0; aIt != aChildren.end(); ++nIndex, ++aIt ) + { + if ( *aIt == rNode ) + return nIndex; + } + return -1; +} + +// ================================================================================ + +ObjectKeyNavigation::ObjectKeyNavigation( + const ObjectHierarchy::tOID & rCurrentOID, + const Reference< chart2::XChartDocument > & xChartDocument, + ExplicitValueProvider * pExplicitValueProvider /* = 0 */ ) : + m_aCurrentOID( rCurrentOID ), + m_xChartDocument( xChartDocument ), + m_pExplicitValueProvider( pExplicitValueProvider ), + m_bStepDownInDiagram( true ) +{ + if ( !m_aCurrentOID.isValid() ) + { + setCurrentSelection( ObjectHierarchy::getRootNodeOID() ); + } +} + +bool ObjectKeyNavigation::handleKeyEvent( + const awt::KeyEvent & rEvent ) +{ + bool bResult = false; + + switch( rEvent.KeyCode ) + { + case awt::Key::TAB: + if( rEvent.Modifiers & awt::KeyModifier::SHIFT ) + bResult = previous(); + else + bResult = next(); + break; + case awt::Key::HOME: + bResult = first(); + break; + case awt::Key::END: + bResult = last(); + break; + case awt::Key::F3: + if( rEvent.Modifiers & awt::KeyModifier::SHIFT ) + bResult = up(); + else + bResult = down(); + break; + case awt::Key::ESCAPE: + setCurrentSelection( ObjectIdentifier() ); + bResult = true; + break; + default: + bResult = false; + break; + } + return bResult; +} + +void ObjectKeyNavigation::setCurrentSelection( const ObjectHierarchy::tOID& rOID ) +{ + m_aCurrentOID = rOID; +} + +ObjectHierarchy::tOID ObjectKeyNavigation::getCurrentSelection() const +{ + return m_aCurrentOID; +} + +bool ObjectKeyNavigation::first() +{ + ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); + ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) ); + bool bResult = !aSiblings.empty(); + if( bResult ) + setCurrentSelection( aSiblings.front()); + else + bResult = veryFirst(); + return bResult; +} + +bool ObjectKeyNavigation::last() +{ + ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); + ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) ); + bool bResult = !aSiblings.empty(); + if( bResult ) + setCurrentSelection( aSiblings.back()); + else + bResult = veryLast(); + return bResult; +} + +bool ObjectKeyNavigation::next() +{ + ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); + ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection() ) ); + bool bResult = !aSiblings.empty(); + if( bResult ) + { + ObjectHierarchy::tChildContainer::const_iterator aIt( + ::std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection())); + OSL_ASSERT( aIt != aSiblings.end()); + if( ++aIt == aSiblings.end()) + aIt = aSiblings.begin(); + setCurrentSelection( *aIt ); + } + else + bResult = veryFirst(); + + return bResult; +} + +bool ObjectKeyNavigation::previous() +{ + ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); + ObjectHierarchy::tChildContainer aSiblings( aHierarchy.getSiblings( getCurrentSelection())); + bool bResult = !aSiblings.empty(); + if( bResult ) + { + ObjectHierarchy::tChildContainer::const_iterator aIt( + ::std::find( aSiblings.begin(), aSiblings.end(), getCurrentSelection())); + OSL_ASSERT( aIt != aSiblings.end()); + if( aIt == aSiblings.begin()) + aIt = aSiblings.end(); + --aIt; + setCurrentSelection( *aIt ); + } + else + bResult = veryLast(); + return bResult; +} + +bool ObjectKeyNavigation::up() +{ + ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); + bool bResult = !ObjectHierarchy::isRootNode( getCurrentSelection()); + if( bResult ) + setCurrentSelection( aHierarchy.getParent( getCurrentSelection())); + return bResult; +} + +bool ObjectKeyNavigation::down() +{ + ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); + bool bResult = aHierarchy.hasChildren( getCurrentSelection()); + if( bResult ) + { + ObjectHierarchy::tChildContainer aChildren = aHierarchy.getChildren( getCurrentSelection()); + OSL_ASSERT( !aChildren.empty()); + setCurrentSelection( aChildren.front()); + } + return bResult; +} + +bool ObjectKeyNavigation::veryFirst() +{ + ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); + ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren()); + bool bResult = !aChildren.empty(); + if( bResult ) + setCurrentSelection( aChildren.front()); + return bResult; +} + +bool ObjectKeyNavigation::veryLast() +{ + ObjectHierarchy aHierarchy( m_xChartDocument, m_pExplicitValueProvider, m_bStepDownInDiagram ); + ObjectHierarchy::tChildContainer aChildren( aHierarchy.getTopLevelChildren()); + bool bResult = !aChildren.empty(); + if( bResult ) + setCurrentSelection( aChildren.back()); + return bResult; +} + +} // namespace chart diff --git a/chart2/source/controller/main/PositionAndSizeHelper.cxx b/chart2/source/controller/main/PositionAndSizeHelper.cxx new file mode 100644 index 000000000000..f0ce3eaaa04e --- /dev/null +++ b/chart2/source/controller/main/PositionAndSizeHelper.cxx @@ -0,0 +1,189 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "PositionAndSizeHelper.hxx" +#include "macros.hxx" +#include "ChartModelHelper.hxx" +#include "ControllerLockGuard.hxx" +#include <com/sun/star/chart2/LegendPosition.hpp> +#include <com/sun/star/chart2/RelativePosition.hpp> +#include <com/sun/star/chart2/RelativeSize.hpp> +#include "chartview/ExplicitValueProvider.hxx" + +// header for class Rectangle +#include <tools/gen.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; + +bool PositionAndSizeHelper::moveObject( ObjectType eObjectType + , const uno::Reference< beans::XPropertySet >& xObjectProp + , const awt::Rectangle& rNewPositionAndSize + , const awt::Rectangle& rPageRectangle + ) +{ + if(!xObjectProp.is()) + return false; + Rectangle aObjectRect( Point(rNewPositionAndSize.X,rNewPositionAndSize.Y), Size(rNewPositionAndSize.Width,rNewPositionAndSize.Height) ); + Rectangle aPageRect( Point(rPageRectangle.X,rPageRectangle.Y), Size(rPageRectangle.Width,rPageRectangle.Height) ); + + if( OBJECTTYPE_TITLE==eObjectType ) + { + //@todo decide wether x is primary or secondary + chart2::RelativePosition aRelativePosition; + aRelativePosition.Anchor = drawing::Alignment_CENTER; + //the anchor point at the title object is top/middle + Point aPos = aObjectRect.TopLeft(); + aRelativePosition.Primary = (double(aPos.X())+double(aObjectRect.getWidth())/2.0)/double(aPageRect.getWidth()); + aRelativePosition.Secondary = (double(aPos.Y())+double(aObjectRect.getHeight())/2.0)/double(aPageRect.getHeight()); + xObjectProp->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aRelativePosition) ); + } + else if( OBJECTTYPE_DATA_CURVE_EQUATION==eObjectType ) + { + //@todo decide wether x is primary or secondary + chart2::RelativePosition aRelativePosition; + aRelativePosition.Anchor = drawing::Alignment_TOP_LEFT; + //the anchor point at the title object is top/middle + Point aPos = aObjectRect.TopLeft(); + aRelativePosition.Primary = double(aPos.X())/double(aPageRect.getWidth()); + aRelativePosition.Secondary = double(aPos.Y())/double(aPageRect.getHeight()); + xObjectProp->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aRelativePosition) ); + } + else if(OBJECTTYPE_LEGEND==eObjectType) + { + LegendPosition ePos = LegendPosition_LINE_END; + xObjectProp->getPropertyValue( C2U( "AnchorPosition" )) >>= ePos; + chart2::RelativePosition aRelativePosition; + Point aAnchor = aObjectRect.TopLeft(); + + switch( ePos ) + { + case LegendPosition_LINE_START: + { + //@todo language dependent positions ... + aRelativePosition.Anchor = drawing::Alignment_LEFT; + aAnchor = aObjectRect.LeftCenter(); + } + break; + case LegendPosition_LINE_END: + { + //@todo language dependent positions ... + aRelativePosition.Anchor = drawing::Alignment_RIGHT; + aAnchor = aObjectRect.RightCenter(); + } + break; + case LegendPosition_PAGE_START: + { + //@todo language dependent positions ... + aRelativePosition.Anchor = drawing::Alignment_TOP; + aAnchor = aObjectRect.TopCenter(); + } + break; + case LegendPosition_PAGE_END: + //@todo language dependent positions ... + { + aRelativePosition.Anchor = drawing::Alignment_BOTTOM; + aAnchor = aObjectRect.BottomCenter(); + } + break; + case LegendPosition_CUSTOM: + { + //@todo language dependent positions ... + aRelativePosition.Anchor = drawing::Alignment_TOP_LEFT; + } + break; + case LegendPosition_MAKE_FIXED_SIZE: + OSL_ASSERT( false ); + break; + } + aRelativePosition.Primary = + static_cast< double >( aAnchor.X()) / + static_cast< double >( aPageRect.getWidth() ); + aRelativePosition.Secondary = + static_cast< double >( aAnchor.Y()) / + static_cast< double >( aPageRect.getHeight()); + + xObjectProp->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aRelativePosition) ); + } + else if(OBJECTTYPE_DIAGRAM==eObjectType || OBJECTTYPE_DIAGRAM_WALL==eObjectType || OBJECTTYPE_DIAGRAM_FLOOR==eObjectType) + { + //@todo decide wether x is primary or secondary + + //set position: + chart2::RelativePosition aRelativePosition; + aRelativePosition.Anchor = drawing::Alignment_CENTER; + + Point aPos = aObjectRect.Center(); + aRelativePosition.Primary = double(aPos.X())/double(aPageRect.getWidth()); + aRelativePosition.Secondary = double(aPos.Y())/double(aPageRect.getHeight()); + xObjectProp->setPropertyValue( C2U( "RelativePosition" ), uno::makeAny(aRelativePosition) ); + + //set size: + RelativeSize aRelativeSize; + //the anchor points for the diagram are in the middle of the diagram + //and in the middle of the page + aRelativeSize.Primary = double(aObjectRect.getWidth())/double(aPageRect.getWidth()); + aRelativeSize.Secondary = double(aObjectRect.getHeight())/double(aPageRect.getHeight()); + xObjectProp->setPropertyValue( C2U( "RelativeSize" ), uno::makeAny(aRelativeSize) ); + } + else + return false; + return true; +} + +bool PositionAndSizeHelper::moveObject( const rtl::OUString& rObjectCID + , const uno::Reference< frame::XModel >& xChartModel + , const awt::Rectangle& rNewPositionAndSize + , const awt::Rectangle& rPageRectangle + ) +{ + ControllerLockGuard aLockedControllers( xChartModel ); + + awt::Rectangle aNewPositionAndSize( rNewPositionAndSize ); + + uno::Reference< beans::XPropertySet > xObjectProp = ObjectIdentifier::getObjectPropertySet( rObjectCID, xChartModel ); + ObjectType eObjectType( ObjectIdentifier::getObjectType( rObjectCID ) ); + if(OBJECTTYPE_DIAGRAM==eObjectType || OBJECTTYPE_DIAGRAM_WALL==eObjectType || OBJECTTYPE_DIAGRAM_FLOOR==eObjectType) + { + xObjectProp = uno::Reference< beans::XPropertySet >( ObjectIdentifier::getDiagramForCID( rObjectCID, xChartModel ), uno::UNO_QUERY ); + if(!xObjectProp.is()) + return false; + } + return moveObject( eObjectType, xObjectProp, aNewPositionAndSize, rPageRectangle ); +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/SelectionHelper.cxx b/chart2/source/controller/main/SelectionHelper.cxx new file mode 100644 index 000000000000..567a36473a5b --- /dev/null +++ b/chart2/source/controller/main/SelectionHelper.cxx @@ -0,0 +1,685 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" +#include "SelectionHelper.hxx" +#include "ObjectIdentifier.hxx" +//for C2U +#include "macros.hxx" +#include "DiagramHelper.hxx" +#include "ChartModelHelper.hxx" + +// header for class SdrObjList +#include <svx/svdpage.hxx> +#include <svx/svditer.hxx> +#include "svx/obj3d.hxx" +// header for class SdrPathObj +#include <svx/svdopath.hxx> +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +//using namespace ::com::sun::star::chart2; + +namespace +{ + +rtl::OUString lcl_getObjectName( SdrObject* pObj ) +{ + if(pObj) + return pObj->GetName(); + return rtl::OUString(); +} + +void impl_selectObject( SdrObject* pObjectToSelect, DrawViewWrapper& rDrawViewWrapper ) +{ + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + + if(pObjectToSelect) + { + SelectionHelper aSelectionHelper( pObjectToSelect ); + SdrObject* pMarkObj = aSelectionHelper.getObjectToMark(); + rDrawViewWrapper.setMarkHandleProvider(&aSelectionHelper); + rDrawViewWrapper.MarkObject(pMarkObj); + rDrawViewWrapper.setMarkHandleProvider(NULL); + } +} + +}//anonymous namespace + +bool Selection::hasSelection() +{ + return m_aSelectedOID.isValid(); +} + +rtl::OUString Selection::getSelectedCID() +{ + return m_aSelectedOID.getObjectCID(); +} + +uno::Reference< drawing::XShape > Selection::getSelectedAdditionalShape() +{ + return m_aSelectedOID.getAdditionalShape(); +} + +ObjectIdentifier Selection::getSelectedOID() const +{ + return m_aSelectedOID; +} + +bool Selection::setSelection( const ::rtl::OUString& rCID ) +{ + if ( !rCID.equals( m_aSelectedOID.getObjectCID() ) ) + { + m_aSelectedOID = ObjectIdentifier( rCID ); + return true; + } + return false; +} + +bool Selection::setSelection( const uno::Reference< drawing::XShape >& xShape ) +{ + if ( !( xShape == m_aSelectedOID.getAdditionalShape() ) ) + { + clearSelection(); + m_aSelectedOID = ObjectIdentifier( xShape ); + return true; + } + return false; +} + +void Selection::clearSelection() +{ + m_aSelectedOID = ObjectIdentifier(); + m_aSelectedOID_beforeMouseDown = ObjectIdentifier(); + m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier(); +} + +bool Selection::maybeSwitchSelectionAfterSingleClickWasEnsured() +{ + if ( m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid() + && m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing != m_aSelectedOID ) + { + m_aSelectedOID = m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing; + m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier(); + return true; + } + return false; +} + +void Selection::resetPossibleSelectionAfterSingleClickWasEnsured() +{ + if ( m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid() ) + { + m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier(); + } +} + +void Selection::remindSelectionBeforeMouseDown() +{ + m_aSelectedOID_beforeMouseDown = m_aSelectedOID; +} + +bool Selection::isSelectionDifferentFromBeforeMouseDown() +{ + return ( m_aSelectedOID != m_aSelectedOID_beforeMouseDown ); +} + +void Selection::applySelection( DrawViewWrapper* pDrawViewWrapper ) +{ + if( pDrawViewWrapper ) + { + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + pDrawViewWrapper->UnmarkAll(); + } + SdrObject* pObjectToSelect = 0; + if ( m_aSelectedOID.isAutoGeneratedObject() ) + { + pObjectToSelect = pDrawViewWrapper->getNamedSdrObject( m_aSelectedOID.getObjectCID() ); + } + else if( m_aSelectedOID.isAdditionalShape() ) + { + pObjectToSelect = DrawViewWrapper::getSdrObject( m_aSelectedOID.getAdditionalShape() ); + } + + impl_selectObject( pObjectToSelect, *pDrawViewWrapper ); + } +} + +void Selection::adaptSelectionToNewPos( const Point& rMousePos, DrawViewWrapper* pDrawViewWrapper + , bool bIsRightMouse, bool bWaitingForDoubleClick ) +{ + if( pDrawViewWrapper ) + { + //do not toggel multiclick selection if right clicked on the selected object or waiting for double click + bool bAllowMultiClickSelectionChange = !bIsRightMouse && !bWaitingForDoubleClick; + + ObjectIdentifier aLastSelectedObject( m_aSelectedOID ); + + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + + //bAllowMultiClickSelectionChange==true -> a second click on the same object can lead to a changed selection (e.g. series -> single data point) + + //get object to select: + SdrObject* pNewObj = 0; + { + m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier(); + + //the search for the object to select starts with the hit object deepest in the grouping hierarchy (a leaf in the tree) + //further we travel along the grouping hierarchy from child to parent + pNewObj = pDrawViewWrapper->getHitObject(rMousePos); + m_aSelectedOID = ObjectIdentifier( lcl_getObjectName( pNewObj ) );//name of pNewObj + + //ignore handle only objects for hit test + while( pNewObj && m_aSelectedOID.getObjectCID().match( C2U( "HandlesOnly" ) ) ) + { + pNewObj->SetMarkProtect(true); + pNewObj = pDrawViewWrapper->getHitObject(rMousePos); + m_aSelectedOID = ObjectIdentifier( lcl_getObjectName( pNewObj ) ); + } + + //accept only named objects while searching for the object to select + //this call may change m_aSelectedOID + if ( SelectionHelper::findNamedParent( pNewObj, m_aSelectedOID, true ) ) + { + //if the so far found object is a multi click object further steps are necessary + while( ObjectIdentifier::isMultiClickObject( m_aSelectedOID.getObjectCID() ) ) + { + bool bSameObjectAsLastSelected = ( aLastSelectedObject == m_aSelectedOID ); + if( bSameObjectAsLastSelected ) + { + //if the same child is clicked again don't go up further + break; + } + if ( ObjectIdentifier::areSiblings( aLastSelectedObject.getObjectCID(), m_aSelectedOID.getObjectCID() ) ) + { + //if a sibling of the last selected object is clicked don't go up further + break; + } + SdrObject* pLastChild = pNewObj; + ObjectIdentifier aLastChild = m_aSelectedOID; + if ( !SelectionHelper::findNamedParent( pNewObj, m_aSelectedOID, false ) ) + { + //take the one found so far + break; + } + //if the last selected object is found don't go up further + //but take the last child if selection change is allowed + if ( aLastSelectedObject == m_aSelectedOID ) + { + if( bAllowMultiClickSelectionChange ) + { + pNewObj = pLastChild; + m_aSelectedOID = aLastChild; + } + else + m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = aLastChild; + + break; + } + } + + DBG_ASSERT( pNewObj && m_aSelectedOID.isValid(), "somehow lost selected object" ); + } + else + { + //maybe an additional shape was hit + if ( pNewObj ) + { + m_aSelectedOID = ObjectIdentifier( uno::Reference< drawing::XShape >( pNewObj->getUnoShape(), uno::UNO_QUERY ) ); + } + else + { + m_aSelectedOID = ObjectIdentifier(); + } + } + + if ( !m_aSelectedOID.isAdditionalShape() ) + { + rtl::OUString aPageCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, rtl::OUString() ) );//@todo read CID from model + + if ( !m_aSelectedOID.isAutoGeneratedObject() ) + { + m_aSelectedOID = ObjectIdentifier( aPageCID ); + } + + //check wether the diagram was hit but not selected (e.g. because it has no filling): + rtl::OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ) );//@todo read CID from model + if ( m_aSelectedOID.getObjectCID().equals( aPageCID ) || m_aSelectedOID.getObjectCID().equals( aWallCID ) || !m_aSelectedOID.isAutoGeneratedObject() ) + { + rtl::OUString aDiagramCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, rtl::OUString::valueOf( sal_Int32(0) ) ); + //todo: if more than one diagram is available in future do chack the list of all diagrams here + SdrObject* pDiagram = pDrawViewWrapper->getNamedSdrObject( aDiagramCID ); + if( pDiagram ) + { + if( pDrawViewWrapper->IsObjectHit( pDiagram, rMousePos ) ) + { + m_aSelectedOID = ObjectIdentifier( aDiagramCID ); + pNewObj = pDiagram; + } + } + } + } + } + + if ( bIsRightMouse && m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing.isValid() ) + { + m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing = ObjectIdentifier(); + } + } +} + +bool Selection::isResizeableObjectSelected() +{ + ObjectType eObjectType = m_aSelectedOID.getObjectType(); + switch( eObjectType ) + { + case OBJECTTYPE_DIAGRAM: + case OBJECTTYPE_DIAGRAM_WALL: + case OBJECTTYPE_SHAPE: + return true; + default: + return false; + } + return false; +} + +bool Selection::isRotateableObjectSelected( const uno::Reference< frame::XModel >& xChartModel ) +{ + return SelectionHelper::isRotateableObject( m_aSelectedOID.getObjectCID(), xChartModel ); +} + +bool Selection::isDragableObjectSelected() +{ + return m_aSelectedOID.isDragableObject(); +} + +bool Selection::isAdditionalShapeSelected() const +{ + return m_aSelectedOID.isAdditionalShape(); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +//static +bool SelectionHelper::findNamedParent( SdrObject*& pInOutObject + , rtl::OUString& rOutName + , bool bGivenObjectMayBeResult ) +{ + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + //find the deepest named group + SdrObject* pObj = pInOutObject; + rtl::OUString aName; + if( bGivenObjectMayBeResult ) + aName = lcl_getObjectName( pObj ); + + while( pObj && !ObjectIdentifier::isCID( aName ) ) + { + SdrObjList* pObjList = pObj->GetObjList(); + if( !pObjList ) + return false;; + SdrObject* pOwner = pObjList->GetOwnerObj(); + if( !pOwner ) + return false; + pObj = pOwner; + aName = lcl_getObjectName( pObj ); + } + + if(!pObj) + return false; + if(!aName.getLength()) + return false; + + pInOutObject = pObj; + rOutName = aName; + return true; +} + +//static +bool SelectionHelper::findNamedParent( SdrObject*& pInOutObject + , ObjectIdentifier& rOutObject + , bool bGivenObjectMayBeResult ) +{ + rtl::OUString aName; + if ( findNamedParent( pInOutObject, aName, bGivenObjectMayBeResult ) ) + { + rOutObject = ObjectIdentifier( aName ); + return true; + } + return false; +} + +//static +bool SelectionHelper::isDragableObjectHitTwice( const Point& rMPos + , const rtl::OUString& rNameOfSelectedObject + , const DrawViewWrapper& rDrawViewWrapper ) +{ + if(!rNameOfSelectedObject.getLength()) + return false; + if( !ObjectIdentifier::isDragableObject(rNameOfSelectedObject) ) + return false; + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + SdrObject* pObj = rDrawViewWrapper.getNamedSdrObject( rNameOfSelectedObject ); + if( !rDrawViewWrapper.IsObjectHit( pObj, rMPos ) ) + return false; + return true; +} + +// static +::rtl::OUString SelectionHelper::getHitObjectCID( + const Point& rMPos, + DrawViewWrapper& rDrawViewWrapper, + bool bGetDiagramInsteadOf_Wall ) +{ + // //- solar mutex + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + rtl::OUString aRet; + + SdrObject* pNewObj = rDrawViewWrapper.getHitObject(rMPos); + aRet = lcl_getObjectName( pNewObj );//name of pNewObj + + //ignore handle only objects for hit test + while( pNewObj && aRet.match(C2U("HandlesOnly")) ) + { + pNewObj->SetMarkProtect(true); + pNewObj = rDrawViewWrapper.getHitObject(rMPos); + aRet = lcl_getObjectName( pNewObj ); + } + + //accept only named objects while searching for the object to select + if( !findNamedParent( pNewObj, aRet, true ) ) + { + aRet = ::rtl::OUString(); + } + + rtl::OUString aPageCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, rtl::OUString() ) );//@todo read CID from model + //get page when nothing was hit + if( aRet.getLength() == 0 && !pNewObj ) + { + aRet = aPageCID; + } + + //get diagram instead wall or page if hit inside diagram + if( aRet.getLength() != 0 ) + { + if( aRet.equals( aPageCID ) ) + { + rtl::OUString aDiagramCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, rtl::OUString::valueOf( sal_Int32(0) ) ); + //todo: if more than one diagram is available in future do chack the list of all diagrams here + SdrObject* pDiagram = rDrawViewWrapper.getNamedSdrObject( aDiagramCID ); + if( pDiagram ) + { + if( rDrawViewWrapper.IsObjectHit( pDiagram, rMPos ) ) + { + aRet = aDiagramCID; + } + } + } + else if( bGetDiagramInsteadOf_Wall ) + { + rtl::OUString aWallCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM_WALL, rtl::OUString() ) );//@todo read CID from model + + if( aRet.equals( aWallCID ) ) + { + rtl::OUString aDiagramCID = ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, rtl::OUString::valueOf( sal_Int32(0) ) ); + aRet = aDiagramCID; + } + } + } + + return aRet; + // \\- solar mutex +} + +//static +bool SelectionHelper::isRotateableObject( const ::rtl::OUString& rCID + , const uno::Reference< frame::XModel >& xChartModel ) +{ + if( !ObjectIdentifier::isRotateableObject( rCID ) ) + return false; + + sal_Int32 nDimensionCount = DiagramHelper::getDimension( ChartModelHelper::findDiagram( xChartModel ) ); + + if( nDimensionCount == 3 ) + return true; + return false; +} + +SelectionHelper::SelectionHelper( SdrObject* pSelectedObj ) + : m_pSelectedObj( pSelectedObj ) +{ + +} +SelectionHelper::~SelectionHelper() +{ +} + +//virtual +bool SelectionHelper::getFrameDragSingles() +{ + bool bFrameDragSingles = true;//true == green == surrounding handles + if( m_pSelectedObj && m_pSelectedObj->ISA(E3dObject) ) + bFrameDragSingles = false; + return bFrameDragSingles; +} + +//static +SdrObject* SelectionHelper::getMarkHandlesObject( SdrObject* pObj ) +{ + if(!pObj) + return 0; + rtl::OUString aName( lcl_getObjectName( pObj ) ); + if( aName.match(C2U("MarkHandles")) || aName.match(C2U("HandlesOnly")) ) + return pObj; + if( aName.getLength() )//dont't get the markhandles of a different object + return 0; + + //search for a child with name "MarkHandles" or "HandlesOnly" + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + SdrObjList* pSubList = pObj->GetSubList(); + if(pSubList) + { + SdrObjListIter aIterator(*pSubList, IM_FLAT); + while (aIterator.IsMore()) + { + SdrObject* pMarkHandles = SelectionHelper::getMarkHandlesObject( aIterator.Next() ); + if( pMarkHandles ) + return pMarkHandles; + } + } + return 0; +} + +SdrObject* SelectionHelper::getObjectToMark() +{ + //return the selected object itself + //or a specific other object if that exsists + SdrObject* pObj = m_pSelectedObj; + m_pMarkObj = pObj; + + //search for a child with name "MarkHandles" or "HandlesOnly" + if(pObj) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + SdrObjList* pSubList = pObj->GetSubList(); + if(pSubList) + { + SdrObjListIter aIterator(*pSubList, IM_FLAT); + while (aIterator.IsMore()) + { + SdrObject* pMarkHandles = SelectionHelper::getMarkHandlesObject( aIterator.Next() ); + if( pMarkHandles ) + { + m_pMarkObj = pMarkHandles; + break; + } + } + } + } + return m_pMarkObj; +} + +//static +E3dScene* SelectionHelper::getSceneToRotate( SdrObject* pObj ) +{ + //search wether the object or one of its children is a 3D object + //if so, return the accessory 3DScene + + E3dObject* pRotateable = 0; + + if(pObj) + { + pRotateable = dynamic_cast<E3dObject*>(pObj); + if( !pRotateable ) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + SdrObjList* pSubList = pObj->GetSubList(); + if(pSubList) + { + SdrObjListIter aIterator(*pSubList, IM_DEEPWITHGROUPS); + while( aIterator.IsMore() && !pRotateable ) + { + SdrObject* pSubObj = aIterator.Next(); + pRotateable = dynamic_cast<E3dObject*>(pSubObj); + } + } + } + } + + E3dScene* pScene = 0; + if(pRotateable) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + pScene = pRotateable->GetScene(); + } + return pScene; + +} + +//virtual +bool SelectionHelper::getMarkHandles( SdrHdlList& rHdlList ) +{ + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + + //@todo -> more flexible handle creation + //2 scenarios possible: + //1. add an additional invisible shape as a child to the selected object + //this child needs to be named somehow and handles need to be generated therefrom ... + //or 2. offer a central service per view where renderer and so can register for handle creation for a special shape + //.. or 3. feature from drawinglayer to create handles for each shape ... (bad performance ... ?) ? + + //scenario 1 is now used: + //if a child with name MarkHandles exsists + //this child is marked instead of the logical selected object + +/* + //if a special mark object was found + //that object should be used for marking only + if( m_pMarkObj != m_pSelectedObj) + return false; +*/ + //if a special mark object was found + //that object should be used to create handles from + if( m_pMarkObj && m_pMarkObj != m_pSelectedObj) + { + rHdlList.Clear(); + if( m_pMarkObj->ISA(SdrPathObj) ) + { + //if th object is a polygon + //from each point a handle is generated + const ::basegfx::B2DPolyPolygon& rPolyPolygon = ((SdrPathObj*)m_pMarkObj)->GetPathPoly(); + for( sal_uInt32 nN = 0L; nN < rPolyPolygon.count(); nN++) + { + const ::basegfx::B2DPolygon aPolygon(rPolyPolygon.getB2DPolygon(nN)); + for( sal_uInt32 nM = 0L; nM < aPolygon.count(); nM++) + { + const ::basegfx::B2DPoint aPoint(aPolygon.getB2DPoint(nM)); + SdrHdl* pHdl = new SdrHdl(Point(basegfx::fround(aPoint.getX()), basegfx::fround(aPoint.getY())), HDL_POLY); + rHdlList.AddHdl(pHdl); + } + } + return true; + } + else + return false; //use the special MarkObject for marking + } + + //@todo: + //add and document good marking defaults ... + + rHdlList.Clear(); + + SdrObject* pObj = m_pSelectedObj; + if(!pObj) + return false; + SdrObjList* pSubList = pObj->GetSubList(); + if( !pSubList )//no group object !pObj->IsGroupObject() + return false; + + rtl::OUString aName( lcl_getObjectName( pObj ) ); + ObjectType eObjectType( ObjectIdentifier::getObjectType( aName ) ); + if( OBJECTTYPE_DATA_POINT == eObjectType + || OBJECTTYPE_DATA_LABEL == eObjectType + || OBJECTTYPE_LEGEND_ENTRY == eObjectType + || OBJECTTYPE_AXIS_UNITLABEL == eObjectType ) + { + return false; + } + + SdrObjListIter aIterator(*pSubList, IM_FLAT); + + while (aIterator.IsMore()) + { + SdrObject* pSubObj = aIterator.Next(); + if( OBJECTTYPE_DATA_SERIES == eObjectType ) + { + rtl::OUString aSubName( lcl_getObjectName( pSubObj ) ); + ObjectType eSubObjectType( ObjectIdentifier::getObjectType( aSubName ) ); + if( eSubObjectType!=OBJECTTYPE_DATA_POINT ) + return false; + } + + Point aPos = pSubObj->GetCurrentBoundRect().Center(); + SdrHdl* pHdl = new SdrHdl(aPos,HDL_POLY); + rHdlList.AddHdl(pHdl); + } + return true; +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/SelectionHelper.hxx b/chart2/source/controller/main/SelectionHelper.hxx new file mode 100644 index 000000000000..b3516e2326a4 --- /dev/null +++ b/chart2/source/controller/main/SelectionHelper.hxx @@ -0,0 +1,139 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _CHART2_SELECTIONHELPER_HXX +#define _CHART2_SELECTIONHELPER_HXX + +#include "DrawViewWrapper.hxx" +#include "ObjectIdentifier.hxx" + +class SdrObject; +// header for enum SdrDragMode +#include <svx/svdtypes.hxx> +#include <com/sun/star/drawing/XShape.hpp> + +//............................................................................. +namespace chart +{ +//............................................................................. + +class ObjectIdentifier; + +//----------------------------------------------------------------------------- +/** +*/ +class Selection +{ +public: //methods + bool hasSelection(); + + rtl::OUString getSelectedCID(); + ::com::sun::star::uno::Reference< + ::com::sun::star::drawing::XShape > getSelectedAdditionalShape(); + ObjectIdentifier getSelectedOID() const; + + bool isResizeableObjectSelected(); + bool isRotateableObjectSelected( const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel >& xChartModel ); + bool isDragableObjectSelected(); + + bool isAdditionalShapeSelected() const; + + //returns true if selection has changed + bool setSelection( const ::rtl::OUString& rCID ); + bool setSelection( const ::com::sun::star::uno::Reference< + ::com::sun::star::drawing::XShape >& xShape ); + + void clearSelection(); + + //returns true if the selection has changed + bool maybeSwitchSelectionAfterSingleClickWasEnsured(); + void resetPossibleSelectionAfterSingleClickWasEnsured(); + + void remindSelectionBeforeMouseDown(); + bool isSelectionDifferentFromBeforeMouseDown(); + + void adaptSelectionToNewPos( const Point& rMousePos, DrawViewWrapper* pDrawViewWrapper + , bool bIsRightMouse, bool bWaitingForDoubleClick ); + + void applySelection( DrawViewWrapper* pDrawViewWrapper ); + +private: //member + //the selection could be given by a CID or by a shape + //if m_aSelectedObjectCID is not empty this indicates the selection + //the content of m_xSelectedShape is ignored in that case + //the strings are used for autogenerated chart specific objects + //the shape reference is used for additional shapes + ObjectIdentifier m_aSelectedOID; //only single object selection so far + ObjectIdentifier m_aSelectedOID_beforeMouseDown; + ObjectIdentifier m_aSelectedOID_selectOnlyIfNoDoubleClickIsFollowing; +}; + +class SelectionHelper : public MarkHandleProvider +{ +public: + static bool findNamedParent( SdrObject*& pInOutObject + , rtl::OUString& rOutName + , bool bGivenObjectMayBeResult ); + static bool findNamedParent( SdrObject*& pInOutObject + , ObjectIdentifier& rOutObject + , bool bGivenObjectMayBeResult ); + static SdrObject* getMarkHandlesObject( SdrObject* pObj ); + static E3dScene* getSceneToRotate( SdrObject* pObj ); + static bool isDragableObjectHitTwice( const Point& rMPos + , const rtl::OUString& rNameOfSelectedObject + , const DrawViewWrapper& rDrawViewWrapper ); + + static ::rtl::OUString getHitObjectCID( + const Point& rMPos, + DrawViewWrapper& rDrawViewWrapper, + bool bGetDiagramInsteadOf_Wall=false ); + + static bool isRotateableObject( const ::rtl::OUString& rCID + , const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel >& xChartModel ); + + + SelectionHelper( SdrObject* pSelectedObj ); + virtual ~SelectionHelper(); + + + //MarkHandleProvider: + virtual bool getMarkHandles( SdrHdlList& rHdlList ); + virtual bool getFrameDragSingles(); + + SdrObject* getObjectToMark();//sets also internally the mark object + //-> getMarkHandles will behave different if this method has found a Mark Object different from m_pSelectedObj + +private: + SdrObject* m_pSelectedObj;//hit and logically selected object + SdrObject* m_pMarkObj;//object that is marked instead to have more pretty handles +}; + +//............................................................................. +} //namespace chart +//............................................................................. +#endif diff --git a/chart2/source/controller/main/ShapeController.cxx b/chart2/source/controller/main/ShapeController.cxx new file mode 100644 index 000000000000..b6adf9bf7477 --- /dev/null +++ b/chart2/source/controller/main/ShapeController.cxx @@ -0,0 +1,738 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "ShapeController.hxx" +#include "ShapeController.hrc" +#include "ChartController.hxx" +#include "ChartWindow.hxx" +#include "ViewElementListProvider.hxx" +#include "dlg_ShapeFont.hxx" +#include "dlg_ShapeParagraph.hxx" +#include "chartview/DrawModelWrapper.hxx" +#include "macros.hxx" + +#include <com/sun/star/frame/XStorable.hpp> + +#include <vos/mutex.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/svapp.hxx> +#include <editeng/brkitem.hxx> +#include <svx/dialogs.hrc> +#include <svx/drawitem.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/hyznitem.hxx> +#include <editeng/orphitem.hxx> +#include <editeng/spltitem.hxx> +#include <svx/svxdlg.hxx> +#include <editeng/widwitem.hxx> + +#include <boost/scoped_ptr.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::frame; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +//............................................................................. +namespace chart +{ +//............................................................................. + +ShapeController::ShapeController( const Reference< uno::XComponentContext >& rxContext, + ChartController* pController ) + :FeatureCommandDispatchBase( rxContext ) + ,m_pChartController( pController ) +{ +} + +ShapeController::~ShapeController() +{ +} + +void ShapeController::initialize() +{ + FeatureCommandDispatchBase::initialize(); +} + +// WeakComponentImplHelperBase +void ShapeController::disposing() +{ +} + +// XEventListener +void ShapeController::disposing( const lang::EventObject& /* Source */ ) + throw (uno::RuntimeException) +{ +} + +FeatureState ShapeController::getState( const ::rtl::OUString& rCommand ) +{ + FeatureState aReturn; + aReturn.bEnabled = false; + aReturn.aState <<= false; + + bool bWritable = false; + if ( m_pChartController ) + { + Reference< frame::XStorable > xStorable( m_pChartController->getModel(), uno::UNO_QUERY ); + if ( xStorable.is() ) + { + bWritable = !xStorable->isReadonly(); + } + } + + SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( rCommand ); + if ( aIter != m_aSupportedFeatures.end() ) + { + sal_uInt16 nFeatureId = aIter->second.nFeatureId; + switch ( nFeatureId ) + { + case COMMAND_ID_FORMAT_LINE: + case COMMAND_ID_FORMAT_AREA: + case COMMAND_ID_TEXT_ATTRIBUTES: + case COMMAND_ID_TRANSFORM_DIALOG: + case COMMAND_ID_OBJECT_TITLE_DESCRIPTION: + case COMMAND_ID_RENAME_OBJECT: + { + aReturn.bEnabled = bWritable; + aReturn.aState <<= false; + } + break; + case COMMAND_ID_BRING_TO_FRONT: + case COMMAND_ID_FORWARD: + { + aReturn.bEnabled = ( bWritable && isForwardPossible() ); + aReturn.aState <<= false; + } + break; + case COMMAND_ID_BACKWARD: + case COMMAND_ID_SEND_TO_BACK: + { + + aReturn.bEnabled = ( bWritable && isBackwardPossible() ); + aReturn.aState <<= false; + } + break; + case COMMAND_ID_FONT_DIALOG: + case COMMAND_ID_PARAGRAPH_DIALOG: + { + aReturn.bEnabled = bWritable; + aReturn.aState <<= false; + } + break; + default: + { + aReturn.bEnabled = false; + aReturn.aState <<= false; + } + break; + } + } + + return aReturn; +} + +void ShapeController::execute( const ::rtl::OUString& rCommand, const Sequence< beans::PropertyValue>& rArgs ) +{ + (void)rArgs; + + SupportedFeatures::const_iterator aIter = m_aSupportedFeatures.find( rCommand ); + if ( aIter != m_aSupportedFeatures.end() ) + { + sal_uInt16 nFeatureId = aIter->second.nFeatureId; + switch ( nFeatureId ) + { + case COMMAND_ID_FORMAT_LINE: + { + executeDispatch_FormatLine(); + } + break; + case COMMAND_ID_FORMAT_AREA: + { + executeDispatch_FormatArea(); + } + break; + case COMMAND_ID_TEXT_ATTRIBUTES: + { + executeDispatch_TextAttributes(); + } + break; + case COMMAND_ID_TRANSFORM_DIALOG: + { + executeDispatch_TransformDialog(); + } + break; + case COMMAND_ID_OBJECT_TITLE_DESCRIPTION: + { + executeDispatch_ObjectTitleDescription(); + } + break; + case COMMAND_ID_RENAME_OBJECT: + { + executeDispatch_RenameObject(); + } + break; + case COMMAND_ID_BRING_TO_FRONT: + case COMMAND_ID_FORWARD: + case COMMAND_ID_BACKWARD: + case COMMAND_ID_SEND_TO_BACK: + { + executeDispatch_ChangeZOrder( nFeatureId ); + } + break; + case COMMAND_ID_FONT_DIALOG: + { + executeDispatch_FontDialog(); + } + break; + case COMMAND_ID_PARAGRAPH_DIALOG: + { + executeDispatch_ParagraphDialog(); + } + break; + default: + { + } + break; + } + } +} + +void ShapeController::describeSupportedFeatures() +{ + implDescribeSupportedFeature( ".uno:FormatLine", COMMAND_ID_FORMAT_LINE, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:FormatArea", COMMAND_ID_FORMAT_AREA, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:TextAttributes", COMMAND_ID_TEXT_ATTRIBUTES, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:TransformDialog", COMMAND_ID_TRANSFORM_DIALOG, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:ObjectTitleDescription", COMMAND_ID_OBJECT_TITLE_DESCRIPTION, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:RenameObject", COMMAND_ID_RENAME_OBJECT, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:BringToFront", COMMAND_ID_BRING_TO_FRONT, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:Forward", COMMAND_ID_FORWARD, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:Backward", COMMAND_ID_BACKWARD, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:SendToBack", COMMAND_ID_SEND_TO_BACK, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:FontDialog", COMMAND_ID_FONT_DIALOG, CommandGroup::EDIT ); + implDescribeSupportedFeature( ".uno:ParagraphDialog", COMMAND_ID_PARAGRAPH_DIALOG, CommandGroup::EDIT ); +} + +IMPL_LINK( ShapeController, CheckNameHdl, AbstractSvxNameDialog*, pDialog ) +{ + String aName; + if ( pDialog ) + { + pDialog->GetName( aName ); + } + if ( aName.Len() ) + { + DrawViewWrapper* pDrawViewWrapper = ( m_pChartController ? m_pChartController->GetDrawViewWrapper() : NULL ); + if ( pDrawViewWrapper && pDrawViewWrapper->getNamedSdrObject( aName ) ) + { + return 0; + } + } + return 1; +} + +void ShapeController::executeDispatch_FormatLine() +{ + if ( m_pChartController ) + { + Window* pParent = dynamic_cast< Window* >( m_pChartController->m_pChartWindow ); + DrawModelWrapper* pDrawModelWrapper = m_pChartController->GetDrawModelWrapper(); + DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper(); + if ( pParent && pDrawModelWrapper && pDrawViewWrapper ) + { + SdrObject* pSelectedObj = pDrawViewWrapper->getSelectedObject(); + SfxItemSet aAttr( pDrawViewWrapper->GetDefaultAttr() ); + BOOL bHasMarked = pDrawViewWrapper->AreObjectsMarked(); + if ( bHasMarked ) + { + pDrawViewWrapper->MergeAttrFromMarked( aAttr, FALSE ); + } + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + if ( pFact ) + { + ::boost::scoped_ptr< SfxAbstractTabDialog > pDlg( + pFact->CreateSvxLineTabDialog( pParent, &aAttr, &pDrawModelWrapper->getSdrModel(), + pSelectedObj, bHasMarked ) ); + if ( pDlg.get() && ( pDlg->Execute() == RET_OK ) ) + { + const SfxItemSet* pOutAttr = pDlg->GetOutputItemSet(); + if ( bHasMarked ) + { + pDrawViewWrapper->SetAttrToMarked( *pOutAttr, FALSE ); + } + else + { + pDrawViewWrapper->SetDefaultAttr( *pOutAttr, FALSE ); + } + } + } + } + } +} + +void ShapeController::executeDispatch_FormatArea() +{ + if ( m_pChartController ) + { + Window* pParent = dynamic_cast< Window* >( m_pChartController->m_pChartWindow ); + DrawModelWrapper* pDrawModelWrapper = m_pChartController->GetDrawModelWrapper(); + DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper(); + if ( pParent && pDrawModelWrapper && pDrawViewWrapper ) + { + SfxItemSet aAttr( pDrawViewWrapper->GetDefaultAttr() ); + BOOL bHasMarked = pDrawViewWrapper->AreObjectsMarked(); + if ( bHasMarked ) + { + pDrawViewWrapper->MergeAttrFromMarked( aAttr, FALSE ); + } + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + if ( pFact ) + { + ::boost::scoped_ptr< AbstractSvxAreaTabDialog > pDlg( + pFact->CreateSvxAreaTabDialog( pParent, &aAttr, &pDrawModelWrapper->getSdrModel(), + pDrawViewWrapper ) ); + if ( pDlg.get() ) + { + SfxItemPool& rItemPool = pDrawViewWrapper->GetModel()->GetItemPool(); + SfxItemSet aSet( rItemPool, rItemPool.GetFirstWhich(), rItemPool.GetLastWhich() ); + const SvxColorTableItem* pColorItem = static_cast< const SvxColorTableItem* >( aSet.GetItem( SID_COLOR_TABLE ) ); + if ( pColorItem && pColorItem->GetColorTable() == XColorTable::GetStdColorTable() ) + { + pDlg->DontDeleteColorTable(); + } + if ( pDlg->Execute() == RET_OK ) + { + const SfxItemSet* pOutAttr = pDlg->GetOutputItemSet(); + if ( bHasMarked ) + { + pDrawViewWrapper->SetAttrToMarked( *pOutAttr, FALSE ); + } + else + { + pDrawViewWrapper->SetDefaultAttr( *pOutAttr, FALSE ); + } + } + } + } + } + } +} + +void ShapeController::executeDispatch_TextAttributes() +{ + if ( m_pChartController ) + { + Window* pParent = dynamic_cast< Window* >( m_pChartController->m_pChartWindow ); + DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper(); + if ( pParent && pDrawViewWrapper ) + { + SfxItemSet aAttr( pDrawViewWrapper->GetDefaultAttr() ); + BOOL bHasMarked = pDrawViewWrapper->AreObjectsMarked(); + if ( bHasMarked ) + { + pDrawViewWrapper->MergeAttrFromMarked( aAttr, FALSE ); + } + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + if ( pFact ) + { + ::boost::scoped_ptr< SfxAbstractTabDialog > pDlg( + pFact->CreateTextTabDialog( pParent, &aAttr, pDrawViewWrapper ) ); + if ( pDlg.get() && ( pDlg->Execute() == RET_OK ) ) + { + const SfxItemSet* pOutAttr = pDlg->GetOutputItemSet(); + if ( bHasMarked ) + { + pDrawViewWrapper->SetAttributes( *pOutAttr ); + } + else + { + pDrawViewWrapper->SetDefaultAttr( *pOutAttr, FALSE ); + } + } + } + } + } +} + +void ShapeController::executeDispatch_TransformDialog() +{ + if ( m_pChartController ) + { + Window* pParent = dynamic_cast< Window* >( m_pChartController->m_pChartWindow ); + DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper(); + if ( pParent && pDrawViewWrapper ) + { + SdrObject* pSelectedObj = pDrawViewWrapper->getSelectedObject(); + if ( pSelectedObj && pSelectedObj->GetObjIdentifier() == OBJ_CAPTION ) + { + // item set for caption + SfxItemSet aAttr( pDrawViewWrapper->GetModel()->GetItemPool() ); + pDrawViewWrapper->GetAttributes( aAttr ); + // item set for position and size + SfxItemSet aGeoAttr( pDrawViewWrapper->GetGeoAttrFromMarked() ); + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + if ( pFact ) + { + ::boost::scoped_ptr< SfxAbstractTabDialog > pDlg( + pFact->CreateCaptionDialog( pParent, pDrawViewWrapper ) ); + if ( pDlg.get() ) + { + const USHORT* pRange = pDlg->GetInputRanges( *aAttr.GetPool() ); + SfxItemSet aCombAttr( *aAttr.GetPool(), pRange ); + aCombAttr.Put( aAttr ); + aCombAttr.Put( aGeoAttr ); + pDlg->SetInputSet( &aCombAttr ); + if ( pDlg->Execute() == RET_OK ) + { + const SfxItemSet* pOutAttr = pDlg->GetOutputItemSet(); + pDrawViewWrapper->SetAttributes( *pOutAttr ); + pDrawViewWrapper->SetGeoAttrToMarked( *pOutAttr ); + } + } + } + } + else + { + SfxItemSet aGeoAttr( pDrawViewWrapper->GetGeoAttrFromMarked() ); + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + if ( pFact ) + { + ::boost::scoped_ptr< SfxAbstractTabDialog > pDlg( + pFact->CreateSvxTransformTabDialog( pParent, &aGeoAttr, pDrawViewWrapper ) ); + if ( pDlg.get() && ( pDlg->Execute() == RET_OK ) ) + { + const SfxItemSet* pOutAttr = pDlg->GetOutputItemSet(); + pDrawViewWrapper->SetGeoAttrToMarked( *pOutAttr ); + } + } + } + } + } +} + +void ShapeController::executeDispatch_ObjectTitleDescription() +{ + if ( m_pChartController ) + { + DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper(); + if ( pDrawViewWrapper && pDrawViewWrapper->GetMarkedObjectCount() == 1 ) + { + SdrObject* pSelectedObj = pDrawViewWrapper->getSelectedObject(); + if ( pSelectedObj ) + { + String aTitle( pSelectedObj->GetTitle() ); + String aDescription( pSelectedObj->GetDescription() ); + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + if ( pFact ) + { + ::boost::scoped_ptr< AbstractSvxObjectTitleDescDialog > pDlg( + pFact->CreateSvxObjectTitleDescDialog( NULL, aTitle, aDescription ) ); + if ( pDlg.get() && ( pDlg->Execute() == RET_OK ) ) + { + pDlg->GetTitle( aTitle ); + pDlg->GetDescription( aDescription ); + pSelectedObj->SetTitle( aTitle ); + pSelectedObj->SetDescription( aDescription ); + } + } + } + } + } +} + +void ShapeController::executeDispatch_RenameObject() +{ + if ( m_pChartController ) + { + DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper(); + if ( pDrawViewWrapper && pDrawViewWrapper->GetMarkedObjectCount() == 1 ) + { + SdrObject* pSelectedObj = pDrawViewWrapper->getSelectedObject(); + if ( pSelectedObj ) + { + String aName( pSelectedObj->GetName() ); + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + if ( pFact ) + { + ::boost::scoped_ptr< AbstractSvxObjectNameDialog > pDlg( + pFact->CreateSvxObjectNameDialog( NULL, aName ) ); + pDlg->SetCheckNameHdl( LINK( this, ShapeController, CheckNameHdl ) ); + if ( pDlg.get() && ( pDlg->Execute() == RET_OK ) ) + { + pDlg->GetName( aName ); + if ( aName != pSelectedObj->GetName() ) + { + pSelectedObj->SetName( aName ); + } + } + } + } + } + } +} + +void ShapeController::executeDispatch_ChangeZOrder( sal_uInt16 nId ) +{ + DrawViewWrapper* pDrawViewWrapper = ( m_pChartController ? m_pChartController->GetDrawViewWrapper() : NULL ); + if ( pDrawViewWrapper ) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + switch ( nId ) + { + case COMMAND_ID_BRING_TO_FRONT: + { + if ( isForwardPossible() ) + { + pDrawViewWrapper->PutMarkedToTop(); + } + } + break; + case COMMAND_ID_FORWARD: + { + if ( isForwardPossible() ) + { + pDrawViewWrapper->MovMarkedToTop(); + } + } + break; + case COMMAND_ID_BACKWARD: + { + if ( isBackwardPossible() ) + { + pDrawViewWrapper->MovMarkedToBtm(); + } + } + break; + case COMMAND_ID_SEND_TO_BACK: + { + if ( isBackwardPossible() ) + { + SdrObject* pFirstObj = getFirstAdditionalShape(); + pDrawViewWrapper->PutMarkedBehindObj( pFirstObj ); + } + } + break; + default: + { + } + break; + } + } +} + +void ShapeController::executeDispatch_FontDialog() +{ + if ( m_pChartController ) + { + Window* pParent = dynamic_cast< Window* >( m_pChartController->m_pChartWindow ); + DrawModelWrapper* pDrawModelWrapper = m_pChartController->GetDrawModelWrapper(); + DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper(); + if ( pParent && pDrawModelWrapper && pDrawViewWrapper ) + { + SfxItemSet aAttr( pDrawViewWrapper->GetModel()->GetItemPool() ); + pDrawViewWrapper->GetAttributes( aAttr ); + ViewElementListProvider aViewElementListProvider( pDrawModelWrapper ); + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + ::boost::scoped_ptr< ShapeFontDialog > pDlg( new ShapeFontDialog( pParent, &aAttr, &aViewElementListProvider ) ); + if ( pDlg.get() && ( pDlg->Execute() == RET_OK ) ) + { + const SfxItemSet* pOutAttr = pDlg->GetOutputItemSet(); + pDrawViewWrapper->SetAttributes( *pOutAttr ); + } + } + } +} + +void ShapeController::executeDispatch_ParagraphDialog() +{ + if ( m_pChartController ) + { + Window* pParent = dynamic_cast< Window* >( m_pChartController->m_pChartWindow ); + DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper(); + if ( pParent && pDrawViewWrapper ) + { + SfxItemPool& rPool = pDrawViewWrapper->GetModel()->GetItemPool(); + SfxItemSet aAttr( rPool ); + pDrawViewWrapper->GetAttributes( aAttr ); + + SfxItemSet aNewAttr( rPool, + EE_ITEMS_START, EE_ITEMS_END, + SID_ATTR_PARA_HYPHENZONE, SID_ATTR_PARA_HYPHENZONE, + SID_ATTR_PARA_PAGEBREAK, SID_ATTR_PARA_PAGEBREAK, + SID_ATTR_PARA_SPLIT, SID_ATTR_PARA_SPLIT, + SID_ATTR_PARA_WIDOWS, SID_ATTR_PARA_WIDOWS, + SID_ATTR_PARA_ORPHANS, SID_ATTR_PARA_ORPHANS, + 0 ); + aNewAttr.Put( aAttr ); + aNewAttr.Put( SvxHyphenZoneItem( sal_False, SID_ATTR_PARA_HYPHENZONE ) ); + aNewAttr.Put( SvxFmtBreakItem( SVX_BREAK_NONE, SID_ATTR_PARA_PAGEBREAK ) ); + aNewAttr.Put( SvxFmtSplitItem( sal_True, SID_ATTR_PARA_SPLIT) ); + aNewAttr.Put( SvxWidowsItem( 0, SID_ATTR_PARA_WIDOWS) ); + aNewAttr.Put( SvxOrphansItem( 0, SID_ATTR_PARA_ORPHANS) ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + ::boost::scoped_ptr< ShapeParagraphDialog > pDlg( new ShapeParagraphDialog( pParent, &aNewAttr ) ); + if ( pDlg.get() && ( pDlg->Execute() == RET_OK ) ) + { + const SfxItemSet* pOutAttr = pDlg->GetOutputItemSet(); + pDrawViewWrapper->SetAttributes( *pOutAttr ); + } + } + } +} + +SdrObject* ShapeController::getFirstAdditionalShape() +{ + SdrObject* pFirstObj = NULL; + + try + { + DrawModelWrapper* pDrawModelWrapper = ( m_pChartController ? m_pChartController->GetDrawModelWrapper() : NULL ); + if ( pDrawModelWrapper ) + { + Reference< drawing::XShape > xFirstShape; + Reference< drawing::XDrawPage > xDrawPage( pDrawModelWrapper->getMainDrawPage() ); + Reference< drawing::XShapes > xDrawPageShapes( xDrawPage, uno::UNO_QUERY_THROW ); + Reference< drawing::XShapes > xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) ); + sal_Int32 nCount = xDrawPageShapes->getCount(); + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + Reference< drawing::XShape > xShape; + if ( xDrawPageShapes->getByIndex( i ) >>= xShape ) + { + if ( xShape.is() && xShape != xChartRoot ) + { + xFirstShape = xShape; + break; + } + } + } + if ( xFirstShape.is() ) + { + pFirstObj = DrawViewWrapper::getSdrObject( xFirstShape ); + } + } + } + catch ( uno::Exception& ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return pFirstObj; +} + +SdrObject* ShapeController::getLastAdditionalShape() +{ + SdrObject* pLastObj = NULL; + + try + { + DrawModelWrapper* pDrawModelWrapper = ( m_pChartController ? m_pChartController->GetDrawModelWrapper() : NULL ); + if ( pDrawModelWrapper ) + { + Reference< drawing::XShape > xLastShape; + Reference< drawing::XDrawPage > xDrawPage( pDrawModelWrapper->getMainDrawPage() ); + Reference< drawing::XShapes > xDrawPageShapes( xDrawPage, uno::UNO_QUERY_THROW ); + Reference< drawing::XShapes > xChartRoot( DrawModelWrapper::getChartRootShape( xDrawPage ) ); + sal_Int32 nCount = xDrawPageShapes->getCount(); + for ( sal_Int32 i = nCount - 1; i >= 0; --i ) + { + Reference< drawing::XShape > xShape; + if ( xDrawPageShapes->getByIndex( i ) >>= xShape ) + { + if ( xShape.is() && xShape != xChartRoot ) + { + xLastShape = xShape; + break; + } + } + } + if ( xLastShape.is() ) + { + pLastObj = DrawViewWrapper::getSdrObject( xLastShape ); + } + } + } + catch ( uno::Exception& ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return pLastObj; +} + +bool ShapeController::isBackwardPossible() +{ + if ( m_pChartController && m_pChartController->m_aSelection.isAdditionalShapeSelected() ) + { + DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper(); + if ( pDrawViewWrapper ) + { + SdrObject* pSelectedObj = pDrawViewWrapper->getSelectedObject(); + SdrObject* pFirstObj = getFirstAdditionalShape(); + if ( pSelectedObj && pFirstObj && pSelectedObj != pFirstObj ) + { + return true; + } + } + } + return false; +} + +bool ShapeController::isForwardPossible() +{ + if ( m_pChartController && m_pChartController->m_aSelection.isAdditionalShapeSelected() ) + { + DrawViewWrapper* pDrawViewWrapper = m_pChartController->GetDrawViewWrapper(); + if ( pDrawViewWrapper ) + { + SdrObject* pSelectedObj = pDrawViewWrapper->getSelectedObject(); + SdrObject* pLastObj = getLastAdditionalShape(); + if ( pSelectedObj && pLastObj && pSelectedObj != pLastObj ) + { + return true; + } + } + } + return false; +} + +//............................................................................. +} // namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/ShapeController.hxx b/chart2/source/controller/main/ShapeController.hxx new file mode 100644 index 000000000000..aea01d6c478d --- /dev/null +++ b/chart2/source/controller/main/ShapeController.hxx @@ -0,0 +1,100 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_SHAPECONTROLLER_HXX +#define CHART2_SHAPECONTROLLER_HXX + +#include "FeatureCommandDispatchBase.hxx" +#include <tools/link.hxx> + +class AbstractSvxNameDialog; +class SdrObject; + +//............................................................................. +namespace chart +{ +//............................................................................. + +class ChartController; + +/** This is a CommandDispatch implementation for shapes. + */ +class ShapeController: public FeatureCommandDispatchBase +{ + friend class ControllerCommandDispatch; + +public: + ShapeController( const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext >& rxContext, ChartController* pController ); + virtual ~ShapeController(); + + // late initialisation, especially for adding as listener + virtual void initialize(); + +protected: + // WeakComponentImplHelperBase + virtual void SAL_CALL disposing(); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) + throw (::com::sun::star::uno::RuntimeException); + + // state of a feature + virtual FeatureState getState( const ::rtl::OUString& rCommand ); + + // execute a feature + virtual void execute( const ::rtl::OUString& rCommand, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue>& rArgs ); + + // all the features which should be handled by this class + virtual void describeSupportedFeatures(); + +private: + DECL_LINK( CheckNameHdl, AbstractSvxNameDialog* ); + + void executeDispatch_FormatLine(); + void executeDispatch_FormatArea(); + void executeDispatch_TextAttributes(); + void executeDispatch_TransformDialog(); + void executeDispatch_ObjectTitleDescription(); + void executeDispatch_RenameObject(); + void executeDispatch_ChangeZOrder( sal_uInt16 nId ); + void executeDispatch_FontDialog(); + void executeDispatch_ParagraphDialog(); + + SdrObject* getFirstAdditionalShape(); + SdrObject* getLastAdditionalShape(); + bool isBackwardPossible(); + bool isForwardPossible(); + + ChartController* m_pChartController; +}; + +//............................................................................. +} // namespace chart +//............................................................................. + +// CHART2_SHAPECONTROLLER_HXX +#endif diff --git a/chart2/source/controller/main/ShapeToolbarController.cxx b/chart2/source/controller/main/ShapeToolbarController.cxx new file mode 100644 index 000000000000..9c6ed747e1d5 --- /dev/null +++ b/chart2/source/controller/main/ShapeToolbarController.cxx @@ -0,0 +1,298 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "ShapeToolbarController.hxx" + +#include <vos/mutex.hxx> +#include <comphelper/sequence.hxx> +#include <vcl/svapp.hxx> +#include <vcl/toolbox.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <svx/svxids.hrc> +#include <svx/tbxcustomshapes.hxx> + + +using namespace com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +//............................................................................. +namespace chart +{ +//............................................................................. + +::rtl::OUString ShapeToolbarController::getImplementationName() throw (uno::RuntimeException) +{ + return getImplementationName_Static(); +} + +::rtl::OUString ShapeToolbarController::getImplementationName_Static() throw (uno::RuntimeException) +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.ShapeToolbarController" ) ); +} + +Sequence< ::rtl::OUString > ShapeToolbarController::getSupportedServiceNames_Static() throw (uno::RuntimeException) +{ + Sequence< ::rtl::OUString > aSupported(1); + aSupported.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.ShapeToolbarController" ) ); + return aSupported; +} + +::sal_Bool ShapeToolbarController::supportsService( const ::rtl::OUString& ServiceName ) throw (uno::RuntimeException) +{ + return ::comphelper::existsValue( ServiceName, getSupportedServiceNames_Static() ); +} + +Sequence< ::rtl::OUString> ShapeToolbarController::getSupportedServiceNames() throw (uno::RuntimeException) +{ + return getSupportedServiceNames_Static(); +} + +Reference< uno::XInterface > ShapeToolbarController::create( const Reference< uno::XComponentContext >& xContext ) +{ + return *( new ShapeToolbarController( Reference< lang::XMultiServiceFactory >( xContext->getServiceManager(), uno::UNO_QUERY ) ) ); +} + +ShapeToolbarController::ShapeToolbarController( const Reference< lang::XMultiServiceFactory >& rxFact ) + :m_pToolbarController( NULL ) + ,m_nToolBoxId( 1 ) + ,m_nSlotId( 0 ) +{ + osl_incrementInterlockedCount( &m_refCount ); + m_xServiceManager = rxFact; + osl_decrementInterlockedCount( &m_refCount ); +} + +ShapeToolbarController::~ShapeToolbarController() +{ +} + +// ::com::sun::star::uno::XInterface +uno::Any ShapeToolbarController::queryInterface( const uno::Type& rType ) throw (uno::RuntimeException) +{ + uno::Any aReturn = ToolboxController::queryInterface( rType ); + if ( !aReturn.hasValue() ) + { + aReturn = ShapeToolbarController_Base::queryInterface( rType ); + } + return aReturn; +} + +void ShapeToolbarController::acquire() throw () +{ + ToolboxController::acquire(); +} + +void ShapeToolbarController::release() throw () +{ + ToolboxController::release(); +} + +// ::com::sun::star::lang::XInitialization +void ShapeToolbarController::initialize( const Sequence< uno::Any >& rArguments ) throw (uno::Exception, uno::RuntimeException) +{ + ToolboxController::initialize( rArguments ); + ::vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + ToolBox* pToolBox = static_cast< ToolBox* >( VCLUnoHelper::GetWindow( getParent() ) ); + if ( pToolBox ) + { + const USHORT nCount = pToolBox->GetItemCount(); + for ( USHORT nPos = 0; nPos < nCount; ++nPos ) + { + const USHORT nItemId = pToolBox->GetItemId( nPos ); + if ( pToolBox->GetItemCommand( nItemId ) == String( m_aCommandURL ) ) + { + m_nToolBoxId = nItemId; + break; + } + } + if ( m_aCommandURL.equalsAscii( ".uno:BasicShapes" ) ) + { + m_aStates.insert( TCommandState::value_type( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:BasicShapes" ) ), sal_True ) ); + m_nSlotId = SID_DRAWTBX_CS_BASIC; + m_pToolbarController = TToolbarHelper::createFromQuery( new SvxTbxCtlCustomShapes( m_nSlotId, m_nToolBoxId, *pToolBox ) ); + } + else if ( m_aCommandURL.equalsAscii( ".uno:SymbolShapes" ) ) + { + m_aStates.insert( TCommandState::value_type( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:SymbolShapes" ) ), sal_True ) ); + m_nSlotId = SID_DRAWTBX_CS_SYMBOL; + m_pToolbarController = TToolbarHelper::createFromQuery( new SvxTbxCtlCustomShapes( m_nSlotId, m_nToolBoxId, *pToolBox ) ); + } + else if ( m_aCommandURL.equalsAscii( ".uno:ArrowShapes" ) ) + { + m_aStates.insert( TCommandState::value_type( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:ArrowShapes" ) ), sal_True ) ); + m_nSlotId = SID_DRAWTBX_CS_ARROW; + m_pToolbarController = TToolbarHelper::createFromQuery( new SvxTbxCtlCustomShapes( m_nSlotId, m_nToolBoxId, *pToolBox) ); + } + else if ( m_aCommandURL.equalsAscii( ".uno:FlowChartShapes" ) ) + { + m_aStates.insert( TCommandState::value_type( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:FlowChartShapes" ) ), sal_True ) ); + m_nSlotId = SID_DRAWTBX_CS_FLOWCHART; + m_pToolbarController = TToolbarHelper::createFromQuery( new SvxTbxCtlCustomShapes( m_nSlotId, m_nToolBoxId, *pToolBox ) ); + } + else if ( m_aCommandURL.equalsAscii( ".uno:CalloutShapes" ) ) + { + m_aStates.insert( TCommandState::value_type( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:CalloutShapes" ) ), sal_True ) ); + m_nSlotId = SID_DRAWTBX_CS_CALLOUT; + m_pToolbarController = TToolbarHelper::createFromQuery( new SvxTbxCtlCustomShapes( m_nSlotId, m_nToolBoxId, *pToolBox ) ); + } + else if ( m_aCommandURL.equalsAscii( ".uno:StarShapes" ) ) + { + m_aStates.insert( TCommandState::value_type( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:StarShapes" ) ), sal_True ) ); + m_nSlotId = SID_DRAWTBX_CS_STAR; + m_pToolbarController = TToolbarHelper::createFromQuery( new SvxTbxCtlCustomShapes( m_nSlotId, m_nToolBoxId, *pToolBox ) ); + } + + for ( TCommandState::iterator aIter( m_aStates.begin() ); aIter != m_aStates.end(); ++aIter ) + { + addStatusListener( aIter->first ); + } + + if ( m_pToolbarController.is() ) + { + m_pToolbarController->initialize( rArguments ); + } + + // check if paste special is allowed, when not don't add DROPDOWN + pToolBox->SetItemBits( m_nToolBoxId, pToolBox->GetItemBits( m_nToolBoxId ) | TIB_DROPDOWN ); + } +} + +// ::com::sun::star::frame::XStatusListener +void ShapeToolbarController::statusChanged( const frame::FeatureStateEvent& Event ) throw ( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + TCommandState::iterator aFind = m_aStates.find( Event.FeatureURL.Complete ); + if ( aFind != m_aStates.end() ) + { + aFind->second = Event.IsEnabled; + if ( m_pToolbarController.is() ) + { + sal_Bool bCheckmark = sal_False; + ToolBox& rTb = m_pToolbarController->GetToolBox(); + + for ( USHORT i = 0; i < rTb.GetItemCount(); ++i ) + { + USHORT nId = rTb.GetItemId( i ); + if ( nId == 0 ) + { + continue; + } + ::rtl::OUString aCmd = rTb.GetItemCommand( nId ); + if ( aCmd == Event.FeatureURL.Complete ) + { + rTb.EnableItem( nId, Event.IsEnabled ); + if ( Event.State >>= bCheckmark ) + { + rTb.CheckItem( nId, bCheckmark ); + } + else + { + ::rtl::OUString aItemText; + if ( Event.State >>= aItemText ) + { + rTb.SetItemText( nId, aItemText ); + } + } + } + } + } + } +} + +// ::com::sun::star::frame::XToolbarController +Reference< awt::XWindow > ShapeToolbarController::createPopupWindow() throw (uno::RuntimeException) +{ + ::vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + Reference< awt::XWindow > xRet; + if ( m_pToolbarController.is() ) + { + xRet = m_pToolbarController.getRef()->createPopupWindow(); + } + + return xRet; +} + +// ::com::sun::star::frame::XSubToolbarController +::sal_Bool ShapeToolbarController::opensSubToolbar() throw (uno::RuntimeException) +{ + return ( m_nSlotId == SID_DRAWTBX_CS_BASIC || + m_nSlotId == SID_DRAWTBX_CS_SYMBOL || + m_nSlotId == SID_DRAWTBX_CS_ARROW || + m_nSlotId == SID_DRAWTBX_CS_FLOWCHART || + m_nSlotId == SID_DRAWTBX_CS_CALLOUT || + m_nSlotId == SID_DRAWTBX_CS_STAR ); +} + +::rtl::OUString ShapeToolbarController::getSubToolbarName() throw (uno::RuntimeException) +{ + ::vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard(m_aMutex); + uno::Reference< frame::XSubToolbarController > xSub( m_pToolbarController.getRef(), uno::UNO_QUERY ); + if ( xSub.is() ) + { + return xSub->getSubToolbarName(); + } + return ::rtl::OUString(); +} + +void ShapeToolbarController::functionSelected( const ::rtl::OUString& rCommand ) throw (uno::RuntimeException) +{ + ::vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + uno::Reference< frame::XSubToolbarController > xSub( m_pToolbarController.getRef(), uno::UNO_QUERY ); + if ( xSub.is() ) + { + m_aCommandURL = rCommand; + xSub->functionSelected( rCommand ); + } +} + +void ShapeToolbarController::updateImage() throw (uno::RuntimeException) +{ + ::vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + uno::Reference< frame::XSubToolbarController > xSub( m_pToolbarController.getRef(), uno::UNO_QUERY ); + if ( xSub.is() ) + { + xSub->updateImage(); + } +} + +//............................................................................. +} // namespace chart +//............................................................................. diff --git a/chart2/source/controller/main/ShapeToolbarController.hxx b/chart2/source/controller/main/ShapeToolbarController.hxx new file mode 100644 index 000000000000..544cac7f9831 --- /dev/null +++ b/chart2/source/controller/main/ShapeToolbarController.hxx @@ -0,0 +1,103 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_SHAPETOOLBARCONTROLLER_HXX +#define CHART2_SHAPETOOLBARCONTROLLER_HXX + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/frame/XSubToolbarController.hpp> + +#include <cppuhelper/implbase2.hxx> +#include <comphelper/implementationreference.hxx> +#include <comphelper/stl_types.hxx> +#include <svtools/toolboxcontroller.hxx> + +class SfxToolBoxControl; + +//............................................................................. +namespace chart +{ +//............................................................................. + +typedef ::cppu::ImplHelper2 < ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::frame::XSubToolbarController> ShapeToolbarController_Base; + +typedef ::comphelper::ImplementationReference< SfxToolBoxControl, ::com::sun::star::frame::XToolbarController > TToolbarHelper; + +class ShapeToolbarController : public ::svt::ToolboxController + ,public ShapeToolbarController_Base +{ + DECLARE_STL_USTRINGACCESS_MAP( sal_Bool, TCommandState ); + TCommandState m_aStates; + TToolbarHelper m_pToolbarController; + sal_uInt16 m_nToolBoxId; + sal_uInt16 m_nSlotId; + ShapeToolbarController( const ShapeToolbarController& ); + void operator =( const ShapeToolbarController& ); + +public: + ShapeToolbarController( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFact ); + virtual ~ShapeToolbarController(); + + // ::com::sun::star::uno::XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type& rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw (); + virtual void SAL_CALL release() throw (); + + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // needed by registration + static ::rtl::OUString getImplementationName_Static() throw( ::com::sun::star::uno::RuntimeException ); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static(void) throw(::com::sun::star::uno::RuntimeException); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL + create( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& xContext ); + virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::frame::XStatusListener + virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::frame::XToolbarController + virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL createPopupWindow() throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::frame::XSubToolbarController + virtual ::sal_Bool SAL_CALL opensSubToolbar() throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getSubToolbarName() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL functionSelected( const ::rtl::OUString& aCommand ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateImage() throw (::com::sun::star::uno::RuntimeException); +}; + +//............................................................................. +} // namespace chart +//............................................................................. + +#endif //CHART2_SHAPETOOLBARCONTROLLER_HXX + diff --git a/chart2/source/controller/main/StatusBarCommandDispatch.cxx b/chart2/source/controller/main/StatusBarCommandDispatch.cxx new file mode 100644 index 000000000000..d80d37eff7da --- /dev/null +++ b/chart2/source/controller/main/StatusBarCommandDispatch.cxx @@ -0,0 +1,156 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "StatusBarCommandDispatch.hxx" +#include "ObjectNameProvider.hxx" +#include "macros.hxx" +#include <com/sun/star/util/XModifyBroadcaster.hpp> + +// #ifndef _VOS_MUTEX_HXX_ +// #include <vos/mutex.hxx> +// #endif +// #ifndef _SV_SVAPP_HXX +// #include <vcl/svapp.hxx> +// #endif + +// for ressource strings STR_UNDO and STR_REDO +#include <sfx2/sfx.hrc> + +#include "ResId.hxx" + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace chart +{ + +StatusBarCommandDispatch::StatusBarCommandDispatch( + const Reference< uno::XComponentContext > & xContext, + const Reference< frame::XModel > & xModel, + const Reference< view::XSelectionSupplier > & xSelSupp ) : + impl::StatusBarCommandDispatch_Base( xContext ), + m_xModifiable( xModel, uno::UNO_QUERY ), + m_xSelectionSupplier( xSelSupp ), + m_bIsModified( false ) +{} + +StatusBarCommandDispatch::~StatusBarCommandDispatch() +{} + +void StatusBarCommandDispatch::initialize() +{ + if( m_xModifiable.is()) + { + Reference< util::XModifyBroadcaster > xModifyBroadcaster( m_xModifiable, uno::UNO_QUERY ); + OSL_ASSERT( xModifyBroadcaster.is()); + if( xModifyBroadcaster.is()) + xModifyBroadcaster->addModifyListener( this ); + } + + if( m_xSelectionSupplier.is()) + { + m_xSelectionSupplier->addSelectionChangeListener( this ); + } +} + +void StatusBarCommandDispatch::fireStatusEvent( + const OUString & rURL, + const Reference< frame::XStatusListener > & xSingleListener /* = 0 */ ) +{ + bool bFireAll(rURL.getLength() == 0); + bool bFireContext( bFireAll || rURL.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(".uno:Context"))); + bool bFireModified( bFireAll || rURL.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(".uno:ModifiedStatus"))); + + if( bFireContext ) + { + uno::Any aArg; + Reference< chart2::XChartDocument > xDoc( m_xModifiable, uno::UNO_QUERY ); + aArg <<= ObjectNameProvider::getSelectedObjectText( m_aSelectedOID.getObjectCID(), xDoc ); + fireStatusEventForURL( C2U(".uno:Context"), aArg, true, xSingleListener ); + } + if( bFireModified ) + { + uno::Any aArg; + if( m_bIsModified ) + aArg <<= C2U("*"); + fireStatusEventForURL( C2U(".uno:ModifiedStatus"), aArg, true, xSingleListener ); + } +} + +// ____ XDispatch ____ +void SAL_CALL StatusBarCommandDispatch::dispatch( + const util::URL& /* URL */, + const Sequence< beans::PropertyValue >& /* Arguments */ ) + throw (uno::RuntimeException) +{ + // nothing to do here +} + +// ____ WeakComponentImplHelperBase ____ +/// is called when this is disposed +void SAL_CALL StatusBarCommandDispatch::disposing() +{ + m_xModifiable.clear(); + m_xSelectionSupplier.clear(); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL StatusBarCommandDispatch::disposing( const lang::EventObject& /* Source */ ) + throw (uno::RuntimeException) +{ + m_xModifiable.clear(); + m_xSelectionSupplier.clear(); +} + +// ____ XModifyListener ____ +void SAL_CALL StatusBarCommandDispatch::modified( const lang::EventObject& aEvent ) + throw (uno::RuntimeException) +{ + if( m_xModifiable.is()) + m_bIsModified = m_xModifiable->isModified(); + + CommandDispatch::modified( aEvent ); +} + +// ____ XSelectionChangeListener ____ +void SAL_CALL StatusBarCommandDispatch::selectionChanged( const lang::EventObject& /* aEvent */ ) + throw (uno::RuntimeException) +{ + if( m_xSelectionSupplier.is()) + m_aSelectedOID = ObjectIdentifier( m_xSelectionSupplier->getSelection() ); + else + m_aSelectedOID = ObjectIdentifier(); + fireAllStatusEvents( 0 ); +} + +} // namespace chart diff --git a/chart2/source/controller/main/StatusBarCommandDispatch.hxx b/chart2/source/controller/main/StatusBarCommandDispatch.hxx new file mode 100644 index 000000000000..c84f81f83258 --- /dev/null +++ b/chart2/source/controller/main/StatusBarCommandDispatch.hxx @@ -0,0 +1,110 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_STATUSBARCOMMANDDISPATCH_HXX +#define CHART2_STATUSBARCOMMANDDISPATCH_HXX + +#include "CommandDispatch.hxx" +#include "ObjectIdentifier.hxx" +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <com/sun/star/util/XModifiable.hpp> + +namespace chart +{ + +/** This is a CommandDispatch implementation for all commands the status bar offers + + This class reads the information needed from the XModel passed here. + */ + +namespace impl +{ +typedef ::cppu::ImplInheritanceHelper1< + CommandDispatch, + ::com::sun::star::view::XSelectionChangeListener > + StatusBarCommandDispatch_Base; +} + +class StatusBarCommandDispatch : public impl::StatusBarCommandDispatch_Base +{ +public: + explicit StatusBarCommandDispatch( + const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > & xContext, + const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel, + const ::com::sun::star::uno::Reference< + ::com::sun::star::view::XSelectionSupplier > & xSelSupp ); + virtual ~StatusBarCommandDispatch(); + + // late initialisation, especially for adding as listener + virtual void initialize(); + +protected: + // ____ XDispatch ____ + virtual void SAL_CALL dispatch( + const ::com::sun::star::util::URL& URL, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& Arguments ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ WeakComponentImplHelperBase ____ + /// is called when this is disposed + virtual void SAL_CALL disposing(); + + // ____ XModifyListener (override from CommandDispatch) ____ + virtual void SAL_CALL modified( + const ::com::sun::star::lang::EventObject& aEvent ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ XEventListener (base of XModifyListener) ____ + virtual void SAL_CALL disposing( + const ::com::sun::star::lang::EventObject& Source ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void fireStatusEvent( + const ::rtl::OUString & rURL, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & xSingleListener ); + + // ____ XSelectionChangeListener ____ + virtual void SAL_CALL selectionChanged( + const ::com::sun::star::lang::EventObject& aEvent ) + throw (::com::sun::star::uno::RuntimeException); + +private: + ::com::sun::star::uno::Reference< + ::com::sun::star::util::XModifiable > m_xModifiable; + ::com::sun::star::uno::Reference< + ::com::sun::star::view::XSelectionSupplier > m_xSelectionSupplier; + bool m_bIsModified; + ObjectIdentifier m_aSelectedOID; +}; + +} // namespace chart + +// CHART2_STATUSBARCOMMANDDISPATCH_HXX +#endif diff --git a/chart2/source/controller/main/UndoCommandDispatch.cxx b/chart2/source/controller/main/UndoCommandDispatch.cxx new file mode 100644 index 000000000000..eb3d00a2723a --- /dev/null +++ b/chart2/source/controller/main/UndoCommandDispatch.cxx @@ -0,0 +1,147 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "UndoCommandDispatch.hxx" +#include "macros.hxx" + +#include <com/sun/star/chart2/XUndoSupplier.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> + +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> + +// for ressource strings STR_UNDO and STR_REDO +#include <sfx2/sfx.hrc> + +#include "ResId.hxx" + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace chart +{ + +UndoCommandDispatch::UndoCommandDispatch( + const Reference< uno::XComponentContext > & xContext, + const Reference< frame::XModel > & xModel ) : + CommandDispatch( xContext ), + m_xModel( xModel ) +{ + Reference< chart2::XUndoSupplier > xUndoSupplier( xModel, uno::UNO_QUERY ); + OSL_ASSERT( xUndoSupplier.is()); + if( xUndoSupplier.is()) + m_xUndoManager.set( xUndoSupplier->getUndoManager()); +} + +UndoCommandDispatch::~UndoCommandDispatch() +{} + +void UndoCommandDispatch::initialize() +{ + Reference< util::XModifyBroadcaster > xBroadcaster( m_xUndoManager, uno::UNO_QUERY ); + if( xBroadcaster.is() ) + { + xBroadcaster->addModifyListener( this ); + } +} + +void UndoCommandDispatch::fireStatusEvent( + const OUString & rURL, + const Reference< frame::XStatusListener > & xSingleListener /* = 0 */ ) +{ + if( m_xUndoManager.is() ) + { + bool bFireAll = (rURL.getLength() == 0); + uno::Any aUndoState, aRedoState; + if( m_xUndoManager->undoPossible()) + { + // using assignment for broken gcc 3.3 + OUString aUndo = OUString( String( SchResId( STR_UNDO ))); + aUndoState <<= ( aUndo + m_xUndoManager->getCurrentUndoString()); + } + if( m_xUndoManager->redoPossible()) + { + // using assignment for broken gcc 3.3 + OUString aRedo = OUString( String( SchResId( STR_REDO ))); + aRedoState <<= ( aRedo + m_xUndoManager->getCurrentRedoString()); + } + + if( bFireAll || rURL.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(".uno:Undo"))) + fireStatusEventForURL( C2U(".uno:Undo"), aUndoState, m_xUndoManager->undoPossible(), xSingleListener ); + if( bFireAll || rURL.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(".uno:Redo"))) + fireStatusEventForURL( C2U(".uno:Redo"), aRedoState, m_xUndoManager->redoPossible(), xSingleListener ); + } +} + +// ____ XDispatch ____ +void SAL_CALL UndoCommandDispatch::dispatch( + const util::URL& URL, + const Sequence< beans::PropertyValue >& /* Arguments */ ) + throw (uno::RuntimeException) +{ + if( m_xUndoManager.is() ) + { + // why is it necessary to lock the solar mutex here? + // /-- + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + if( URL.Path.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Undo" ))) + m_xUndoManager->undo( m_xModel ); + else + m_xUndoManager->redo( m_xModel ); + // \-- + } +} + +// ____ WeakComponentImplHelperBase ____ +/// is called when this is disposed +void SAL_CALL UndoCommandDispatch::disposing() +{ + Reference< util::XModifyBroadcaster > xBroadcaster( m_xUndoManager, uno::UNO_QUERY ); + if( xBroadcaster.is() ) + { + xBroadcaster->removeModifyListener( this ); + } + + m_xUndoManager.clear(); + m_xModel.clear(); +} + +// ____ XEventListener (base of XModifyListener) ____ +void SAL_CALL UndoCommandDispatch::disposing( const lang::EventObject& /* Source */ ) + throw (uno::RuntimeException) +{ + m_xUndoManager.clear(); + m_xModel.clear(); +} + +} // namespace chart diff --git a/chart2/source/controller/main/UndoCommandDispatch.hxx b/chart2/source/controller/main/UndoCommandDispatch.hxx new file mode 100644 index 000000000000..28fb813f63de --- /dev/null +++ b/chart2/source/controller/main/UndoCommandDispatch.hxx @@ -0,0 +1,86 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef CHART2_UNDOCOMMANDDISPATCH_HXX +#define CHART2_UNDOCOMMANDDISPATCH_HXX + +#include "CommandDispatch.hxx" + +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/chart2/XUndoManager.hpp> + +namespace chart +{ + +/** This is a CommandDispatch implementation for Undo and Redo. + + You need to pass an UndoManager to this class that is then used for Undo and + Redo. The changes are applied to the given XModel. + */ +class UndoCommandDispatch : public CommandDispatch +{ +public: + explicit UndoCommandDispatch( + const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > & xContext, + const ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > & xModel ); + virtual ~UndoCommandDispatch(); + + // late initialisation, especially for adding as listener + virtual void initialize(); + +protected: + // ____ XDispatch ____ + virtual void SAL_CALL dispatch( + const ::com::sun::star::util::URL& URL, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& Arguments ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ WeakComponentImplHelperBase ____ + /// is called when this is disposed + virtual void SAL_CALL disposing(); + + // ____ XEventListener (base of XModifyListener) ____ + virtual void SAL_CALL disposing( + const ::com::sun::star::lang::EventObject& Source ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void fireStatusEvent( + const ::rtl::OUString & rURL, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & xSingleListener ); + +private: + ::com::sun::star::uno::Reference< + ::com::sun::star::frame::XModel > m_xModel; + ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XUndoManager > m_xUndoManager; +}; + +} // namespace chart + +// CHART2_UNDOCOMMANDDISPATCH_HXX +#endif diff --git a/chart2/source/controller/main/UndoGuard.cxx b/chart2/source/controller/main/UndoGuard.cxx new file mode 100644 index 000000000000..8513b6ba9093 --- /dev/null +++ b/chart2/source/controller/main/UndoGuard.cxx @@ -0,0 +1,143 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "UndoGuard.hxx" + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace chart +{ + +UndoGuard_Base::UndoGuard_Base( const OUString& rUndoString + , const uno::Reference< chart2::XUndoManager > & xUndoManager + , const uno::Reference< frame::XModel > & xModel ) + : m_xModel( xModel ) + , m_xUndoManager( xUndoManager ) + , m_aUndoString( rUndoString ) + , m_bActionPosted( false ) +{ +} + +UndoGuard_Base::~UndoGuard_Base() +{ +} + +void UndoGuard_Base::commitAction() +{ + if( !m_bActionPosted && m_xUndoManager.is() ) + m_xUndoManager->postAction( m_aUndoString ); + m_bActionPosted = true; +} + +//----------------------------------------------------------------------------- + +UndoGuard::UndoGuard( const OUString& rUndoString + , const uno::Reference< chart2::XUndoManager > & xUndoManager + , const uno::Reference< frame::XModel > & xModel ) + : UndoGuard_Base( rUndoString, xUndoManager, xModel ) +{ + if( m_xUndoManager.is() ) + m_xUndoManager->preAction( m_xModel ); +} + +UndoGuard::~UndoGuard() +{ + if( !m_bActionPosted && m_xUndoManager.is() ) + m_xUndoManager->cancelAction(); +} + +//----------------------------------------------------------------------------- + +UndoLiveUpdateGuard::UndoLiveUpdateGuard( const OUString& rUndoString + , const uno::Reference< chart2::XUndoManager > & xUndoManager + , const uno::Reference< frame::XModel > & xModel ) + : UndoGuard_Base( rUndoString, xUndoManager, xModel ) +{ + if( m_xUndoManager.is() ) + m_xUndoManager->preAction( m_xModel ); +} + +UndoLiveUpdateGuard::~UndoLiveUpdateGuard() +{ + if( !m_bActionPosted && m_xUndoManager.is() ) + m_xUndoManager->cancelActionWithUndo( m_xModel ); +} + +//----------------------------------------------------------------------------- + +UndoLiveUpdateGuardWithData::UndoLiveUpdateGuardWithData( const OUString& rUndoString + , const uno::Reference< chart2::XUndoManager > & xUndoManager + , const uno::Reference< frame::XModel > & xModel ) + : UndoGuard_Base( rUndoString, xUndoManager, xModel ) +{ + if( m_xUndoManager.is() ) + { + Sequence< beans::PropertyValue > aArgs(1); + aArgs[0] = beans::PropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("WithData")), -1, uno::Any(), + beans::PropertyState_DIRECT_VALUE ); + m_xUndoManager->preActionWithArguments( m_xModel, aArgs ); + } +} + +UndoLiveUpdateGuardWithData::~UndoLiveUpdateGuardWithData() +{ + if( !m_bActionPosted && m_xUndoManager.is() ) + m_xUndoManager->cancelActionWithUndo( m_xModel ); +} + +//----------------------------------------------------------------------------- + +UndoGuardWithSelection::UndoGuardWithSelection( const rtl::OUString& rUndoString + , const uno::Reference< chart2::XUndoManager > & xUndoManager + , const uno::Reference< frame::XModel > & xModel ) + : UndoGuard_Base( rUndoString, xUndoManager, xModel ) +{ + if( m_xUndoManager.is() ) + { + Sequence< beans::PropertyValue > aArgs(1); + aArgs[0] = beans::PropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("WithSelection")), -1, uno::Any(), + beans::PropertyState_DIRECT_VALUE ); + m_xUndoManager->preActionWithArguments( m_xModel, aArgs ); + } +} + +UndoGuardWithSelection::~UndoGuardWithSelection() +{ + if( !m_bActionPosted && m_xUndoManager.is() ) + m_xUndoManager->cancelAction(); +} + +} // namespace chart diff --git a/chart2/source/controller/main/UndoManager.cxx b/chart2/source/controller/main/UndoManager.cxx new file mode 100644 index 000000000000..21e27922b1c8 --- /dev/null +++ b/chart2/source/controller/main/UndoManager.cxx @@ -0,0 +1,440 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" + +#include "UndoManager.hxx" +#include "ImplUndoManager.hxx" +#include "DisposeHelper.hxx" +#include "MutexContainer.hxx" +#include "macros.hxx" +#include "ChartViewHelper.hxx" + +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> + +#include <unotools/configitem.hxx> +#include <cppuhelper/compbase1.hxx> +#include <rtl/uuid.h> +#include <svx/svdundo.hxx> + +#include <functional> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + + +// -------------------------------------------------------------------------------- + +namespace chart +{ + +namespace impl +{ +typedef ::cppu::WeakComponentImplHelper1< + util::XModifyBroadcaster > + ModifyBroadcaster_Base; + +class ModifyBroadcaster : + public ::chart::MutexContainer, + public ModifyBroadcaster_Base +{ +public: + ModifyBroadcaster(); + + void fireEvent(); + +protected: + // ____ XModifyBroadcaster ____ + virtual void SAL_CALL addModifyListener( const Reference< util::XModifyListener >& xListener ) + throw (uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( const Reference< util::XModifyListener >& xListener ) + throw (uno::RuntimeException); +}; + +ModifyBroadcaster::ModifyBroadcaster() : + ModifyBroadcaster_Base( m_aMutex ) +{} + +void SAL_CALL ModifyBroadcaster::addModifyListener( + const Reference< util::XModifyListener >& xListener ) + throw (uno::RuntimeException) +{ + rBHelper.addListener( ::getCppuType( & xListener ), xListener); +} + +void SAL_CALL ModifyBroadcaster::removeModifyListener( + const Reference< util::XModifyListener >& xListener ) + throw (uno::RuntimeException) +{ + rBHelper.removeListener( ::getCppuType( & xListener ), xListener ); +} + +void ModifyBroadcaster::fireEvent() +{ + ::cppu::OInterfaceContainerHelper* pIC = rBHelper.getContainer( + ::getCppuType((const uno::Reference< util::XModifyListener >*)0) ); + if( pIC ) + { + lang::EventObject aEvent( static_cast< lang::XComponent* >( this ) ); + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + { + uno::Reference< util::XModifyListener > xListener( aIt.next(), uno::UNO_QUERY ); + if( xListener.is() ) + xListener->modified( aEvent ); + } + } +} + +} // namespace impl + +UndoManager::UndoManager() : + impl::UndoManager_Base( m_aMutex ), + m_apUndoStack( new impl::UndoStack()), + m_apRedoStack( new impl::UndoStack()), + m_pLastRemeberedUndoElement( 0 ), + m_nMaxNumberOfUndos( 100 ), + m_pModifyBroadcaster( 0 ) +{} + +UndoManager::~UndoManager() +{ + DisposeHelper::Dispose( m_xModifyBroadcaster ); + m_apUndoStack->disposeAndClear(); + m_apRedoStack->disposeAndClear(); + + delete m_pLastRemeberedUndoElement; + m_pLastRemeberedUndoElement = 0; +} + +void UndoManager::addShapeUndoAction( SdrUndoAction* pAction ) +{ + if ( !pAction ) + { + return; + } + + impl::ShapeUndoElement* pShapeUndoElement = new impl::ShapeUndoElement( pAction->GetComment(), pAction ); + if ( pShapeUndoElement ) + { + m_apUndoStack->push( pShapeUndoElement ); + m_apRedoStack->disposeAndClear(); + if ( !m_apUndoStepsConfigItem.get() ) + { + retrieveConfigUndoSteps(); + } + fireModifyEvent(); + } +} + +void UndoManager::impl_undoRedo( + Reference< frame::XModel > & xCurrentModel, + impl::UndoStack * pStackToRemoveFrom, + impl::UndoStack * pStackToAddTo, + bool bUndo ) +{ + if( pStackToRemoveFrom && ! pStackToRemoveFrom->empty() ) + { + // get model from undo/redo + impl::UndoElement * pTop( pStackToRemoveFrom->top()); + if( pTop ) + { + impl::ShapeUndoElement* pShapeUndoElement = dynamic_cast< impl::ShapeUndoElement* >( pTop ); + if ( pShapeUndoElement ) + { + impl::ShapeUndoElement* pNewShapeUndoElement = new impl::ShapeUndoElement( *pShapeUndoElement ); + pStackToAddTo->push( pNewShapeUndoElement ); + SdrUndoAction* pAction = pNewShapeUndoElement->getSdrUndoAction(); + if ( pAction ) + { + if ( bUndo ) + { + pAction->Undo(); + } + else + { + pAction->Redo(); + } + } + } + else + { + // put a clone of current model into redo/undo stack with the same + // action string as the undo/redo + pStackToAddTo->push( pTop->createFromModel( xCurrentModel )); + // change current model by properties of the model from undo + pTop->applyToModel( xCurrentModel ); + } + // remove the top undo element + pStackToRemoveFrom->pop(), pTop = 0; + ChartViewHelper::setViewToDirtyState( xCurrentModel ); + fireModifyEvent(); + } + } + else + { + OSL_ENSURE( false, "Can't Undo/Redo" ); + } +} + +void UndoManager::fireModifyEvent() +{ + if( m_xModifyBroadcaster.is()) + m_pModifyBroadcaster->fireEvent(); +} + + +// ____ ConfigItemListener ____ +void UndoManager::notify( const ::rtl::OUString & rPropertyName ) +{ + OSL_ENSURE( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Steps" )), + "Unwanted config property change Notified" ); + if( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Steps" ))) + retrieveConfigUndoSteps(); +} + +void UndoManager::retrieveConfigUndoSteps() +{ + if( ! m_apUndoStepsConfigItem.get()) + m_apUndoStepsConfigItem.reset( new impl::UndoStepsConfigItem( *this )); + m_nMaxNumberOfUndos = m_apUndoStepsConfigItem->getUndoSteps(); + m_apUndoStack->limitSize( m_nMaxNumberOfUndos ); + m_apRedoStack->limitSize( m_nMaxNumberOfUndos ); + + // a list of available undo steps could shrink here + fireModifyEvent(); +} + +// ____ XModifyBroadcaster ____ +void SAL_CALL UndoManager::addModifyListener( const Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + if( ! m_xModifyBroadcaster.is()) + { + m_pModifyBroadcaster = new impl::ModifyBroadcaster(); + m_xModifyBroadcaster.set( static_cast< cppu::OWeakObject* >( m_pModifyBroadcaster ), uno::UNO_QUERY ); + } + m_xModifyBroadcaster->addModifyListener( aListener ); +} + +void SAL_CALL UndoManager::removeModifyListener( const Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + if( ! m_xModifyBroadcaster.is()) + { + m_pModifyBroadcaster = new impl::ModifyBroadcaster(); + m_xModifyBroadcaster.set( static_cast< cppu::OWeakObject* >( m_pModifyBroadcaster ), uno::UNO_QUERY ); + } + m_xModifyBroadcaster->removeModifyListener( aListener ); +} + +// ____ chart2::XUndoManager ____ +void SAL_CALL UndoManager::preAction( const Reference< frame::XModel >& xModelBeforeChange ) + throw (uno::RuntimeException) +{ + OSL_ENSURE( ! m_pLastRemeberedUndoElement, "Looks like postAction or cancelAction call was missing" ); + m_pLastRemeberedUndoElement = new impl::UndoElement( xModelBeforeChange ); +} + +void SAL_CALL UndoManager::preActionWithArguments( + const Reference< frame::XModel >& xModelBeforeChange, + const Sequence< beans::PropertyValue >& aArguments ) + throw (uno::RuntimeException) +{ + bool bActionHandled( false ); + OSL_ENSURE( ! m_pLastRemeberedUndoElement, "Looks like postAction or cancelAction call was missing" ); + if( aArguments.getLength() > 0 ) + { + OSL_ENSURE( aArguments.getLength() == 1, "More than one argument is not supported yet" ); + if( aArguments[0].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("WithData"))) + { + m_pLastRemeberedUndoElement = new impl::UndoElementWithData( xModelBeforeChange ); + bActionHandled = true; + } + else if( aArguments[0].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("WithSelection"))) + { + m_pLastRemeberedUndoElement = new impl::UndoElementWithSelection( xModelBeforeChange ); + bActionHandled = true; + } + } + + if( !bActionHandled ) + preAction( xModelBeforeChange ); +} + +void SAL_CALL UndoManager::postAction( const OUString& aUndoText ) + throw (uno::RuntimeException) +{ + OSL_ENSURE( m_pLastRemeberedUndoElement, "Looks like preAction call was missing" ); + if( m_pLastRemeberedUndoElement ) + { + m_pLastRemeberedUndoElement->setActionString( aUndoText ); + m_apUndoStack->push( m_pLastRemeberedUndoElement ); + m_pLastRemeberedUndoElement = 0; + + // redo no longer possible + m_apRedoStack->disposeAndClear(); + + // it suffices to get the number of undo steps from config after the + // first time postAction has been called + if( ! m_apUndoStepsConfigItem.get()) + retrieveConfigUndoSteps(); + + fireModifyEvent(); + } +} + +void SAL_CALL UndoManager::cancelAction() + throw (uno::RuntimeException) +{ + delete m_pLastRemeberedUndoElement; + m_pLastRemeberedUndoElement = 0; +} + +void SAL_CALL UndoManager::cancelActionWithUndo( Reference< frame::XModel >& xModelToRestore ) + throw (uno::RuntimeException) +{ + if( m_pLastRemeberedUndoElement ) + { + m_pLastRemeberedUndoElement->applyToModel( xModelToRestore ); + cancelAction(); + } +} + +void SAL_CALL UndoManager::undo( Reference< frame::XModel >& xCurrentModel ) + throw (uno::RuntimeException) +{ + OSL_ASSERT( m_apUndoStack.get() && m_apRedoStack.get()); + impl_undoRedo( xCurrentModel, m_apUndoStack.get(), m_apRedoStack.get(), true ); +} + +void SAL_CALL UndoManager::redo( Reference< frame::XModel >& xCurrentModel ) + throw (uno::RuntimeException) +{ + OSL_ASSERT( m_apUndoStack.get() && m_apRedoStack.get()); + impl_undoRedo( xCurrentModel, m_apRedoStack.get(), m_apUndoStack.get(), false ); +} + +::sal_Bool SAL_CALL UndoManager::undoPossible() + throw (uno::RuntimeException) +{ + return ! m_apUndoStack->empty(); +} + +::sal_Bool SAL_CALL UndoManager::redoPossible() + throw (uno::RuntimeException) +{ + return ! m_apRedoStack->empty(); +} + +OUString SAL_CALL UndoManager::getCurrentUndoString() + throw (uno::RuntimeException) +{ + return m_apUndoStack->topUndoString(); +} + +OUString SAL_CALL UndoManager::getCurrentRedoString() + throw (uno::RuntimeException) +{ + return m_apRedoStack->topUndoString(); +} + +Sequence< OUString > SAL_CALL UndoManager::getAllUndoStrings() + throw (uno::RuntimeException) +{ + return m_apUndoStack->getUndoStrings(); +} + +Sequence< OUString > SAL_CALL UndoManager::getAllRedoStrings() + throw (uno::RuntimeException) +{ + return m_apRedoStack->getUndoStrings(); +} + +// ____ XUndoHelper ____ +Reference< frame::XModel > SAL_CALL UndoManager::getModelCloneForUndo( + const Reference< frame::XModel >& xModelBeforeChange ) + throw (uno::RuntimeException) +{ + return impl::UndoElement::cloneModel( xModelBeforeChange ); +} + +void SAL_CALL UndoManager::applyModelContent( + Reference< frame::XModel >& xModelToChange, + const Reference< frame::XModel >& xModelToCopyFrom ) + throw (uno::RuntimeException) +{ + impl::UndoElement::applyModelContentToModel( xModelToChange, xModelToCopyFrom ); +} + +// ____ XUnoTunnel ____ +sal_Int64 UndoManager::getSomething( const Sequence< sal_Int8 >& rId ) + throw (uno::RuntimeException) +{ + if ( rId.getLength() == 16 && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this ) ); + } + return 0; +} + +// static +const Sequence< sal_Int8 >& UndoManager::getUnoTunnelId() +{ + static Sequence< sal_Int8 >* pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +UndoManager* UndoManager::getImplementation( const Reference< uno::XInterface > xObj ) +{ + UndoManager* pRet = NULL; + Reference< lang::XUnoTunnel > xUT( xObj, uno::UNO_QUERY ); + if ( xUT.is() ) + { + pRet = reinterpret_cast< UndoManager* >( sal::static_int_cast< sal_IntPtr >( xUT->getSomething( getUnoTunnelId() ) ) ); + } + return pRet; +} + +} // namespace chart diff --git a/chart2/source/controller/main/_serviceregistration_controller.cxx b/chart2/source/controller/main/_serviceregistration_controller.cxx new file mode 100644 index 000000000000..0371f50f9996 --- /dev/null +++ b/chart2/source/controller/main/_serviceregistration_controller.cxx @@ -0,0 +1,118 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_chart2.hxx" +#include "ChartController.hxx" +#include "ChartFrameloader.hxx" +#include "dlg_CreationWizard_UNO.hxx" +#include "dlg_ChartType_UNO.hxx" +#include "ChartDocumentWrapper.hxx" +#include "AccessibleChartView.hxx" +#include "ElementSelector.hxx" +#include "ShapeToolbarController.hxx" +#include <cppuhelper/implementationentry.hxx> + +static struct ::cppu::ImplementationEntry g_entries_chart2_controller[] = +{ + { + ::chart::ChartController::create + , ::chart::ChartController::getImplementationName_Static + , ::chart::ChartController::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::ChartFrameLoader::create + , ::chart::ChartFrameLoader::getImplementationName_Static + , ::chart::ChartFrameLoader::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::CreationWizardUnoDlg::create + , ::chart::CreationWizardUnoDlg::getImplementationName_Static + , ::chart::CreationWizardUnoDlg::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::ChartTypeUnoDlg::Create + , ::chart::ChartTypeUnoDlg::getImplementationName_Static + , ::chart::ChartTypeUnoDlg::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::wrapper::ChartDocumentWrapper::create + , ::chart::wrapper::ChartDocumentWrapper::getImplementationName_Static + , ::chart::wrapper::ChartDocumentWrapper::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::ElementSelectorToolbarController::create + , ::chart::ElementSelectorToolbarController::getImplementationName_Static + , ::chart::ElementSelectorToolbarController::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ + ::chart::ShapeToolbarController::create + , ::chart::ShapeToolbarController::getImplementationName_Static + , ::chart::ShapeToolbarController::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } + ,{ 0, 0, 0, 0, 0, 0 } +}; + +// component exports +extern "C" +{ +//================================================================================================== +SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} +//================================================================================================== +SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + return ::cppu::component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey , g_entries_chart2_controller ); +} +} +//========================================================================= diff --git a/chart2/source/controller/main/makefile.mk b/chart2/source/controller/main/makefile.mk new file mode 100644 index 000000000000..729276d5bd0e --- /dev/null +++ b/chart2/source/controller/main/makefile.mk @@ -0,0 +1,84 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ= ..$/..$/.. +PRJINC= $(PRJ)$/source +PRJNAME= chart2 +TARGET= chcontroller + +ENABLE_EXCEPTIONS= TRUE +VISIBILITY_HIDDEN=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE: settings.mk + +# --- export library ------------------------------------------------- + +#object files to build and link together to lib $(SLB)$/$(TARGET).lib +SLOFILES = \ + $(SLO)$/ConfigurationAccess.obj \ + $(SLO)$/ElementSelector.obj \ + $(SLO)$/SelectionHelper.obj \ + $(SLO)$/PositionAndSizeHelper.obj \ + $(SLO)$/ChartWindow.obj \ + $(SLO)$/ChartController.obj \ + $(SLO)$/ChartController_EditData.obj \ + $(SLO)$/ChartController_Window.obj \ + $(SLO)$/ChartController_Properties.obj \ + $(SLO)$/ChartController_Insert.obj \ + $(SLO)$/ChartController_TextEdit.obj \ + $(SLO)$/ChartController_Position.obj \ + $(SLO)$/ChartController_Tools.obj \ + $(SLO)$/ChartFrameloader.obj \ + $(SLO)$/ChartRenderer.obj \ + $(SLO)$/CommandDispatchContainer.obj \ + $(SLO)$/CommandDispatch.obj \ + $(SLO)$/ControllerCommandDispatch.obj \ + $(SLO)$/UndoCommandDispatch.obj \ + $(SLO)$/DragMethod_Base.obj \ + $(SLO)$/DragMethod_RotateDiagram.obj \ + $(SLO)$/DragMethod_PieSegment.obj \ + $(SLO)$/ObjectHierarchy.obj \ + $(SLO)$/_serviceregistration_controller.obj \ + $(SLO)$/ChartDropTargetHelper.obj \ + $(SLO)$/StatusBarCommandDispatch.obj \ + $(SLO)$/ChartTransferable.obj \ + $(SLO)$/FeatureCommandDispatchBase.obj \ + $(SLO)$/DrawCommandDispatch.obj \ + $(SLO)$/ShapeController.obj \ + $(SLO)$/ShapeToolbarController.obj \ + $(SLO)$/ImplUndoManager.obj \ + $(SLO)$/UndoManager.obj \ + $(SLO)$/UndoGuard.obj + +# $(SLO)$/CommonConverters.obj \ +# $(SLO)$/Scaling.obj \ + +# --- Targets ----------------------------------------------------------------- + +.INCLUDE: target.mk |