summaryrefslogtreecommitdiff
path: root/sw/source/core/txtnode/atrflyin.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/txtnode/atrflyin.cxx')
-rw-r--r--sw/source/core/txtnode/atrflyin.cxx286
1 files changed, 286 insertions, 0 deletions
diff --git a/sw/source/core/txtnode/atrflyin.cxx b/sw/source/core/txtnode/atrflyin.cxx
new file mode 100644
index 000000000000..4a7319993d0a
--- /dev/null
+++ b/sw/source/core/txtnode/atrflyin.cxx
@@ -0,0 +1,286 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "hintids.hxx"
+#include "cntfrm.hxx" // _GetFly
+#include "doc.hxx"
+#include <IDocumentUndoRedo.hxx>
+#include "pam.hxx" // fuer SwTxtFlyCnt
+#include "flyfrm.hxx" // fuer SwTxtFlyCnt
+#include "ndtxt.hxx" // SwFlyFrmFmt
+#include "frmfmt.hxx" // SwFlyFrmFmt
+#include <fmtflcnt.hxx>
+#include <txtflcnt.hxx>
+#include <fmtanchr.hxx>
+#include "swfont.hxx"
+#include "txtfrm.hxx"
+#include "flyfrms.hxx"
+#include <objectformatter.hxx>
+#include <switerator.hxx>
+
+SwFmtFlyCnt::SwFmtFlyCnt( SwFrmFmt *pFrmFmt )
+ : SfxPoolItem( RES_TXTATR_FLYCNT ),
+ pTxtAttr( 0 ),
+ pFmt( pFrmFmt )
+{
+}
+
+int SwFmtFlyCnt::operator==( const SfxPoolItem& rAttr ) const
+{
+ OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
+ return( pTxtAttr && ((SwFmtFlyCnt&)rAttr).pTxtAttr &&
+ *pTxtAttr->GetStart() == *((SwFmtFlyCnt&)rAttr).pTxtAttr->GetStart() &&
+ pFmt == ((SwFmtFlyCnt&)rAttr).GetFrmFmt() );
+}
+
+SfxPoolItem* SwFmtFlyCnt::Clone( SfxItemPool* ) const
+{
+ return new SwFmtFlyCnt( pFmt );
+}
+
+SwTxtFlyCnt::SwTxtFlyCnt( SwFmtFlyCnt& rAttr, xub_StrLen nStartPos )
+ : SwTxtAttr( rAttr, nStartPos )
+{
+ rAttr.pTxtAttr = this;
+ SetHasDummyChar(true);
+}
+
+
+
+/*************************************************************************
+ * SwTxtFlyCnt::MakeTxtHint()
+ *
+ * An dieser Stelle soll einmal der Gesamtzusammenhang bei der Erzeugung
+ * eines neuen SwTxtFlyCnt erlaeutert werden.
+ * Das MakeTxtHint() wird z.B. im SwTxtNode::Copy() gerufen.
+ * Fuer die komplette Verdopplung sind folgende Schritte notwendig:
+ * 1) Duplizieren des pFmt incl. Inhalt, Attributen etc.
+ * 2) Setzen des Ankers
+ * 3) Benachrichtigung
+ * Da fuer die Bewaeltigung der Aufgaben nicht immer alle Informationen
+ * bereitstehen und darueber hinaus bestimmte Methoden erst zu einem
+ * spaeteren Zeitpunkt gerufen werden duerfen (weil nocht nicht alle
+ * Nodeinformationen vorliegen), verteilt sich der Ablauf.
+ * ad 1) MakeTxtHint() wird durch den Aufruf von SwDoc::CopyLayout()
+ * der das neue FlyFrmFmt erzeugt und mit dem duplizierten Inhalt des
+ * FlyFrm verbunden.
+ * ad 2) SetAnchor() wird von SwTxtNode::Insert() gerufen und sorgt fuer das
+ * setzen des Ankers (die SwPosition des Dummy-Zeichens wird dem FlyFrmFmt
+ * per SetAttr bekannt gegeben). Dies kann nicht im MakeTxtHint erledigt
+ * werden, da der Zielnode unbestimmt ist.
+ * ad 3) _GetFlyFrm() wird im Formatierungsprozess vom LineIter gerufen
+ * und sucht den FlyFrm zum Dummyzeichen des aktuellen CntntFrm. Wird keiner
+ * gefunden, so wird ein neuer FlyFrm angelegt.
+ * Kritisch an diesem Vorgehen ist, dass das pCntnt->AppendFly() eine
+ * sofortige Neuformatierung von pCntnt anstoesst. Die Rekursion kommt
+ * allerdings durch den Lockmechanismus in SwTxtFrm::Format() nicht
+ * zu stande.
+ * Attraktiv ist der Umstand, dass niemand ueber die vom Node abhaengigen
+ * CntntFrms iterieren braucht, um die FlyInCntFrm anzulegen. Dies geschieht
+ * bei der Arbeit.
+ *************************************************************************/
+
+void SwTxtFlyCnt::CopyFlyFmt( SwDoc* pDoc )
+{
+ SwFrmFmt* pFmt = GetFlyCnt().GetFrmFmt();
+ OSL_ENSURE( pFmt, "von welchem Format soll ich eine Kopie erzeugen?" );
+ // Das FlyFrmFmt muss dupliziert werden.
+ // In CopyLayoutFmt (siehe doclay.cxx) wird das FlyFrmFmt erzeugt
+ // und der Inhalt dupliziert.
+
+ // disable undo while copying attribute
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+ SwFmtAnchor aAnchor( pFmt->GetAnchor() );
+ if ((FLY_AT_PAGE != aAnchor.GetAnchorId()) &&
+ (pDoc != pFmt->GetDoc())) // different documents?
+ {
+ // JP 03.06.96: dann sorge dafuer, das der koperierte Anker auf
+ // gueltigen Content zeigt! Die Umsetzung auf die
+ // richtige Position erfolgt spaeter.
+ SwNodeIndex aIdx( pDoc->GetNodes().GetEndOfExtras(), +2 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = pDoc->GetNodes().GoNext( &aIdx );
+
+ SwPosition* pPos = (SwPosition*)aAnchor.GetCntntAnchor();
+ pPos->nNode = aIdx;
+ if (FLY_AS_CHAR == aAnchor.GetAnchorId())
+ {
+ pPos->nContent.Assign( pCNd, 0 );
+ }
+ else
+ {
+ pPos->nContent.Assign( 0, 0 );
+ OSL_ENSURE( !this, "CopyFlyFmt: Was fuer ein Anker?" );
+ }
+ }
+
+ SwFrmFmt* pNew = pDoc->CopyLayoutFmt( *pFmt, aAnchor, false, false );
+ ((SwFmtFlyCnt&)GetFlyCnt()).SetFlyFmt( pNew );
+}
+
+/*************************************************************************
+ * SwTxtFlyCnt::SetAnchor()
+ *
+ * SetAnchor() wird von SwTxtNode::Insert() gerufen und sorgt fuer das
+ * setzen des Ankers (die SwPosition des Dummy-Zeichens wird dem FlyFrmFmt
+ * per SetAttr bekannt gegeben). Dies kann nicht im MakeTxtHint erledigt
+ * werden, da der Zielnode unbestimmt ist.
+ * (siehe Kommentar in SwTxtFlyCnt::MakeTxtHint)
+ *************************************************************************/
+
+void SwTxtFlyCnt::SetAnchor( const SwTxtNode *pNode )
+{
+ // fuers Undo muss der neue Anker schon bekannt sein !
+
+ // Wir ermitteln den Index im Nodesarray zum Node
+
+ SwDoc* pDoc = (SwDoc*)pNode->GetDoc();
+
+ SwIndex aIdx( (SwTxtNode*)pNode, *GetStart() );
+ SwPosition aPos( *pNode->StartOfSectionNode(), aIdx );
+ SwFrmFmt* pFmt = GetFlyCnt().GetFrmFmt();
+ SwFmtAnchor aAnchor( pFmt->GetAnchor() );
+
+ if( !aAnchor.GetCntntAnchor() ||
+ !aAnchor.GetCntntAnchor()->nNode.GetNode().GetNodes().IsDocNodes() ||
+ &aAnchor.GetCntntAnchor()->nNode.GetNode() != (SwNode*)pNode )
+ aPos.nNode = *pNode;
+ else
+ aPos.nNode = aAnchor.GetCntntAnchor()->nNode;
+
+ aAnchor.SetType( FLY_AS_CHAR ); // default!
+ aAnchor.SetAnchor( &aPos );
+
+ // beim Ankerwechsel werden immer alle FlyFrms vom Attribut geloescht
+ // JP 25.04.95: wird innerhalb des SplitNodes die Frames verschoben
+ // koennen die Frames erhalten bleiben.
+ if( ( !pNode->GetpSwpHints() || !pNode->GetpSwpHints()->IsInSplitNode() )
+ && RES_DRAWFRMFMT != pFmt->Which() )
+ pFmt->DelFrms();
+
+ // stehen wir noch im falschen Dokument ?
+ if( pDoc != pFmt->GetDoc() )
+ {
+ // disable undo while copying attribute
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+ SwFrmFmt* pNew = pDoc->CopyLayoutFmt( *pFmt, aAnchor, false, false );
+
+ ::sw::UndoGuard const undoGuardFmt(
+ pFmt->GetDoc()->GetIDocumentUndoRedo());
+ pFmt->GetDoc()->DelLayoutFmt( pFmt );
+ ((SwFmtFlyCnt&)GetFlyCnt()).SetFlyFmt( pNew );
+ }
+ else if( pNode->GetpSwpHints() &&
+ pNode->GetpSwpHints()->IsInSplitNode() &&
+ RES_DRAWFRMFMT != pFmt->Which() )
+ {
+ pFmt->LockModify();
+ pFmt->SetFmtAttr( aAnchor ); // nur den Anker neu setzen
+ pFmt->UnlockModify();
+ }
+ else
+ pFmt->SetFmtAttr( aAnchor ); // nur den Anker neu setzen
+
+ // Am Node haengen u.a. abhaengige CntFrms.
+ // Fuer jeden CntFrm wird ein SwFlyInCntFrm angelegt.
+}
+
+/*************************************************************************
+ * SwTxtFlyCnt::_GetFlyFrm()
+ *
+ * _GetFlyFrm() wird im Formatierungsprozess vom LineIter gerufen
+ * und sucht den FlyFrm zum Dummyzeichen des aktuellen CntntFrm. Wird keiner
+ * gefunden, so wird ein neuer FlyFrm angelegt.
+ * (siehe Kommentar ind SwTxtFlyCnt::MakeTxtHint)
+ *************************************************************************/
+
+SwFlyInCntFrm *SwTxtFlyCnt::_GetFlyFrm( const SwFrm *pCurrFrm )
+{
+ SwFrmFmt* pFrmFmt = GetFlyCnt().GetFrmFmt();
+ if( RES_DRAWFRMFMT == pFrmFmt->Which() )
+ {
+ OSL_ENSURE( !this, "SwTxtFlyCnt::_GetFlyFrm: DrawInCnt-Baustelle!" );
+ return NULL;
+ }
+
+ SwIterator<SwFlyFrm,SwFmt> aIter( *GetFlyCnt().pFmt );
+ OSL_ENSURE( pCurrFrm->IsTxtFrm(), "SwTxtFlyCnt::_GetFlyFrm for TxtFrms only." );
+ SwFrm* pFrm = aIter.First();
+ if ( pFrm )
+ {
+ SwTxtFrm *pFirst = (SwTxtFrm*)pCurrFrm;
+ while ( pFirst->IsFollow() )
+ pFirst = pFirst->FindMaster();
+ do
+ {
+ SwTxtFrm *pTmp = pFirst;
+ do
+ { if( ( (SwFlyFrm*)pFrm )->GetAnchorFrm() == (SwFrm*) pTmp )
+ {
+ if ( pTmp != pCurrFrm )
+ {
+ pTmp->RemoveFly( (SwFlyFrm*)pFrm );
+ ((SwTxtFrm*)pCurrFrm)->AppendFly( (SwFlyFrm*)pFrm );
+ }
+ return (SwFlyInCntFrm*)pFrm;
+ }
+ pTmp = pTmp->GetFollow();
+ } while ( pTmp );
+
+ pFrm = aIter.Next();
+
+ } while( pFrm );
+ }
+
+ // Wir haben keinen passenden FlyFrm gefunden, deswegen wird ein
+ // neuer angelegt.
+ // Dabei wird eine sofortige Neuformatierung von pCurrFrm angestossen.
+ // Die Rekursion wird durch den Lockmechanismus in SwTxtFrm::Format()
+ // abgewuergt.
+ SwFrm* pCurrFrame = const_cast< SwFrm* >(pCurrFrm);
+ SwFlyInCntFrm *pFly = new SwFlyInCntFrm( (SwFlyFrmFmt*)pFrmFmt, pCurrFrame, pCurrFrame );
+ pCurrFrame->AppendFly( pFly );
+ pFly->RegistFlys();
+
+ // 7922: Wir muessen dafuer sorgen, dass der Inhalt des FlyInCnt
+ // nach seiner Konstruktion stramm durchformatiert wird.
+ // --> OD 2004-11-09 #i26945# - Use new object formatter to format Writer
+ // fly frame and its content.
+ SwObjectFormatter::FormatObj( *pFly, const_cast<SwFrm*>(pCurrFrm),
+ pCurrFrm->FindPageFrm() );
+ // <--
+
+ return pFly;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */