LibreOffice Module svx (master)  1
textchainflow.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 
21 #include <svx/svdotext.hxx>
22 #include <svx/svdoutl.hxx>
23 #include <editeng/outlobj.hxx>
24 #include <editeng/editobj.hxx>
26 #include <textchainflow.hxx>
27 #include <sal/log.hxx>
28 
30  : mpTargetLink(pChainTarget)
31 {
32  SAL_INFO("svx.chaining", "[TEXTCHAINFLOW] Creating a new TextChainFlow");
33 
36 
37  bUnderflow = bOverflow = false;
38 
39  mbOFisUFinduced = false;
40 
41  mpOverflChText = nullptr;
42  mpUnderflChText = nullptr;
43 
44  mbPossiblyCursorOut = false;
45 }
46 
47 
49 {
50  mpOverflChText.reset();
51  mpUnderflChText.reset();
52 }
53 
55 {
56  // Nothing to do if not in editing mode
57 }
58 
59 /*
60  * Check for overflow in the state of pFlowOutl.
61  * If pParamOutl is not NULL sets some parameters from there.
62  * This is useful in case the outliner is not set for overflow
63  * (e.g. in editing mode we check for overflow in drawing outl but
64  * parameters come from editing outliner)
65 */
67 {
68  bool bOldUpdateMode = pFlowOutl->GetUpdateMode();
69 
70  // XXX: This could be reorganized moving most of this stuff inside EditingTextChainFlow
71  if (pParamOutl != nullptr)
72  {
73  // We need this since it's required to check overflow
74  pFlowOutl->SetUpdateMode(true);
75 
76  // XXX: does this work if you do it before setting the text? Seems so.
77  impSetFlowOutlinerParams(pFlowOutl, pParamOutl);
78  }
79 
80  bool bIsPageOverflow = pFlowOutl->IsPageOverflow();
81 
82  // NOTE: overflow and underflow cannot be both true
83  bOverflow = bIsPageOverflow && mpNextLink;
84  bUnderflow = !bIsPageOverflow && mpNextLink && mpNextLink->HasText();
85 
86  // Get old state on whether to merge para-s or not
87  // NOTE: We handle UF/OF using the _old_ state. The new one is simply saved
88  bool bMustMergeParaAmongLinks = GetTextChain()->GetIsPartOfLastParaInNextLink(mpTargetLink);
89 
90  // Set (Non)OverflowingTxt here (if any)
91 
92  // If we had an underflow before we have to deep merge paras anyway
93  bool bMustMergeParaOF = bMustMergeParaAmongLinks || mbOFisUFinduced;
94 
95  mpOverflChText.reset( bOverflow ?
96  new OFlowChainedText(pFlowOutl, bMustMergeParaOF) :
97  nullptr );
98 
99  // Set current underflowing text (if any)
100  mpUnderflChText.reset( bUnderflow ?
101  new UFlowChainedText(pFlowOutl, bMustMergeParaAmongLinks) :
102  nullptr );
103 
104  // Reset update mode // Reset it here because we use WriteRTF (needing updatemode = true) in the two constructors above
105  if (!bOldUpdateMode) // Reset only if the old value was false
106  pFlowOutl->SetUpdateMode(bOldUpdateMode);
107 
108  // NOTE: Must be called after mp*ChText abd b*flow have been set but before mbOFisUFinduced is reset
110 
111  // To check whether an overflow is underflow induced or not (useful in cursor checking)
113 }
114 
116 {
117  // XXX: Maybe we can get rid of mbOFisUFinduced by not allowing handling of more than one event by the same TextChainFlow
118  // if this is not an OF triggered during an UF
119 
121 
122  if(mbPossiblyCursorOut ) {
123  maOverflowPosSel = mpOverflChText->GetOverflowPointSel();
125  // Might be an invalid selection if the cursor at UF time was before
126  // the (possibly UF-induced) Overflowing point but we don't use it in that case
128  aSelAtUFTime.nStartPos-maOverflowPosSel.nStartPos );
129  }
130 
131  // XXX: It may not be necessary anymore to keep this method separated from EditingTextChainFlow::impBroadcastCursorInfo
132 }
133 
135 {
136  impCheckForFlowEvents(pFlowOutl, nullptr);
137 }
138 
139 
141 {
142  return bOverflow;
143 }
144 
146 {
147  return bUnderflow;
148 }
149 
150 
151 // XXX: In editing mode you need to get "underflowing" text from editing outliner, so it's kinda separate from the drawing one!
152 
153 // XXX:Would it be possible to unify underflow and its possibly following overflow?
155 {
156  //GetTextChain()->SetNilChainingEvent(mpTargetLink, true);
157  // making whole text
158  // merges underflowing text with the one in the next box
159  std::unique_ptr<OutlinerParaObject> pNewText = mpUnderflChText->CreateMergedUnderflowParaObject(pOutl, mpNextLink->GetOutlinerParaObject());
160 
161  // Set the other box empty; it will be replaced by the rest of the text if overflow occurs
164 
165  // We store the size since NbcSetOutlinerParaObject can change it
166  //Size aOldSize = pOutl->GetMaxAutoPaperSize();
167 
168  auto pNewTextTemp = pNewText.get(); // because we need to access it after a std::move
169  // This should not be done in editing mode!! //XXX
170  if (!mpTargetLink->IsInEditMode())
171  {
172  mpTargetLink->NbcSetOutlinerParaObject(std::move(pNewText));
173  }
174 
175  // Restore size and set new text
176  //pOutl->SetMaxAutoPaperSize(aOldSize); // XXX (it seems to be working anyway without this)
177  pOutl->SetText(*pNewTextTemp);
178 
179  //GetTextChain()->SetNilChainingEvent(mpTargetLink, false);
180 
181  // Check for new overflow
182  CheckForFlowEvents(pOutl);
183 }
184 
185 void TextChainFlow::ExecuteOverflow(SdrOutliner *pNonOverflOutl, SdrOutliner *pOverflOutl)
186 {
187  //GetTextChain()->SetNilChainingEvent(mpTargetLink, true);
188  // Leave only non overflowing text
189  impLeaveOnlyNonOverflowingText(pNonOverflOutl);
190 
191  // Transfer of text to next link
192  if (!mpTargetLink->GetPreventChainable() ) // we don't transfer text while dragging because of resizing
193  {
194  impMoveChainedTextToNextLink(pOverflOutl);
195  }
196 
197  //GetTextChain()->SetNilChainingEvent(mpTargetLink, false);
198 }
199 
201 {
202  std::unique_ptr<OutlinerParaObject> pNewText = mpOverflChText->RemoveOverflowingText(pNonOverflOutl);
203 
204  SAL_INFO("svx.chaining", "[TEXTCHAINFLOW - OF] SOURCE box set to "
205  << pNewText->GetTextObject().GetParagraphCount() << " paras");
206 
207  // adds it to current outliner anyway (useful in static decomposition)
208  pNonOverflOutl->SetText(*pNewText);
209 
210  mpTargetLink->NbcSetOutlinerParaObject(std::move(pNewText));
211  // For some reason the paper size is lost after last instruction, so we set it.
212  pNonOverflOutl->SetPaperSize(Size(pNonOverflOutl->GetPaperSize().Width(),
213  pNonOverflOutl->GetTextHeight()));
214 
215 }
216 
218 {
219  // prevent copying text in same box
220  if ( mpNextLink == mpTargetLink ) {
221  SAL_INFO("svx.chaining", "[CHAINING] Trying to copy text for next link in same object");
222  return;
223  }
224 
225  std::unique_ptr<OutlinerParaObject> pNewText =
226  mpOverflChText->InsertOverflowingText(pOverflOutl,
228  SAL_INFO("svx.chaining", "[TEXTCHAINFLOW - OF] DEST box set to "
229  << pNewText->GetTextObject().GetParagraphCount() << " paras");
230 
231  if (pNewText)
232  mpNextLink->NbcSetOutlinerParaObject(std::move(pNewText));
233 
234  // Set Deep Merge status
235  SAL_INFO("svx.chaining", "[DEEPMERGE] Setting deepMerge to "
236  << mpOverflChText->IsLastParaInterrupted());
238  mpTargetLink,
239  mpOverflChText->IsLastParaInterrupted());
240 }
241 
243 {
244  return mpTargetLink;
245 }
246 
248 {
249  return mpTextChain;
250 }
251 
252 // EditingTextChainFlow
253 
255  TextChainFlow(pLinkTarget)
256 {
257  SAL_INFO("svx.chaining", "[TEXTCHAINFLOW] Creating a new EditingTextChainFlow");
258 }
259 
261 {
262  // if this is editing outliner no need to set parameters
263  if (pFlowOutl == GetLinkTarget()->pEdtOutl)
264  impCheckForFlowEvents(pFlowOutl, nullptr);
265  else
266  impCheckForFlowEvents(pFlowOutl, GetLinkTarget()->pEdtOutl);
267 
268  // Broadcast events for cursor handling
270 }
271 
273 {
274  mpOverflChText->RemoveOverflowingText(pNonOverflOutl);
275  //impSetTextForEditingOutliner(pNewText); //XXX: Don't call it since we do everything with NonOverflowingText::ToParaObject // XXX: You may need this for Underflow
276 
277  // XXX: I'm not sure whether we need this (after all operations such as Paste don't change this - as far as I understand)
278  //GetLinkTarget()->NbcSetOutlinerParaObject(pNewText);
279 }
280 
282 {
283  // Set right size for overflow
284  pFlowOutl->SetMaxAutoPaperSize(pParamOutl->GetMaxAutoPaperSize());
285  pFlowOutl->SetMinAutoPaperSize(pParamOutl->GetMinAutoPaperSize());
286  pFlowOutl->SetPaperSize(pParamOutl->GetPaperSize());
287 }
288 
290 {
291  ESelection aPreChainingSel = GetTextChain()->GetPreChainingSel(GetLinkTarget()) ;
292 
293  // Test whether the cursor is out of the box.
294  bool bCursorOut = mbPossiblyCursorOut && maOverflowPosSel < aPreChainingSel;
295 
296  // NOTE: I handled already the stuff for the comments below. They will be kept temporarily till stuff settles down.
297  // Possibility: 1) why don't we stop passing the actual event to the TextChain and instead we pass
298  // the overflow pos and mbPossiblyCursorOut
299  // 2) We pass the current selection before anything happens and we make impBroadcastCursorInfo compute it.
300 
301 
302  if (bCursorOut) {
303  //maCursorEvent = CursorChainingEvent::TO_NEXT_LINK;
306  } else {
307  //maCursorEvent = CursorChainingEvent::UNCHANGED;
308  GetTextChain()->SetPostChainingSel(GetLinkTarget(), aPreChainingSel);
310  }
311 
312 
313 }
314 
315 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
void impUpdateCursorInfo()
bool IsOverflow() const
sal_Int32 nStartPara
std::unique_ptr< UFlowChainedText > mpUnderflChText
virtual void impSetFlowOutlinerParams(SdrOutliner *, SdrOutliner *)
void SetPaperSize(const Size &rSize)
TextChain * mpTextChain
const Size & GetMinAutoPaperSize() const
bool IsInEditMode() const
Definition: svdotext.hxx:323
void ExecuteUnderflow(SdrOutliner *)
ESelection const & GetPreChainingSel(const SdrTextObj *)
Definition: textchain.cxx:49
void impCheckForFlowEvents(SdrOutliner *, SdrOutliner *)
TextChain * GetTextChain() const
Definition: svdotext.cxx:1477
virtual void impSetFlowOutlinerParams(SdrOutliner *, SdrOutliner *) override
const Size & GetMaxAutoPaperSize() const
bool IsUnderflow() const
bool GetPreventChainable() const
Definition: svdotext.cxx:2019
TextChainFlow(SdrTextObj *pChainTarget)
void SetText(const OutlinerParaObject &)
SdrTextObj * GetLinkTarget() const
void ExecuteOverflow(SdrOutliner *, SdrOutliner *)
std::unique_ptr< OutlinerParaObject > GetEmptyParaObject() const
void impBroadcastCursorInfo() const
bool IsPageOverflow()
virtual void impLeaveOnlyNonOverflowingText(SdrOutliner *) override
SdrTextObj * GetNextLinkInChain() const
Definition: svdotext.cxx:1969
bool GetIsPartOfLastParaInNextLink(const SdrTextObj *)
Definition: textchain.cxx:71
std::unique_ptr< OFlowChainedText > mpOverflChText
SdrTextObj * mpTargetLink
ESelection maOverflowPosSel
virtual void NbcSetOutlinerParaObject(std::unique_ptr< OutlinerParaObject > pTextObject) override
Definition: svdotext.cxx:1363
void SetCursorEvent(const SdrTextObj *, CursorChainingEvent const &)
Definition: textchain.cxx:32
TextChain * GetTextChain() const
void SetMaxAutoPaperSize(const Size &rSz)
virtual OutlinerParaObject * GetOutlinerParaObject() const override
Definition: svdotext.cxx:1354
#define SAL_INFO(area, stream)
void SetMinAutoPaperSize(const Size &rSz)
SdrTextObj * mpNextLink
EditingTextChainFlow(SdrTextObj *)
void SetUpdateMode(bool bUpdate)
ESelection maPostChainingSel
virtual void impLeaveOnlyNonOverflowingText(SdrOutliner *)
void SetIsPartOfLastParaInNextLink(const SdrTextObj *, bool)
Definition: textchain.cxx:76
sal_uLong GetTextHeight() const
void impMoveChainedTextToNextLink(SdrOutliner *)
virtual ~TextChainFlow()
void SetPostChainingSel(const SdrTextObj *, ESelection const &)
Definition: textchain.cxx:65
bool GetUpdateMode() const
bool mbPossiblyCursorOut
virtual void CheckForFlowEvents(SdrOutliner *)
sal_Int32 nStartPos
const Size & GetPaperSize() const
virtual void CheckForFlowEvents(SdrOutliner *) override