diff options
author | matteocam <matteo.campanelli@gmail.com> | 2015-09-06 11:30:31 +0200 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2015-09-20 13:05:14 +0200 |
commit | e59fca52399ab1f96b5bb525b56b444c5674ae6d (patch) | |
tree | b7a9e910a4ebc016d570a2ce4a22831e4af4bed9 /svx/source | |
parent | 4c33aa61b3ea1fa170b9446fbfdffe85b659ff3b (diff) |
chained editeng: Add TextChainCursor related files
Change-Id: I6c98a28ae800197d58df8791e72a00b6490a2e2e
Diffstat (limited to 'svx/source')
-rw-r--r-- | svx/source/svdraw/textchaincursor.cxx | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/svx/source/svdraw/textchaincursor.cxx b/svx/source/svdraw/textchaincursor.cxx new file mode 100644 index 000000000000..23bd8f54a0a3 --- /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: */ |