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