LibreOffice Module svx (master)  1
textchaincursor.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <textchain.hxx>
21 #include <textchaincursor.hxx>
22 #include <svx/svdedxv.hxx>
23 #include <svx/svdoutl.hxx>
24 #include <vcl/event.hxx>
25 
26 // XXX: Possible duplication of code in behavior with stuff in ImpEditView (or ImpEditEngine) and OutlinerView
27 
28 // XXX: We violate Demeter's Law several times here, I'm afraid
29 
31  mpEditView(pEditView),
32  mpTextObj(pTextObj),
33  mbHandlingDel(false)
34 {
37 
38 }
39 
41 {
42  ESelection aNewSel;
43  CursorChainingEvent aCursorEvent;
44 
45  // check what the cursor/event situation looks like
46  bool bCompletelyHandled = false;
47  impDetectEvent(rKEvt, aCursorEvent, aNewSel, bCompletelyHandled);
48 
49  if (aCursorEvent == CursorChainingEvent::NULL_EVENT)
50  return false;
51  else {
52  HandleCursorEvent(aCursorEvent, aNewSel);
53  // return value depends on the situation we are in
54  return bCompletelyHandled;
55  }
56 }
57 
59  CursorChainingEvent& rOutCursorEvt,
60  ESelection& rOutSel,
61  bool& rOutHandled)
62 {
65 
66  SdrTextObj *pNextLink = mpTextObj->GetNextLinkInChain();
67  SdrTextObj *pPrevLink = mpTextObj->GetPrevLinkInChain();
68 
69  KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction();
70 
71  // We need to have this KeyFuncType
72  if (eFunc != KeyFuncType::DONTKNOW && eFunc != KeyFuncType::DELETE)
73  {
74  rOutCursorEvt = CursorChainingEvent::NULL_EVENT;
75  return;
76  }
77 
78  sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
79  ESelection aCurSel = pOLV->GetSelection();
80 
81  ESelection aEndSelPrevBox(100000, 100000);
82 
83  sal_Int32 nLastPara = pOutl->GetParagraphCount()-1;
84  OUString aLastParaText = pOutl->GetText(pOutl->GetParagraph(nLastPara));
85  sal_Int32 nLastParaLen = aLastParaText.getLength();
86 
87  ESelection aEndSel(nLastPara, nLastParaLen);
88  bool bAtEndOfTextContent = aCurSel == aEndSel;
89 
90  // Possibility: Are we "pushing" at the end of the object?
91  if (nCode == KEY_RIGHT && bAtEndOfTextContent && pNextLink)
92  {
93  rOutCursorEvt = CursorChainingEvent::TO_NEXT_LINK;
94  // Selection unchanged: we are at the beginning of the box
95  rOutHandled = true; // Nothing more to do than move cursor
96  return;
97  }
98 
99  // Possibility: Are we "pushing" at the end of the object?
100  if (eFunc == KeyFuncType::DELETE && bAtEndOfTextContent && pNextLink)
101  {
102  rOutCursorEvt = CursorChainingEvent::TO_NEXT_LINK;
103  // Selection unchanged: we are at the beginning of the box
104  rOutHandled = false; // We still need to delete the characters
105  mbHandlingDel = true;
106  return;
107  }
108 
109  ESelection aStartSel(0, 0);
110  bool bAtStartOfTextContent = aCurSel == aStartSel;
111 
112  // Possibility: Are we "pushing" at the start of the object?
113  if (nCode == KEY_LEFT && bAtStartOfTextContent && pPrevLink)
114  {
115  rOutCursorEvt = CursorChainingEvent::TO_PREV_LINK;
116  rOutSel = aEndSelPrevBox; // Set at end of selection
117  rOutHandled = true; // Nothing more to do than move cursor
118  return;
119  }
120 
121  // Possibility: Are we "pushing" at the start of the object and deleting left?
122  if (nCode == KEY_BACKSPACE && bAtStartOfTextContent && pPrevLink)
123  {
124  rOutCursorEvt = CursorChainingEvent::TO_PREV_LINK;
125  rOutSel = aEndSelPrevBox; // Set at end of selection
126  rOutHandled = false; // We need to delete characters after moving cursor
127  return;
128  }
129 
130  // If arrived here there is no event detected
131  rOutCursorEvt = CursorChainingEvent::NULL_EVENT;
132 
133 }
134 
136  const CursorChainingEvent aCurEvt,
137  const ESelection& aNewSel)
138 
139 {
140  // Special case for DELETE handling: we need to get back at the end of the prev box
141  if (mbHandlingDel) {
142  // reset flag
143  mbHandlingDel = false;
144 
145  // Move to end of prev box
146  SdrTextObj *pPrevLink = mpTextObj->GetPrevLinkInChain();
147  ESelection aEndSel(100000, 100000);
148  impChangeEditingTextObj(pPrevLink, aEndSel);
149  return;
150  }
151 
152  // Standard handling
153  HandleCursorEvent(aCurEvt, aNewSel);
154 }
155 
156 
158  const CursorChainingEvent aCurEvt,
159  const ESelection& aNewSel)
160 
161 {
162 
164  SdrTextObj *pNextLink = mpTextObj->GetNextLinkInChain();
165  SdrTextObj *pPrevLink = mpTextObj->GetPrevLinkInChain();
166 
167 
168  switch ( aCurEvt ) {
170  // Set same selection as before the chaining (which is saved as PostChainingSel)
171  // We need an explicit set because the Outliner is messed up
172  // after text transfer and otherwise it brings us at arbitrary positions.
173  pOLV->SetSelection(aNewSel);
174  break;
177  impChangeEditingTextObj(pNextLink, aNewSel);
178  break;
180  impChangeEditingTextObj(pPrevLink, aNewSel);
181  break;
183  // Do nothing here
184  break;
185  }
186 
187 }
188 
190 {
191  assert(pTargetTextObj);
192 
194  mpEditView->SdrBeginTextEdit(pTargetTextObj);
195  // OutlinerView has changed, so we update the pointer
197  pOLV->SetSelection(aNewSel);
198 
199  // Update reference text obj
200  mpTextObj = pTargetTextObj;
201 }
202 
203 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual SdrEndTextEditKind SdrEndTextEdit(bool bDontDeleteReally=false)
Definition: svdedxv.cxx:1392
void impChangeEditingTextObj(SdrTextObj *pTargetTextObj, ESelection aNewSel)
void impDetectEvent(const KeyEvent &rKEvt, CursorChainingEvent &rOutCursorEvt, ESelection &rOutSel, bool &rOutHandled)
sal_uInt16 GetCode() const
sal_Int32 GetParagraphCount() const
KeyFuncType
TextChain * GetTextChain() const
Definition: svdotext.cxx:1477
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
TextChainCursorManager(SdrObjEditView *pEditView, const SdrTextObj *pTextObj)
sal_uInt16 nCode
const SdrOutliner * GetTextEditOutliner() const
Definition: svdedxv.hxx:233
void SetSwitchingToNextBox(const SdrTextObj *, bool)
Definition: textchain.cxx:87
const SdrTextObj * mpTextObj
void HandleCursorEvent(const CursorChainingEvent aCurEvt, const ESelection &aNewSel)
void HandleCursorEventAfterChaining(const CursorChainingEvent aCurEvt, const ESelection &aNewSel)
virtual bool SdrBeginTextEdit(SdrObject *pObj, SdrPageView *pPV=nullptr, vcl::Window *pWin=nullptr, bool bIsNewObj=false, SdrOutliner *pGivenOutliner=nullptr, OutlinerView *pGivenOutlinerView=nullptr, bool bDontDeleteOutliner=false, bool bOnlyOneView=false, bool bGrabFocus=true)
Definition: svdedxv.cxx:1045
SdrObjEditView * mpEditView
const OutlinerView * GetTextEditOutlinerView() const
Definition: svdedxv.hxx:235
OUString GetText(Paragraph const *pPara, sal_Int32 nParaCount=1) const
KeyFuncType GetFunction() const
CursorChainingEvent
Definition: textchain.hxx:35
SdrTextObj * GetNextLinkInChain() const
Definition: svdotext.cxx:1969
Paragraph * GetParagraph(sal_Int32 nAbsPos) const
constexpr sal_uInt16 KEY_RIGHT
ESelection GetSelection() const
const vcl::KeyCode & GetKeyCode() const
void SetSelection(const ESelection &)
bool HandleKeyEvent(const KeyEvent &rKEvt)
constexpr sal_uInt16 KEY_BACKSPACE
constexpr sal_uInt16 KEY_LEFT
SdrTextObj * GetPrevLinkInChain() const
Definition: svdotext.cxx:2007