diff options
author | Armin Le Grand <alg@apache.org> | 2012-08-09 08:42:27 +0000 |
---|---|---|
committer | Armin Le Grand <alg@apache.org> | 2012-08-09 08:42:27 +0000 |
commit | a096725779b210c7a2706e72596fd7c80e049fdd (patch) | |
tree | a5515afecb4b91d75566039393f47eaf6334beb3 | |
parent | 24796e7163489d0c10fc9e98e09a2f1cd1e95866 (diff) |
#120498# Enhanced Undo/Redo and user experience when editing texts in graphic objects and/or tables
Notes
Notes:
merged as: 12a4200e8ff7f045efcc7e9d15a24b15b248c437
-rw-r--r-- | editeng/inc/editeng/editeng.hxx | 4 | ||||
-rw-r--r-- | editeng/inc/editeng/editund2.hxx | 11 | ||||
-rw-r--r-- | editeng/inc/editeng/outliner.hxx | 4 | ||||
-rw-r--r-- | editeng/source/editeng/editeng.cxx | 6 | ||||
-rw-r--r-- | editeng/source/editeng/editundo.cxx | 58 | ||||
-rw-r--r-- | editeng/source/editeng/impedit.hxx | 28 | ||||
-rw-r--r-- | editeng/source/outliner/outliner.cxx | 6 | ||||
-rw-r--r-- | sd/inc/undo/undomanager.hxx | 10 | ||||
-rw-r--r-- | sd/source/core/undo/undomanager.cxx | 9 | ||||
-rw-r--r-- | sd/source/ui/view/drviewse.cxx | 4 | ||||
-rw-r--r-- | svx/Library_svxcore.mk | 1 | ||||
-rw-r--r-- | svx/Package_inc.mk | 1 | ||||
-rwxr-xr-x | svx/inc/svx/sdrundomanager.hxx | 59 | ||||
-rw-r--r-- | svx/inc/svx/svdedxv.hxx | 8 | ||||
-rwxr-xr-x | svx/source/svdraw/sdrundomanager.cxx | 114 | ||||
-rw-r--r-- | svx/source/svdraw/svdedxv.cxx | 84 |
16 files changed, 355 insertions, 52 deletions
diff --git a/editeng/inc/editeng/editeng.hxx b/editeng/inc/editeng/editeng.hxx index c502b562a240..8947d5f5d765 100644 --- a/editeng/inc/editeng/editeng.hxx +++ b/editeng/inc/editeng/editeng.hxx @@ -266,8 +266,8 @@ public: void ShowParagraph( sal_uInt16 nParagraph, sal_Bool bShow = sal_True ); sal_Bool IsParagraphVisible( sal_uInt16 nParagraph ); - ::svl::IUndoManager& - GetUndoManager(); + ::svl::IUndoManager& GetUndoManager(); + ::svl::IUndoManager* SetUndoManager(::svl::IUndoManager* pNew); void UndoActionStart( sal_uInt16 nId ); void UndoActionEnd( sal_uInt16 nId ); sal_Bool IsInUndo(); diff --git a/editeng/inc/editeng/editund2.hxx b/editeng/inc/editeng/editund2.hxx index 0c0a83e08388..cea9150febb2 100644 --- a/editeng/inc/editeng/editund2.hxx +++ b/editeng/inc/editeng/editund2.hxx @@ -29,15 +29,18 @@ class ImpEditEngine; -class EDITENG_DLLPRIVATE EditUndoManager : public SfxUndoManager +class EDITENG_DLLPUBLIC EditUndoManager : public SfxUndoManager { +private: using SfxUndoManager::Undo; using SfxUndoManager::Redo; + friend class ImpEditEngine; + + ImpEditEngine* mpImpEE; + void SetImpEditEngine(ImpEditEngine* pNew); -private: - ImpEditEngine* pImpEE; public: - EditUndoManager( ImpEditEngine* pImpEE ); + EditUndoManager(sal_uInt16 nMaxUndoActionCount = 20); virtual sal_Bool Undo(); virtual sal_Bool Redo(); diff --git a/editeng/inc/editeng/outliner.hxx b/editeng/inc/editeng/outliner.hxx index 76ae11f85888..74034df0c89a 100644 --- a/editeng/inc/editeng/outliner.hxx +++ b/editeng/inc/editeng/outliner.hxx @@ -939,8 +939,8 @@ public: // nFormat muss ein Wert aus dem enum EETextFormat sein (wg.CLOOKS) sal_uLong Read( SvStream& rInput, const String& rBaseURL, sal_uInt16, SvKeyValueIterator* pHTTPHeaderAttrs = NULL ); - ::svl::IUndoManager& - GetUndoManager(); + ::svl::IUndoManager& GetUndoManager(); + ::svl::IUndoManager* SetUndoManager(::svl::IUndoManager* pNew); void QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel ); void QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel ); diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx index c7c5d9e1bf54..b15da58cdc74 100644 --- a/editeng/source/editeng/editeng.cxx +++ b/editeng/source/editeng/editeng.cxx @@ -147,6 +147,12 @@ sal_Bool EditEngine::IsInUndo() return pImpEditEngine->GetUndoManager(); } +::svl::IUndoManager* EditEngine::SetUndoManager(::svl::IUndoManager* pNew) +{ + DBG_CHKTHIS( EditEngine, 0 ); + return pImpEditEngine->SetUndoManager(pNew); +} + void EditEngine::UndoActionStart( sal_uInt16 nId ) { DBG_CHKTHIS( EditEngine, 0 ); diff --git a/editeng/source/editeng/editundo.cxx b/editeng/source/editeng/editundo.cxx index 0e2348ee4b5f..51fa7198f585 100644 --- a/editeng/source/editeng/editundo.cxx +++ b/editeng/source/editeng/editundo.cxx @@ -65,22 +65,28 @@ void lcl_DoSetSelection( EditView* pView, sal_uInt16 nPara ) // ----------------------------------------------------------------------- // EditUndoManager // ------------------------------------------------------------------------ -EditUndoManager::EditUndoManager( ImpEditEngine* p ) +EditUndoManager::EditUndoManager(sal_uInt16 nMaxUndoActionCount ) +: SfxUndoManager(nMaxUndoActionCount), + mpImpEE(0) { - pImpEE = p; +} + +void EditUndoManager::SetImpEditEngine(ImpEditEngine* pNew) +{ + mpImpEE = pNew; } sal_Bool __EXPORT EditUndoManager::Undo() { - if ( GetUndoActionCount() == 0 ) + if ( !mpImpEE || GetUndoActionCount() == 0 ) return sal_False; - DBG_ASSERT( pImpEE->GetActiveView(), "Active View?" ); + DBG_ASSERT( mpImpEE->GetActiveView(), "Active View?" ); - if ( !pImpEE->GetActiveView() ) + if ( !mpImpEE->GetActiveView() ) { - if ( pImpEE->GetEditViews().Count() ) - pImpEE->SetActiveView( pImpEE->GetEditViews().GetObject(0) ); + if ( mpImpEE->GetEditViews().Count() ) + mpImpEE->SetActiveView( mpImpEE->GetEditViews().GetObject(0) ); else { DBG_ERROR( "Undo in Engine ohne View nicht moeglich!" ); @@ -88,34 +94,34 @@ sal_Bool __EXPORT EditUndoManager::Undo() } } - pImpEE->GetActiveView()->GetImpEditView()->DrawSelection(); // alte Selektion entfernen + mpImpEE->GetActiveView()->GetImpEditView()->DrawSelection(); // alte Selektion entfernen - pImpEE->SetUndoMode( sal_True ); + mpImpEE->SetUndoMode( sal_True ); sal_Bool bDone = SfxUndoManager::Undo(); - pImpEE->SetUndoMode( sal_False ); + mpImpEE->SetUndoMode( sal_False ); - EditSelection aNewSel( pImpEE->GetActiveView()->GetImpEditView()->GetEditSelection() ); + EditSelection aNewSel( mpImpEE->GetActiveView()->GetImpEditView()->GetEditSelection() ); DBG_ASSERT( !aNewSel.IsInvalid(), "Ungueltige Selektion nach Undo()" ); - DBG_ASSERT( !aNewSel.DbgIsBuggy( pImpEE->GetEditDoc() ), "Kaputte Selektion nach Undo()" ); + DBG_ASSERT( !aNewSel.DbgIsBuggy( mpImpEE->GetEditDoc() ), "Kaputte Selektion nach Undo()" ); aNewSel.Min() = aNewSel.Max(); - pImpEE->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); - pImpEE->FormatAndUpdate( pImpEE->GetActiveView() ); + mpImpEE->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); + mpImpEE->FormatAndUpdate( mpImpEE->GetActiveView() ); return bDone; } sal_Bool __EXPORT EditUndoManager::Redo() { - if ( GetRedoActionCount() == 0 ) + if ( !mpImpEE || GetRedoActionCount() == 0 ) return sal_False; - DBG_ASSERT( pImpEE->GetActiveView(), "Active View?" ); + DBG_ASSERT( mpImpEE->GetActiveView(), "Active View?" ); - if ( !pImpEE->GetActiveView() ) + if ( !mpImpEE->GetActiveView() ) { - if ( pImpEE->GetEditViews().Count() ) - pImpEE->SetActiveView( pImpEE->GetEditViews().GetObject(0) ); + if ( mpImpEE->GetEditViews().Count() ) + mpImpEE->SetActiveView( mpImpEE->GetEditViews().GetObject(0) ); else { DBG_ERROR( "Redo in Engine ohne View nicht moeglich!" ); @@ -123,19 +129,19 @@ sal_Bool __EXPORT EditUndoManager::Redo() } } - pImpEE->GetActiveView()->GetImpEditView()->DrawSelection(); // alte Selektion entfernen + mpImpEE->GetActiveView()->GetImpEditView()->DrawSelection(); // alte Selektion entfernen - pImpEE->SetUndoMode( sal_True ); + mpImpEE->SetUndoMode( sal_True ); sal_Bool bDone = SfxUndoManager::Redo(); - pImpEE->SetUndoMode( sal_False ); + mpImpEE->SetUndoMode( sal_False ); - EditSelection aNewSel( pImpEE->GetActiveView()->GetImpEditView()->GetEditSelection() ); + EditSelection aNewSel( mpImpEE->GetActiveView()->GetImpEditView()->GetEditSelection() ); DBG_ASSERT( !aNewSel.IsInvalid(), "Ungueltige Selektion nach Undo()" ); - DBG_ASSERT( !aNewSel.DbgIsBuggy( pImpEE->GetEditDoc() ), "Kaputte Selektion nach Redo()" ); + DBG_ASSERT( !aNewSel.DbgIsBuggy( mpImpEE->GetEditDoc() ), "Kaputte Selektion nach Redo()" ); aNewSel.Min() = aNewSel.Max(); - pImpEE->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); - pImpEE->FormatAndUpdate( pImpEE->GetActiveView() ); + mpImpEE->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); + mpImpEE->FormatAndUpdate( mpImpEE->GetActiveView() ); return bDone; } diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx index bfeedfecc458..3fecaf94906a 100644 --- a/editeng/source/editeng/impedit.hxx +++ b/editeng/source/editeng/impedit.hxx @@ -709,6 +709,7 @@ public: const EditDoc& GetEditDoc() const { return aEditDoc; } inline EditUndoManager& GetUndoManager(); + inline ::svl::IUndoManager* SetUndoManager(::svl::IUndoManager* pNew); void SetUpdateMode( sal_Bool bUp, EditView* pCurView = 0, sal_Bool bForceUpdate = sal_False ); sal_Bool GetUpdateMode() const { return bUpdate; } @@ -1097,14 +1098,35 @@ inline void ImpEditEngine::IdleFormatAndUpdate( EditView* pCurView ) aIdleFormatter.DoIdleFormat( pCurView ); } -#ifndef SVX_LIGHT inline EditUndoManager& ImpEditEngine::GetUndoManager() { if ( !pUndoManager ) - pUndoManager = new EditUndoManager( this ); + { + pUndoManager = new EditUndoManager(); + pUndoManager->SetImpEditEngine(this); + } return *pUndoManager; } -#endif + +inline ::svl::IUndoManager* ImpEditEngine::SetUndoManager(::svl::IUndoManager* pNew) +{ + ::svl::IUndoManager* pRetval = pUndoManager; + EditUndoManager* pNewEditUndoManager = dynamic_cast< EditUndoManager* >(pNew); + + if(pUndoManager) + { + pUndoManager->SetImpEditEngine(0); + } + + pUndoManager = dynamic_cast< EditUndoManager* >(pNew); + + if(pUndoManager) + { + pUndoManager->SetImpEditEngine(this); + } + + return pRetval; +} inline ParaPortion* ImpEditEngine::FindParaPortion( ContentNode* pNode ) const { diff --git a/editeng/source/outliner/outliner.cxx b/editeng/source/outliner/outliner.cxx index 323a50e157dc..bdef7897dbbd 100644 --- a/editeng/source/outliner/outliner.cxx +++ b/editeng/source/outliner/outliner.cxx @@ -1229,6 +1229,12 @@ void Outliner::ImpFilterIndents( sal_uLong nFirstPara, sal_uLong nLastPara ) return pEditEngine->GetUndoManager(); } +::svl::IUndoManager* Outliner::SetUndoManager(::svl::IUndoManager* pNew) +{ + DBG_CHKTHIS(Outliner,0); + return pEditEngine->SetUndoManager(pNew); +} + void Outliner::ImpTextPasted( sal_uLong nStartPara, sal_uInt16 nCount ) { DBG_CHKTHIS(Outliner,0); diff --git a/sd/inc/undo/undomanager.hxx b/sd/inc/undo/undomanager.hxx index 9db16a02250c..81e9af752ed0 100644 --- a/sd/inc/undo/undomanager.hxx +++ b/sd/inc/undo/undomanager.hxx @@ -24,13 +24,13 @@ #ifndef _SD_UNDOMANAGER_HXX #define _SD_UNDOMANAGER_HXX -#include "misc/scopelock.hxx" -#include <svl/undo.hxx> +#include <misc/scopelock.hxx> +#include <svx/sdrundomanager.hxx> namespace sd { -class UndoManager : public SfxUndoManager +class UndoManager : public SdrUndoManager { public: UndoManager( sal_uInt16 nMaxUndoActionCount = 20 ); @@ -44,8 +44,8 @@ public: void SetLinkedUndoManager (::svl::IUndoManager* pLinkedUndoManager); private: - using SfxUndoManager::Undo; - using SfxUndoManager::Redo; + using SdrUndoManager::Undo; + using SdrUndoManager::Redo; /** Used when the outline view is visible as a last resort to synchronize the undo managers. diff --git a/sd/source/core/undo/undomanager.cxx b/sd/source/core/undo/undomanager.cxx index 675e8a93c78b..b3abb0191381 100644 --- a/sd/source/core/undo/undomanager.cxx +++ b/sd/source/core/undo/undomanager.cxx @@ -23,13 +23,14 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sd.hxx" + #include <tools/debug.hxx> -#include "undo/undomanager.hxx" +#include <undo/undomanager.hxx> using namespace sd; UndoManager::UndoManager( sal_uInt16 nMaxUndoActionCount /* = 20 */ ) -: SfxUndoManager( nMaxUndoActionCount ) +: SdrUndoManager( nMaxUndoActionCount ) , mpLinkedUndoManager(NULL) { } @@ -39,7 +40,7 @@ void UndoManager::EnterListAction(const UniString &rComment, const UniString& rR if( !IsDoing() ) { ClearLinkedRedoActions(); - SfxUndoManager::EnterListAction( rComment, rRepeatComment, nId ); + SdrUndoManager::EnterListAction( rComment, rRepeatComment, nId ); } } @@ -48,7 +49,7 @@ void UndoManager::AddUndoAction( SfxUndoAction *pAction, sal_Bool bTryMerg /* = if( !IsDoing() ) { ClearLinkedRedoActions(); - SfxUndoManager::AddUndoAction( pAction, bTryMerg ); + SdrUndoManager::AddUndoAction( pAction, bTryMerg ); } else { diff --git a/sd/source/ui/view/drviewse.cxx b/sd/source/ui/view/drviewse.cxx index f7aed4d6f7ac..075384674b57 100644 --- a/sd/source/ui/view/drviewse.cxx +++ b/sd/source/ui/view/drviewse.cxx @@ -639,10 +639,6 @@ void DrawViewShell::FuPermanent(SfxRequest& rReq) } } -////////////////////////////////////////////////////////////////////////////// -// service routine for Undo/Redo implementation -extern SfxUndoManager* ImpGetUndoManagerFromViewShell(DrawViewShell& rDViewShell); - /************************************************************************* |* |* SfxRequests fuer Support-Funktionen diff --git a/svx/Library_svxcore.mk b/svx/Library_svxcore.mk index 048e32e9f958..61a6eeee6c2b 100644 --- a/svx/Library_svxcore.mk +++ b/svx/Library_svxcore.mk @@ -299,6 +299,7 @@ $(eval $(call gb_Library_add_exception_objects,svxcore,\ svx/source/svdraw/gradtrns \ svx/source/svdraw/polypolygoneditor \ svx/source/svdraw/sdrcomment \ + svx/source/svdraw/sdrundomanager \ svx/source/svdraw/sdrhittesthelper \ svx/source/svdraw/sdrmasterpagedescriptor \ svx/source/svdraw/sdrpagewindow \ diff --git a/svx/Package_inc.mk b/svx/Package_inc.mk index 1451bf8bd86c..440671280f8b 100644 --- a/svx/Package_inc.mk +++ b/svx/Package_inc.mk @@ -376,6 +376,7 @@ $(eval $(call gb_Package_add_file,svx_inc,inc/svx/relfld.hxx,svx/relfld.hxx)) $(eval $(call gb_Package_add_file,svx_inc,inc/svx/AccessibleShapeInfo.hxx,svx/AccessibleShapeInfo.hxx)) $(eval $(call gb_Package_add_file,svx_inc,inc/svx/numvset.hxx,svx/numvset.hxx)) $(eval $(call gb_Package_add_file,svx_inc,inc/svx/sdrcomment.hxx,svx/sdrcomment.hxx)) +$(eval $(call gb_Package_add_file,svx_inc,inc/svx/sdrundomanager.hxx,svx/sdrundomanager.hxx)) $(eval $(call gb_Package_add_file,svx_inc,inc/svx/txenctab.hxx,svx/txenctab.hxx)) $(eval $(call gb_Package_add_file,svx_inc,inc/svx/svdorect.hxx,svx/svdorect.hxx)) $(eval $(call gb_Package_add_file,svx_inc,inc/svx/xftshit.hxx,svx/xftshit.hxx)) diff --git a/svx/inc/svx/sdrundomanager.hxx b/svx/inc/svx/sdrundomanager.hxx new file mode 100755 index 000000000000..db907bf3b463 --- /dev/null +++ b/svx/inc/svx/sdrundomanager.hxx @@ -0,0 +1,59 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +#ifndef _SDR_UNDOMANAGER_HXX +#define _SDR_UNDOMANAGER_HXX + +#include "svx/svxdllapi.h" +#include <sal/types.h> +#include <editeng/editund2.hxx> +#include <tools/link.hxx> + +////////////////////////////////////////////////////////////////////////////// + +class SVX_DLLPUBLIC SdrUndoManager : public EditUndoManager +{ +private: + using EditUndoManager::Undo; + using EditUndoManager::Redo; + + Link maEndTextEditHdl; + SfxUndoAction* mpLastUndoActionBeforeTextEdit; + +public: + SdrUndoManager(sal_uInt16 nMaxUndoActionCount = 20); + virtual ~SdrUndoManager(); + + /// react depending on edit mode and if no more undo is possible + virtual sal_Bool Undo(); + virtual sal_Bool Redo(); + + // Call for the view which starts the interactive text edit. Use link to + // activate (start text edit) and empty link to reset (end text edit). On + // reset all text edit actions will be removed from this undo manager to + // restore the state before activation + void SetEndTextEditHdl(const Link& rLink); +}; + +////////////////////////////////////////////////////////////////////////////// + +#endif //_SDR_UNDOMANAGER_HXX +// eof diff --git a/svx/inc/svx/svdedxv.hxx b/svx/inc/svx/svdedxv.hxx index 8bb996c55fe0..f7e1ff82a71f 100644 --- a/svx/inc/svx/svdedxv.hxx +++ b/svx/inc/svx/svdedxv.hxx @@ -42,6 +42,7 @@ class EditStatus; class EditFieldInfo; class ImpSdrEditPara; struct PasteOrDropInfos; +class SdrUndoManager; namespace com { namespace sun { namespace star { namespace uno { class Any; @@ -101,7 +102,7 @@ protected: Link aOldCalcFieldValueLink; // Zum rufen des alten Handlers Point aMacroDownPos; - sal_uInt16 nMacroTol; + sal_uInt16 nMacroTol; unsigned bTextEditDontDelete : 1; // Outliner und View bei SdrEndTextEdit nicht deleten (f. Rechtschreibpruefung) unsigned bTextEditOnlyOneView : 1; // Nur eine OutlinerView (f. Rechtschreibpruefung) @@ -114,6 +115,8 @@ protected: rtl::Reference< sdr::SelectionController > mxLastSelectionController; private: + ::svl::IUndoManager* mpOldTextEditUndoManager; + SVX_DLLPRIVATE void ImpClearVars(); protected: @@ -134,6 +137,9 @@ protected: DECL_LINK(ImpOutlinerStatusEventHdl,EditStatus*); DECL_LINK(ImpOutlinerCalcFieldValueHdl,EditFieldInfo*); + // link for EndTextEditHdl + DECL_LINK(EndTextEditHdl, SdrUndoManager*); + void ImpMacroUp(const Point& rUpPos); void ImpMacroDown(const Point& rDownPos); diff --git a/svx/source/svdraw/sdrundomanager.cxx b/svx/source/svdraw/sdrundomanager.cxx new file mode 100755 index 000000000000..8eb92546ec1d --- /dev/null +++ b/svx/source/svdraw/sdrundomanager.cxx @@ -0,0 +1,114 @@ +/************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + *************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <svx/sdrundomanager.hxx> + +////////////////////////////////////////////////////////////////////////////// + +SdrUndoManager::SdrUndoManager(sal_uInt16 nMaxUndoActionCount) +: EditUndoManager(nMaxUndoActionCount), + maEndTextEditHdl(), + mpLastUndoActionBeforeTextEdit(0) +{ +} + +SdrUndoManager::~SdrUndoManager() +{ +} + +sal_Bool SdrUndoManager::Undo() +{ + sal_Bool bRetval(sal_False); + + if(maEndTextEditHdl.IsSet()) + { + // we are in text edit mode + if(GetUndoActionCount() && mpLastUndoActionBeforeTextEdit != GetUndoAction(0)) + { + // there is an undo action for text edit, trigger it + bRetval = EditUndoManager::Undo(); + } + else + { + // no more text edit undo, end text edit + maEndTextEditHdl.Call(this); + } + } + + if(!bRetval && GetUndoActionCount()) + { + // no undo triggered up to now, trigger local one + bRetval = SfxUndoManager::Undo(); + } + + return bRetval; +} + +sal_Bool SdrUndoManager::Redo() +{ + sal_Bool bRetval(sal_False); + + if(maEndTextEditHdl.IsSet()) + { + // we are in text edit mode + bRetval = EditUndoManager::Redo(); + } + + if(!bRetval) + { + // no redo triggered up to now, trigger local one + bRetval = SfxUndoManager::Redo(); + } + + return bRetval; +} + +void SdrUndoManager::SetEndTextEditHdl(const Link& rLink) +{ + maEndTextEditHdl = rLink; + + if(maEndTextEditHdl.IsSet()) + { + // text edit start, remember last non-textedit action for later cleanup + mpLastUndoActionBeforeTextEdit = GetUndoActionCount() ? GetUndoAction(0) : 0; + } + else + { + // text edit ends, pop all textedit actions up to the remembered non-textedit action from the start + // to set back the UndoManager to the state before text edit started. If that action is already gone + // (due to being removed from the undo stack in the meantime), all need to be removed anyways + while(GetUndoActionCount() && mpLastUndoActionBeforeTextEdit != GetUndoAction(0)) + { + RemoveLastUndoAction(); + } + + // urgently needed: RemoveLastUndoAction does NOT correct the Redo stack by itself (!) + ClearRedo(); + + // forget marker again + mpLastUndoActionBeforeTextEdit = 0; + } +} + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx index 1b20db1a639b..acb8aeeee5ed 100644 --- a/svx/source/svdraw/svdedxv.cxx +++ b/svx/source/svdraw/svdedxv.cxx @@ -73,6 +73,7 @@ #include <svtools/colorcfg.hxx> #include <vcl/svapp.hxx> //add CHINA001 #include <svx/sdrpaintwindow.hxx> +#include <svx/sdrundomanager.hxx> //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -97,7 +98,8 @@ void SdrObjEditView::ImpClearVars() } SdrObjEditView::SdrObjEditView(SdrModel* pModel1, OutputDevice* pOut): - SdrGlueEditView(pModel1,pOut) + SdrGlueEditView(pModel1,pOut), + mpOldTextEditUndoManager(0) { ImpClearVars(); } @@ -109,6 +111,11 @@ SdrObjEditView::~SdrObjEditView() if (pTextEditOutliner!=NULL) { delete pTextEditOutliner; } + + if(mpOldTextEditUndoManager) + { + delete mpOldTextEditUndoManager; + } } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -537,6 +544,12 @@ IMPL_LINK(SdrObjEditView,ImpOutlinerCalcFieldValueHdl,EditFieldInfo*,pFI) return 0; } +IMPL_LINK(SdrObjEditView, EndTextEditHdl, SdrUndoManager*, /*pUndoManager*/) +{ + SdrEndTextEdit(); + return 0; +} + sal_Bool SdrObjEditView::SdrBeginTextEdit( SdrObject* pObj, SdrPageView* pPV, Window* pWin, sal_Bool bIsNewObj, SdrOutliner* pGivenOutliner, @@ -765,6 +778,31 @@ sal_Bool SdrObjEditView::SdrBeginTextEdit( if( mxSelectionController.is() ) mxSelectionController->onSelectionHasChanged(); + if(IsUndoEnabled()) + { + SdrUndoManager* pSdrUndoManager = dynamic_cast< SdrUndoManager* >(GetModel()->GetSdrUndoManager()); + + if(pSdrUndoManager) + { + // we have an outliner, undo manager and it's an EditUndoManager, exchange + // the document undo manager and the default one from the outliner and tell + // it that text edit starts by setting a callback if it needs to end text edit mode. + if(mpOldTextEditUndoManager) + { + // should not happen, delete it + delete mpOldTextEditUndoManager; + mpOldTextEditUndoManager = 0; + } + + mpOldTextEditUndoManager = pTextEditOutliner->SetUndoManager(pSdrUndoManager); + pSdrUndoManager->SetEndTextEditHdl(LINK(this, SdrObjEditView, EndTextEditHdl)); + } + else + { + OSL_ENSURE(false, "The document undo manager is not derived from SdrUndoManager (!)"); + } + } + return sal_True; // Gut gelaufen, TextEdit laeuft nun } else @@ -822,6 +860,42 @@ SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(sal_Bool bDontDeleteReally) SdrOutliner* pTEOutliner =pTextEditOutliner; OutlinerView* pTEOutlinerView=pTextEditOutlinerView; Cursor* pTECursorMerker=pTextEditCursorMerker; + SdrUndoManager* pExtraUndoEditUndoManager = 0; + + if(IsUndoEnabled() && GetModel() && pTEObj && pTEOutliner) + { + // change back the UndoManager to the remembered original one + ::svl::IUndoManager* pOriginal = pTEOutliner->SetUndoManager(mpOldTextEditUndoManager); + mpOldTextEditUndoManager = 0; + + if(pOriginal) + { + // check if we got back our document undo manager + SdrUndoManager* pSdrUndoManager = dynamic_cast< SdrUndoManager* >(GetModel()->GetSdrUndoManager()); + + if(pSdrUndoManager && dynamic_cast< SdrUndoManager* >(pOriginal) == pSdrUndoManager) + { + // We are ending text edit; execute all redos to create a complete text change + // undo action for the redo buffer. Also mark this state when at least one redo was + // executed; the created TextChange needs to be undone plus the first real undo + // outside the text edit changes + while(pSdrUndoManager->GetRedoActionCount()) + { + pExtraUndoEditUndoManager = pSdrUndoManager; + pSdrUndoManager->Redo(); + } + + // reset the callback link and let the undo manager cleanup all text edit + // undo actions to get the stack back to the form before the text edit + pSdrUndoManager->SetEndTextEditHdl(Link()); + } + else + { + OSL_ENSURE(false, "Got UndoManager back in SdrEndTextEdit which is NOT the expected document UndoManager (!)"); + delete pOriginal; + } + } + } // send HINT_ENDEDIT #99840# if( GetModel() && mxTextEditObj.is() ) @@ -1031,6 +1105,14 @@ SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(sal_Bool bDontDeleteReally) ((SfxBroadcaster*)pTEObj->GetBroadcaster())->Broadcast(aHint); } + if(pExtraUndoEditUndoManager) + { + // undo the text edit action since it was created as part of a EndTextEdit + // callback from undo itself. This needs to be done after the call to + // FmFormView::SdrEndTextEdit since it gets created there + pExtraUndoEditUndoManager->Undo(); + } + return eRet; } |