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->IsUpdateLayout();
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->SetUpdateLayout(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
96 new OFlowChainedText(pFlowOutl, bMustMergeParaOF) :
97 nullptr );
98
99 // Set current underflowing text (if any)
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->SetUpdateLayout(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
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::optional<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 // This should not be done in editing mode!! //XXX
170 {
172 }
173
174 // Restore size and set new text
175 //pOutl->SetMaxAutoPaperSize(aOldSize); // XXX (it seems to be working anyway without this)
176 pOutl->SetText(*pNewText);
177
178 //GetTextChain()->SetNilChainingEvent(mpTargetLink, false);
179
180 // Check for new overflow
181 CheckForFlowEvents(pOutl);
182}
183
184void TextChainFlow::ExecuteOverflow(SdrOutliner *pNonOverflOutl, SdrOutliner *pOverflOutl)
185{
186 //GetTextChain()->SetNilChainingEvent(mpTargetLink, true);
187 // Leave only non overflowing text
188 impLeaveOnlyNonOverflowingText(pNonOverflOutl);
189
190 // Transfer of text to next link
191 if (!mpTargetLink->GetPreventChainable() ) // we don't transfer text while dragging because of resizing
192 {
193 impMoveChainedTextToNextLink(pOverflOutl);
194 }
195
196 //GetTextChain()->SetNilChainingEvent(mpTargetLink, false);
197}
198
200{
201 std::optional<OutlinerParaObject> pNewText = mpOverflChText->RemoveOverflowingText(pNonOverflOutl);
202
203 SAL_INFO("svx.chaining", "[TEXTCHAINFLOW - OF] SOURCE box set to "
204 << pNewText->GetTextObject().GetParagraphCount() << " paras");
205
206 // adds it to current outliner anyway (useful in static decomposition)
207 pNonOverflOutl->SetText(*pNewText);
208
209 mpTargetLink->NbcSetOutlinerParaObject(std::move(pNewText));
210 // For some reason the paper size is lost after last instruction, so we set it.
211 pNonOverflOutl->SetPaperSize(Size(pNonOverflOutl->GetPaperSize().Width(),
212 pNonOverflOutl->GetTextHeight()));
213
214}
215
217{
218 // prevent copying text in same box
219 if ( mpNextLink == mpTargetLink ) {
220 SAL_INFO("svx.chaining", "[CHAINING] Trying to copy text for next link in same object");
221 return;
222 }
223
225 mpOverflChText->InsertOverflowingText(pOverflOutl,
227 SAL_INFO("svx.chaining", "[TEXTCHAINFLOW - OF] DEST box set to "
228 << pNewText->GetTextObject().GetParagraphCount() << " paras");
229
230 if (pNewText)
231 mpNextLink->NbcSetOutlinerParaObject(std::move(pNewText));
232
233 // Set Deep Merge status
234 SAL_INFO("svx.chaining", "[DEEPMERGE] Setting deepMerge to "
235 << mpOverflChText->IsLastParaInterrupted());
238 mpOverflChText->IsLastParaInterrupted());
239}
240
242{
243 return mpTargetLink;
244}
245
247{
248 return mpTextChain;
249}
250
251// EditingTextChainFlow
252
254 TextChainFlow(pLinkTarget)
255{
256 SAL_INFO("svx.chaining", "[TEXTCHAINFLOW] Creating a new EditingTextChainFlow");
257}
258
260{
261 // if this is editing outliner no need to set parameters
262 if (pFlowOutl == GetLinkTarget()->mpEditingOutliner)
263 impCheckForFlowEvents(pFlowOutl, nullptr);
264 else
265 impCheckForFlowEvents(pFlowOutl, GetLinkTarget()->mpEditingOutliner);
266
267 // Broadcast events for cursor handling
269}
270
272{
273 mpOverflChText->RemoveOverflowingText(pNonOverflOutl);
274 //impSetTextForEditingOutliner(pNewText); //XXX: Don't call it since we do everything with NonOverflowingText::ToParaObject // XXX: You may need this for Underflow
275
276 // XXX: I'm not sure whether we need this (after all operations such as Paste don't change this - as far as I understand)
277 //GetLinkTarget()->NbcSetOutlinerParaObject(pNewText);
278}
279
281{
282 // Set right size for overflow
283 pFlowOutl->SetMaxAutoPaperSize(pParamOutl->GetMaxAutoPaperSize());
284 pFlowOutl->SetMinAutoPaperSize(pParamOutl->GetMinAutoPaperSize());
285 pFlowOutl->SetPaperSize(pParamOutl->GetPaperSize());
286}
287
289{
291
292 // Test whether the cursor is out of the box.
293 bool bCursorOut = mbPossiblyCursorOut && maOverflowPosSel < aPreChainingSel;
294
295 // NOTE: I handled already the stuff for the comments below. They will be kept temporarily till stuff settles down.
296 // Possibility: 1) why don't we stop passing the actual event to the TextChain and instead we pass
297 // the overflow pos and mbPossiblyCursorOut
298 // 2) We pass the current selection before anything happens and we make impBroadcastCursorInfo compute it.
299
300
301 if (bCursorOut) {
302 //maCursorEvent = CursorChainingEvent::TO_NEXT_LINK;
305 } else {
306 //maCursorEvent = CursorChainingEvent::UNCHANGED;
307 GetTextChain()->SetPostChainingSel(GetLinkTarget(), aPreChainingSel);
309 }
310
311
312}
313
314/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual sal_Int32 GetParagraphCount() const=0
virtual void CheckForFlowEvents(SdrOutliner *) override
virtual void impSetFlowOutlinerParams(SdrOutliner *, SdrOutliner *) override
virtual void impLeaveOnlyNonOverflowingText(SdrOutliner *) override
void impBroadcastCursorInfo() const
EditingTextChainFlow(SdrTextObj *)
const EditTextObject & GetTextObject() const
void SetMaxAutoPaperSize(const Size &rSz)
void SetText(const OutlinerParaObject &)
bool IsUpdateLayout() const
const Size & GetPaperSize() const
OutlinerParaObject GetEmptyParaObject() const
void SetMinAutoPaperSize(const Size &rSz)
void SetPaperSize(const Size &rSize)
bool SetUpdateLayout(bool bUpdate)
bool IsPageOverflow()
const Size & GetMaxAutoPaperSize() const
sal_uInt32 GetTextHeight() const
const Size & GetMinAutoPaperSize() const
SdrTextObj * GetNextLinkInChain() const
Definition: svdotext.cxx:2076
bool IsInEditMode() const
Definition: svdotext.hxx:339
virtual OutlinerParaObject * GetOutlinerParaObject() const override
Definition: svdotext.cxx:1412
virtual bool HasText() const override
Definition: svdotxat.cxx:420
virtual void NbcSetOutlinerParaObject(std::optional< OutlinerParaObject > pTextObject) override
Definition: svdotext.cxx:1421
TextChain * GetTextChain() const
Definition: svdotext.cxx:1544
bool GetPreventChainable() const
Definition: svdotext.cxx:2126
constexpr tools::Long Width() const
virtual ~TextChainFlow()
ESelection maOverflowPosSel
SdrTextObj * GetLinkTarget() const
bool IsOverflow() const
std::unique_ptr< OFlowChainedText > mpOverflChText
virtual void impSetFlowOutlinerParams(SdrOutliner *, SdrOutliner *)
TextChain * mpTextChain
SdrTextObj * mpTargetLink
TextChainFlow(SdrTextObj *pChainTarget)
bool IsUnderflow() const
void ExecuteUnderflow(SdrOutliner *)
virtual void impLeaveOnlyNonOverflowingText(SdrOutliner *)
void ExecuteOverflow(SdrOutliner *, SdrOutliner *)
TextChain * GetTextChain() const
void impUpdateCursorInfo()
virtual void CheckForFlowEvents(SdrOutliner *)
ESelection maPostChainingSel
bool mbPossiblyCursorOut
void impCheckForFlowEvents(SdrOutliner *, SdrOutliner *)
std::unique_ptr< UFlowChainedText > mpUnderflChText
void impMoveChainedTextToNextLink(SdrOutliner *)
SdrTextObj * mpNextLink
void SetCursorEvent(const SdrTextObj *, CursorChainingEvent const &)
Definition: textchain.cxx:32
void SetIsPartOfLastParaInNextLink(const SdrTextObj *, bool)
Definition: textchain.cxx:76
ESelection const & GetPreChainingSel(const SdrTextObj *)
Definition: textchain.cxx:49
void SetPostChainingSel(const SdrTextObj *, ESelection const &)
Definition: textchain.cxx:65
bool GetIsPartOfLastParaInNextLink(const SdrTextObj *)
Definition: textchain.cxx:71
#define SAL_INFO(area, stream)
sal_Int32 nStartPara
sal_Int32 nStartPos