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;
77 SetHasDummyChar(true);
82 /*************************************************************************
83 * SwTxtFlyCnt::MakeTxtHint()
85 * An dieser Stelle soll einmal der Gesamtzusammenhang bei der Erzeugung
86 * eines neuen SwTxtFlyCnt erlaeutert werden.
87 * Das MakeTxtHint() wird z.B. im SwTxtNode::Copy() gerufen.
88 * Fuer die komplette Verdopplung sind folgende Schritte notwendig:
89 * 1) Duplizieren des pFmt incl. Inhalt, Attributen etc.
90 * 2) Setzen des Ankers
92 * Da fuer die Bewaeltigung der Aufgaben nicht immer alle Informationen
93 * bereitstehen und darueber hinaus bestimmte Methoden erst zu einem
94 * spaeteren Zeitpunkt gerufen werden duerfen (weil nocht nicht alle
95 * Nodeinformationen vorliegen), verteilt sich der Ablauf.
96 * ad 1) MakeTxtHint() wird durch den Aufruf von SwDoc::CopyLayout()
97 * der das neue FlyFrmFmt erzeugt und mit dem duplizierten Inhalt des
99 * ad 2) SetAnchor() wird von SwTxtNode::Insert() gerufen und sorgt fuer das
100 * setzen des Ankers (die SwPosition des Dummy-Zeichens wird dem FlyFrmFmt
101 * per SetAttr bekannt gegeben). Dies kann nicht im MakeTxtHint erledigt
102 * werden, da der Zielnode unbestimmt ist.
103 * ad 3) _GetFlyFrm() wird im Formatierungsprozess vom LineIter gerufen
104 * und sucht den FlyFrm zum Dummyzeichen des aktuellen CntntFrm. Wird keiner
105 * gefunden, so wird ein neuer FlyFrm angelegt.
106 * Kritisch an diesem Vorgehen ist, dass das pCntnt->AppendFly() eine
107 * sofortige Neuformatierung von pCntnt anstoesst. Die Rekursion kommt
108 * allerdings durch den Lockmechanismus in SwTxtFrm::Format() nicht
110 * Attraktiv ist der Umstand, dass niemand ueber die vom Node abhaengigen
111 * CntntFrms iterieren braucht, um die FlyInCntFrm anzulegen. Dies geschieht
113 *************************************************************************/
115 void SwTxtFlyCnt::CopyFlyFmt( SwDoc
* pDoc
)
117 SwFrmFmt
* pFmt
= GetFlyCnt().GetFrmFmt();
118 ASSERT( pFmt
, "von welchem Format soll ich eine Kopie erzeugen?" )
119 // Das FlyFrmFmt muss dupliziert werden.
120 // In CopyLayoutFmt (siehe doclay.cxx) wird das FlyFrmFmt erzeugt
121 // und der Inhalt dupliziert.
123 // fuers kopieren vom Attribut das Undo immer abschalten
124 BOOL bUndo
= pDoc
->DoesUndo();
125 pDoc
->DoUndo( FALSE
);
126 SwFmtAnchor
aAnchor( pFmt
->GetAnchor() );
127 if( FLY_PAGE
!= aAnchor
.GetAnchorId() &&
128 pDoc
!= pFmt
->GetDoc() ) // Unterschiedliche Docs?
130 // JP 03.06.96: dann sorge dafuer, das der koperierte Anker auf
131 // gueltigen Content zeigt! Die Umsetzung auf die
132 // richtige Position erfolgt spaeter.
133 SwNodeIndex
aIdx( pDoc
->GetNodes().GetEndOfExtras(), +2 );
134 SwCntntNode
* pCNd
= aIdx
.GetNode().GetCntntNode();
136 pCNd
= pDoc
->GetNodes().GoNext( &aIdx
);
138 SwPosition
* pPos
= (SwPosition
*)aAnchor
.GetCntntAnchor();
140 if( FLY_IN_CNTNT
== aAnchor
.GetAnchorId() )
141 pPos
->nContent
.Assign( pCNd
, 0 );
144 pPos
->nContent
.Assign( 0, 0 );
145 ASSERT( !this, "CopyFlyFmt: Was fuer ein Anker?" );
149 SwFrmFmt
* pNew
= pDoc
->CopyLayoutFmt( *pFmt
, aAnchor
, false, false );
150 pDoc
->DoUndo( bUndo
);
151 ((SwFmtFlyCnt
&)GetFlyCnt()).SetFlyFmt( pNew
);
154 /*************************************************************************
155 * SwTxtFlyCnt::SetAnchor()
157 * SetAnchor() wird von SwTxtNode::Insert() gerufen und sorgt fuer das
158 * setzen des Ankers (die SwPosition des Dummy-Zeichens wird dem FlyFrmFmt
159 * per SetAttr bekannt gegeben). Dies kann nicht im MakeTxtHint erledigt
160 * werden, da der Zielnode unbestimmt ist.
161 * (siehe Kommentar in SwTxtFlyCnt::MakeTxtHint)
162 *************************************************************************/
164 void SwTxtFlyCnt::SetAnchor( const SwTxtNode
*pNode
)
166 // fuers Undo muss der neue Anker schon bekannt sein !
168 // Wir ermitteln den Index im Nodesarray zum Node
170 SwDoc
* pDoc
= (SwDoc
*)pNode
->GetDoc();
172 SwIndex
aIdx( (SwTxtNode
*)pNode
, *GetStart() );
173 SwPosition
aPos( *pNode
->StartOfSectionNode(), aIdx
);
174 SwFrmFmt
* pFmt
= GetFlyCnt().GetFrmFmt();
175 SwFmtAnchor
aAnchor( pFmt
->GetAnchor() );
177 if( !aAnchor
.GetCntntAnchor() ||
178 !aAnchor
.GetCntntAnchor()->nNode
.GetNode().GetNodes().IsDocNodes() ||
179 &aAnchor
.GetCntntAnchor()->nNode
.GetNode() != (SwNode
*)pNode
)
182 aPos
.nNode
= aAnchor
.GetCntntAnchor()->nNode
;
184 aAnchor
.SetType( FLY_IN_CNTNT
); // defaulten !!
185 aAnchor
.SetAnchor( &aPos
);
187 // beim Ankerwechsel werden immer alle FlyFrms vom Attribut geloescht
188 // JP 25.04.95: wird innerhalb des SplitNodes die Frames verschoben
189 // koennen die Frames erhalten bleiben.
190 if( ( !pNode
->GetpSwpHints() || !pNode
->GetpSwpHints()->IsInSplitNode() )
191 && RES_DRAWFRMFMT
!= pFmt
->Which() )
194 // stehen wir noch im falschen Dokument ?
195 if( pDoc
!= pFmt
->GetDoc() )
197 // fuers kopieren vom Attribut das Undo immer abschalten
198 BOOL bUndo
= pDoc
->DoesUndo();
199 pDoc
->DoUndo( FALSE
);
200 SwFrmFmt
* pNew
= pDoc
->CopyLayoutFmt( *pFmt
, aAnchor
, false, false );
201 pDoc
->DoUndo( bUndo
);
203 bUndo
= pFmt
->GetDoc()->DoesUndo();
204 pFmt
->GetDoc()->DoUndo( FALSE
);
205 pFmt
->GetDoc()->DelLayoutFmt( pFmt
);
206 pFmt
->GetDoc()->DoUndo( bUndo
);
207 ((SwFmtFlyCnt
&)GetFlyCnt()).SetFlyFmt( pNew
);
209 else if( pNode
->GetpSwpHints() &&
210 pNode
->GetpSwpHints()->IsInSplitNode() &&
211 RES_DRAWFRMFMT
!= pFmt
->Which() )
214 pFmt
->SetFmtAttr( aAnchor
); // nur den Anker neu setzen
215 pFmt
->UnlockModify();
218 pFmt
->SetFmtAttr( aAnchor
); // nur den Anker neu setzen
220 // Am Node haengen u.a. abhaengige CntFrms.
221 // Fuer jeden CntFrm wird ein SwFlyInCntFrm angelegt.
224 /*************************************************************************
225 * SwTxtFlyCnt::_GetFlyFrm()
227 * _GetFlyFrm() wird im Formatierungsprozess vom LineIter gerufen
228 * und sucht den FlyFrm zum Dummyzeichen des aktuellen CntntFrm. Wird keiner
229 * gefunden, so wird ein neuer FlyFrm angelegt.
230 * (siehe Kommentar ind SwTxtFlyCnt::MakeTxtHint)
231 *************************************************************************/
233 SwFlyInCntFrm
*SwTxtFlyCnt::_GetFlyFrm( const SwFrm
*pCurrFrm
)
235 SwFrmFmt
* pFrmFmt
= GetFlyCnt().GetFrmFmt();
236 if( RES_DRAWFRMFMT
== pFrmFmt
->Which() )
238 ASSERT( !this, "SwTxtFlyCnt::_GetFlyFrm: DrawInCnt-Baustelle!" );
242 SwClientIter
aIter( *GetFlyCnt().pFmt
);
243 ASSERT( pCurrFrm
->IsTxtFrm(), "SwTxtFlyCnt::_GetFlyFrm for TxtFrms only." );
245 if( aIter
.GoStart() )
247 SwTxtFrm
*pFirst
= (SwTxtFrm
*)pCurrFrm
;
248 while ( pFirst
->IsFollow() )
249 pFirst
= pFirst
->FindMaster();
251 { SwFrm
* pFrm
= PTR_CAST( SwFrm
, aIter() );
254 SwTxtFrm
*pTmp
= pFirst
;
256 { if( ( (SwFlyFrm
*)pFrm
)->GetAnchorFrm() == (SwFrm
*) pTmp
)
258 if ( pTmp
!= pCurrFrm
)
260 pTmp
->RemoveFly( (SwFlyFrm
*)pFrm
);
261 ((SwTxtFrm
*)pCurrFrm
)->AppendFly( (SwFlyFrm
*)pFrm
);
263 return (SwFlyInCntFrm
*)pFrm
;
265 pTmp
= pTmp
->GetFollow();
271 // Wir haben keinen passenden FlyFrm gefunden, deswegen wird ein
273 // Dabei wird eine sofortige Neuformatierung von pCurrFrm angestossen.
274 // Die Rekursion wird durch den Lockmechanismus in SwTxtFrm::Format()
276 SwFlyInCntFrm
*pFly
= new SwFlyInCntFrm( (SwFlyFrmFmt
*)pFrmFmt
, (SwFrm
*)pCurrFrm
);
277 ((SwFrm
*)pCurrFrm
)->AppendFly( pFly
);
280 // 7922: Wir muessen dafuer sorgen, dass der Inhalt des FlyInCnt
281 // nach seiner Konstruktion stramm durchformatiert wird.
282 // --> OD 2004-11-09 #i26945# - Use new object formatter to format Writer
283 // fly frame and its content.
284 SwObjectFormatter::FormatObj( *pFly
, const_cast<SwFrm
*>(pCurrFrm
),
285 pCurrFrm
->FindPageFrm() );