1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
22 #include <IDocumentUndoRedo.hxx>
24 #include <pagedesc.hxx>
25 #include <SwUndoPageDesc.hxx>
26 #include <SwRewriter.hxx>
28 #include <strings.hrc>
29 #include <fmtcntnt.hxx>
30 #include <fmthdft.hxx>
31 #include <osl/diagnose.h>
33 SwUndoPageDesc::SwUndoPageDesc(const SwPageDesc
& _aOld
,
34 const SwPageDesc
& _aNew
,
36 : SwUndo( _aOld
.GetName() != _aNew
.GetName() ?
37 SwUndoId::RENAME_PAGEDESC
:
38 SwUndoId::CHANGE_PAGEDESC
,
40 m_aOld(_aOld
, _pDoc
), m_aNew(_aNew
, _pDoc
), m_pDoc(_pDoc
), m_bExchange( false )
42 OSL_ENSURE(nullptr != m_pDoc
, "no document?");
45 The page description changes.
46 If there are no header/footer content changes like header on/off or change from shared content
47 to unshared etc., there is no reason to duplicate the content nodes (Crash i55547)
48 But this happens, this Undo Ctor will destroy the unnecessary duplicate and manipulate the
49 content pointer of the both page descriptions.
51 SwPageDesc
&rOldDesc
= m_aOld
.m_PageDesc
;
52 SwPageDesc
&rNewDesc
= m_aNew
.m_PageDesc
;
53 const SwFormatHeader
& rOldHead
= rOldDesc
.GetMaster().GetHeader();
54 const SwFormatHeader
& rNewHead
= rNewDesc
.GetMaster().GetHeader();
55 const SwFormatFooter
& rOldFoot
= rOldDesc
.GetMaster().GetFooter();
56 const SwFormatFooter
& rNewFoot
= rNewDesc
.GetMaster().GetFooter();
57 /* bExchange must not be set, if the old page descriptor will stay active.
59 #i67735#: renaming a page descriptor
60 #i67334#: changing the follow style
61 If header/footer will be activated or deactivated, this undo will not work.
63 m_bExchange
= ( m_aOld
.GetName() == m_aNew
.GetName() ) &&
64 ( _aOld
.GetFollow() == _aNew
.GetFollow() ) &&
65 ( rOldHead
.IsActive() == rNewHead
.IsActive() ) &&
66 ( rOldFoot
.IsActive() == rNewFoot
.IsActive() );
67 if( rOldHead
.IsActive() && ( rOldDesc
.IsHeaderShared() != rNewDesc
.IsHeaderShared() ) )
69 if( rOldFoot
.IsActive() && ( rOldDesc
.IsFooterShared() != rNewDesc
.IsFooterShared() ) )
71 if( ( rOldHead
.IsActive() || rOldFoot
.IsActive() ) && ( rOldDesc
.IsFirstShared() != rNewDesc
.IsFirstShared() ) )
76 if( rNewHead
.IsActive() )
78 SwFrameFormat
* pFormat
= new SwFrameFormat( *rNewHead
.GetHeaderFormat() );
79 // The Ctor of this object will remove the duplicate!
80 SwFormatHeader
aFormatHeader(pFormat
);
82 if (!rNewDesc
.IsHeaderShared())
84 pFormat
= new SwFrameFormat( *rNewDesc
.GetLeft().GetHeader().GetHeaderFormat() );
85 // The Ctor of this object will remove the duplicate!
86 SwFormatHeader
aLeftHeader(pFormat
);
89 if (!rNewDesc
.IsFirstShared())
91 pFormat
= new SwFrameFormat( *rNewDesc
.GetFirstMaster().GetHeader().GetHeaderFormat() );
92 // The Ctor of this object will remove the duplicate!
93 SwFormatHeader
aFirstHeader(pFormat
);
97 // Same procedure for footers...
98 if( rNewFoot
.IsActive() )
100 SwFrameFormat
* pFormat
= new SwFrameFormat( *rNewFoot
.GetFooterFormat() );
101 // The Ctor of this object will remove the duplicate!
102 SwFormatFooter
aFormatFooter(pFormat
);
104 if (!rNewDesc
.IsFooterShared())
106 pFormat
= new SwFrameFormat( *rNewDesc
.GetLeft().GetFooter().GetFooterFormat() );
107 // The Ctor of this object will remove the duplicate!
108 SwFormatFooter
aLeftFooter(pFormat
);
111 if (!rNewDesc
.IsFirstShared())
113 pFormat
= new SwFrameFormat( *rNewDesc
.GetFirstMaster().GetFooter().GetFooterFormat() );
114 // The Ctor of this object will remove the duplicate!
115 SwFormatFooter
aFirstFooter(pFormat
);
120 // After this exchange method the old page description will point to zero,
121 // the new one will point to the node position of the original content nodes.
122 ExchangeContentNodes( m_aOld
.m_PageDesc
, m_aNew
.m_PageDesc
);
125 SwUndoPageDesc::~SwUndoPageDesc()
129 void SwUndoPageDesc::ExchangeContentNodes( SwPageDesc
& rSource
, SwPageDesc
&rDest
)
131 OSL_ENSURE( m_bExchange
, "You shouldn't do that." );
132 const SwFormatHeader
& rDestHead
= rDest
.GetMaster().GetHeader();
133 const SwFormatHeader
& rSourceHead
= rSource
.GetMaster().GetHeader();
134 if( rDestHead
.IsActive() )
136 // Let the destination page description point to the source node position,
137 // from now on this descriptor is responsible for the content nodes!
138 const SwFormatHeader
* pItem
= rDest
.GetMaster().GetAttrSet().GetItemIfSet( RES_HEADER
, false );
139 std::unique_ptr
<SwFormatHeader
> pNewItem(pItem
->Clone());
140 SwFrameFormat
* pNewFormat
= pNewItem
->GetHeaderFormat();
141 pNewFormat
->SetFormatAttr( rSourceHead
.GetHeaderFormat()->GetContent() );
143 // Let the source page description point to zero node position,
144 // it loses the responsible and can be destroyed without removing the content nodes.
145 pItem
= rSource
.GetMaster().GetAttrSet().GetItemIfSet( RES_HEADER
, false );
146 pNewItem
.reset(pItem
->Clone());
147 pNewFormat
= pNewItem
->GetHeaderFormat();
148 pNewFormat
->SetFormatAttr( SwFormatContent() );
150 if( !rDest
.IsHeaderShared() )
152 // Same procedure for unshared header...
153 const SwFormatHeader
& rSourceLeftHead
= rSource
.GetLeft().GetHeader();
154 pItem
= rDest
.GetLeft().GetAttrSet().GetItemIfSet( RES_HEADER
, false );
155 pNewItem
.reset(pItem
->Clone());
156 pNewFormat
= pNewItem
->GetHeaderFormat();
157 pNewFormat
->SetFormatAttr( rSourceLeftHead
.GetHeaderFormat()->GetContent() );
158 pItem
= rSource
.GetLeft().GetAttrSet().GetItemIfSet( RES_HEADER
, false );
159 pNewItem
.reset(pItem
->Clone());
160 pNewFormat
= pNewItem
->GetHeaderFormat();
161 pNewFormat
->SetFormatAttr( SwFormatContent() );
163 if (!rDest
.IsFirstShared())
165 // Same procedure for unshared header...
166 const SwFormatHeader
& rSourceFirstMasterHead
= rSource
.GetFirstMaster().GetHeader();
167 pItem
= rDest
.GetFirstMaster().GetAttrSet().GetItemIfSet( RES_HEADER
, false );
168 pNewItem
.reset(pItem
->Clone());
169 pNewFormat
= pNewItem
->GetHeaderFormat();
170 pNewFormat
->SetFormatAttr( rSourceFirstMasterHead
.GetHeaderFormat()->GetContent() );
171 pItem
= rSource
.GetFirstMaster().GetAttrSet().GetItemIfSet( RES_HEADER
, false );
172 pNewItem
.reset(pItem
->Clone());
173 pNewFormat
= pNewItem
->GetHeaderFormat();
174 pNewFormat
->SetFormatAttr( SwFormatContent() );
177 // Same procedure for footers...
178 const SwFormatFooter
& rDestFoot
= rDest
.GetMaster().GetFooter();
179 const SwFormatFooter
& rSourceFoot
= rSource
.GetMaster().GetFooter();
180 if( !rDestFoot
.IsActive() )
183 const SwFormatFooter
* pItem
;
184 pItem
= rDest
.GetMaster().GetAttrSet().GetItemIfSet( RES_FOOTER
, false );
185 std::unique_ptr
<SwFormatFooter
> pNewItem(pItem
->Clone());
186 SwFrameFormat
*pNewFormat
= pNewItem
->GetFooterFormat();
187 pNewFormat
->SetFormatAttr( rSourceFoot
.GetFooterFormat()->GetContent() );
189 pItem
= rSource
.GetMaster().GetAttrSet().GetItemIfSet( RES_FOOTER
, false );
190 pNewItem
.reset(pItem
->Clone());
191 pNewFormat
= pNewItem
->GetFooterFormat();
192 pNewFormat
->SetFormatAttr( SwFormatContent() );
194 if( !rDest
.IsFooterShared() )
196 const SwFormatFooter
& rSourceLeftFoot
= rSource
.GetLeft().GetFooter();
197 pItem
= rDest
.GetLeft().GetAttrSet().GetItemIfSet( RES_FOOTER
, false );
198 pNewItem
.reset(pItem
->Clone());
199 pNewFormat
= pNewItem
->GetFooterFormat();
200 pNewFormat
->SetFormatAttr( rSourceLeftFoot
.GetFooterFormat()->GetContent() );
201 pItem
= rSource
.GetLeft().GetAttrSet().GetItemIfSet( RES_FOOTER
, false );
202 pNewItem
.reset(pItem
->Clone());
203 pNewFormat
= pNewItem
->GetFooterFormat();
204 pNewFormat
->SetFormatAttr( SwFormatContent() );
206 if (rDest
.IsFirstShared())
209 const SwFormatFooter
& rSourceFirstMasterFoot
= rSource
.GetFirstMaster().GetFooter();
210 pItem
= rDest
.GetFirstMaster().GetAttrSet().GetItemIfSet( RES_FOOTER
, false );
211 pNewItem
.reset(pItem
->Clone());
212 pNewFormat
= pNewItem
->GetFooterFormat();
213 pNewFormat
->SetFormatAttr( rSourceFirstMasterFoot
.GetFooterFormat()->GetContent() );
214 pItem
= rSource
.GetFirstMaster().GetAttrSet().GetItemIfSet( RES_FOOTER
, false );
215 pNewItem
.reset(pItem
->Clone());
216 pNewFormat
= pNewItem
->GetFooterFormat();
217 pNewFormat
->SetFormatAttr( SwFormatContent() );
220 void SwUndoPageDesc::ExitHeaderFooterEdit()
222 SwEditShell
* pESh
= m_pDoc
->GetEditShell();
225 if (pESh
->IsHeaderFooterEdit())
226 pESh
->ToggleHeaderFooterEdit();
229 void SwUndoPageDesc::UndoImpl(::sw::UndoRedoContext
&)
231 // Move (header/footer)content node responsibility from new page descriptor to old one again.
233 ExchangeContentNodes( m_aNew
.m_PageDesc
, m_aOld
.m_PageDesc
);
234 m_pDoc
->ChgPageDesc(m_aOld
.GetName(), m_aOld
);
235 ExitHeaderFooterEdit();
238 void SwUndoPageDesc::RedoImpl(::sw::UndoRedoContext
&)
240 // Move (header/footer)content node responsibility from old page descriptor to new one again.
242 ExchangeContentNodes( m_aOld
.m_PageDesc
, m_aNew
.m_PageDesc
);
243 m_pDoc
->ChgPageDesc(m_aNew
.GetName(), m_aNew
);
244 ExitHeaderFooterEdit();
247 SwRewriter
SwUndoPageDesc::GetRewriter() const
251 aResult
.AddRule(UndoArg1
, m_aOld
.GetName());
252 aResult
.AddRule(UndoArg2
, SwResId(STR_YIELDS
));
253 aResult
.AddRule(UndoArg3
, m_aNew
.GetName());
258 SwUndoPageDescCreate::SwUndoPageDescCreate(const SwPageDesc
* pNew
,
260 : SwUndo(SwUndoId::CREATE_PAGEDESC
, _pDoc
), m_pDesc(pNew
), m_aNew(*pNew
, _pDoc
),
263 OSL_ENSURE(nullptr != m_pDoc
, "no document?");
266 SwUndoPageDescCreate::~SwUndoPageDescCreate()
270 void SwUndoPageDescCreate::UndoImpl(::sw::UndoRedoContext
&)
278 m_pDoc
->DelPageDesc(m_aNew
.GetName(), true);
281 void SwUndoPageDescCreate::DoImpl()
283 SwPageDesc aPageDesc
= m_aNew
;
284 m_pDoc
->MakePageDesc(m_aNew
.GetName(), &aPageDesc
, false, true);
287 void SwUndoPageDescCreate::RedoImpl(::sw::UndoRedoContext
&)
292 void SwUndoPageDescCreate::RepeatImpl(::sw::RepeatContext
&)
294 ::sw::UndoGuard
const undoGuard(m_pDoc
->GetIDocumentUndoRedo());
298 SwRewriter
SwUndoPageDescCreate::GetRewriter() const
303 aResult
.AddRule(UndoArg1
, m_pDesc
->GetName());
305 aResult
.AddRule(UndoArg1
, m_aNew
.GetName());
310 SwUndoPageDescDelete::SwUndoPageDescDelete(const SwPageDesc
& _aOld
,
312 : SwUndo(SwUndoId::DELETE_PAGEDESC
, _pDoc
), m_aOld(_aOld
, _pDoc
), m_pDoc(_pDoc
)
314 OSL_ENSURE(nullptr != m_pDoc
, "no document?");
317 SwUndoPageDescDelete::~SwUndoPageDescDelete()
321 void SwUndoPageDescDelete::UndoImpl(::sw::UndoRedoContext
&)
323 SwPageDesc aPageDesc
= m_aOld
;
324 m_pDoc
->MakePageDesc(m_aOld
.GetName(), &aPageDesc
, false, true);
327 void SwUndoPageDescDelete::DoImpl()
329 m_pDoc
->DelPageDesc(m_aOld
.GetName(), true);
332 void SwUndoPageDescDelete::RedoImpl(::sw::UndoRedoContext
&)
337 void SwUndoPageDescDelete::RepeatImpl(::sw::RepeatContext
&)
339 ::sw::UndoGuard
const undoGuard(m_pDoc
->GetIDocumentUndoRedo());
343 SwRewriter
SwUndoPageDescDelete::GetRewriter() const
347 aResult
.AddRule(UndoArg1
, m_aOld
.GetName());
352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */