diff --git a/chart2/source/controller/main/ChartController.cxx b/chart2/source/controller/main/ChartController.cxx index b104e232b3b6..cde145046dec 100644 --- a/chart2/source/controller/main/ChartController.cxx +++ b/chart2/source/controller/main/ChartController.cxx @@ -56,6 +56,7 @@ #include "AccessibleChartView.hxx" #include "DrawCommandDispatch.hxx" #include "ShapeController.hxx" +#include "UndoManager.hxx" #include @@ -1384,6 +1385,20 @@ void SAL_CALL ChartController::modified( const lang::EventObject& /* aEvent */ ) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- +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() ) @@ -1391,6 +1406,10 @@ DrawModelWrapper* ChartController::GetDrawModelWrapper() 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(); } diff --git a/chart2/source/controller/main/ChartController.hxx b/chart2/source/controller/main/ChartController.hxx index d391975b832b..99035429f95d 100644 --- a/chart2/source/controller/main/ChartController.hxx +++ b/chart2/source/controller/main/ChartController.hxx @@ -477,6 +477,8 @@ public: bool isShapeContext() const; + DECL_LINK( NotifyUndoActionHdl, SdrUndoAction* ); + public: //----------------------------------------------------------------- //----------------------------------------------------------------- diff --git a/chart2/source/controller/main/ChartController_TextEdit.cxx b/chart2/source/controller/main/ChartController_TextEdit.cxx index 41eb44d215ca..ed041b3d6cc6 100644 --- a/chart2/source/controller/main/ChartController_TextEdit.cxx +++ b/chart2/source/controller/main/ChartController_TextEdit.cxx @@ -166,15 +166,26 @@ bool ChartController::EndTextEdit() TitleHelper::setCompleteString( aString, uno::Reference< ::com::sun::star::chart2::XTitle >::query( xPropSet ), m_xCC ); - } - try - { - m_xUndoManager->postAction( C2U("Edit Text") ); + try + { + m_xUndoManager->postAction( C2U("Edit Text") ); + } + catch( uno::RuntimeException& e) + { + ASSERT_EXCEPTION( e ); + } } - catch( uno::RuntimeException& e) + else { - ASSERT_EXCEPTION( e ); + try + { + m_xUndoManager->cancelAction(); + } + catch ( uno::RuntimeException& e ) + { + ASSERT_EXCEPTION( e ); + } } } return true; diff --git a/chart2/source/controller/main/ChartController_Tools.cxx b/chart2/source/controller/main/ChartController_Tools.cxx index a19e6dcd807d..6a991b01ee3c 100644 --- a/chart2/source/controller/main/ChartController_Tools.cxx +++ b/chart2/source/controller/main/ChartController_Tools.cxx @@ -79,10 +79,13 @@ // for SolarMutex #include #include +#include +#include // for OutlinerView #include #include #include +#include #include #include @@ -413,13 +416,14 @@ void ChartController::impl_PasteGraphic( void ChartController::impl_PasteShapes( SdrModel* pModel ) { DrawModelWrapper* pDrawModelWrapper( this->GetDrawModelWrapper() ); - if ( pDrawModelWrapper ) + 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 ) { @@ -442,6 +446,7 @@ void ChartController::impl_PasteShapes( SdrModel* pModel ) } pDestPage->InsertObject( pNewObj ); + m_pDrawViewWrapper->AddUndo( new SdrUndoInsertObj( *pNewObj ) ); xSelShape = xShape; } } @@ -456,6 +461,8 @@ void ChartController::impl_PasteShapes( SdrModel* pModel ) // select last inserted shape m_aSelection.setSelection( xSelShape ); m_aSelection.applySelection( m_pDrawViewWrapper ); + + m_pDrawViewWrapper->EndUndo(); } } } @@ -463,7 +470,7 @@ void ChartController::impl_PasteShapes( SdrModel* pModel ) void ChartController::impl_PasteStringAsTextShape( const OUString& rString, const awt::Point& rPosition ) { DrawModelWrapper* pDrawModelWrapper( this->GetDrawModelWrapper() ); - if ( pDrawModelWrapper ) + if ( pDrawModelWrapper && m_pDrawViewWrapper ) { const Reference< lang::XMultiServiceFactory >& xShapeFactory( pDrawModelWrapper->getShapeFactory() ); const Reference< drawing::XDrawPage >& xDrawPage( pDrawModelWrapper->getMainDrawPage() ); @@ -495,6 +502,14 @@ void ChartController::impl_PasteStringAsTextShape( const OUString& rString, cons 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(); + } } catch ( const uno::Exception& ex ) { diff --git a/chart2/source/inc/UndoManager.hxx b/chart2/source/inc/UndoManager.hxx index 6c71e668a2b5..72cb5f85eb9d 100644 --- a/chart2/source/inc/UndoManager.hxx +++ b/chart2/source/inc/UndoManager.hxx @@ -39,8 +39,9 @@ #include #include #include +#include -#include +#include #include // for pair @@ -48,6 +49,8 @@ // for auto_ptr #include +class SdrUndoAction; + namespace com { namespace sun { namespace star { namespace frame { class XModel; @@ -65,10 +68,11 @@ class UndoElement; class UndoStack; class ModifyBroadcaster; -typedef ::cppu::WeakComponentImplHelper3< +typedef ::cppu::WeakComponentImplHelper4< ::com::sun::star::util::XModifyBroadcaster, ::com::sun::star::chart2::XUndoManager, - ::com::sun::star::chart2::XUndoHelper > + ::com::sun::star::chart2::XUndoHelper, + ::com::sun::star::lang::XUnoTunnel > UndoManager_Base; } // namespace impl @@ -90,6 +94,15 @@ public: explicit UndoManager(); virtual ~UndoManager(); + void addShapeUndoAction( SdrUndoAction* pAction ); + + // ____ XUnoTunnel ____ + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rId ) + throw (::com::sun::star::uno::RuntimeException); + + static const ::com::sun::star::uno::Sequence< sal_Int8 >& getUnoTunnelId(); + static UndoManager* getImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> xObj ); + protected: // ____ ConfigItemListener ____ virtual void notify( const ::rtl::OUString & rPropertyName ); @@ -148,7 +161,8 @@ private: ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > & xCurrentModel, impl::UndoStack * pStackToRemoveFrom, - impl::UndoStack * pStackToAddTo ); + impl::UndoStack * pStackToAddTo, + bool bUndo = true ); ::std::auto_ptr< impl::UndoStack > m_apUndoStack; ::std::auto_ptr< impl::UndoStack > m_apRedoStack; diff --git a/chart2/source/tools/ImplUndoManager.cxx b/chart2/source/tools/ImplUndoManager.cxx index 91d5f869bc53..bf5bfc7800ad 100644 --- a/chart2/source/tools/ImplUndoManager.cxx +++ b/chart2/source/tools/ImplUndoManager.cxx @@ -110,7 +110,10 @@ UndoElement::~UndoElement() void UndoElement::initialize( const Reference< frame::XModel > & xModel ) { - m_xModel.set( UndoElement::cloneModel( xModel )); + if ( xModel.is() ) + { + m_xModel.set( UndoElement::cloneModel( xModel ) ); + } } void UndoElement::dispose() @@ -356,6 +359,29 @@ UndoElement * UndoElementWithSelection::createFromModel( 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() : diff --git a/chart2/source/tools/ImplUndoManager.hxx b/chart2/source/tools/ImplUndoManager.hxx index 94d04b69a5a4..62469f8b9dd6 100644 --- a/chart2/source/tools/ImplUndoManager.hxx +++ b/chart2/source/tools/ImplUndoManager.hxx @@ -41,6 +41,9 @@ #include #include + +class SdrUndoAction; + namespace com { namespace sun { namespace star { namespace chart2 { class XInternalDataProvider; @@ -149,6 +152,19 @@ private: ::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 diff --git a/chart2/source/tools/UndoManager.cxx b/chart2/source/tools/UndoManager.cxx index e1542ade6020..b280db180d02 100644 --- a/chart2/source/tools/UndoManager.cxx +++ b/chart2/source/tools/UndoManager.cxx @@ -44,6 +44,8 @@ #include #include +#include +#include #include @@ -134,10 +136,31 @@ UndoManager::~UndoManager() 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 ) + impl::UndoStack * pStackToAddTo, + bool bUndo ) { if( pStackToRemoveFrom && ! pStackToRemoveFrom->empty() ) { @@ -145,11 +168,32 @@ void UndoManager::impl_undoRedo( impl::UndoElement * pTop( pStackToRemoveFrom->top()); if( pTop ) { - // 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 ); + 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 ); @@ -290,14 +334,14 @@ 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()); + 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()); + impl_undoRedo( xCurrentModel, m_apRedoStack.get(), m_apUndoStack.get(), false ); } ::sal_Bool SAL_CALL UndoManager::undoPossible() @@ -352,4 +396,44 @@ void SAL_CALL UndoManager::applyModelContent( 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