1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: atrflyin.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
36 #include "hintids.hxx"
37 #include "cntfrm.hxx" // _GetFly
39 #include "pam.hxx" // fuer SwTxtFlyCnt
40 #include "flyfrm.hxx" // fuer SwTxtFlyCnt
41 #include "ndtxt.hxx" // SwFlyFrmFmt
42 #include "frmfmt.hxx" // SwFlyFrmFmt
43 #include <fmtflcnt.hxx>
44 #include <txtflcnt.hxx>
45 #include <fmtanchr.hxx>
48 #include "flyfrms.hxx"
49 // --> OD 2004-11-09 #i26945#
50 #include <objectformatter.hxx>
53 SwFmtFlyCnt::SwFmtFlyCnt( SwFrmFmt
*pFrmFmt
)
54 : SfxPoolItem( RES_TXTATR_FLYCNT
),
60 int __EXPORT
SwFmtFlyCnt::operator==( const SfxPoolItem
& rAttr
) const
62 ASSERT( SfxPoolItem::operator==( rAttr
), "keine gleichen Attribute" );
63 return( pTxtAttr
&& ((SwFmtFlyCnt
&)rAttr
).pTxtAttr
&&
64 *pTxtAttr
->GetStart() == *((SwFmtFlyCnt
&)rAttr
).pTxtAttr
->GetStart() &&
65 pFmt
== ((SwFmtFlyCnt
&)rAttr
).GetFrmFmt() );
68 SfxPoolItem
* __EXPORT
SwFmtFlyCnt::Clone( SfxItemPool
* ) const
70 return new SwFmtFlyCnt( pFmt
);
73 SwTxtFlyCnt::SwTxtFlyCnt( SwFmtFlyCnt
& rAttr
, xub_StrLen nStartPos
)
74 : SwTxtAttr( rAttr
, nStartPos
)
76 rAttr
.pTxtAttr
= this;
81 /*************************************************************************
82 * SwTxtFlyCnt::MakeTxtHint()
84 * An dieser Stelle soll einmal der Gesamtzusammenhang bei der Erzeugung
85 * eines neuen SwTxtFlyCnt erlaeutert werden.
86 * Das MakeTxtHint() wird z.B. im SwTxtNode::Copy() gerufen.
87 * Fuer die komplette Verdopplung sind folgende Schritte notwendig:
88 * 1) Duplizieren des pFmt incl. Inhalt, Attributen etc.
89 * 2) Setzen des Ankers
91 * Da fuer die Bewaeltigung der Aufgaben nicht immer alle Informationen
92 * bereitstehen und darueber hinaus bestimmte Methoden erst zu einem
93 * spaeteren Zeitpunkt gerufen werden duerfen (weil nocht nicht alle
94 * Nodeinformationen vorliegen), verteilt sich der Ablauf.
95 * ad 1) MakeTxtHint() wird durch den Aufruf von SwDoc::CopyLayout()
96 * der das neue FlyFrmFmt erzeugt und mit dem duplizierten Inhalt des
98 * ad 2) SetAnchor() wird von SwTxtNode::Insert() gerufen und sorgt fuer das
99 * setzen des Ankers (die SwPosition des Dummy-Zeichens wird dem FlyFrmFmt
100 * per SetAttr bekannt gegeben). Dies kann nicht im MakeTxtHint erledigt
101 * werden, da der Zielnode unbestimmt ist.
102 * ad 3) _GetFlyFrm() wird im Formatierungsprozess vom LineIter gerufen
103 * und sucht den FlyFrm zum Dummyzeichen des aktuellen CntntFrm. Wird keiner
104 * gefunden, so wird ein neuer FlyFrm angelegt.
105 * Kritisch an diesem Vorgehen ist, dass das pCntnt->AppendFly() eine
106 * sofortige Neuformatierung von pCntnt anstoesst. Die Rekursion kommt
107 * allerdings durch den Lockmechanismus in SwTxtFrm::Format() nicht
109 * Attraktiv ist der Umstand, dass niemand ueber die vom Node abhaengigen
110 * CntntFrms iterieren braucht, um die FlyInCntFrm anzulegen. Dies geschieht
112 *************************************************************************/
114 void SwTxtFlyCnt::CopyFlyFmt( SwDoc
* pDoc
)
116 SwFrmFmt
* pFmt
= GetFlyCnt().GetFrmFmt();
117 ASSERT( pFmt
, "von welchem Format soll ich eine Kopie erzeugen?" )
118 // Das FlyFrmFmt muss dupliziert werden.
119 // In CopyLayoutFmt (siehe doclay.cxx) wird das FlyFrmFmt erzeugt
120 // und der Inhalt dupliziert.
122 // fuers kopieren vom Attribut das Undo immer abschalten
123 BOOL bUndo
= pDoc
->DoesUndo();
124 pDoc
->DoUndo( FALSE
);
125 SwFmtAnchor
aAnchor( pFmt
->GetAnchor() );
126 if( FLY_PAGE
!= aAnchor
.GetAnchorId() &&
127 pDoc
!= pFmt
->GetDoc() ) // Unterschiedliche Docs?
129 // JP 03.06.96: dann sorge dafuer, das der koperierte Anker auf
130 // gueltigen Content zeigt! Die Umsetzung auf die
131 // richtige Position erfolgt spaeter.
132 SwNodeIndex
aIdx( pDoc
->GetNodes().GetEndOfExtras(), +2 );
133 SwCntntNode
* pCNd
= aIdx
.GetNode().GetCntntNode();
135 pCNd
= pDoc
->GetNodes().GoNext( &aIdx
);
137 SwPosition
* pPos
= (SwPosition
*)aAnchor
.GetCntntAnchor();
139 if( FLY_IN_CNTNT
== aAnchor
.GetAnchorId() )
140 pPos
->nContent
.Assign( pCNd
, 0 );
143 pPos
->nContent
.Assign( 0, 0 );
144 ASSERT( !this, "CopyFlyFmt: Was fuer ein Anker?" );
148 SwFrmFmt
* pNew
= pDoc
->CopyLayoutFmt( *pFmt
, aAnchor
, false, false );
149 pDoc
->DoUndo( bUndo
);
150 ((SwFmtFlyCnt
&)GetFlyCnt()).SetFlyFmt( pNew
);
153 /*************************************************************************
154 * SwTxtFlyCnt::SetAnchor()
156 * SetAnchor() wird von SwTxtNode::Insert() gerufen und sorgt fuer das
157 * setzen des Ankers (die SwPosition des Dummy-Zeichens wird dem FlyFrmFmt
158 * per SetAttr bekannt gegeben). Dies kann nicht im MakeTxtHint erledigt
159 * werden, da der Zielnode unbestimmt ist.
160 * (siehe Kommentar in SwTxtFlyCnt::MakeTxtHint)
161 *************************************************************************/
163 void SwTxtFlyCnt::SetAnchor( const SwTxtNode
*pNode
)
165 // fuers Undo muss der neue Anker schon bekannt sein !
167 // Wir ermitteln den Index im Nodesarray zum Node
169 SwDoc
* pDoc
= (SwDoc
*)pNode
->GetDoc();
171 SwIndex
aIdx( (SwTxtNode
*)pNode
, *GetStart() );
172 SwPosition
aPos( *pNode
->StartOfSectionNode(), aIdx
);
173 SwFrmFmt
* pFmt
= GetFlyCnt().GetFrmFmt();
174 SwFmtAnchor
aAnchor( pFmt
->GetAnchor() );
176 if( !aAnchor
.GetCntntAnchor() ||
177 !aAnchor
.GetCntntAnchor()->nNode
.GetNode().GetNodes().IsDocNodes() ||
178 &aAnchor
.GetCntntAnchor()->nNode
.GetNode() != (SwNode
*)pNode
)
181 aPos
.nNode
= aAnchor
.GetCntntAnchor()->nNode
;
183 aAnchor
.SetType( FLY_IN_CNTNT
); // defaulten !!
184 aAnchor
.SetAnchor( &aPos
);
186 // beim Ankerwechsel werden immer alle FlyFrms vom Attribut geloescht
187 // JP 25.04.95: wird innerhalb des SplitNodes die Frames verschoben
188 // koennen die Frames erhalten bleiben.
189 if( ( !pNode
->GetpSwpHints() || !pNode
->GetpSwpHints()->IsInSplitNode() )
190 && RES_DRAWFRMFMT
!= pFmt
->Which() )
193 // stehen wir noch im falschen Dokument ?
194 if( pDoc
!= pFmt
->GetDoc() )
196 // fuers kopieren vom Attribut das Undo immer abschalten
197 BOOL bUndo
= pDoc
->DoesUndo();
198 pDoc
->DoUndo( FALSE
);
199 SwFrmFmt
* pNew
= pDoc
->CopyLayoutFmt( *pFmt
, aAnchor
, false, false );
200 pDoc
->DoUndo( bUndo
);
202 bUndo
= pFmt
->GetDoc()->DoesUndo();
203 pFmt
->GetDoc()->DoUndo( FALSE
);
204 pFmt
->GetDoc()->DelLayoutFmt( pFmt
);
205 pFmt
->GetDoc()->DoUndo( bUndo
);
206 ((SwFmtFlyCnt
&)GetFlyCnt()).SetFlyFmt( pNew
);
208 else if( pNode
->GetpSwpHints() &&
209 pNode
->GetpSwpHints()->IsInSplitNode() &&
210 RES_DRAWFRMFMT
!= pFmt
->Which() )
213 pFmt
->SetFmtAttr( aAnchor
); // nur den Anker neu setzen
214 pFmt
->UnlockModify();
217 pFmt
->SetFmtAttr( aAnchor
); // nur den Anker neu setzen
219 // Am Node haengen u.a. abhaengige CntFrms.
220 // Fuer jeden CntFrm wird ein SwFlyInCntFrm angelegt.
223 /*************************************************************************
224 * SwTxtFlyCnt::_GetFlyFrm()
226 * _GetFlyFrm() wird im Formatierungsprozess vom LineIter gerufen
227 * und sucht den FlyFrm zum Dummyzeichen des aktuellen CntntFrm. Wird keiner
228 * gefunden, so wird ein neuer FlyFrm angelegt.
229 * (siehe Kommentar ind SwTxtFlyCnt::MakeTxtHint)
230 *************************************************************************/
232 SwFlyInCntFrm
*SwTxtFlyCnt::_GetFlyFrm( const SwFrm
*pCurrFrm
)
234 SwFrmFmt
* pFrmFmt
= GetFlyCnt().GetFrmFmt();
235 if( RES_DRAWFRMFMT
== pFrmFmt
->Which() )
237 ASSERT( !this, "SwTxtFlyCnt::_GetFlyFrm: DrawInCnt-Baustelle!" );
241 SwClientIter
aIter( *GetFlyCnt().pFmt
);
242 ASSERT( pCurrFrm
->IsTxtFrm(), "SwTxtFlyCnt::_GetFlyFrm for TxtFrms only." );
244 if( aIter
.GoStart() )
246 SwTxtFrm
*pFirst
= (SwTxtFrm
*)pCurrFrm
;
247 while ( pFirst
->IsFollow() )
248 pFirst
= pFirst
->FindMaster();
250 { SwFrm
* pFrm
= PTR_CAST( SwFrm
, aIter() );
253 SwTxtFrm
*pTmp
= pFirst
;
255 { if( ( (SwFlyFrm
*)pFrm
)->GetAnchorFrm() == (SwFrm
*) pTmp
)
257 if ( pTmp
!= pCurrFrm
)
259 pTmp
->RemoveFly( (SwFlyFrm
*)pFrm
);
260 ((SwTxtFrm
*)pCurrFrm
)->AppendFly( (SwFlyFrm
*)pFrm
);
262 return (SwFlyInCntFrm
*)pFrm
;
264 pTmp
= pTmp
->GetFollow();
270 // Wir haben keinen passenden FlyFrm gefunden, deswegen wird ein
272 // Dabei wird eine sofortige Neuformatierung von pCurrFrm angestossen.
273 // Die Rekursion wird durch den Lockmechanismus in SwTxtFrm::Format()
275 SwFlyInCntFrm
*pFly
= new SwFlyInCntFrm( (SwFlyFrmFmt
*)pFrmFmt
, (SwFrm
*)pCurrFrm
);
276 ((SwFrm
*)pCurrFrm
)->AppendFly( pFly
);
279 // 7922: Wir muessen dafuer sorgen, dass der Inhalt des FlyInCnt
280 // nach seiner Konstruktion stramm durchformatiert wird.
281 // --> OD 2004-11-09 #i26945# - Use new object formatter to format Writer
282 // fly frame and its content.
283 SwObjectFormatter::FormatObj( *pFly
, const_cast<SwFrm
*>(pCurrFrm
),
284 pCurrFrm
->FindPageFrm() );