Line data Source code
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 "hintids.hxx"
21 : #include "cntfrm.hxx"
22 : #include "doc.hxx"
23 : #include <IDocumentUndoRedo.hxx>
24 : #include "pam.hxx"
25 : #include "flyfrm.hxx"
26 : #include "ndtxt.hxx"
27 : #include "frmfmt.hxx"
28 : #include <fmtflcnt.hxx>
29 : #include <txtflcnt.hxx>
30 : #include <fmtanchr.hxx>
31 : #include "swfont.hxx"
32 : #include "txtfrm.hxx"
33 : #include "flyfrms.hxx"
34 : #include <objectformatter.hxx>
35 : #include <switerator.hxx>
36 :
37 0 : SwFmtFlyCnt::SwFmtFlyCnt( SwFrmFmt *pFrmFmt )
38 : : SfxPoolItem( RES_TXTATR_FLYCNT ),
39 : pTxtAttr( 0 ),
40 0 : pFmt( pFrmFmt )
41 : {
42 0 : }
43 :
44 0 : bool SwFmtFlyCnt::operator==( const SfxPoolItem& rAttr ) const
45 : {
46 : OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
47 0 : return( pTxtAttr && ((SwFmtFlyCnt&)rAttr).pTxtAttr &&
48 0 : *pTxtAttr->GetStart() == *((SwFmtFlyCnt&)rAttr).pTxtAttr->GetStart() &&
49 0 : pFmt == ((SwFmtFlyCnt&)rAttr).GetFrmFmt() );
50 : }
51 :
52 0 : SfxPoolItem* SwFmtFlyCnt::Clone( SfxItemPool* ) const
53 : {
54 0 : return new SwFmtFlyCnt( pFmt );
55 : }
56 :
57 0 : SwTxtFlyCnt::SwTxtFlyCnt( SwFmtFlyCnt& rAttr, sal_Int32 nStartPos )
58 0 : : SwTxtAttr( rAttr, nStartPos )
59 : {
60 0 : rAttr.pTxtAttr = this;
61 0 : SetHasDummyChar(true);
62 0 : }
63 :
64 : /*************************************************************************
65 : * SwTxtFlyCnt::MakeTxtHint()
66 : *
67 : * An dieser Stelle soll einmal der Gesamtzusammenhang bei der Erzeugung
68 : * eines neuen SwTxtFlyCnt erlaeutert werden.
69 : * Das MakeTxtHint() wird z.B. im SwTxtNode::Copy() gerufen.
70 : * Fuer die komplette Verdopplung sind folgende Schritte notwendig:
71 : * 1) Duplizieren des pFmt incl. Inhalt, Attributen etc.
72 : * 2) Setzen des Ankers
73 : * 3) Benachrichtigung
74 : * Da fuer die Bewaeltigung der Aufgaben nicht immer alle Informationen
75 : * bereitstehen und darueber hinaus bestimmte Methoden erst zu einem
76 : * spaeteren Zeitpunkt gerufen werden duerfen (weil nocht nicht alle
77 : * Nodeinformationen vorliegen), verteilt sich der Ablauf.
78 : * ad 1) MakeTxtHint() wird durch den Aufruf von SwDoc::CopyLayout()
79 : * der das neue FlyFrmFmt erzeugt und mit dem duplizierten Inhalt des
80 : * FlyFrm verbunden.
81 : * ad 2) SetAnchor() wird von SwTxtNode::Insert() gerufen und sorgt fuer das
82 : * setzen des Ankers (die SwPosition des Dummy-Zeichens wird dem FlyFrmFmt
83 : * per SetAttr bekannt gegeben). Dies kann nicht im MakeTxtHint erledigt
84 : * werden, da der Zielnode unbestimmt ist.
85 : * ad 3) _GetFlyFrm() wird im Formatierungsprozess vom LineIter gerufen
86 : * und sucht den FlyFrm zum Dummyzeichen des aktuellen CntntFrm. Wird keiner
87 : * gefunden, so wird ein neuer FlyFrm angelegt.
88 : * Kritisch an diesem Vorgehen ist, dass das pCntnt->AppendFly() eine
89 : * sofortige Neuformatierung von pCntnt anstoesst. Die Rekursion kommt
90 : * allerdings durch den Lockmechanismus in SwTxtFrm::Format() nicht
91 : * zu stande.
92 : * Attraktiv ist der Umstand, dass niemand ueber die vom Node abhaengigen
93 : * CntntFrms iterieren braucht, um die FlyInCntFrm anzulegen. Dies geschieht
94 : * bei der Arbeit.
95 : *************************************************************************/
96 :
97 0 : void SwTxtFlyCnt::CopyFlyFmt( SwDoc* pDoc )
98 : {
99 0 : SwFrmFmt* pFmt = GetFlyCnt().GetFrmFmt();
100 : OSL_ENSURE( pFmt, "von welchem Format soll ich eine Kopie erzeugen?" );
101 : // Das FlyFrmFmt muss dupliziert werden.
102 : // In CopyLayoutFmt (siehe doclay.cxx) wird das FlyFrmFmt erzeugt
103 : // und der Inhalt dupliziert.
104 :
105 : // disable undo while copying attribute
106 0 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
107 0 : SwFmtAnchor aAnchor( pFmt->GetAnchor() );
108 0 : if ((FLY_AT_PAGE != aAnchor.GetAnchorId()) &&
109 0 : (pDoc != pFmt->GetDoc())) // different documents?
110 : {
111 : // JP 03.06.96: dann sorge dafuer, das der koperierte Anker auf
112 : // gueltigen Content zeigt! Die Umsetzung auf die
113 : // richtige Position erfolgt spaeter.
114 0 : SwNodeIndex aIdx( pDoc->GetNodes().GetEndOfExtras(), +2 );
115 0 : SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
116 0 : if( !pCNd )
117 0 : pCNd = pDoc->GetNodes().GoNext( &aIdx );
118 :
119 0 : SwPosition* pPos = (SwPosition*)aAnchor.GetCntntAnchor();
120 0 : pPos->nNode = aIdx;
121 0 : if (FLY_AS_CHAR == aAnchor.GetAnchorId())
122 : {
123 0 : pPos->nContent.Assign( pCNd, 0 );
124 : }
125 : else
126 : {
127 0 : pPos->nContent.Assign( 0, 0 );
128 : OSL_ENSURE( !this, "CopyFlyFmt: Was fuer ein Anker?" );
129 0 : }
130 : }
131 :
132 0 : SwFrmFmt* pNew = pDoc->CopyLayoutFmt( *pFmt, aAnchor, false, false );
133 0 : ((SwFmtFlyCnt&)GetFlyCnt()).SetFlyFmt( pNew );
134 0 : }
135 :
136 : /*************************************************************************
137 : * SwTxtFlyCnt::SetAnchor()
138 : *
139 : * SetAnchor() wird von SwTxtNode::Insert() gerufen und sorgt fuer das
140 : * setzen des Ankers (die SwPosition des Dummy-Zeichens wird dem FlyFrmFmt
141 : * per SetAttr bekannt gegeben). Dies kann nicht im MakeTxtHint erledigt
142 : * werden, da der Zielnode unbestimmt ist.
143 : * (siehe Kommentar in SwTxtFlyCnt::MakeTxtHint)
144 : *************************************************************************/
145 :
146 0 : void SwTxtFlyCnt::SetAnchor( const SwTxtNode *pNode )
147 : {
148 : // fuers Undo muss der neue Anker schon bekannt sein !
149 :
150 : // Wir ermitteln den Index im Nodesarray zum Node
151 :
152 0 : SwDoc* pDoc = (SwDoc*)pNode->GetDoc();
153 :
154 0 : SwIndex aIdx( (SwTxtNode*)pNode, *GetStart() );
155 0 : SwPosition aPos( *pNode->StartOfSectionNode(), aIdx );
156 0 : SwFrmFmt* pFmt = GetFlyCnt().GetFrmFmt();
157 0 : SwFmtAnchor aAnchor( pFmt->GetAnchor() );
158 :
159 0 : if( !aAnchor.GetCntntAnchor() ||
160 0 : !aAnchor.GetCntntAnchor()->nNode.GetNode().GetNodes().IsDocNodes() ||
161 0 : &aAnchor.GetCntntAnchor()->nNode.GetNode() != (SwNode*)pNode )
162 0 : aPos.nNode = *pNode;
163 : else
164 0 : aPos.nNode = aAnchor.GetCntntAnchor()->nNode;
165 :
166 0 : aAnchor.SetType( FLY_AS_CHAR ); // default!
167 0 : aAnchor.SetAnchor( &aPos );
168 :
169 : // beim Ankerwechsel werden immer alle FlyFrms vom Attribut geloescht
170 : // JP 25.04.95: wird innerhalb des SplitNodes die Frames verschoben
171 : // koennen die Frames erhalten bleiben.
172 0 : if( ( !pNode->GetpSwpHints() || !pNode->GetpSwpHints()->IsInSplitNode() )
173 0 : && RES_DRAWFRMFMT != pFmt->Which() )
174 0 : pFmt->DelFrms();
175 :
176 : // stehen wir noch im falschen Dokument ?
177 0 : if( pDoc != pFmt->GetDoc() )
178 : {
179 : // disable undo while copying attribute
180 0 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
181 0 : SwFrmFmt* pNew = pDoc->CopyLayoutFmt( *pFmt, aAnchor, false, false );
182 :
183 : ::sw::UndoGuard const undoGuardFmt(
184 0 : pFmt->GetDoc()->GetIDocumentUndoRedo());
185 0 : pFmt->GetDoc()->DelLayoutFmt( pFmt );
186 0 : ((SwFmtFlyCnt&)GetFlyCnt()).SetFlyFmt( pNew );
187 : }
188 0 : else if( pNode->GetpSwpHints() &&
189 0 : pNode->GetpSwpHints()->IsInSplitNode() &&
190 0 : RES_DRAWFRMFMT != pFmt->Which() )
191 : {
192 0 : pFmt->LockModify();
193 0 : pFmt->SetFmtAttr( aAnchor ); // nur den Anker neu setzen
194 0 : pFmt->UnlockModify();
195 : }
196 : else
197 0 : pFmt->SetFmtAttr( aAnchor ); // nur den Anker neu setzen
198 :
199 : // Am Node haengen u.a. abhaengige CntFrms.
200 : // Fuer jeden CntFrm wird ein SwFlyInCntFrm angelegt.
201 0 : }
202 :
203 : /*************************************************************************
204 : * SwTxtFlyCnt::_GetFlyFrm()
205 : *
206 : * _GetFlyFrm() wird im Formatierungsprozess vom LineIter gerufen
207 : * und sucht den FlyFrm zum Dummyzeichen des aktuellen CntntFrm. Wird keiner
208 : * gefunden, so wird ein neuer FlyFrm angelegt.
209 : * (siehe Kommentar ind SwTxtFlyCnt::MakeTxtHint)
210 : *************************************************************************/
211 :
212 0 : SwFlyInCntFrm *SwTxtFlyCnt::_GetFlyFrm( const SwFrm *pCurrFrm )
213 : {
214 0 : SwFrmFmt* pFrmFmt = GetFlyCnt().GetFrmFmt();
215 0 : if( RES_DRAWFRMFMT == pFrmFmt->Which() )
216 : {
217 : OSL_ENSURE( !this, "SwTxtFlyCnt::_GetFlyFrm: DrawInCnt-Baustelle!" );
218 0 : return NULL;
219 : }
220 :
221 0 : SwIterator<SwFlyFrm,SwFmt> aIter( *GetFlyCnt().pFmt );
222 : OSL_ENSURE( pCurrFrm->IsTxtFrm(), "SwTxtFlyCnt::_GetFlyFrm for TxtFrms only." );
223 0 : SwFrm* pFrm = aIter.First();
224 0 : if ( pFrm )
225 : {
226 0 : SwTxtFrm *pFirst = (SwTxtFrm*)pCurrFrm;
227 0 : while ( pFirst->IsFollow() )
228 0 : pFirst = pFirst->FindMaster();
229 0 : do
230 : {
231 0 : SwTxtFrm *pTmp = pFirst;
232 0 : do
233 0 : { if( ( (SwFlyFrm*)pFrm )->GetAnchorFrm() == (SwFrm*) pTmp )
234 : {
235 0 : if ( pTmp != pCurrFrm )
236 : {
237 0 : pTmp->RemoveFly( (SwFlyFrm*)pFrm );
238 0 : ((SwTxtFrm*)pCurrFrm)->AppendFly( (SwFlyFrm*)pFrm );
239 : }
240 0 : return (SwFlyInCntFrm*)pFrm;
241 : }
242 0 : pTmp = pTmp->GetFollow();
243 : } while ( pTmp );
244 :
245 0 : pFrm = aIter.Next();
246 :
247 : } while( pFrm );
248 : }
249 :
250 : // Wir haben keinen passenden FlyFrm gefunden, deswegen wird ein
251 : // neuer angelegt.
252 : // Dabei wird eine sofortige Neuformatierung von pCurrFrm angestossen.
253 : // Die Rekursion wird durch den Lockmechanismus in SwTxtFrm::Format()
254 : // abgewuergt.
255 0 : SwFrm* pCurrFrame = const_cast< SwFrm* >(pCurrFrm);
256 0 : SwFlyInCntFrm *pFly = new SwFlyInCntFrm( (SwFlyFrmFmt*)pFrmFmt, pCurrFrame, pCurrFrame );
257 0 : pCurrFrame->AppendFly( pFly );
258 0 : pFly->RegistFlys();
259 :
260 : // 7922: Wir muessen dafuer sorgen, dass der Inhalt des FlyInCnt
261 : // nach seiner Konstruktion stramm durchformatiert wird.
262 : // #i26945# - Use new object formatter to format Writer
263 : // fly frame and its content.
264 : SwObjectFormatter::FormatObj( *pFly, const_cast<SwFrm*>(pCurrFrm),
265 0 : pCurrFrm->FindPageFrm() );
266 :
267 0 : return pFly;
268 : }
269 :
270 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|