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