You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/kword/KWFrameList.cpp

198 lines
6.6 KiB

/* This file is part of the KOffice project
* Copyright (C) 2005 Thomas Zander <zander@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; version 2.
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <algorithm>
#include "KWFrameList.h"
#include "KWFrame.h"
#include "KWFrameSet.h"
#include "KWTextFrameSet.h"
#include "KWDocument.h"
#include "KWViewMode.h"
#include "KWPageManager.h"
//#define DEBUG_SPEED
KWFrameList::KWFrameList(KWDocument *doc, KWFrame *theFrame) {
m_doc = doc;
m_frame = theFrame;
update();
}
TQValueList<KWFrame *> KWFrameList::framesBelow() const {
TQValueList<KWFrame *> frames;
//kdDebug() << "framesBelow " << endl;
// Copy until we find m_frame
for ( TQValueVector<KWFrame*>::const_iterator it = m_frames.begin(), end = m_frames.end(); it != end && *it != m_frame; ++it) {
frames.append( *it );
}
return frames;
}
TQValueList<KWFrame *> KWFrameList::framesOnTop() const {
//kdDebug() << "framesOnTop " << endl;
TQValueList<KWFrame *> frames;
// Copy from m_frame to the end
bool found = false;
for ( TQValueVector<KWFrame*>::const_iterator it = m_frames.begin(), end = m_frames.end(); it != end; ++it) {
KWFrame* frame = *it;
if ( found ) {
Q_ASSERT( !frame->frameSet()->isFloating() );
frames.append( frame );
}
else if ( frame == m_frame )
found = true;
}
return frames;
}
void KWFrameList::setFrames(const TQPtrList<KWFrame> &frames) {
// kdDebug(31001) << "KWFrameList::setFrames for " << m_frame->frameSet()->name() << endl;
m_frames.clear();
if ( m_doc->layoutViewMode() && !m_doc->layoutViewMode()->hasFrames() )
return;
TQPtrList<KWFrameSet> parentFramesets;
KWFrameSet *fs = m_frame->frameSet();
while(fs) {
parentFramesets.append(fs);
fs = (KWFrameSet*) fs->anchorFrameset();
}
// We now look at all other frames (in the same page)
// to check for intersections. This is o(n^2), but with n small.
TQPtrListIterator<KWFrame> it( frames );
for ( ; it.current() ; ++it )
{
KWFrame* daFrame = it.current();
// kdDebug(32001) << "frame: " << daFrame->frameSet()->name() << endl;
if ( m_frame == daFrame ) {
m_frames.append( daFrame );
continue;
}
// Skip 'daFrame' if it belongs to a table.
// We trust that KWTableFrameSet will not make cells overlap ;)
if ( m_frame->frameSet()->groupmanager() || daFrame->frameSet()->groupmanager() )
continue;
// Skip all frames from the parent frameset, if 'm_frame' is floating
// ## might need a for loop for the case of inline-inside-inline,
// or maybe calling isPaintedBy instead [depending on what should happen for tables]
if ( daFrame->frameSet()->isFloating() &&
(parentFramesets.contains(daFrame->frameSet()->anchorFrameset()) ||
daFrame->frameSet()->isPaintedBy(m_frame->frameSet())) )
continue;
// Floating frames are not "on top", they are "inside".
// They are not "below" anything either - the parent frameset is.
if ( m_frame->frameSet()->isFloating() )
continue;
KoRect intersect = m_frame->intersect( daFrame->outerKoRect() );
if ( !intersect.isEmpty() )
m_frames.append( daFrame );
}
std::sort( m_frames.begin(), m_frames.end(), KWFrame::compareFrameZOrder );
}
void KWFrameList::updateAfterMove(int oldPageNum) {
int pageNumber = m_doc->pageManager()->pageNumber(m_frame);
updateZOrderFor(m_doc->framesInPage( pageNumber, false ));
if (pageNumber != oldPageNum)
updateZOrderFor(m_doc->framesInPage( oldPageNum, false ));
}
void KWFrameList::update() {
int pageNumber = m_doc->pageManager()->pageNumber(m_frame);
if(pageNumber == -1)
return;
updateZOrderFor(m_doc->framesInPage( pageNumber, false ));
}
void KWFrameList::updateZOrderFor(const TQPtrList<KWFrame> &frames) {
#ifdef DEBUG_SPEED
kdDebug(32001) << "KWFrameList::updateZOrderFor " << frames.count() << " frames"<< endl;
TQTime dt;
dt.start();
int numberAdded = 0;
#endif
TQPtrListIterator<KWFrame> iter(frames);
while( iter.current() ) {
KWFrame *frame = iter.current();
Q_ASSERT( frame->frameStack() );
frame->frameStack()->setFrames(frames);
#ifdef DEBUG_SPEED
numberAdded += frame->frameStack()->m_frames.count();
#endif
++iter;
}
#ifdef DEBUG_SPEED
kdDebug(32001) << " updateZOrderFor took " << (float)(dt.elapsed()) / 1000 << " seconds, added " << numberAdded << " frames" << endl;
#endif
}
// ****** statics ******
KWFrameList *KWFrameList::getFirstFrameList(KWDocument *doc) {
for (TQPtrListIterator<KWFrameSet> fsit = doc->framesetsIterator(); fsit.current() ; ++fsit ) {
KWFrame *frame = fsit.current()->frame(0);
if (frame && frame->frameStack())
return frame->frameStack();
}
return 0;
}
void KWFrameList::recalcFrames(KWDocument *doc, int pageFrom, int pageTo) {
for(int i=pageTo; i >= pageFrom; i--) {
TQPtrList<KWFrame> framesOnPage = doc->framesInPage( i, false );
KWFrame *f = framesOnPage.first();
while(f) {
Q_ASSERT(f->frameStack());
f->frameStack()->setFrames(framesOnPage);
f = framesOnPage.next();
}
}
}
void KWFrameList::recalcAllFrames(KWDocument *doc) {
recalcFrames(doc, doc->startPage(), doc->lastPage());
}
void KWFrameList::createFrameList(KWFrame *f, KWDocument *doc) {
Q_ASSERT(f);
Q_ASSERT(doc);
if(f->frameStack())
return;
f->setFrameStack(new KWFrameList(doc, f));
}
void KWFrameList::createFrameList(KWFrameSet *fs, KWDocument *doc, bool forceUpdate) {
TQPtrListIterator<KWFrame> iter( fs->frameIterator() );
KWFrame *f = iter.current();
while(f) {
createFrameList(f, doc);
if(forceUpdate)
f->frameStack()->update();
++iter;
f = iter.current();
}
}