Rebased ref, commits from common ancestor: commit 98d911f7a692f52d2487aa6905e3a29975197e8a Author: Thorsten Behrens <thorsten.behr...@cib.de> Date: Sun Sep 20 01:42:12 2015 +0200
chained editeng: Convert fprintf to SAL_INFO Change-Id: I8e0cfedd34d7e0d70a30147a3bbf0f1cd8e6d3cc diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx index 2298ecc..aef05f5 100644 --- a/editeng/source/editeng/impedit3.cxx +++ b/editeng/source/editeng/impedit3.cxx @@ -564,18 +564,13 @@ void ImpEditEngine::CheckAutoPageSize() void ImpEditEngine::CheckPageOverflow() { - // FIXME(matteocam) - /* fprintf( stderr, IsPageOverflow(aPaperSize, aPrevPaperSize) - ? "YES Overflow!\n" : "NO Overflow!\n" ); */ - // setting overflow status - - fprintf(stderr, "[CONTROL_STATUS] AutoPageSize is %s", ( aStatus.GetControlWord() & EEControlBits::AUTOPAGESIZE ) ? "ON\n" : "OFF\n" ); + SAL_INFO("editeng.chaining", "[CONTROL_STATUS] AutoPageSize is " << (( aStatus.GetControlWord() & EEControlBits::AUTOPAGESIZE ) ? "ON" : "OFF") ); sal_uInt32 nBoxHeight = GetMaxAutoPaperSize().Height(); - fprintf(stderr, "[OVERFLOW-CHECK] Current MaxAutoPaperHeight is %d\n", nBoxHeight); + SAL_INFO("editeng.chaining", "[OVERFLOW-CHECK] Current MaxAutoPaperHeight is " << nBoxHeight); sal_uInt32 nTxtHeight = CalcTextHeight(NULL); - fprintf(stderr, "[OVERFLOW-CHECK] Current Text Height is %d\n", nTxtHeight); + SAL_INFO("editeng.chaining", "[OVERFLOW-CHECK] Current Text Height is " << nTxtHeight); sal_uInt32 nParaCount = GetParaPortions().Count(); sal_uInt32 nFirstLineCount = GetLineCount(0); @@ -4638,7 +4633,7 @@ void ImpEditEngine::ImplUpdateOverflowingParaNum(sal_uInt32 nPaperHeight) if ( nY > nPaperHeight /*nCurTextHeight*/ ) // found first paragraph overflowing { mnOverflowingPara = nPara; - fprintf(stderr, "[CHAINING] Setting first overflowing #Para#: %d\n", nPara); + SAL_INFO("editeng.chaining", "[CHAINING] Setting first overflowing #Para#: " << nPara); ImplUpdateOverflowingLineNum( nPaperHeight, nPara, nY-nPH); return; } @@ -4664,13 +4659,13 @@ void ImpEditEngine::ImplUpdateOverflowingLineNum(sal_uInt32 nPaperHeight, // Debugging output if (nLine == 0) { - fprintf(stderr, "[CHAINING] First line has height %d\n", nLH); + SAL_INFO("editeng.chaining", "[CHAINING] First line has height " << nLH); } if ( nY > nPaperHeight ) // found first line overflowing { mnOverflowingLine = nLine; - fprintf(stderr, "[CHAINING] Setting first overflowing -Line- to: %d\n", nLine); + SAL_INFO("editeng.chaining", "[CHAINING] Setting first overflowing -Line- to: " << nLine); return; } } diff --git a/editeng/source/outliner/outliner.cxx b/editeng/source/outliner/outliner.cxx index f0c982f..1f077c2 100644 --- a/editeng/source/outliner/outliner.cxx +++ b/editeng/source/outliner/outliner.cxx @@ -2081,17 +2081,16 @@ NonOverflowingText *Outliner::GetNonOverflowingText() const // Defensive check: oveflowing para index beyond actual # of paragraphs? if ( nCount > GetParagraphCount()-1) { - fprintf(stderr, - "[Overflowing] Ops, trying to retrieve para %d when max index is %d\n", - nCount, - GetParagraphCount()-1); + SAL_INFO("editeng.chaining", + "[Overflowing] Ops, trying to retrieve para " + << nCount << " when max index is " << GetParagraphCount()-1 ); return NULL; } if (nCount < 0) { - fprintf(stderr, - "[Overflowing] No Overflowing text but GetNonOverflowinText called?!\n"); + SAL_INFO("editeng.chaining", + "[Overflowing] No Overflowing text but GetNonOverflowinText called?!"); return NULL; } @@ -2189,10 +2188,10 @@ OverflowingText *Outliner::GetOverflowingText() const // Defensive check: oveflowing para index beyond actual # of paragraphs? if ( pEditEngine->GetOverflowingParaNum() > GetParagraphCount()-1) { - fprintf(stderr, - "[Overflowing] Ops, trying to retrieve para %d when max index is %d\n", - pEditEngine->GetOverflowingParaNum(), - GetParagraphCount()-1); + SAL_INFO("editeng.chaining", + "[Overflowing] Ops, trying to retrieve para " + << pEditEngine->GetOverflowingParaNum() << " when max index is " + << GetParagraphCount()-1 ); return NULL; } diff --git a/editeng/source/outliner/overflowingtxt.cxx b/editeng/source/outliner/overflowingtxt.cxx index 60120e5..0993e37 100644 --- a/editeng/source/outliner/overflowingtxt.cxx +++ b/editeng/source/outliner/overflowingtxt.cxx @@ -19,7 +19,6 @@ #include "rtl/ustring.hxx" #include "tools/debug.hxx" -#include "sal/info.hxx" #include "editeng/overflowingtxt.hxx" #include "editeng/outliner.hxx" @@ -158,11 +157,9 @@ bool NonOverflowingText::IsLastParaInterrupted() const OutlinerParaObject *NonOverflowingText::RemoveOverflowingText(Outliner *pOutliner) const { pOutliner->QuickDelete(maContentSel); - fprintf(stderr, "Deleting selection from (Para: %d, Pos: %d) to (Para: %d, Pos: %d)\n", - maContentSel.nStartPara, - maContentSel.nStartPos, - maContentSel.nEndPara, - maContentSel.nEndPos); + SAL_INFO("editeng.chaining", "Deleting selection from (Para: " << maContentSel.nStartPara + << ", Pos: " << maContentSel.nStartPos << ") to (Para: " << maContentSel.nEndPara + << ", Pos: " << maContentSel.nEndPos << ")"); return pOutliner->CreateParaObject(); } @@ -213,10 +210,10 @@ OutlinerParaObject *OFlowChainedText::InsertOverflowingText(Outliner *pOutliner, return NULL; if (mbIsDeepMerge) { - fprintf(stderr, "[TEXTCHAINFLOW - OF] Deep merging paras\n" ); + SAL_INFO("editeng.chaining", "[TEXTCHAINFLOW - OF] Deep merging paras" ); return mpOverflowingTxt->DeeplyMergeParaObject(pOutliner, pTextToBeMerged ); } else { - fprintf(stderr, "[TEXTCHAINFLOW - OF] Juxtaposing paras\n" ); + SAL_INFO("editeng.chaining", "[TEXTCHAINFLOW - OF] Juxtaposing paras" ); return mpOverflowingTxt->JuxtaposeParaObject(pOutliner, pTextToBeMerged ); } } @@ -249,11 +246,11 @@ OutlinerParaObject *UFlowChainedText::CreateMergedUnderflowParaObject(Outliner * OutlinerParaObject *pNewText = NULL; if (mbIsDeepMerge) { - fprintf(stderr, "[TEXTCHAINFLOW - UF] Deep merging paras\n" ); + SAL_INFO("editeng.chaining", "[TEXTCHAINFLOW - UF] Deep merging paras" ); pNewText = TextChainingUtils::DeeplyMergeParaObject(mxUnderflowingTxt, pOutl, pNextLinkWholeText); } else { // NewTextForCurBox = Txt(CurBox) ++ Txt(NextBox) - fprintf(stderr, "[TEXTCHAINFLOW - UF] Juxtaposing paras\n" ); + SAL_INFO("editeng.chaining", "[TEXTCHAINFLOW - UF] Juxtaposing paras" ); pNewText = TextChainingUtils::JuxtaposeParaObject(mxUnderflowingTxt, pOutl, pNextLinkWholeText); } diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx index 0b477ca..0d7d013 100644 --- a/svx/source/svdraw/svdedxv.cxx +++ b/svx/source/svdraw/svdedxv.cxx @@ -543,7 +543,7 @@ void SdrObjEditView::ImpChainingEventHdl() pTextChain->SetNilChainingEvent(pTextObj, false); } else { // XXX - fprintf(stderr, "[OnChaining] No Edit Outliner View\n"); + SAL_INFO("svx.chaining", "[OnChaining] No Edit Outliner View"); } } diff --git a/svx/source/svdraw/svdotext.cxx b/svx/source/svdraw/svdotext.cxx index 55948aa..cc3f479 100644 --- a/svx/source/svdraw/svdotext.cxx +++ b/svx/source/svdraw/svdotext.cxx @@ -2020,7 +2020,7 @@ void ImpUpdateChainLinks(SdrTextObj *pTextObj, OUString aNextLinkName) SdrTextObj *pNextTextObj = dynamic_cast< SdrTextObj * > (ImpGetObjByName(pPage, aNextLinkName)); if (!pNextTextObj) { - fprintf(stderr, "[CHAINING] Can't find object as next link.\n"); + SAL_INFO("svx.chaining", "[CHAINING] Can't find object as next link."); return; } @@ -2061,25 +2061,21 @@ void SdrTextObj::onChainingEvent() EditingTextChainFlow aTxtChainFlow(this); aTxtChainFlow.CheckForFlowEvents(pEdtOutl); - if (aTxtChainFlow.IsOverflow()) { - fprintf(stderr, "[CHAINING] Overflow going on\n"); + SAL_INFO("svx.chaining", "[CHAINING] Overflow going on"); // One outliner is for non-overflowing text, the other for overflowing text // We remove text directly from the editing outliner aTxtChainFlow.ExecuteOverflow(pEdtOutl, &aDrawOutliner); } else if (aTxtChainFlow.IsUnderflow()) { - fprintf(stderr, "[CHAINING] Underflow going on\n"); + SAL_INFO("svx.chaining", "[CHAINING] Underflow going on"); // underflow-induced overflow aTxtChainFlow.ExecuteUnderflow(&aDrawOutliner); bool bIsOverflowFromUnderflow = aTxtChainFlow.IsOverflow(); // handle overflow if (bIsOverflowFromUnderflow) { - fprintf(stderr, "[CHAINING] Overflow going on (underflow induced)\n"); + SAL_INFO("svx.chaining", "[CHAINING] Overflow going on (underflow induced)"); // prevents infinite loops when setting text for editing outliner - - aTxtChainFlow.ExecuteOverflow(&aDrawOutliner, &aDrawOutliner); - } } } diff --git a/svx/source/svdraw/svdotextdecomposition.cxx b/svx/source/svdraw/svdotextdecomposition.cxx index be19e39..3ad8f71 100644 --- a/svx/source/svdraw/svdotextdecomposition.cxx +++ b/svx/source/svdraw/svdotextdecomposition.cxx @@ -1425,7 +1425,7 @@ void SdrTextObj::impHandleChainingEventsDuringDecomposition(SdrOutliner &rOutlin SdrTextObj *pCurObj = (SdrTextObj *) pPage->GetObj(i); if (pCurObj == this) { - fprintf(stderr, "Working on TextBox %d\n", i); + SAL_INFO("svx.chaining", "Working on TextBox " << i); break; } } diff --git a/svx/source/svdraw/textchainflow.cxx b/svx/source/svdraw/textchainflow.cxx index 3286b86..71d4649 100644 --- a/svx/source/svdraw/textchainflow.cxx +++ b/svx/source/svdraw/textchainflow.cxx @@ -28,7 +28,7 @@ TextChainFlow::TextChainFlow(SdrTextObj *pChainTarget) : mpTargetLink(pChainTarget) { - fprintf(stderr, "\n[TEXTCHAINFLOW] Creating a new TextChainFlow\n"); + SAL_INFO("svx.chaining", "[TEXTCHAINFLOW] Creating a new TextChainFlow"); mpTextChain = mpTargetLink->GetTextChain(); mpNextLink = mpTargetLink->GetNextLinkInChain(); @@ -205,7 +205,8 @@ void TextChainFlow::impLeaveOnlyNonOverflowingText(SdrOutliner *pNonOverflOutl) { OutlinerParaObject *pNewText = mpOverflChText->RemoveOverflowingText(pNonOverflOutl); - fprintf(stderr, "[TEXTCHAINFLOW - OF] SOURCE box set to %d paras \n", pNewText->GetTextObject().GetParagraphCount()); + SAL_INFO("svx.chaining", "[TEXTCHAINFLOW - OF] SOURCE box set to " + << pNewText->GetTextObject().GetParagraphCount() << " paras"); // adds it to current outliner anyway (useful in static decomposition) pNonOverflOutl->SetText(*pNewText); @@ -221,20 +222,22 @@ void TextChainFlow::impMoveChainedTextToNextLink(SdrOutliner *pOverflOutl) { // prevent copying text in same box if ( mpNextLink == mpTargetLink ) { - fprintf(stderr, "[CHAINING] Trying to copy text for next link in same object\n"); + SAL_INFO("svx.chaining", "[CHAINING] Trying to copy text for next link in same object"); return; } OutlinerParaObject *pNewText = mpOverflChText->InsertOverflowingText(pOverflOutl, mpNextLink->GetOutlinerParaObject()); - fprintf(stderr, "[TEXTCHAINFLOW - OF] DEST box set to %d paras \n", pNewText->GetTextObject().GetParagraphCount()); + SAL_INFO("svx.chaining", "[TEXTCHAINFLOW - OF] DEST box set to " + << pNewText->GetTextObject().GetParagraphCount() << " paras"); if (pNewText) mpNextLink->NbcSetOutlinerParaObject(pNewText); // Set Deep Merge status - fprintf(stderr, "[DEEPMERGE] Setting deepMerge to %d\n", mpOverflChText->IsLastParaInterrupted()); + SAL_INFO("svx.chaining", "[DEEPMERGE] Setting deepMerge to " + << mpOverflChText->IsLastParaInterrupted()); GetTextChain()->SetIsPartOfLastParaInNextLink( mpTargetLink, mpOverflChText->IsLastParaInterrupted()); @@ -284,7 +287,7 @@ UFlowChainedText *TextChainFlow::GetUnderflowChainedText() const EditingTextChainFlow::EditingTextChainFlow(SdrTextObj *pLinkTarget) : TextChainFlow(pLinkTarget) { - fprintf(stderr, "[TEXTCHAINFLOW] Creating a new EditingTextChainFlow\n"); + SAL_INFO("svx.chaining", "[TEXTCHAINFLOW] Creating a new EditingTextChainFlow"); } void EditingTextChainFlow::CheckForFlowEvents(SdrOutliner *pFlowOutl) commit b9e1cb098b2b064528c078cdd91ae69e4425c4d6 Author: matteocam <matteo.campane...@gmail.com> Date: Mon Sep 7 20:01:35 2015 +0200 chained editeng: Handle chaining for cutting and pasting Change-Id: Iec08e339a7f06c5fa56e67b42206b31c766f845b diff --git a/editeng/source/outliner/outlvw.cxx b/editeng/source/outliner/outlvw.cxx index 4a0d96e..edf617f 100644 --- a/editeng/source/outliner/outlvw.cxx +++ b/editeng/source/outliner/outlvw.cxx @@ -675,8 +675,12 @@ void OutlinerView::InsertText( const OutlinerParaObject& rParaObj ) void OutlinerView::Cut() { - if ( !ImpCalcSelectedPages( false ) || pOwner->ImpCanDeleteSelectedPages( this ) ) + if ( !ImpCalcSelectedPages( false ) || pOwner->ImpCanDeleteSelectedPages( this ) ) { pEditView->Cut(); + // Chaining handling + if (aEndCutPasteLink.IsSet()) + aEndCutPasteLink.Call(NULL); + } } void OutlinerView::Paste() @@ -705,6 +709,11 @@ void OutlinerView::PasteSpecial() pEditView->SetEditEngineUpdateMode( true ); pOwner->UndoActionEnd( OLUNDO_INSERT ); pEditView->ShowCursor( true ); + + // Chaining handling + // NOTE: We need to do this last because it pEditView may be deleted if a switch of box occurs + if (aEndCutPasteLink.IsSet()) + aEndCutPasteLink.Call(NULL); } } commit c9e0b17b74a7daba6b447b6dfa00b0734086f27e Author: matteocam <matteo.campane...@gmail.com> Date: Mon Sep 7 19:58:16 2015 +0200 chained editeng: Handle DEL key for chaining Change-Id: I124b1adf6df3c42a58d45eaeb0e1e053c0eea4c9 diff --git a/sd/source/ui/view/drviewse.cxx b/sd/source/ui/view/drviewse.cxx index da65984..d9e0a99 100644 --- a/sd/source/ui/view/drviewse.cxx +++ b/sd/source/ui/view/drviewse.cxx @@ -950,7 +950,10 @@ void DrawViewShell::FuSupport(SfxRequest& rReq) { vcl::KeyCode aKCode(KEY_DELETE); KeyEvent aKEvt( 0, aKCode); - pOLV->PostKeyEvent(aKEvt); + //pOLV->PostKeyEvent(aKEvt); + // We use SdrObjEditView to handle DEL for underflow handling + mpDrawView->KeyInput(aKEvt, NULL); + } } else commit b290d18432089193f44e487009ba4b501ecf9c29 Author: matteocam <matteo.campane...@gmail.com> Date: Mon Sep 7 16:37:56 2015 +0200 chained editeng: Enable chaining after a key is pressed Change-Id: I64351619dd0886f3bb0c080557864c46a17d737d diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx index 9dbf0ab..0b477ca 100644 --- a/svx/source/svdraw/svdedxv.cxx +++ b/svx/source/svdraw/svdedxv.cxx @@ -1312,6 +1312,15 @@ bool SdrObjEditView::KeyInput(const KeyEvent& rKEvt, vcl::Window* pWin) { if(pTextEditOutlinerView) { + /* Start special handling of keys within a chain */ + // We possibly move to another box before any handling + bool bHandled = false; + TextChainCursorManager *pCursorManager = + ImpHandleMotionThroughBoxesKeyInput(rKEvt, pWin, &bHandled); + if (bHandled) + return true; + /* End special handling of keys within a chain */ + if (pTextEditOutlinerView->PostKeyEvent(rKEvt, pWin)) { if( mpModel ) @@ -1320,6 +1329,11 @@ bool SdrObjEditView::KeyInput(const KeyEvent& rKEvt, vcl::Window* pWin) mpModel->SetChanged(); } + /* Start chaining processing */ + ImpChainingEventHdl(); + ImpMoveCursorAfterChainingEvent(pCursorManager); + /* End chaining processing */ + if (pWin!=NULL && pWin!=pTextEditWin) SetTextEditWin(pWin); #ifdef DBG_UTIL if (mpItemBrowser!=nullptr) mpItemBrowser->SetDirty(); commit 938eb9b6c4be4638f7ffcdb93c3d2974dd660b9b Author: matteocam <matteo.campane...@gmail.com> Date: Mon Sep 7 16:33:39 2015 +0200 chained editeng: Add methods and basic setup for editing-mode chaining Change-Id: I8065bebaf2a54170bc7b3ddbd35740bcca42298d diff --git a/include/svx/svdedxv.hxx b/include/svx/svdedxv.hxx index 5dc3514..bec7338 100644 --- a/include/svx/svdedxv.hxx +++ b/include/svx/svdedxv.hxx @@ -34,6 +34,7 @@ class EditFieldInfo; class ImpSdrEditPara; struct PasteOrDropInfos; class SdrUndoManager; +class TextChainCursorManager; namespace com { namespace sun { namespace star { namespace uno { class Any; @@ -101,6 +102,10 @@ protected: // provide their document UndoManager and derive it from SdrUndoManager. virtual SdrUndoManager* getSdrUndoManagerForEnhancedTextEdit() const; + void ImpMoveCursorAfterChainingEvent(TextChainCursorManager *pCursorManager); + TextChainCursorManager *ImpHandleMotionThroughBoxesKeyInput(const KeyEvent& rKEvt, vcl::Window* pWin, bool *bOutHandled); + + OutlinerView* ImpFindOutlinerView(vcl::Window* pWin) const; // Create a new OutlinerView at the heap and initialize all required parameters. @@ -109,6 +114,11 @@ protected: void ImpPaintOutlinerView(OutlinerView& rOutlView, const Rectangle& rRect, OutputDevice& rTargetDevice) const; void ImpInvalidateOutlinerView(OutlinerView& rOutlView) const; + // Chaining + void ImpChainingEventHdl(); + DECL_LINK(ImpAfterCutOrPasteChainingEventHdl,void*); + + // Check if the whole text is selected. // Still returns sal_True if there is no text present. bool ImpIsTextEditAllSelected() const; diff --git a/sd/source/ui/view/outlview.cxx b/sd/source/ui/view/outlview.cxx index 6bb82ad7..79c3c30 100644 --- a/sd/source/ui/view/outlview.cxx +++ b/sd/source/ui/view/outlview.cxx @@ -1370,6 +1370,7 @@ void OutlineView::ResetLinks() const mrOutliner.SetDrawPortionHdl(Link<DrawPortionInfo*,void>()); mrOutliner.SetBeginPasteOrDropHdl(Link<PasteOrDropInfos*,void>()); mrOutliner.SetEndPasteOrDropHdl(Link<PasteOrDropInfos*,void>()); + mrOutliner.SetChainingEventHdl(aEmptyLink); } sal_Int8 OutlineView::AcceptDrop( const AcceptDropEvent&, DropTargetHelper&, ::sd::Window*, sal_uInt16, sal_uInt16) diff --git a/sd/source/ui/view/sdview.cxx b/sd/source/ui/view/sdview.cxx index 18fbf2e..524faba 100644 --- a/sd/source/ui/view/sdview.cxx +++ b/sd/source/ui/view/sdview.cxx @@ -1204,6 +1204,7 @@ void View::OnBeginPasteOrDrop( PasteOrDropInfos* /*pInfos*/ ) get the correct style sheet. */ void View::OnEndPasteOrDrop( PasteOrDropInfos* pInfos ) { + /* Style Sheet handling */ SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( GetTextEditObject() ); SdrOutliner* pOutliner = GetTextEditOutliner(); if( pOutliner && pTextObj && pTextObj->GetPage() ) diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx index ea6ae00..9dbf0ab 100644 --- a/svx/source/svdraw/svdedxv.cxx +++ b/svx/source/svdraw/svdedxv.cxx @@ -51,6 +51,8 @@ #include "svx/svdstr.hrc" #include "svdglob.hxx" #include "svx/globl3d.hxx" +#include <svx/textchain.hxx> +#include <svx/textchaincursor.hxx> #include <editeng/outliner.hxx> #include <editeng/adjustitem.hxx> #include <svtools/colorcfg.hxx> @@ -486,6 +488,102 @@ IMPL_LINK_TYPED(SdrObjEditView,ImpOutlinerStatusEventHdl, EditStatus&, rEditStat } } +void SdrObjEditView::ImpChainingEventHdl() +{ + if(pTextEditOutliner ) + { + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj * >( mxTextEditObj.get() ); + OutlinerView* pOLV = GetTextEditOutlinerView(); + if( pTextObj && pOLV) + { + TextChain *pTextChain = pTextObj->GetTextChain(); + + // XXX: IsChainable and GetNilChainingEvent are a bit mixed up atm + if (!pTextObj->IsChainable()) { + return; + } + // This is true during an underflow-caused overflow (with pEdtOutl->SetText()) + if (pTextChain->GetNilChainingEvent(pTextObj)) { + return; + } + + // We prevent to trigger further handling of overflow/underflow for pTextObj + pTextChain->SetNilChainingEvent(pTextObj, true); // XXX + + // Save previous selection pos // NOTE: It must be done to have the right CursorEvent in KeyInput + pTextChain->SetPreChainingSel(pTextObj, pOLV->GetSelection()); + //maPreChainingSel = new ESelection(pOLV->GetSelection()); + + // Handling Undo + const int nText = 0; // XXX: hardcoded index (SdrTextObj::getText handles only 0) + + SdrUndoObjSetText *pTxtUndo = dynamic_cast< SdrUndoObjSetText* > + ( GetModel()->GetSdrUndoFactory().CreateUndoObjectSetText(*pTextObj, nText ) ); + + // trigger actual chaining + pTextObj->onChainingEvent(); + + if (pTxtUndo!=NULL) + { + pTxtUndo->AfterSetText(); + if (!pTxtUndo->IsDifferent()) + { + delete pTxtUndo; + pTxtUndo=NULL; + } + } + + if (pTxtUndo) + AddUndo(pTxtUndo); + + //maCursorEvent = new CursorChainingEvent(pTextChain->GetCursorEvent(pTextObj)); + //SdrTextObj *pNextLink = pTextObj->GetNextLinkInChain(); + + // NOTE: Must be called. Don't let the function return if you set it to true and not reset it + pTextChain->SetNilChainingEvent(pTextObj, false); + } else { + // XXX + fprintf(stderr, "[OnChaining] No Edit Outliner View\n"); + } + } + +} + +IMPL_LINK_NOARG(SdrObjEditView,ImpAfterCutOrPasteChainingEventHdl) +{ + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj * >( GetTextEditObject()); + if (!pTextObj) + return 0; + ImpChainingEventHdl(); + TextChainCursorManager *pCursorManager = new TextChainCursorManager(this, pTextObj); + ImpMoveCursorAfterChainingEvent(pCursorManager); + return 0; +} + +void SdrObjEditView::ImpMoveCursorAfterChainingEvent(TextChainCursorManager *pCursorManager) +{ + if (!mxTextEditObj.is() || !pCursorManager) + return; + + SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>(mxTextEditObj.get()); + + // Check if it has links to move it to + if (!pTextObj->IsChainable()) + return; + + TextChain *pTextChain = pTextObj->GetTextChain(); + ESelection aNewSel = pTextChain->GetPostChainingSel(pTextObj); + + + pCursorManager->HandleCursorEventAfterChaining( + pTextChain->GetCursorEvent(pTextObj), + aNewSel); + + // Reset event + pTextChain->SetCursorEvent(pTextObj, CursorChainingEvent::NULL_EVENT); +} + + IMPL_LINK_TYPED(SdrObjEditView,ImpOutlinerCalcFieldValueHdl,EditFieldInfo*,pFI,void) { bool bOk=false; @@ -724,6 +822,10 @@ bool SdrObjEditView::SdrBeginTextEdit( pTextEditOutlinerView->ShowCursor(); pTextEditOutliner->SetStatusEventHdl(LINK(this,SdrObjEditView,ImpOutlinerStatusEventHdl)); + if (pTextObj->IsChainable()) { + pTextEditOutlinerView->SetEndCutPasteLinkHdl(LINK(this,SdrObjEditView,ImpAfterCutOrPasteChainingEventHdl) ); + } + #ifdef DBG_UTIL if (mpItemBrowser!=nullptr) mpItemBrowser->SetDirty(); #endif @@ -913,6 +1015,8 @@ SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(bool bDontDeleteReally) pTEOutliner->SetBeginPasteOrDropHdl(Link<PasteOrDropInfos*,void>()); pTEOutliner->SetEndPasteOrDropHdl(Link<PasteOrDropInfos*,void>()); + pTEOutliner->SetChainingEventHdl(Link<>()); + const bool bUndo = IsUndoEnabled(); if( bUndo ) { @@ -1176,6 +1280,32 @@ bool SdrObjEditView::IsTextEditFrameHit(const Point& rHit) const return bOk; } +TextChainCursorManager *SdrObjEditView::ImpHandleMotionThroughBoxesKeyInput( + const KeyEvent& rKEvt, + vcl::Window*, + bool *bOutHandled) +{ + *bOutHandled = false; + + SdrTextObj* pTextObj = NULL; + if (mxTextEditObj.is()) + pTextObj= dynamic_cast<SdrTextObj*>(mxTextEditObj.get()); + else + return NULL; + + if (!pTextObj->GetNextLinkInChain() && !pTextObj->GetPrevLinkInChain()) + return NULL; + + TextChainCursorManager *pCursorManager = new TextChainCursorManager(this, pTextObj); + if( pCursorManager->HandleKeyEvent(rKEvt) ) { + // Possibly do other stuff here if necessary... + // XXX: Careful with the checks below (in KeyInput) for pWin and co. You should do them here I guess. + *bOutHandled = true; + } + + return pCursorManager; +} + bool SdrObjEditView::KeyInput(const KeyEvent& rKEvt, vcl::Window* pWin) commit 87cf1959aa595e4f3f847ddf97a6e06fa572674d Author: matteocam <matteo.campane...@gmail.com> Date: Mon Sep 7 12:44:37 2015 +0200 chained editeng: Change EndTextEdit behavior to support recursive overflow Change-Id: I14009fa2e91b19a850e45484de7cd234e872689a diff --git a/svx/source/svdraw/svdotxed.cxx b/svx/source/svdraw/svdotxed.cxx index c68b085..4e07027 100644 --- a/svx/source/svdraw/svdotxed.cxx +++ b/svx/source/svdraw/svdotxed.cxx @@ -23,10 +23,12 @@ #include <svx/svdoutl.hxx> #include <editeng/editdata.hxx> #include <editeng/outliner.hxx> +#include <editeng/overflowingtxt.hxx> #include <editeng/editstat.hxx> #include <svl/itemset.hxx> #include <editeng/eeitem.hxx> #include <svx/sdtfchim.hxx> +#include <svx/textchain.hxx> bool SdrTextObj::HasTextEdit() const @@ -126,6 +128,19 @@ bool SdrTextObj::BegTextEdit(SdrOutliner& rOutl) return true; } +void ImpUpdateOutlParamsForOverflow(SdrOutliner *pOutl, SdrTextObj *pTextObj) +{ + // Code from ImpSetTextEditParams + Size aPaperMin; + Size aPaperMax; + Rectangle aEditArea; + pTextObj->TakeTextEditArea(&aPaperMin,&aPaperMax,&aEditArea,NULL); + + pOutl->SetMinAutoPaperSize(aPaperMin); + pOutl->SetMaxAutoPaperSize(aPaperMax); + pOutl->SetPaperSize(Size()); +} + void SdrTextObj::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, Rectangle* pViewInit, Rectangle* pViewMin) const { bool bFitToSize(IsFitToSize()); @@ -263,9 +278,10 @@ void SdrTextObj::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, Rectangle* p void SdrTextObj::EndTextEdit(SdrOutliner& rOutl) { + OutlinerParaObject* pNewText = NULL; + if(rOutl.IsModified()) { - OutlinerParaObject* pNewText = NULL; // to make the gray field background vanish again rOutl.UpdateFields(); @@ -277,8 +293,39 @@ void SdrTextObj::EndTextEdit(SdrOutliner& rOutl) // uses GetCurrentBoundRect() which needs to take the text into account // to work correct mbInEditMode = false; - SetOutlinerParaObject(pNewText); + + // We don't want broadcasting if we are merely trying to move to next box (this prevents infinite loops) + if (IsChainable() && GetTextChain()->GetSwitchingToNextBox(this)) { + GetTextChain()->SetSwitchingToNextBox(this, false); + if( getActiveText() ) + getActiveText()->SetOutlinerParaObject( pNewText); + } else { // If we are not doing in-chaining switching just set the ParaObject + SetOutlinerParaObject(pNewText); + } + } + + /* Beginning Chaining-related code */ + rOutl.ClearOverflowingParaNum(); + + /* Flush overflow for next textbox - Necessary for recursive chaining */ + if (false && + IsChainable() && + GetNextLinkInChain() && + GetTextChain()->GetPendingOverflowCheck(GetNextLinkInChain()) ) + { + GetTextChain()->SetPendingOverflowCheck(GetNextLinkInChain(), false); + + SdrOutliner rDrawOutl = GetNextLinkInChain()->ImpGetDrawOutliner(); + // Prepare Outliner for overflow check + ImpUpdateOutlParamsForOverflow(&rDrawOutl, GetNextLinkInChain()); + const OutlinerParaObject *pObj = GetNextLinkInChain()->GetOutlinerParaObject(); + rDrawOutl.SetText(*pObj); + + rDrawOutl.SetUpdateMode(true); + // XXX: Change name of method below to impHandleChainingEventsNonEditMode + GetNextLinkInChain()->impHandleChainingEventsDuringDecomposition(rDrawOutl); } + /* End Chaining-related code */ pEdtOutl = NULL; rOutl.Clear(); commit f1e81b2b7aab8b9ec65dec934c620a914fee0cab Author: matteocam <matteo.campane...@gmail.com> Date: Mon Sep 7 12:32:14 2015 +0200 chained editeng: Change size settings if box is chainable Change-Id: I3717324b3be36b9503cae195fd42249d92d2c685 diff --git a/svx/source/svdraw/svdotext.cxx b/svx/source/svdraw/svdotext.cxx index 8fd7bc2..55948aa 100644 --- a/svx/source/svdraw/svdotext.cxx +++ b/svx/source/svdraw/svdotext.cxx @@ -755,14 +755,19 @@ void SdrTextObj::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, boo if (eAniDirection==SDRTEXTANI_UP || eAniDirection==SDRTEXTANI_DOWN) nHgt=1000000; } - // #i119885# Do not limit/force height to geometrical frame (vice versa for vertical writing) - if(IsVerticalWriting()) - { - nWdt = 1000000; - } - else - { - nHgt = 1000000; + bool bChainedFrame = IsChainable(); + // Might be required for overflow check working: do limit height to frame if box is chainable. + if (!bChainedFrame) { + // #i119885# Do not limit/force height to geometrical frame (vice versa for vertical writing) + + if(IsVerticalWriting()) + { + nWdt = 1000000; + } + else + { + nHgt = 1000000; + } } rOutliner.SetMaxAutoPaperSize(Size(nWdt,nHgt)); diff --git a/svx/source/svdraw/svdotxed.cxx b/svx/source/svdraw/svdotxed.cxx index b0b2ccc..c68b085 100644 --- a/svx/source/svdraw/svdotxed.cxx +++ b/svx/source/svdraw/svdotxed.cxx @@ -62,6 +62,14 @@ bool SdrTextObj::BegTextEdit(SdrOutliner& rOutl) rOutl.SetControlWord(nStat); } + // disable AUTOPAGESIZE if IsChainable (might be required for overflow check) + if ( IsChainable() ) { + EEControlBits nStat1=rOutl.GetControlWord(); + nStat1 &=~EEControlBits::AUTOPAGESIZE; + rOutl.SetControlWord(nStat1); + } + + OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); if(pOutlinerParaObject!=NULL) { @@ -181,14 +189,18 @@ void SdrTextObj::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, Rectangle* p if (eAniDirection==SDRTEXTANI_UP || eAniDirection==SDRTEXTANI_DOWN) nMaxHgt=1000000; } - // #i119885# Do not limit/force height to geometrical frame (vice versa for vertical writing) - if(IsVerticalWriting()) - { - nMaxWdt = 1000000; - } - else - { - nMaxHgt = 1000000; + bool bChainedFrame = IsChainable(); + // Might be required for overflow check working: do limit height to frame if box is chainable. + if (!bChainedFrame) { + // #i119885# Do not limit/force height to geometrical frame (vice versa for vertical writing) + if(IsVerticalWriting()) + { + nMaxWdt = 1000000; + } + else + { + nMaxHgt = 1000000; + } } aPaperMax.Width()=nMaxWdt; commit b28e1b646e7e97bdac171085d8adecf2e4dad036 Author: matteocam <matteo.campane...@gmail.com> Date: Mon Sep 7 12:17:30 2015 +0200 chained editeng: Add Chaining-related UNO attribute Definition and mechanisms for UNO API. Change-Id: I7fd3969804ca9b04881ced0b1e43ab6236cbefcc diff --git a/include/editeng/unoprnms.hxx b/include/editeng/unoprnms.hxx index 0566288..498d417 100644 --- a/include/editeng/unoprnms.hxx +++ b/include/editeng/unoprnms.hxx @@ -113,6 +113,7 @@ #define UNO_NAME_TEXT_WRITINGMODE "TextWritingMode" #define UNO_NAME_TEXT_FONTINDEPENDENTLINESPACING "FontIndependentLineSpacing" #define UNO_NAME_TEXT_WORDWRAP "TextWordWrap" +#define UNO_NAME_TEXT_CHAINNEXTNAME "TextChainNextName" #define UNO_NAME_MEASUREKIND "MeasureKind" #define UNO_NAME_MEASURETEXTHPOS "MeasureTextHorizontalPosition" diff --git a/include/svx/svdstr.hrc b/include/svx/svdstr.hrc index 6663f01..d6bc94b 100644 --- a/include/svx/svdstr.hrc +++ b/include/svx/svdstr.hrc @@ -714,5 +714,7 @@ #define STR_TABLE_STYLE_SETTINGS (SIP_Begin + 275) #define SIP_SA_CROP_MARKERS (SIP_Begin + 276) #define STR_TABLE_DELETE_CELL_CONTENTS (SIP_Begin + 277) +#define SIP_SA_CHAINNEXTNAME (SIP_Begin + 278) + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/unoshprp.hxx b/include/svx/unoshprp.hxx index b7a95be..2f8e35e 100644 --- a/include/svx/unoshprp.hxx +++ b/include/svx/unoshprp.hxx @@ -291,6 +291,7 @@ { OUString(UNO_NAME_TEXT_FONTINDEPENDENTLINESPACING),SDRATTR_TEXT_USEFIXEDCELLHEIGHT,cppu::UnoType<bool>::get(), 0, 0}, \ { OUString(UNO_NAME_TEXT_VERTADJUST), SDRATTR_TEXT_VERTADJUST, cppu::UnoType<css::drawing::TextVerticalAdjust>::get(), 0, 0},\ { OUString(UNO_NAME_TEXT_WORDWRAP), SDRATTR_TEXT_WORDWRAP, cppu::UnoType<bool>::get(), 0, 0}, \ + { OUString(UNO_NAME_TEXT_CHAINNEXTNAME), SDRATTR_TEXT_CHAINNEXTNAME, ::cppu::UnoType<OUString>::get(), 0, 0}, \ SVX_UNOEDIT_CHAR_PROPERTIES, \ SVX_UNOEDIT_PARA_PROPERTIES, diff --git a/svx/source/svdraw/svdattr.cxx b/svx/source/svdraw/svdattr.cxx index 69fc2b5..0447ca8 100644 --- a/svx/source/svdraw/svdattr.cxx +++ b/svx/source/svdraw/svdattr.cxx @@ -162,6 +162,7 @@ SdrItemPool::SdrItemPool( mppLocalPoolDefaults[SDRATTR_TEXT_CONTOURFRAME -SDRATTR_START]=new SdrOnOffItem(SDRATTR_TEXT_CONTOURFRAME, false); mppLocalPoolDefaults[SDRATTR_CUSTOMSHAPE_ADJUSTMENT -SDRATTR_START]=new SdrCustomShapeAdjustmentItem; mppLocalPoolDefaults[SDRATTR_XMLATTRIBUTES -SDRATTR_START]=new SvXMLAttrContainerItem( SDRATTR_XMLATTRIBUTES ); + mppLocalPoolDefaults[SDRATTR_TEXT_CHAINNEXTNAME -SDRATTR_START]=new SfxStringItem(SDRATTR_TEXT_CHAINNEXTNAME, ""); mppLocalPoolDefaults[SDRATTR_TEXT_USEFIXEDCELLHEIGHT -SDRATTR_START]=new SdrTextFixedCellHeightItem; mppLocalPoolDefaults[SDRATTR_TEXT_WORDWRAP -SDRATTR_START]=new SdrOnOffItem(SDRATTR_TEXT_WORDWRAP, true); mppLocalPoolDefaults[SDRATTR_TEXT_AUTOGROWSIZE -SDRATTR_START]=new SdrOnOffItem(SDRATTR_TEXT_AUTOGROWSIZE, false); @@ -499,6 +500,7 @@ void SdrItemPool::TakeItemName(sal_uInt16 nWhich, OUString& rItemName) case SDRATTR_XMLATTRIBUTES : nResId = SIP_SA_XMLATTRIBUTES;break; case SDRATTR_TEXT_USEFIXEDCELLHEIGHT: nResId = SIP_SA_TEXT_USEFIXEDCELLHEIGHT;break; case SDRATTR_TEXT_WORDWRAP : nResId = SIP_SA_WORDWRAP;break; + case SDRATTR_TEXT_CHAINNEXTNAME : nResId = SIP_SA_CHAINNEXTNAME;break; case SDRATTR_TEXT_AUTOGROWSIZE : nResId = SIP_SA_AUTOGROWSIZE;break; case SDRATTR_EDGEKIND : nResId = SIP_SA_EDGEKIND;break; diff --git a/svx/source/svdraw/svdstr.src b/svx/source/svdraw/svdstr.src index f790f00..16383f8 100644 --- a/svx/source/svdraw/svdstr.src +++ b/svx/source/svdraw/svdstr.src @@ -2114,6 +2114,12 @@ String SIP_SA_WORDWRAP Text[ en-US ] = "Word wrap text in shape"; }; +String SIP_SA_CHAINNEXTNAME +{ + Text[ en-US ] = "Next link in text chain"; +}; + + String SIP_SA_AUTOGROWSIZE { Text[ en-US ] = "Auto grow shape to fit text"; diff --git a/svx/source/unodraw/unoshap2.cxx b/svx/source/unodraw/unoshap2.cxx index ae70d17..55a20ba 100644 --- a/svx/source/unodraw/unoshap2.cxx +++ b/svx/source/unodraw/unoshap2.cxx @@ -671,6 +671,7 @@ SvxShapeControlPropertyMapping[] = { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_EDIT_CHAR_COLOR), RTL_CONSTASCII_STRINGPARAM("TextColor") }, { RTL_CONSTASCII_STRINGPARAM("CharBackColor"), RTL_CONSTASCII_STRINGPARAM("CharBackColor") }, { RTL_CONSTASCII_STRINGPARAM("CharBackTransparent"), RTL_CONSTASCII_STRINGPARAM("CharBackTransparent") }, + { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_TEXT_CHAINNEXTNAME), RTL_CONSTASCII_STRINGPARAM(UNO_NAME_TEXT_CHAINNEXTNAME) }, { RTL_CONSTASCII_STRINGPARAM("CharRelief"), RTL_CONSTASCII_STRINGPARAM("FontRelief") }, { RTL_CONSTASCII_STRINGPARAM("CharUnderlineColor"), RTL_CONSTASCII_STRINGPARAM("TextLineColor") }, { RTL_CONSTASCII_STRINGPARAM(UNO_NAME_EDIT_PARA_ADJUST), RTL_CONSTASCII_STRINGPARAM("Align") }, diff --git a/xmloff/source/draw/sdpropls.cxx b/xmloff/source/draw/sdpropls.cxx index 442e5db..5896cc8 100644 --- a/xmloff/source/draw/sdpropls.cxx +++ b/xmloff/source/draw/sdpropls.cxx @@ -146,6 +146,7 @@ const XMLPropertyMapEntry aXMLSDProperties[] = GMAP( "NumberingRules", XML_NAMESPACE_TEXT, XML_LIST_STYLE, XML_SD_TYPE_NUMBULLET|MID_FLAG_ELEMENT_ITEM, CTF_NUMBERINGRULES ), GMAP( "NumberingRules", XML_NAMESPACE_TEXT, XML_LIST_STYLE_NAME, XML_TYPE_STRING, CTF_SD_NUMBERINGRULES_NAME ), GMAP( "TextWordWrap", XML_NAMESPACE_FO, XML_WRAP_OPTION, XML_TYPE_WRAP_OPTION, 0 ), + GMAP( "TextChainNextName", XML_NAMESPACE_DRAW, XML_CHAIN_NEXT_NAME, XML_TYPE_STRING, 0 ), // shadow attributes GMAP( "Shadow", XML_NAMESPACE_DRAW, XML_SHADOW, XML_SD_TYPE_SHADOW, 0 ), diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx index e5eb4a6..8a067f6 100644 --- a/xmloff/source/draw/ximpshap.cxx +++ b/xmloff/source/draw/ximpshap.cxx @@ -1600,7 +1600,8 @@ SdXMLTextBoxShapeContext::SdXMLTextBoxShapeContext( uno::Reference< drawing::XShapes >& rShapes, bool bTemporaryShape) : SdXMLShapeContext( rImport, nPrfx, rLocalName, xAttrList, rShapes, bTemporaryShape ), - mnRadius(0) + mnRadius(0), + maChainNextName("") { } @@ -1619,6 +1620,13 @@ void SdXMLTextBoxShapeContext::processAttribute( sal_uInt16 nPrefix, const OUStr mnRadius, rValue); return; } + + if( IsXMLToken( rLocalName, XML_CHAIN_NEXT_NAME ) ) + { + maChainNextName = rValue; + return; + } + } SdXMLShapeContext::processAttribute( nPrefix, rLocalName, rValue ); @@ -1752,6 +1760,23 @@ void SdXMLTextBoxShapeContext::StartElement(const uno::Reference< xml::sax::XAtt } } + if(maChainNextName != "") + { + uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY); + if(xPropSet.is()) + { + try + { + xPropSet->setPropertyValue("TextChainNextName", + uno::makeAny( maChainNextName ) ); + } + catch(const uno::Exception&) + { + OSL_FAIL( "exception during setting of name of next chain link!"); + } + } + } + SdXMLShapeContext::StartElement(mxAttrList); } } diff --git a/xmloff/source/draw/ximpshap.hxx b/xmloff/source/draw/ximpshap.hxx index 73c9d8c..fdf1e70 100644 --- a/xmloff/source/draw/ximpshap.hxx +++ b/xmloff/source/draw/ximpshap.hxx @@ -247,6 +247,7 @@ public: class SdXMLTextBoxShapeContext : public SdXMLShapeContext { sal_Int32 mnRadius; + OUString maChainNextName; public: TYPEINFO_OVERRIDE(); commit ecf8c69ee793054f2a6b77e89141ec309967d0e7 Author: matteocam <matteo.campane...@gmail.com> Date: Mon Sep 7 11:37:27 2015 +0200 chained editeng: Add chaining attributes and chaining primitive creation logic Change-Id: I957d5261dd847fe5e950441585e879cfd5ae2fb2 diff --git a/include/svx/sdr/attribute/sdrtextattribute.hxx b/include/svx/sdr/attribute/sdrtextattribute.hxx index 66e3e7a..7d5de1d 100644 --- a/include/svx/sdr/attribute/sdrtextattribute.hxx +++ b/include/svx/sdr/attribute/sdrtextattribute.hxx @@ -76,7 +76,10 @@ namespace drawinglayer bool bScroll, bool bInEditMode, bool bFixedCellHeight, - bool bWrongSpell); + bool bWrongSpell, + bool bToBeChained, + bool bChainable); + SdrTextAttribute(); SdrTextAttribute(const SdrTextAttribute& rCandidate); SdrTextAttribute& operator=(const SdrTextAttribute& rCandidate); @@ -107,6 +110,10 @@ namespace drawinglayer SdrTextHorzAdjust getSdrTextHorzAdjust() const; SdrTextVertAdjust getSdrTextVertAdjust() const; + bool isToBeChained() const; + bool isChainable() const; + + // helpers: animation timing generators void getBlinkTextTiming( drawinglayer::animation::AnimationEntryList& rAnimList) const; diff --git a/svx/source/sdr/attribute/sdrtextattribute.cxx b/svx/source/sdr/attribute/sdrtextattribute.cxx index ddd1ce1..cefefb1 100644 --- a/svx/source/sdr/attribute/sdrtextattribute.cxx +++ b/svx/source/sdr/attribute/sdrtextattribute.cxx @@ -67,6 +67,10 @@ namespace drawinglayer bool mbFixedCellHeight : 1; bool mbWrongSpell : 1; + bool mbToBeChained : 1; + bool mbChainable : 1; + + public: ImpSdrTextAttribute( const SdrText* pSdrText, @@ -86,7 +90,9 @@ namespace drawinglayer bool bScroll, bool bInEditMode, bool bFixedCellHeight, - bool bWrongSpell) + bool bWrongSpell, + bool bToBeChained, + bool bChainable) : mpSdrText(pSdrText), mxOutlinerParaObject(new OutlinerParaObject(rOutlinerParaObject)), maSdrFormTextAttribute(), @@ -105,7 +111,9 @@ namespace drawinglayer mbScroll(bScroll), mbInEditMode(bInEditMode), mbFixedCellHeight(bFixedCellHeight), - mbWrongSpell(bWrongSpell) + mbWrongSpell(bWrongSpell), + mbToBeChained(bToBeChained), + mbChainable(bChainable) { if(pSdrText) { @@ -141,7 +149,9 @@ namespace drawinglayer mbScroll(false), mbInEditMode(false), mbFixedCellHeight(false), - mbWrongSpell(false) + mbWrongSpell(false), + mbToBeChained(false), + mbChainable(false) { } @@ -167,6 +177,8 @@ namespace drawinglayer bool isInEditMode() const { return mbInEditMode; } bool isFixedCellHeight() const { return mbFixedCellHeight; } bool isWrongSpell() const { return mbWrongSpell; } + bool isToBeChained() const { return mbToBeChained; } + bool isChainable() const { return mbChainable; } const SdrFormTextAttribute& getSdrFormTextAttribute() const { return maSdrFormTextAttribute; } sal_Int32 getTextLeftDistance() const { return maTextLeftDistance; } sal_Int32 getTextUpperDistance() const { return maTextUpperDistance; } @@ -225,7 +237,8 @@ namespace drawinglayer && isScroll() == rCandidate.isScroll() && isInEditMode() == rCandidate.isInEditMode() && isFixedCellHeight() == rCandidate.isFixedCellHeight() - && isWrongSpell() == rCandidate.isWrongSpell()); + && isWrongSpell() == rCandidate.isWrongSpell() + && isToBeChained() == rCandidate.isToBeChained() ); } }; @@ -253,13 +266,16 @@ namespace drawinglayer bool bScroll, bool bInEditMode, bool bFixedCellHeight, - bool bWrongSpell) + bool bWrongSpell, + bool bIsToBeChained, + bool bChainable) : mpSdrTextAttribute( ImpSdrTextAttribute( &rSdrText, rOutlinerParaObject, eFormTextStyle, aTextLeftDistance, aTextUpperDistance, aTextRightDistance, aTextLowerDistance, aSdrTextHorzAdjust, aSdrTextVertAdjust, bContour, bFitToSize, bAutoFit, - bHideContour, bBlink, bScroll, bInEditMode, bFixedCellHeight, bWrongSpell)) + bHideContour, bBlink, bScroll, bInEditMode, bFixedCellHeight, bWrongSpell, + bIsToBeChained, bChainable)) { } @@ -342,6 +358,17 @@ namespace drawinglayer return mpSdrTextAttribute->isInEditMode(); } + bool SdrTextAttribute::isToBeChained() const + { + return mpSdrTextAttribute->isToBeChained(); + } + + bool SdrTextAttribute::isChainable() const + { + return mpSdrTextAttribute->isChainable(); + } + + bool SdrTextAttribute::isFixedCellHeight() const { return mpSdrTextAttribute->isFixedCellHeight(); diff --git a/svx/source/sdr/primitive2d/sdrattributecreator.cxx b/svx/source/sdr/primitive2d/sdrattributecreator.cxx index 5222367..2ec29ed 100644 --- a/svx/source/sdr/primitive2d/sdrattributecreator.cxx +++ b/svx/source/sdr/primitive2d/sdrattributecreator.cxx @@ -520,6 +520,11 @@ namespace drawinglayer { const SdrTextObj& rTextObj = rText.GetObject(); + // Save chaining attributes + bool bToBeChained = rTextObj.IsToBeChained(); + bool bChainable = rTextObj.IsChainable(); + + if(rText.GetOutlinerParaObject() && rText.GetModel()) { // added TextEdit text suppression @@ -578,7 +583,9 @@ namespace drawinglayer SDRTEXTANI_SCROLL == eAniKind || SDRTEXTANI_ALTERNATE == eAniKind || SDRTEXTANI_SLIDE == eAniKind, bInEditMode, static_cast<const SdrTextFixedCellHeightItem&>(rSet.Get(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue(), - bWrongSpell); + bWrongSpell, + bToBeChained, + bChainable); } return attribute::SdrTextAttribute(); diff --git a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx index ddc6608..390683f 100644 --- a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx +++ b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx @@ -307,7 +307,18 @@ namespace drawinglayer else if(rText.isAutoFit()) { // isotrophically scaled text in range - pNew = new SdrAutoFitTextPrimitive2D(&rText.getSdrText(), rText.getOutlinerParaObject(), aAnchorTransform, bWordWrap); + pNew = new SdrAutoFitTextPrimitive2D( + &rText.getSdrText(), + rText.getOutlinerParaObject(), + aAnchorTransform, + bWordWrap); + } + else if( rText.isChainable() && !rText.isInEditMode() ) + { + pNew = new SdrChainedTextPrimitive2D( + &rText.getSdrText(), + rText.getOutlinerParaObject(), + aAnchorTransform ); } else // text in range { commit 17b9641cc74798769ea00f07df59a38e2a6fdb6c Author: matteocam <matteo.campane...@gmail.com> Date: Sun Sep 6 12:06:47 2015 +0200 chained editeng: Enhance existing svx classes with chaining-related methods Change-Id: I10829d8f07f8881af6d1a9422cbdae00e83a7ac8 diff --git a/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx b/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx index 0fae52a..1161f2c 100644 --- a/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx +++ b/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx @@ -48,6 +48,7 @@ #define PRIMITIVE2D_ID_SDRCONTROLPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_SVX| 21) #define PRIMITIVE2D_ID_SDROLECONTENTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_SVX| 22) #define PRIMITIVE2D_ID_SDRAUTOFITTEXTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_SVX| 23) +#define PRIMITIVE2D_ID_SDRCHAINEDTEXTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_SVX| 24) diff --git a/include/svx/svddef.hxx b/include/svx/svddef.hxx index 0e92e7f..5b3e5e9 100644 --- a/include/svx/svddef.hxx +++ b/include/svx/svddef.hxx @@ -112,7 +112,8 @@ #define SDRATTR_TEXT_USEFIXEDCELLHEIGHT (SDRATTR_MISC_FIRST +24) /* 1121 */ /* 1121 */ /* 1104 */ /* Pool V2 */ #define SDRATTR_TEXT_WORDWRAP (SDRATTR_MISC_FIRST +25) /* 1122 */ /* 1122 */ /* 1105 */ /* Pool V2 */ #define SDRATTR_TEXT_AUTOGROWSIZE (SDRATTR_MISC_FIRST +26) /* 1123 */ /* 1123 */ /* 1106 */ /* Pool V2 */ -#define SDRATTR_MISC_LAST (SDRATTR_TEXT_AUTOGROWSIZE) /* 1125 */ /* 1125 */ /* 1108 */ /* Pool V1: 1056 */ +#define SDRATTR_TEXT_CHAINNEXTNAME (SDRATTR_MISC_FIRST + 27) /* 1124 */ /* 11124 */ +#define SDRATTR_MISC_LAST (SDRATTR_TEXT_CHAINNEXTNAME) /* 1125 */ /* 1125 */ /* 1108 */ /* Pool V1: 1056 */ #define SDRATTR_EDGE_FIRST (SDRATTR_MISC_LAST + 1) /* 1127 */ /* Pool V4 */ #define SDRATTR_EDGEKIND (SDRATTR_EDGE_FIRST + 0) /* 1127 */ /* Pool V4 */ diff --git a/include/svx/svdmodel.hxx b/include/svx/svdmodel.hxx index 194a3e1..d571af7 100644 --- a/include/svx/svdmodel.hxx +++ b/include/svx/svdmodel.hxx @@ -76,6 +76,7 @@ class SvNumberFormatter; class SdrOutlinerCache; class SdrUndoFactory; class ImageMap; +class TextChain; namespace comphelper { class IEmbeddedHelper; @@ -172,6 +173,7 @@ protected: m_pEmbeddedHelper; // helper for embedded objects to get rid of the SfxObjectShell SdrOutliner* pDrawOutliner; // an Outliner for outputting text SdrOutliner* pHitTestOutliner;// an Outliner for the HitTest + SdrOutliner* pChainingOutliner; // an Outliner for chaining overflowing text sal_uIntPtr nDefTextHgt; // Default text height in logical units VclPtr<OutputDevice> pRefOutDev; // ReferenceDevice for the EditEngine /// Set if we are doing tiled rendering. @@ -215,6 +217,7 @@ protected: sal_uInt16 nDefaultTabulator; sal_uInt32 nMaxUndoCount; + TextChain* pTextChain; // sdr::Comment interface @@ -327,6 +330,10 @@ public: void SetTextDefaults() const; static void SetTextDefaults( SfxItemPool* pItemPool, sal_uIntPtr nDefTextHgt ); + SdrOutliner& GetChainingOutliner(const SdrTextObj* pObj=NULL) const; + TextChain *GetTextChain() const; + void SetNextLinkInTextChain(SdrTextObj *pPrev, SdrTextObj *pNext); + // ReferenceDevice for the EditEngine void SetRefDevice(OutputDevice* pDev); OutputDevice* GetRefDevice() const { return pRefOutDev.get(); } diff --git a/include/svx/svdotext.hxx b/include/svx/svdotext.hxx index 0b62bab..82950f0f 100644 --- a/include/svx/svdotext.hxx +++ b/include/svx/svdotext.hxx @@ -38,12 +38,16 @@ class OutlinerParaObject; +class OverflowingText; class SdrOutliner; class SdrTextObj; class SdrTextObjTest; class SvxFieldItem; class ImpSdrObjTextLink; class EditStatus; +class TextChain; +class TextChainFlow; + namespace sdr { namespace properties { class TextProperties; @@ -55,6 +59,7 @@ namespace drawinglayer { namespace primitive2d { class SdrBlockTextPrimitive2D; class SdrAutoFitTextPrimitive2D; class SdrStretchTextPrimitive2D; + class SdrChainedTextPrimitive2D; }} namespace drawinglayer { namespace animation { @@ -133,6 +138,11 @@ private: friend class sdr::table::SdrTableRtfExporter; friend class sdr::table::SdrTableRTFParser; + friend class TextChain; + friend class TextChainFlow; + friend class EditingTextChainFlow; + + // CustomShapeproperties need to access the "bTextFrame" member: friend class sdr::properties::CustomShapeProperties; @@ -209,11 +219,24 @@ protected: // position of the virtual object. This offset is used when setting up // and maintaining the OutlinerView. Point maTextEditOffset; + + virtual SdrObject* getFullDragClone() const SAL_OVERRIDE; + public: const Point& GetTextEditOffset() const { return maTextEditOffset; } void SetTextEditOffset(const Point& rNew) { maTextEditOffset = rNew; } protected: + OverflowingText *mpOverflowingText = NULL; + bool mbIsUnchainableClone = false; + + // the successor in a chain + SdrTextObj *mpNextInChain = NULL; + SdrTextObj *mpPrevInChain = NULL; + + // indicating the for its text to be chained to another text box + bool mbToBeChained : 1; + // Fuer beschriftete Zeichenobjekte ist bTextFrame=FALSE. Der Textblock // wird dann hoizontal und vertikal an aRect zentriert. Bei bTextFrame= // sal_True wird der Text in aRect hineinformatiert. Der eigentliche Textrahmen @@ -343,6 +366,17 @@ public: bool IsAutoFit() const; /// returns true if the old feature for fitting shape content should into shape is enabled. implies IsAutoFit()==false! bool IsFitToSize() const; + + // Chaining + bool IsToBeChained() const; + SdrTextObj *GetNextLinkInChain() const; + void SetNextLinkInChain(SdrTextObj *); + SdrTextObj *GetPrevLinkInChain() const; + bool IsChainable() const; + void SetPreventChainable(); + bool GetPreventChainable() const; + TextChain *GetTextChain() const; + SdrObjKind GetTextKind() const { return eTextKind; } // #i121917# @@ -491,6 +525,8 @@ public: void SetTextEditOutliner(SdrOutliner* pOutl) { pEdtOutl=pOutl; } + void SetToBeChained(bool bToBeChained); + /** Setup given Outliner equivalently to SdrTextObj::Paint() To setup an arbitrary Outliner in the same way as the draw @@ -529,6 +565,10 @@ public: /** called from the SdrObjEditView during text edit when the status of the edit outliner changes */ virtual void onEditOutlinerStatusEvent( EditStatus* pEditStatus ); + /** called from the SdrObjEditView during text edit when a chain of boxes is to be updated */ + virtual void onChainingEvent(); + + // transformation interface for StarOfficeAPI. This implements support for @@ -588,6 +628,11 @@ public: drawinglayer::primitive2d::Primitive2DSequence& rTarget, const drawinglayer::primitive2d::SdrStretchTextPrimitive2D& rSdrStretchTextPrimitive, const drawinglayer::geometry::ViewInformation2D& aViewInformation) const; + void impDecomposeChainedTextPrimitive( + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const drawinglayer::primitive2d::SdrChainedTextPrimitive2D& rSdrChainedTextPrimitive, + const drawinglayer::geometry::ViewInformation2D& aViewInformation) const; + void impHandleChainingEventsDuringDecomposition(SdrOutliner &rOutliner) const; // timing generators diff --git a/svx/inc/sdr/primitive2d/sdrtextprimitive2d.hxx b/svx/inc/sdr/primitive2d/sdrtextprimitive2d.hxx index e31bac9..db10e08 100644 --- a/svx/inc/sdr/primitive2d/sdrtextprimitive2d.hxx +++ b/svx/inc/sdr/primitive2d/sdrtextprimitive2d.hxx @@ -331,6 +331,43 @@ namespace drawinglayer } // end of namespace primitive2d } // end of namespace drawinglayer +namespace drawinglayer +{ + namespace primitive2d + { + class SdrChainedTextPrimitive2D : public SdrTextPrimitive2D + { + private: + // XXX: might have position of overflowing text + + ::basegfx::B2DHomMatrix maTextRangeTransform; // text range transformation from unit range ([0.0 .. 1.0]) to text range + protected: + // local decomposition. + virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& aViewInformation) const SAL_OVERRIDE; + + public: + SdrChainedTextPrimitive2D( + const SdrText* pSdrText, + const OutlinerParaObject& rOutlinerParaObjectPtrs, + const ::basegfx::B2DHomMatrix& rTextRangeTransform); + + // get data + const basegfx::B2DHomMatrix& getTextRangeTransform() const { return maTextRangeTransform; } + //bool getWordWrap() const { return true; } // XXX: Hack! Should have a proper implementation// + + // compare operator + virtual bool operator==(const BasePrimitive2D& rPrimitive) const SAL_OVERRIDE; + + // transformed clone operator + virtual SdrTextPrimitive2D* createTransformedClone(const basegfx::B2DHomMatrix& rTransform) const SAL_OVERRIDE; + + // provide unique ID + DeclPrimitive2DIDBlock() + }; + } // end of namespace primitive2d +} // end of namespace drawinglayer + + #endif // INCLUDED_SVX_INC_SDR_PRIMITIVE2D_SDRTEXTPRIMITIVE2D_HXX diff --git a/svx/source/sdr/primitive2d/sdrtextprimitive2d.cxx b/svx/source/sdr/primitive2d/sdrtextprimitive2d.cxx index 385de99..ac7815d 100644 --- a/svx/source/sdr/primitive2d/sdrtextprimitive2d.cxx +++ b/svx/source/sdr/primitive2d/sdrtextprimitive2d.cxx @@ -480,6 +480,48 @@ namespace drawinglayer } // end of namespace primitive2d } // end of namespace drawinglayer +namespace drawinglayer +{ + namespace primitive2d + { + + SdrChainedTextPrimitive2D::SdrChainedTextPrimitive2D( + const SdrText* pSdrText, + const OutlinerParaObject& rOutlinerParaObject, + const basegfx::B2DHomMatrix& rTextRangeTransform) + : SdrTextPrimitive2D(pSdrText, rOutlinerParaObject), + maTextRangeTransform(rTextRangeTransform) + { } + + Primitive2DSequence SdrChainedTextPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& aViewInformation) const + { + Primitive2DSequence aRetval; + getSdrText()->GetObject().impDecomposeChainedTextPrimitive(aRetval, *this, aViewInformation); + + return encapsulateWithTextHierarchyBlockPrimitive2D(aRetval); + } + + bool SdrChainedTextPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const + { + if(SdrTextPrimitive2D::operator==(rPrimitive)) + { + const SdrBlockTextPrimitive2D& rCompare = (SdrBlockTextPrimitive2D&)rPrimitive; + + return (getTextRangeTransform() == rCompare.getTextRangeTransform()); + } + + return false; + } + + SdrTextPrimitive2D* SdrChainedTextPrimitive2D::createTransformedClone(const basegfx::B2DHomMatrix& rTransform) const + { + return new SdrChainedTextPrimitive2D(getSdrText(), getOutlinerParaObject(), rTransform * getTextRangeTransform()); + } + + // provide unique ID + ImplPrimitive2DIDBlock(SdrChainedTextPrimitive2D, PRIMITIVE2D_ID_SDRCHAINEDTEXTPRIMITIVE2D) + } // end of namespace primitive2d +} // end of namespace drawinglayer namespace drawinglayer diff --git a/svx/source/svdraw/svdmodel.cxx b/svx/source/svdraw/svdmodel.cxx index 5478cdc..942d623 100644 --- a/svx/source/svdraw/svdmodel.cxx +++ b/svx/source/svdraw/svdmodel.cxx @@ -56,6 +56,7 @@ #include <svx/svdpool.hxx> #include <svx/svdobj.hxx> #include <svx/svdotext.hxx> +#include <svx/textchain.hxx> #include <svx/svdetc.hxx> #include <svx/svdoutl.hxx> #include <svx/svdoole2.hxx> @@ -221,6 +222,15 @@ void SdrModel::ImpCtor(SfxItemPool* pPool, ::comphelper::IEmbeddedHelper* _pEmbe pHitTestOutliner = SdrMakeOutliner(OUTLINERMODE_TEXTOBJECT, *this); ImpSetOutlinerDefaults(pHitTestOutliner, true); + /* Start Text Chaining related code */ + // Initialize Chaining Outliner + pChainingOutliner = SdrMakeOutliner( OUTLINERMODE_TEXTOBJECT, *this ); + ImpSetOutlinerDefaults(pChainingOutliner, true); + + // Make a TextChain + pTextChain = new TextChain; + /* End Text Chaining related code */ + ImpCreateTables(); } @@ -763,6 +773,12 @@ SdrOutliner& SdrModel::GetDrawOutliner(const SdrTextObj* pObj) const return *pDrawOutliner; } +SdrOutliner& SdrModel::GetChainingOutliner(const SdrTextObj* pObj) const +{ + pChainingOutliner->SetTextObj(pObj); + return *pChainingOutliner; +} + const SdrTextObj* SdrModel::GetFormattingTextObj() const { if (pDrawOutliner!=NULL) { @@ -1994,6 +2010,17 @@ void SdrModel::PageListChanged() { } +TextChain *SdrModel::GetTextChain() const +{ + return pTextChain; +} + +void SdrModel::SetNextLinkInTextChain(SdrTextObj *pPrev, SdrTextObj *pNext) +{ + // Delegate to SdrTextObj + pPrev->SetNextLinkInChain(pNext); +} + const SdrPage* SdrModel::GetMasterPage(sal_uInt16 nPgNum) const { DBG_ASSERT(nPgNum < maMaPag.size(), "SdrModel::GetMasterPage: Access out of range (!)"); diff --git a/svx/source/svdraw/svdotext.cxx b/svx/source/svdraw/svdotext.cxx index 6feb877..8fd7bc2 100644 --- a/svx/source/svdraw/svdotext.cxx +++ b/svx/source/svdraw/svdotext.cxx @@ -38,6 +38,8 @@ #include <editeng/editobj.hxx> #include <editeng/outliner.hxx> #include <editeng/fhgtitem.hxx> +#include <svx/textchain.hxx> +#include <svx/textchainflow.hxx> #include <svl/itempool.hxx> #include <editeng/adjustitem.hxx> #include <editeng/flditem.hxx> @@ -102,6 +104,9 @@ SdrTextObj::SdrTextObj() mbTextAnimationAllowed = true; maTextEditOffset = Point(0, 0); + // chaining + mbToBeChained = false; + // #i25616# mbSupportTextIndentingOnLineWidthChange = true; mbInDownScale = false; @@ -130,6 +135,9 @@ SdrTextObj::SdrTextObj(const Rectangle& rNewRect) mbInDownScale = false; maTextEditOffset = Point(0, 0); + // chaining + mbToBeChained = false; + // #i25616# mbSupportTextIndentingOnLineWidthChange = true; } @@ -155,6 +163,9 @@ SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind) mbInDownScale = false; maTextEditOffset = Point(0, 0); + // chaining + mbToBeChained = false; + // #i25616# mbSupportTextIndentingOnLineWidthChange = true; } @@ -176,6 +187,9 @@ SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind, const Rectangle& rNewRect) bDisableAutoWidthOnDragging=false; ImpJustifyRect(maRect); + // chaining + mbToBeChained = false; + mbInEditMode = false; mbTextHidden = false; mbTextAnimationAllowed = true; @@ -1520,6 +1534,25 @@ void SdrTextObj::ForceOutlinerParaObject() } } +// chaining +bool SdrTextObj::IsToBeChained() const +{ + return mbToBeChained; +} + +void SdrTextObj::SetToBeChained(bool bToBeChained) +{ + mbToBeChained = bToBeChained; +} + +TextChain *SdrTextObj::GetTextChain() const +{ + //if (!IsChainable()) + // return NULL; + + return pModel->GetTextChain(); +} + bool SdrTextObj::IsVerticalWriting() const { if(pEdtOutl) @@ -1948,6 +1981,179 @@ void SdrTextObj::onEditOutlinerStatusEvent( EditStatus* pEditStatus ) } } +/* Begin chaining code */ + +// XXX: Make it a method somewhere? +SdrObject *ImpGetObjByName(SdrObjList *pObjList, OUString aObjName) +{ + // scan the whole list + size_t nObjCount = pObjList->GetObjCount(); + for (unsigned i = 0; i < nObjCount; i++) { + SdrObject *pCurObj = pObjList->GetObj(i); + + if (pCurObj->GetName() == aObjName) { + return pCurObj; + } + } + // not found + return NULL; +} + +// XXX: Make it a (private) method of SdrTextObj +void ImpUpdateChainLinks(SdrTextObj *pTextObj, OUString aNextLinkName) +{ + // XXX: Current implementation constraints text boxes to be on the same page + + // No next link + if (aNextLinkName == "") { + pTextObj->SetNextLinkInChain(NULL); + return; + } + + SdrPage *pPage = pTextObj->GetPage(); + assert(pPage); + SdrTextObj *pNextTextObj = dynamic_cast< SdrTextObj * > + (ImpGetObjByName(pPage, aNextLinkName)); + if (!pNextTextObj) { + fprintf(stderr, "[CHAINING] Can't find object as next link.\n"); + return; + } + + pTextObj->SetNextLinkInChain(pNextTextObj); +} + +bool SdrTextObj::IsChainable() const +{ + // Read it as item + const SfxItemSet& rSet = GetObjectItemSet(); + OUString aNextLinkName = static_cast<const SfxStringItem&>(rSet.Get(SDRATTR_TEXT_CHAINNEXTNAME)).GetValue(); + + // Update links if any inconsistency is found + bool bNextLinkUnsetYet = (aNextLinkName != "") && !mpNextInChain; + bool bInconsistentNextLink = mpNextInChain && mpNextInChain->GetName() != aNextLinkName; + // if the link is not set despite there should be one OR if it has changed + if (bNextLinkUnsetYet || bInconsistentNextLink) { + ImpUpdateChainLinks(const_cast<SdrTextObj *>(this), aNextLinkName); + } + + return aNextLinkName != ""; // XXX: Should we also check for GetNilChainingEvent? (see old code below) + +/* + // Check that no overflow is going on + if (!GetTextChain() || GetTextChain()->GetNilChainingEvent(this)) + return false; +*/ +} + +void SdrTextObj::onChainingEvent() +{ + if (!pEdtOutl) + return; + + // Outliner for text transfer + SdrOutliner &aDrawOutliner = ImpGetDrawOutliner(); + + EditingTextChainFlow aTxtChainFlow(this); + aTxtChainFlow.CheckForFlowEvents(pEdtOutl); + + + if (aTxtChainFlow.IsOverflow()) { + fprintf(stderr, "[CHAINING] Overflow going on\n"); + // One outliner is for non-overflowing text, the other for overflowing text + // We remove text directly from the editing outliner + aTxtChainFlow.ExecuteOverflow(pEdtOutl, &aDrawOutliner); + } else if (aTxtChainFlow.IsUnderflow()) { + fprintf(stderr, "[CHAINING] Underflow going on\n"); + // underflow-induced overflow + aTxtChainFlow.ExecuteUnderflow(&aDrawOutliner); + bool bIsOverflowFromUnderflow = aTxtChainFlow.IsOverflow(); + // handle overflow + if (bIsOverflowFromUnderflow) { + fprintf(stderr, "[CHAINING] Overflow going on (underflow induced)\n"); + // prevents infinite loops when setting text for editing outliner + + + aTxtChainFlow.ExecuteOverflow(&aDrawOutliner, &aDrawOutliner); + + } + } +} + +SdrTextObj* SdrTextObj::GetNextLinkInChain() const +{ + /* + if (GetTextChain()) + return GetTextChain()->GetNextLink(this); + + return NULL; + */ + + return mpNextInChain; +} + +void SdrTextObj::SetNextLinkInChain(SdrTextObj *pNextObj) +{ + // Basically a doubly linked list implementation + + SdrTextObj *pOldNextObj = mpNextInChain; + + // Replace next link + mpNextInChain = pNextObj; + // Deal with old next link's prev link + if (pOldNextObj) { + pOldNextObj->mpPrevInChain = NULL; + } + + // Deal with new next link's prev link + if (mpNextInChain) { + // If there is a prev already at all and this is not already the current object + if (mpNextInChain->mpPrevInChain && + mpNextInChain->mpPrevInChain != this) + mpNextInChain->mpPrevInChain->mpNextInChain = NULL; + mpNextInChain->mpPrevInChain = this; + } + + // TODO: Introduce check for circular chains + +} + +SdrTextObj* SdrTextObj::GetPrevLinkInChain() const +{ + /* + if (GetTextChain()) + return GetTextChain()->GetPrevLink(this); + + return NULL; + */ + + return mpPrevInChain; +} + +void SdrTextObj::SetPreventChainable() +{ + mbIsUnchainableClone = true; +} + +bool SdrTextObj::GetPreventChainable() const +{ + // Prevent chaining it 1) during dragging && 2) when we are editing next link + return mbIsUnchainableClone || (GetNextLinkInChain() && GetNextLinkInChain()->IsInEditMode()); +} + + SdrObject* SdrTextObj::getFullDragClone() const + { + SdrObject *pClone = SdrAttrObj::getFullDragClone(); + SdrTextObj *pTextObjClone = dynamic_cast<SdrTextObj *>(pClone); + if (pTextObjClone != NULL) { + // Avoid transferring of text for chainable object during dragging + pTextObjClone->SetPreventChainable(); + } + + return pClone; + } + +/* End chaining code */ + /** returns the currently active text. */ SdrText* SdrTextObj::getActiveText() const { diff --git a/svx/source/svdraw/svdotextdecomposition.cxx b/svx/source/svdraw/svdotextdecomposition.cxx index 74eebf0..be19e39 100644 --- a/svx/source/svdraw/svdotextdecomposition.cxx +++ b/svx/source/svdraw/svdotextdecomposition.cxx @@ -22,6 +22,9 @@ #include <svx/svdoutl.hxx> #include <svx/svdpage.hxx> #include <svx/svdotext.hxx> +#include <svx/svdmodel.hxx> +#include <svx/textchain.hxx> +#include <svx/textchainflow.hxx> #include <basegfx/vector/b2dvector.hxx> #include <sdr/primitive2d/sdrtextprimitive2d.hxx> #include <drawinglayer/primitive2d/textprimitive2d.hxx> @@ -48,6 +51,8 @@ #include <svx/unoapi.hxx> #include <drawinglayer/geometry/viewinformation2d.hxx> #include <editeng/outlobj.hxx> +#include <editeng/editobj.hxx> +#include <editeng/overflowingtxt.hxx> #include <basegfx/matrix/b2dhommatrixtools.hxx> using namespace com::sun::star; @@ -1404,5 +1409,194 @@ void SdrTextObj::impGetScrollTextTiming(drawinglayer::animation::AnimationEntryL } } +void SdrTextObj::impHandleChainingEventsDuringDecomposition(SdrOutliner &rOutliner) const +{ + if (GetTextChain()->GetNilChainingEvent(this)) + return; + + GetTextChain()->SetNilChainingEvent(this, true); + + TextChainFlow aTxtChainFlow(const_cast<SdrTextObj*>(this)); + bool bIsOverflow; + + // Some debug output + size_t nObjCount = pPage->GetObjCount(); + for (unsigned i = 0; i < nObjCount; i++) { + SdrTextObj *pCurObj = (SdrTextObj *) pPage->GetObj(i); + + if (pCurObj == this) { + fprintf(stderr, "Working on TextBox %d\n", i); + break; + } + } + + aTxtChainFlow.CheckForFlowEvents(&rOutliner); + + if (aTxtChainFlow.IsUnderflow() && !IsInEditMode()) + { + // underflow-induced overflow + aTxtChainFlow.ExecuteUnderflow(&rOutliner); + bIsOverflow = aTxtChainFlow.IsOverflow(); + } else { + // standard overflow (no underlow before) + bIsOverflow = aTxtChainFlow.IsOverflow(); + } + + if (bIsOverflow && !IsInEditMode()) { + // Initialize Chaining Outliner + SdrOutliner &rChainingOutl = pModel->GetChainingOutliner(this); + ImpInitDrawOutliner( rChainingOutl ); + rChainingOutl.SetUpdateMode(true); + // We must pass the chaining outliner otherwise we would mess up decomposition + aTxtChainFlow.ExecuteOverflow(&rOutliner, &rChainingOutl); + } + + GetTextChain()->SetNilChainingEvent(this, false); +} + +void SdrTextObj::impDecomposeChainedTextPrimitive( + drawinglayer::primitive2d::Primitive2DSequence& rTarget, + const drawinglayer::primitive2d::SdrChainedTextPrimitive2D& rSdrChainedTextPrimitive, + const drawinglayer::geometry::ViewInformation2D& aViewInformation) const +{ + // decompose matrix to have position and size of text + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + rSdrChainedTextPrimitive.getTextRangeTransform().decompose(aScale, aTranslate, fRotate, fShearX); + + // use B2DRange aAnchorTextRange for calculations + basegfx::B2DRange aAnchorTextRange(aTranslate); + aAnchorTextRange.expand(aTranslate + aScale); + + // prepare outliner + const SfxItemSet& rTextItemSet = rSdrChainedTextPrimitive.getSdrText()->GetItemSet(); + SdrOutliner& rOutliner = ImpGetDrawOutliner(); + + SdrTextVertAdjust eVAdj = GetTextVerticalAdjust(rTextItemSet); + SdrTextHorzAdjust eHAdj = GetTextHorizontalAdjust(rTextItemSet); + const EEControlBits nOriginalControlWord(rOutliner.GetControlWord()); + const Size aNullSize; + + // set visualizing page at Outliner; needed e.g. for PageNumberField decomposition + rOutliner.setVisualizedPage(GetSdrPageFromXDrawPage(aViewInformation.getVisualizedPage())); + + rOutliner.SetControlWord(nOriginalControlWord|EEControlBits::AUTOPAGESIZE|EEControlBits::STRETCHING); + rOutliner.SetMinAutoPaperSize(aNullSize); + rOutliner.SetMaxAutoPaperSize(Size(1000000,1000000)); + + // add one to rage sizes to get back to the old Rectangle and outliner measurements + const sal_uInt32 nAnchorTextWidth(FRound(aAnchorTextRange.getWidth() + 1L)); + const sal_uInt32 nAnchorTextHeight(FRound(aAnchorTextRange.getHeight() + 1L)); + + // Text + const OutlinerParaObject* pOutlinerParaObject = rSdrChainedTextPrimitive.getSdrText()->GetOutlinerParaObject(); + OSL_ENSURE(pOutlinerParaObject, "impDecomposeBlockTextPrimitive used with no OutlinerParaObject (!)"); + + const bool bVerticalWritintg(pOutlinerParaObject->IsVertical()); + const Size aAnchorTextSize(Size(nAnchorTextWidth, nAnchorTextHeight)); + + if(IsTextFrame()) + { + rOutliner.SetMaxAutoPaperSize(aAnchorTextSize); + } + + if(SDRTEXTHORZADJUST_BLOCK == eHAdj && !bVerticalWritintg) + { + rOutliner.SetMinAutoPaperSize(Size(nAnchorTextWidth, 0)); + } + + if(SDRTEXTVERTADJUST_BLOCK == eVAdj && bVerticalWritintg) + { + rOutliner.SetMinAutoPaperSize(Size(0, nAnchorTextHeight)); + } + + rOutliner.SetPaperSize(aNullSize); + rOutliner.SetUpdateMode(true); + // Sets original text + rOutliner.SetText(*pOutlinerParaObject); + + /* Begin overflow/underflow handling */ + + impHandleChainingEventsDuringDecomposition(rOutliner); + + /* End overflow/underflow handling */ + + // set visualizing page at Outliner; needed e.g. for PageNumberField decomposition + rOutliner.setVisualizedPage(GetSdrPageFromXDrawPage(aViewInformation.getVisualizedPage())); + + // now get back the layouted text size from outliner + const Size aOutlinerTextSize(rOutliner.GetPaperSize()); + const basegfx::B2DVector aOutlinerScale(aOutlinerTextSize.Width(), aOutlinerTextSize.Height()); + basegfx::B2DVector aAdjustTranslate(0.0, 0.0); + + // correct horizontal translation using the now known text size + if(SDRTEXTHORZADJUST_CENTER == eHAdj || SDRTEXTHORZADJUST_RIGHT == eHAdj) + { + const double fFree(aAnchorTextRange.getWidth() - aOutlinerScale.getX()); + + if(SDRTEXTHORZADJUST_CENTER == eHAdj) + { + aAdjustTranslate.setX(fFree / 2.0); + } + + if(SDRTEXTHORZADJUST_RIGHT == eHAdj) + { + aAdjustTranslate.setX(fFree); + } + } + + // correct vertical translation using the now known text size + if(SDRTEXTVERTADJUST_CENTER == eVAdj || SDRTEXTVERTADJUST_BOTTOM == eVAdj) + { + const double fFree(aAnchorTextRange.getHeight() - aOutlinerScale.getY()); + + if(SDRTEXTVERTADJUST_CENTER == eVAdj) + { + aAdjustTranslate.setY(fFree / 2.0); + } + + if(SDRTEXTVERTADJUST_BOTTOM == eVAdj) + { + aAdjustTranslate.setY(fFree); + } + } + + // prepare matrices to apply to newly created primitives. aNewTransformA + // will get coordinates in aOutlinerScale size and positive in X, Y. + basegfx::B2DHomMatrix aNewTransformA; + basegfx::B2DHomMatrix aNewTransformB; + + // translate relative to given primitive to get same rotation and shear + // as the master shape we are working on. For vertical, use the top-right + // corner + const double fStartInX(bVerticalWritintg ? aAdjustTranslate.getX() + aOutlinerScale.getX() : aAdjustTranslate.getX()); + aNewTransformA.translate(fStartInX, aAdjustTranslate.getY()); + + // mirroring. We are now in aAnchorTextRange sizes. When mirroring in X and Y, + // move the null point which was top left to bottom right. + const bool bMirrorX(basegfx::fTools::less(aScale.getX(), 0.0)); + const bool bMirrorY(basegfx::fTools::less(aScale.getY(), 0.0)); + aNewTransformB.scale(bMirrorX ? -1.0 : 1.0, bMirrorY ? -1.0 : 1.0); + + // in-between the translations of the single primitives will take place. Afterwards, + // the object's transformations need to be applied + aNewTransformB.shearX(fShearX); + aNewTransformB.rotate(fRotate); + aNewTransformB.translate(aTranslate.getX(), aTranslate.getY()); + + basegfx::B2DRange aClipRange; + + // now break up text primitives. + impTextBreakupHandler aConverter(rOutliner); + aConverter.decomposeBlockTextPrimitive(aNewTransformA, aNewTransformB, aClipRange); + + // cleanup outliner + rOutliner.Clear(); + rOutliner.setVisualizedPage(0); + rOutliner.SetControlWord(nOriginalControlWord); + + rTarget = aConverter.getPrimitive2DSequence(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/svdraw/textchainflow.cxx b/svx/source/svdraw/textchainflow.cxx index 922cfb3..3286b86 100644 --- a/svx/source/svdraw/textchainflow.cxx +++ b/svx/source/svdraw/textchainflow.cxx @@ -170,14 +170,14 @@ void TextChainFlow::ExecuteUnderflow(SdrOutliner *pOutl) mpNextLink->NbcSetOutlinerParaObject(pOutl->GetEmptyParaObject()); // We store the size since NbcSetOutlinerParaObject can change it - Size aOldSize = pOutl->GetMaxAutoPaperSize(); + //Size aOldSize = pOutl->GetMaxAutoPaperSize(); // This should not be done in editing mode!! //XXX if (!mpTargetLink->IsInEditMode()) mpTargetLink->NbcSetOutlinerParaObject(pNewText); // Restore size and set new text - //pOutl->SetMaxAutoPaperSize(aOldSize); // XXX + //pOutl->SetMaxAutoPaperSize(aOldSize); // XXX (it seems to be working anyway without this) pOutl->SetText(*pNewText); //GetTextChain()->SetNilChainingEvent(mpTargetLink, false); commit 53e314579bb9cc8ffa14fc3a17bd8451737747b1 Author: matteocam <matteo.campane...@gmail.com> Date: Sun Sep 6 11:30:31 2015 +0200 chained editeng: Add TextChainCursor related files Change-Id: I6c98a28ae800197d58df8791e72a00b6490a2e2e diff --git a/include/svx/textchaincursor.hxx b/include/svx/textchaincursor.hxx new file mode 100644 index 0000000..61e6939 --- /dev/null +++ b/include/svx/textchaincursor.hxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#ifndef INCLUDED_SVX_TEXTCHAINCURSOR_HXX +#define INCLUDED_SVX_TEXTCHAINCURSOR_HXX + +#include <svx/svxdllapi.h> + +class SdrObjEditView; +class SdrTextObj; +class KeyEvent; +class SdrOutliner; + + +class SVX_DLLPUBLIC TextChainCursorManager +{ +public: + TextChainCursorManager(SdrObjEditView *pEditView, const SdrTextObj *pTextObj); + + bool HandleKeyEvent( const KeyEvent& rKEvt ); + + // Used by HandledKeyEvent and basic building block for handling cursor event + void HandleCursorEvent(const CursorChainingEvent aCurEvt, + const ESelection aNewSel); + + // To be used after chaining event to deal with some nuisances + void HandleCursorEventAfterChaining(const CursorChainingEvent aCurEvt, + const ESelection aNewSel); + +private: + SdrObjEditView *mpEditView; + const SdrTextObj *mpTextObj; + + // flag for handling of CANC which is kind of an exceptional case + bool mbHandlingDel; + + void impChangeEditingTextObj(SdrTextObj *pTargetTextObj, ESelection aNewSel); + void impDetectEvent(const KeyEvent& rKEvt, + CursorChainingEvent *pOutCursorEvt, + ESelection *pOutSel, + bool *bOutHandled); +}; + + +#endif // INCLUDED_SVX_TEXTCHAINCURSOR_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + diff --git a/svx/Library_svxcore.mk b/svx/Library_svxcore.mk index ffbcf01..ca9e5c5 100644 --- a/svx/Library_svxcore.mk +++ b/svx/Library_svxcore.mk @@ -341,6 +341,7 @@ $(eval $(call gb_Library_add_exception_objects,svxcore,\ svx/source/svdraw/svdxcgv \ svx/source/svdraw/textchain \ svx/source/svdraw/textchainflow \ + svx/source/svdraw/textchaincursor \ svx/source/styles/CommonStylePreviewRenderer \ svx/source/styles/CommonStyleManager \ svx/source/styles/ColorSets \ diff --git a/svx/source/svdraw/textchaincursor.cxx b/svx/source/svdraw/textchaincursor.cxx new file mode 100644 index 0000000..23bd8f5 --- /dev/null +++ b/svx/source/svdraw/textchaincursor.cxx @@ -0,0 +1,210 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <svx/textchain.hxx> +#include <svx/textchaincursor.hxx> +#include <svx/svdedxv.hxx> +#include <svx/svdoutl.hxx> + +// XXX: Possible duplication of code in behavior with stuff in ImpEditView (or ImpEditEngine) and OutlinerView + +// XXX: We violate Demeter's Law several times here, I'm afraid + +TextChainCursorManager::TextChainCursorManager(SdrObjEditView *pEditView, const SdrTextObj *pTextObj) : + mpEditView(pEditView), + mpTextObj(pTextObj), + mbHandlingDel(false) +{ + assert(mpEditView); + assert(mpTextObj); + +} + +bool TextChainCursorManager::HandleKeyEvent( const KeyEvent& rKEvt ) +{ + ESelection aNewSel; + CursorChainingEvent aCursorEvent; + + // check what the cursor/event situation looks like + bool bCompletelyHandled = false; + impDetectEvent(rKEvt, &aCursorEvent, &aNewSel, &bCompletelyHandled); + + if (aCursorEvent == CursorChainingEvent::NULL_EVENT) + return false; + else { + HandleCursorEvent(aCursorEvent, aNewSel); + // return value depends on the situation we are in + return bCompletelyHandled; + } +} + +void TextChainCursorManager::impDetectEvent(const KeyEvent& rKEvt, + CursorChainingEvent *pOutCursorEvt, + ESelection *pOutSel, + bool *bOutHandled) +{ + SdrOutliner *pOutl = mpEditView->GetTextEditOutliner(); + OutlinerView *pOLV = mpEditView->GetTextEditOutlinerView(); + + SdrTextObj *pNextLink = mpTextObj->GetNextLinkInChain(); + SdrTextObj *pPrevLink = mpTextObj->GetPrevLinkInChain(); + + KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction(); + + // We need to have this KeyFuncType + if (eFunc != KeyFuncType::DONTKNOW && eFunc != KeyFuncType::DELETE) + { + *pOutCursorEvt = CursorChainingEvent::NULL_EVENT; + return; + } + + sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); + ESelection aCurSel = pOLV->GetSelection(); + + ESelection aEndSelPrevBox(100000, 100000); + + sal_Int32 nLastPara = pOutl->GetParagraphCount()-1; + OUString aLastParaText = pOutl->GetText(pOutl->GetParagraph(nLastPara)); + sal_Int32 nLastParaLen = aLastParaText.getLength(); + + ESelection aEndSel = ESelection(nLastPara, nLastParaLen); + bool bAtEndOfTextContent = aCurSel.IsEqual(aEndSel); + + // Possibility: Are we "pushing" at the end of the object? + if (nCode == KEY_RIGHT && bAtEndOfTextContent && pNextLink) + { + *pOutCursorEvt = CursorChainingEvent::TO_NEXT_LINK; + // Selection unchanged: we are at the beginning of the box + *bOutHandled = true; // Nothing more to do than move cursor + return; + } + + // Possibility: Are we "pushing" at the end of the object? + if (eFunc == KeyFuncType::DELETE && bAtEndOfTextContent && pNextLink) + { + *pOutCursorEvt = CursorChainingEvent::TO_NEXT_LINK; + // Selection unchanged: we are at the beginning of the box + *bOutHandled = false; // We still need to delete the characters + mbHandlingDel = true; + return; + } + + ESelection aStartSel = ESelection(0, 0); + bool bAtStartOfTextContent = aCurSel.IsEqual(aStartSel); + + // Possibility: Are we "pushing" at the start of the object? + if (nCode == KEY_LEFT && bAtStartOfTextContent && pPrevLink) + { + *pOutCursorEvt = CursorChainingEvent::TO_PREV_LINK; + *pOutSel = aEndSelPrevBox; // Set at end of selection + *bOutHandled = true; // Nothing more to do than move cursor + return; + } + + // Possibility: Are we "pushing" at the start of the object and deleting left? + if (nCode == KEY_BACKSPACE && bAtStartOfTextContent && pPrevLink) + { + *pOutCursorEvt = CursorChainingEvent::TO_PREV_LINK; + *pOutSel = aEndSelPrevBox; // Set at end of selection + *bOutHandled = false; // We need to delete characters after moving cursor + return; + } + + // If arrived here there is no event detected + *pOutCursorEvt = CursorChainingEvent::NULL_EVENT; + +} + +void TextChainCursorManager::HandleCursorEventAfterChaining( + const CursorChainingEvent aCurEvt, + const ESelection aNewSel) + +{ + // Special case for DELETE handling: we need to get back at the end of the prev box + if (mbHandlingDel) { + // reset flag + mbHandlingDel = false; + + // Move to end of prev box + SdrTextObj *pPrevLink = mpTextObj->GetPrevLinkInChain(); + ESelection aEndSel(100000, 100000); + impChangeEditingTextObj(pPrevLink, aEndSel); + return; + } + + // Standard handling + HandleCursorEvent(aCurEvt, aNewSel); +} + + +void TextChainCursorManager::HandleCursorEvent( + const CursorChainingEvent aCurEvt, + const ESelection aNewSel) + +{ + + OutlinerView* pOLV = mpEditView->GetTextEditOutlinerView(); + SdrTextObj *pNextLink = mpTextObj->GetNextLinkInChain(); + SdrTextObj *pPrevLink = mpTextObj->GetPrevLinkInChain(); + + + + switch ( aCurEvt ) { + case CursorChainingEvent::UNCHANGED: + // Set same selection as before the chaining (which is saved as PostChainingSel) + // We need an explicit set because the Outliner is messed up + // after text transfer and otherwise it brings us at arbitrary positions. + pOLV->SetSelection(aNewSel); + break; + case CursorChainingEvent::TO_NEXT_LINK: + mpTextObj->GetTextChain()->SetSwitchingToNextBox(mpTextObj, true); + impChangeEditingTextObj(pNextLink, aNewSel); + break; + case CursorChainingEvent::TO_PREV_LINK: + impChangeEditingTextObj(pPrevLink, aNewSel); + break; + case CursorChainingEvent::NULL_EVENT: + // Do nothing here + break; + } + +} + +void TextChainCursorManager::impChangeEditingTextObj(SdrTextObj *pTargetTextObj, ESelection aNewSel) +{ + assert(pTargetTextObj); + + // To ensure that we check for overflow in the next box // This is handled in SdrTextObj::EndTextEdit + SdrTextObj *pNextLink = mpTextObj->GetNextLinkInChain(); + TextChain *pTextChain = mpTextObj->GetTextChain(); + // If we are moving forward + if (pNextLink && pTargetTextObj == pNextLink) + pTextChain->SetPendingOverflowCheck(pNextLink, true); + + mpEditView->SdrEndTextEdit(); + mpEditView->SdrBeginTextEdit(pTargetTextObj); + // OutlinerView has changed, so we update the pointer + OutlinerView *pOLV = mpEditView->GetTextEditOutlinerView(); + pOLV->SetSelection(aNewSel); + + // Update reference text obj + mpTextObj = pTargetTextObj; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit bd7dea64413f264175ff8c9072f7927b09bd546f Author: matteocam <matteo.campane...@gmail.com> Date: Sun Sep 6 11:29:03 2015 +0200 chained editeng: Add TextChainFlow related files Change-Id: I0e4155391fff29dc4484c7aedd4e62f02c4afd25 diff --git a/include/svx/textchainflow.hxx b/include/svx/textchainflow.hxx new file mode 100644 index 0000000..babc157 --- /dev/null +++ b/include/svx/textchainflow.hxx @@ -0,0 +1,119 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#ifndef INCLUDED_SVX_TEXTCHAINFLOW_HXX +#define INCLUDED_SVX_TEXTCHAINFLOW_HXX + +#include <svx/textchain.hxx> + +class SdrTextObj; +class SdrOutliner; +class NonOverflowingText; +class OverflowingText; +class TextChain; +class OutlinerParaObject; +class OFlowChainedText; +class UFlowChainedText; + +class TextChainFlow +{ +public: + TextChainFlow(SdrTextObj *pChainTarget); + virtual ~TextChainFlow(); + + // Check for flow events in Outliner + virtual void CheckForFlowEvents(SdrOutliner *); + + virtual void ExecuteUnderflow(SdrOutliner *); + + // Uses two outliners: one for the non-overfl text and one for overflowing (might be the same) + virtual void ExecuteOverflow(SdrOutliner *, SdrOutliner *); + + bool IsOverflow() const; + bool IsUnderflow() const; + + SdrTextObj *GetLinkTarget() const; + SdrTextObj *GetNextLink() const; + + OFlowChainedText *GetOverflowChainedText() const; + UFlowChainedText *GetUnderflowChainedText() const; + +protected: + // Cursor related + bool mbPossiblyCursorOut; + CursorChainingEvent maCursorEvent; + ESelection maOverflowPosSel; + ESelection maPostChainingSel; + + OFlowChainedText *mpOverflChText; + UFlowChainedText *mpUnderflChText; + + void impCheckForFlowEvents(SdrOutliner *, SdrOutliner *); + + TextChain *GetTextChain() const; + + virtual void impLeaveOnlyNonOverflowingText(SdrOutliner *); + virtual void impMoveChainedTextToNextLink(SdrOutliner *); + + virtual void impSetFlowOutlinerParams(SdrOutliner *, SdrOutliner *); + + OutlinerParaObject *impGetOverflowingParaObject(SdrOutliner *pOutliner); + // impGetMergedUnderflowingParaObject merges underflowing text with the one in the next box + OutlinerParaObject *impGetMergedUnderflowParaObject(SdrOutliner *pOutliner); + +private: + bool mbOFisUFinduced; + + void impUpdateCursorInfo(); + + SdrTextObj *mpTargetLink; + SdrTextObj *mpNextLink; + + TextChain *mpTextChain; + + bool bCheckedFlowEvents; + + bool bUnderflow; + bool bOverflow; +}; + + +// NOTE: EditingTextChainFlow might be strongly coupled with behavior in SdrTextObj::onChainingEvent +class EditingTextChainFlow : public TextChainFlow +{ +public: + EditingTextChainFlow(SdrTextObj *); + virtual void CheckForFlowEvents(SdrOutliner *) SAL_OVERRIDE; + + //virtual void ExecuteOverflow(SdrOutliner *, SdrOutliner *) SAL_OVERRIDE; + +protected: + virtual void impLeaveOnlyNonOverflowingText(SdrOutliner *) SAL_OVERRIDE; + + virtual void impSetTextForEditingOutliner(OutlinerParaObject *); + + virtual void impSetFlowOutlinerParams(SdrOutliner *, SdrOutliner *) SAL_OVERRIDE; + +private: + void impBroadcastCursorInfo() const; +}; + +#endif // INCLUDED_SVX_TEXTCHAINFLOW_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/Library_svxcore.mk b/svx/Library_svxcore.mk index 9c22634..ffbcf01 100644 --- a/svx/Library_svxcore.mk +++ b/svx/Library_svxcore.mk @@ -340,6 +340,7 @@ $(eval $(call gb_Library_add_exception_objects,svxcore,\ svx/source/svdraw/svdviter \ svx/source/svdraw/svdxcgv \ svx/source/svdraw/textchain \ + svx/source/svdraw/textchainflow \ svx/source/styles/CommonStylePreviewRenderer \ svx/source/styles/CommonStyleManager \ svx/source/styles/ColorSets \ diff --git a/svx/source/svdraw/textchainflow.cxx b/svx/source/svdraw/textchainflow.cxx new file mode 100644 index 0000000..922cfb3 --- /dev/null +++ b/svx/source/svdraw/textchainflow.cxx @@ -0,0 +1,353 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + + +#include <svx/svdotext.hxx> +#include <svx/svdoutl.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/editobj.hxx> +#include <editeng/overflowingtxt.hxx> +#include <svx/textchainflow.hxx> + +TextChainFlow::TextChainFlow(SdrTextObj *pChainTarget) + : mpTargetLink(pChainTarget) +{ + fprintf(stderr, "\n[TEXTCHAINFLOW] Creating a new TextChainFlow\n"); + + mpTextChain = mpTargetLink->GetTextChain(); + mpNextLink = mpTargetLink->GetNextLinkInChain(); + bCheckedFlowEvents = false; + + bUnderflow = bOverflow = false; + + mbOFisUFinduced = false; + + mpOverflChText = NULL; + mpUnderflChText = NULL; + + maCursorEvent = CursorChainingEvent::NULL_EVENT; + mbPossiblyCursorOut = false; + +} + + +TextChainFlow::~TextChainFlow() +{ + if (mpOverflChText) + delete mpOverflChText; + if (mpUnderflChText) + delete mpUnderflChText; +} + +void TextChainFlow::impSetFlowOutlinerParams(SdrOutliner *, SdrOutliner *) +{ + // Nothing to do if not in editing mode +} + +/* + * Check for overflow in the state of pFlowOutl. + * If pParamOutl is not NULL sets some parameters from there. + * This is useful in case the outliner is not set for overflow + * (e.g. in editing mode we check for overflow in drawing outl but + * parameters come from editing outliner) +*/ +void TextChainFlow::impCheckForFlowEvents(SdrOutliner *pFlowOutl, SdrOutliner *pParamOutl) +{ + bool bOldUpdateMode = pFlowOutl->GetUpdateMode(); + + // XXX: This could be reorganized moving most of this stuff inside EditingTextChainFlow + if (pParamOutl != NULL) + { + // We need this since it's required to check overflow + pFlowOutl->SetUpdateMode(true); + + // XXX: does this work if you do it before setting the text? Seems so. + impSetFlowOutlinerParams(pFlowOutl, pParamOutl); + } + + bool bIsPageOverflow = pFlowOutl->IsPageOverflow(); + + // NOTE: overflow and underflow cannot be both true + bOverflow = bIsPageOverflow && mpNextLink; + bUnderflow = !bIsPageOverflow && mpNextLink && mpNextLink->HasText(); + + // Get old state on whether to merge para-s or not + // NOTE: We handle UF/OF using the _old_ state. The new one is simply saved + bool bMustMergeParaAmongLinks = GetTextChain()->GetIsPartOfLastParaInNextLink(mpTargetLink); + + // Set (Non)OverflowingTxt here (if any) + + // If we had an underflow before we have to deep merge paras anyway + bool bMustMergeParaOF = bMustMergeParaAmongLinks || mbOFisUFinduced; + + // XXX + bMustMergeParaOF = true; // XXX: Experiment: no deep merging. + + mpOverflChText = bOverflow ? + new OFlowChainedText(pFlowOutl, bMustMergeParaOF) : + NULL; + + // Set current underflowing text (if any) ... etc. - the rest is truncated _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits