diff options
-rw-r--r-- | include/svx/sdr/contact/viewcontact.hxx | 5 | ||||
-rw-r--r-- | include/svx/sdr/contact/viewobjectcontact.hxx | 5 | ||||
-rw-r--r-- | include/svx/svdedxv.hxx | 14 | ||||
-rw-r--r-- | sd/source/ui/view/sdview.cxx | 6 | ||||
-rw-r--r-- | svx/source/sdr/contact/viewcontact.cxx | 23 | ||||
-rw-r--r-- | svx/source/sdr/contact/viewobjectcontact.cxx | 11 | ||||
-rw-r--r-- | svx/source/svdraw/svdedxv.cxx | 87 | ||||
-rw-r--r-- | svx/source/unodraw/unoshtxt.cxx | 8 |
8 files changed, 157 insertions, 2 deletions
diff --git a/include/svx/sdr/contact/viewcontact.hxx b/include/svx/sdr/contact/viewcontact.hxx index 7b6d0f3ab2c1..00b7f6253eae 100644 --- a/include/svx/sdr/contact/viewcontact.hxx +++ b/include/svx/sdr/contact/viewcontact.hxx @@ -27,6 +27,7 @@ class SdrLayerIDSet; class SdrPage; class SdrObject; +class SdrPageView; namespace sdr::contact { @@ -122,6 +123,10 @@ public: // React on changes of the object of this ViewContact virtual void ActionChanged(); + // IASS: helpers for IASS invalidates + void ActionChangedIfDifferentPageView(SdrPageView& rSdrPageView); + bool hasMultipleViewObjectContacts() const; + // access to the local primitive. This will ensure that the primitive is // current in comparing the local one with a fresh created incarnation void getViewIndependentPrimitive2DContainer( diff --git a/include/svx/sdr/contact/viewobjectcontact.hxx b/include/svx/sdr/contact/viewobjectcontact.hxx index 12195a0faa34..8f903d93e04b 100644 --- a/include/svx/sdr/contact/viewobjectcontact.hxx +++ b/include/svx/sdr/contact/viewobjectcontact.hxx @@ -24,6 +24,8 @@ #include <svx/svxdllapi.h> #include <drawinglayer/primitive2d/Primitive2DContainer.hxx> +class SdrPageView; + namespace vcl { class Region; } namespace sdr::animation { @@ -101,6 +103,9 @@ public: // React on changes of the object of this ViewContact virtual void ActionChanged(); + // IASS: helper for IASS invalidates + void ActionChangedIfDifferentPageView(SdrPageView& rSdrPageView); + // LazyInvalidate handling void triggerLazyInvalidate(); diff --git a/include/svx/svdedxv.hxx b/include/svx/svdedxv.hxx index 8ad7f048b682..6c6a37f108a7 100644 --- a/include/svx/svdedxv.hxx +++ b/include/svx/svdedxv.hxx @@ -76,8 +76,15 @@ class SVXCORE_DLLPUBLIC SdrObjEditView : public SdrGlueEditView, public EditView virtual void EditViewCursorRect(const tools::Rectangle& rRect, int nExtTextInputWidth) override; // The OverlayObjects used for visualizing active TextEdit (currently - // using TextEditOverlayObject, but not limited to it + // using TextEditOverlayObject, but not limited to it) sdr::overlay::OverlayObjectList maTEOverlayGroup; + Timer maTextEditUpdateTimer; + + // IASS: allow reaction to active TextEdit changes + DECL_DLLPRIVATE_LINK(ImpModifyHdl, LinkParamNone*, void); + + // IASS: timer-based reaction on TextEdit changes + DECL_DLLPRIVATE_LINK(TextEditUpdate, Timer*, void); protected: // TextEdit @@ -104,10 +111,15 @@ protected: bool mbTextEditNewObj : 1; // current edited object was just recreated bool mbQuickTextEditMode : 1; // persistent(->CrtV). Default=TRUE bool mbMacroDown : 1; + bool mbInteractiveSlideShow : 1; // IASS rtl::Reference< sdr::SelectionController > mxSelectionController; rtl::Reference< sdr::SelectionController > mxLastSelectionController; + // check/set if we are in IASS and need to refresh evtl. + void setInteractiveSlideShow(bool bNew) { mbInteractiveSlideShow = bNew; } + bool isInteractiveSlideShow() const { return mbInteractiveSlideShow; } + private: EditUndoManager* mpOldTextEditUndoManager; std::unique_ptr<SdrUndoManager> mpLocalTextEditUndoManager; diff --git a/sd/source/ui/view/sdview.cxx b/sd/source/ui/view/sdview.cxx index 345ef782ea84..9c4713fcb0ac 100644 --- a/sd/source/ui/view/sdview.cxx +++ b/sd/source/ui/view/sdview.cxx @@ -24,6 +24,7 @@ #include <com/sun/star/linguistic2/XSpellChecker1.hpp> #include <View.hxx> +#include <slideshow.hxx> #include <avmedia/mediawindow.hxx> #include <editeng/outlobj.hxx> #include <editeng/unolingu.hxx> @@ -698,6 +699,11 @@ bool View::SdrBeginTextEdit( pOutl->SetDefaultLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() ); } + // check if we have IASS active and propagate that info to the view with the active TextEdit + rtl::Reference< SlideShow > xSlideshow(SlideShow::GetSlideShow(mpViewSh->GetViewShellBase())); + const bool bIASS(xSlideshow.is() && xSlideshow->isRunning() && xSlideshow->IsInteractiveSlideshow()); + setInteractiveSlideShow(bIASS); + bool bReturn = FmFormView::SdrBeginTextEdit( pObj, pPV, pWin, bIsNewObj, pOutl, pGivenOutlinerView, bDontDeleteOutliner, diff --git a/svx/source/sdr/contact/viewcontact.cxx b/svx/source/sdr/contact/viewcontact.cxx index 99106d0d6ed0..fcc9a6975380 100644 --- a/svx/source/sdr/contact/viewcontact.cxx +++ b/svx/source/sdr/contact/viewcontact.cxx @@ -203,6 +203,29 @@ void ViewContact::ActionChanged() } } +// IASS: helper for IASS invalidates +void ViewContact::ActionChangedIfDifferentPageView(SdrPageView& rSdrPageView) +{ + const sal_uInt32 nCount(maViewObjectContactVector.size()); + + for (sal_uInt32 a(0); a < nCount; a++) + { + ViewObjectContact* pCandidate = maViewObjectContactVector[a]; + DBG_ASSERT(pCandidate, + "ViewContact::GetViewObjectContact() invalid ViewObjectContactList (!)"); + + if (pCandidate) + { + pCandidate->ActionChangedIfDifferentPageView(rSdrPageView); + } + } +} + +bool ViewContact::hasMultipleViewObjectContacts() const +{ + return maViewObjectContactVector.size() > 1; +} + // access to SdrObject and/or SdrPage. May return 0L like the default // implementations do. Override as needed. SdrObject* ViewContact::TryToGetSdrObject() const { return nullptr; } diff --git a/svx/source/sdr/contact/viewobjectcontact.cxx b/svx/source/sdr/contact/viewobjectcontact.cxx index 2e3ebfd8d3f9..03d6eb4bd10c 100644 --- a/svx/source/sdr/contact/viewobjectcontact.cxx +++ b/svx/source/sdr/contact/viewobjectcontact.cxx @@ -250,6 +250,17 @@ void ViewObjectContact::ActionChanged() GetObjectContact().setLazyInvalidate(*this); } +// IASS: helper for IASS invalidates +void ViewObjectContact::ActionChangedIfDifferentPageView(SdrPageView& rSdrPageView) +{ + SdrPageView* pSdrPageView(GetObjectContact().TryToGetSdrPageView()); + + // if there is no SdrPageView or different from given one, force + // invalidate/repaint + if (nullptr == pSdrPageView || pSdrPageView != &rSdrPageView) + ActionChanged(); +} + void ViewObjectContact::triggerLazyInvalidate() { if(!mbLazyInvalidate) diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx index f3f5d4818f20..3685cd55a8ef 100644 --- a/svx/source/svdraw/svdedxv.cxx +++ b/svx/source/svdraw/svdedxv.cxx @@ -68,11 +68,15 @@ #include <textchaincursor.hxx> #include <tools/debug.hxx> #include <vcl/svapp.hxx> +#include <svx/sdr/contact/viewcontact.hxx> #include <memory> SdrObjEditView::SdrObjEditView(SdrModel& rSdrModel, OutputDevice* pOut) : SdrGlueEditView(rSdrModel, pOut) + , maTEOverlayGroup() + , maTextEditUpdateTimer("TextEditUpdateTimer") + , mxWeakTextEditObj() , mpTextEditPV(nullptr) , mpTextEditOutlinerView(nullptr) , mpTextEditWin(nullptr) @@ -80,18 +84,89 @@ SdrObjEditView::SdrObjEditView(SdrModel& rSdrModel, OutputDevice* pOut) , pMacroObj(nullptr) , pMacroPV(nullptr) , pMacroWin(nullptr) + , aTextEditArea() + , aMinTextEditArea() + , aOldCalcFieldValueLink() + , aMacroDownPos() , nMacroTol(0) , mbTextEditDontDelete(false) , mbTextEditOnlyOneView(false) , mbTextEditNewObj(false) , mbQuickTextEditMode(true) , mbMacroDown(false) + , mbInteractiveSlideShow(false) + , mxSelectionController() + , mxLastSelectionController() , mpOldTextEditUndoManager(nullptr) + , mpLocalTextEditUndoManager() { + // init some timer settings (not starting it of course) + maTextEditUpdateTimer.SetTimeout(EDIT_UPDATEDATA_TIMEOUT); + maTextEditUpdateTimer.SetInvokeHandler(LINK(this, SdrObjEditView, TextEditUpdate)); +} + +IMPL_LINK_NOARG(SdrObjEditView, ImpModifyHdl, LinkParamNone*, void) +{ + // IASS: active TextEdit had a model change. Check and react. + if (nullptr == mpTextEditOutliner) + // no Outliner, no TextEdit + return; + + if (!mxWeakTextEditObj.get().is()) + // no TextObject, no TextEdit + return; + + // reset & restart the timer + maTextEditUpdateTimer.SetTimeout(EDIT_UPDATEDATA_TIMEOUT); + maTextEditUpdateTimer.Start(); +} + +IMPL_LINK_NOARG(SdrObjEditView, TextEditUpdate, Timer*, void) +{ + // IASS: text was changed and EDIT_UPDATEDATA_TIMEOUT has passed + // since last user input + maTextEditUpdateTimer.Stop(); + + // be safe: still in TextEdit? + if (nullptr == mpTextEditOutliner) + // no Outliner, no TextEdit + return; + + if (!mxWeakTextEditObj.get().is()) + // no TextObject, no TextEdit + return; + + // lauch an ObjectChange: This is the straightforward method + // to get this broadcasted. We do not risk to set the model + // unwantedly to changed, we had a text edit going on already. + // This is needed for SlideShow since it is not (yet) using the + // standard schema with VC/VOC/OC + if (isInteractiveSlideShow()) + mxWeakTextEditObj.get()->BroadcastObjectChange(); + + // force repaint for objects with changed text in all views + // that are VC/VOC/OC based (SlideShow is not yet) + sdr::contact::ViewContact& rVC(mxWeakTextEditObj.get()->GetViewContact()); + + if (!rVC.hasMultipleViewObjectContacts()) + // only one VOC -> this is us + return; + + if (nullptr == mpTextEditPV) + // should not happen, just invalidate all visualizations + rVC.ActionChanged(); + else + // invalidate only visualizations in different views: + // this is important to not cause evtl. high repaint costs + // in the EditView -> we avoid this by running the TextEdit + // on the overlay. NOTE: This is only for better performance, + // any repaint will just work fine and do the right thing + rVC.ActionChangedIfDifferentPageView(*mpTextEditPV); } SdrObjEditView::~SdrObjEditView() { + maTextEditUpdateTimer.Stop(); mpTextEditWin = nullptr; // so there's no ShowCursor in SdrEndTextEdit assert(!IsTextEdit()); if (IsTextEdit()) @@ -1481,6 +1556,12 @@ bool SdrObjEditView::SdrBeginTextEdit(SdrObject* pObj_, SdrPageView* pPV, vcl::W mpTextEditOutlinerView->ShowCursor(); mpTextEditOutliner->SetStatusEventHdl( LINK(this, SdrObjEditView, ImpOutlinerStatusEventHdl)); + + // IASS: start listening to ModelChanges of TextEdit + if (isInteractiveSlideShow() + || pTextObj->GetViewContact().hasMultipleViewObjectContacts()) + mpTextEditOutliner->SetModifyHdl(LINK(this, SdrObjEditView, ImpModifyHdl)); + if (pTextObj->IsChainable()) { mpTextEditOutlinerView->SetEndCutPasteLinkHdl( @@ -1564,6 +1645,9 @@ bool SdrObjEditView::SdrBeginTextEdit(SdrObject* pObj_, SdrPageView* pPV, vcl::W SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(bool bDontDeleteReally) { + // IASS: stop evtl. running timer immediately + maTextEditUpdateTimer.Stop(); + SdrEndTextEditKind eRet = SdrEndTextEditKind::Unchanged; rtl::Reference<SdrTextObj> pTEObj = mxWeakTextEditObj.get(); vcl::Window* pTEWin = mpTextEditWin; @@ -1682,6 +1766,9 @@ SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(bool bDontDeleteReally) pTEOutliner->SetBeginPasteOrDropHdl(Link<PasteOrDropInfos*, void>()); pTEOutliner->SetEndPasteOrDropHdl(Link<PasteOrDropInfos*, void>()); + // IASS: stop listening to ModelChanges of TextEdit + pTEOutliner->SetModifyHdl(Link<LinkParamNone*, void>()); + const bool bUndo = IsUndoEnabled(); if (bUndo) { diff --git a/svx/source/unodraw/unoshtxt.cxx b/svx/source/unodraw/unoshtxt.cxx index e6b958ce4dc0..e445978d98bb 100644 --- a/svx/source/unodraw/unoshtxt.cxx +++ b/svx/source/unodraw/unoshtxt.cxx @@ -641,7 +641,13 @@ SvxTextForwarder* SvxTextEditSourceImpl::GetTextForwarder() // distinguish the cases // a) connected to view, maybe edit mode is active, can work directly on the EditOutliner // b) background Outliner, reflect changes into ParaOutlinerObject (this is exactly the old UNO code) - if( HasView() ) + + // IASS: testing for HasView() is *not* sufficient - there may be more views of one document + // open and TextEdit is only active in one of them, or - as with IASS - it may even be the view + // of the running SlideShow itself which also will have no active TextEdit and thus no Outliner. + // Thus, to identify the view which indeed does have an outliner (and is in TextEdit mode), + // also check if it has an active Outliner by using GetTextEditOutliner() + if( HasView() && nullptr != mpView->GetTextEditOutliner() ) { if( IsEditMode() != mbForwarderIsEditMode ) { |