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.
754 lines
32 KiB
754 lines
32 KiB
/* This file is part of the KDE project
|
|
Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@kde.org>
|
|
Copyright (C) 2000-2006 David Faure <faure@kde.org>
|
|
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; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
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 "KWFrame.h"
|
|
#include "KWFrameSet.h"
|
|
#include "KWFrameList.h"
|
|
#include "KWDocument.h"
|
|
#include "KWPageManager.h"
|
|
#include "KWTextFrameSet.h"
|
|
#include "KWViewMode.h"
|
|
#include "KWCanvas.h"
|
|
|
|
#include <KoOasisContext.h>
|
|
#include <KoXmlNS.h>
|
|
#include <KoXmlWriter.h>
|
|
#include <KoStyleStack.h>
|
|
|
|
#include <kcommand.h>
|
|
#include <kdebug.h>
|
|
|
|
#include <float.h> // for DBL_DIG
|
|
|
|
//#define DEBUG_DRAW
|
|
|
|
/******************************************************************/
|
|
/* Class: ZOrderedFrameList */
|
|
/******************************************************************/
|
|
|
|
int ZOrderedFrameList::compareItems(TQPtrCollection::Item a, TQPtrCollection::Item b)
|
|
{
|
|
int za = ((KWFrame *)a)->zOrder();
|
|
int zb = ((KWFrame *)b)->zOrder();
|
|
if (za == zb) return 0;
|
|
if (za < zb) return -1;
|
|
return 1;
|
|
}
|
|
|
|
|
|
/******************************************************************/
|
|
/* Class: KWFrame */
|
|
/******************************************************************/
|
|
|
|
KWFrame::KWFrame(KWFrame * frame)
|
|
{
|
|
m_runAround = RA_NO;
|
|
//kdDebug(32001) << "KWFrame::KWFrame this=" << this << " frame=" << frame << endl;
|
|
copySettings( frame );
|
|
m_minFrameHeight=0;
|
|
m_frameStack = 0; // lazy initialisation.
|
|
}
|
|
|
|
KWFrame::KWFrame(KWFrameSet *fs, double left, double top, double width, double height, RunAround ra )
|
|
: KoRect( left, top, width, height ),
|
|
// Initialize member vars here. This ensures they are all initialized, since it's
|
|
// easier to compare this list with the member vars list (compiler ensures order).
|
|
m_sheetSide( AnySide ),
|
|
m_runAround( ra ),
|
|
m_runAroundSide( RA_BIGGEST ),
|
|
m_frameBehavior( AutoExtendFrame ),
|
|
m_newFrameBehavior( ( fs && fs->type() == FT_TEXT ) ? Reconnect : NoFollowup ),
|
|
m_bCopy( false ),
|
|
m_drawFootNoteLine( false ),
|
|
m_runAroundLeft( 1.0 ),
|
|
m_runAroundRight( 1.0 ),
|
|
m_runAroundTop( 1.0 ),
|
|
m_runAroundBottom( 1.0 ),
|
|
m_paddingLeft( 0 ),
|
|
m_paddingRight( 0 ),
|
|
m_paddingTop( 0 ),
|
|
m_paddingBottom( 0 ),
|
|
m_minFrameHeight( 0.01 ), // not 0, since AutoExtendFrame means min-height in odt
|
|
m_internalY( 0 ),
|
|
m_zOrder( 0 ),
|
|
m_backgroundColor( (fs && (fs->type() == FT_PICTURE || fs->type() == FT_PART)) ? TQBrush( TQColor(), TQt::NoBrush) : TQBrush( TQColor() ) ), // valid brush with invalid color ( default )
|
|
m_borderLeft( TQColor(), KoBorder::SOLID, 0 ),
|
|
m_borderRight( TQColor(), KoBorder::SOLID, 0 ),
|
|
m_borderTop( TQColor(), KoBorder::SOLID, 0 ),
|
|
m_borderBottom( TQColor(), KoBorder::SOLID, 0 ),
|
|
m_frameSet( fs )
|
|
{
|
|
//kdDebug(32001) << "KWFrame::KWFrame " << this << " left=" << left << " top=" << top << endl;
|
|
m_frameStack = 0; // lazy initialisation.
|
|
}
|
|
|
|
KWFrame::~KWFrame()
|
|
{
|
|
//kdDebug(32001) << "KWFrame::~KWFrame " << this << endl;
|
|
delete m_frameStack;
|
|
m_frameStack = 0;
|
|
}
|
|
|
|
void KWFrame::setBackgroundColor( const TQBrush &color )
|
|
{
|
|
m_backgroundColor = color;
|
|
}
|
|
|
|
|
|
int KWFrame::pageNumber() const
|
|
{
|
|
Q_ASSERT( m_frameSet );
|
|
if( !m_frameSet ) {
|
|
kdDebug() << k_funcinfo << this << " has no frameset!" << endl;
|
|
return 0;
|
|
}
|
|
if( !m_frameSet->pageManager() ) {
|
|
kdWarning() << k_funcinfo << this << " is not a frame that is in use; misses a pageManager!" << endl;
|
|
return -1;
|
|
}
|
|
return frameSet()->pageManager()->pageNumber(this);
|
|
}
|
|
|
|
int KWFrame::pageNumber( KWDocument* doc ) const
|
|
{
|
|
return doc->pageManager()->pageNumber(this);
|
|
}
|
|
|
|
KWFrame *KWFrame::getCopy() {
|
|
/* returns a deep copy of self */
|
|
return new KWFrame(this);
|
|
}
|
|
|
|
void KWFrame::copySettings(KWFrame *frm)
|
|
{
|
|
setFrameSet( frm->frameSet() ); // do this first in case of debug output in the methods below
|
|
setRect(frm->x(), frm->y(), frm->width(), frm->height());
|
|
// Keep order identical as member var order (and init in ctor)
|
|
setSheetSide(frm->sheetSide());
|
|
setRunAround(frm->runAround());
|
|
setRunAroundSide(frm->runAroundSide());
|
|
setFrameBehavior(frm->frameBehavior());
|
|
setNewFrameBehavior(frm->newFrameBehavior());
|
|
setRunAroundGap(frm->runAroundLeft(), frm->runAroundRight(), frm->runAroundTop(), frm->runAroundBottom());
|
|
setPaddingLeft(frm->paddingLeft());
|
|
setPaddingRight(frm->paddingRight());
|
|
setPaddingTop(frm->paddingTop());
|
|
setPaddingBottom(frm->paddingBottom());
|
|
setMinimumFrameHeight(frm->minimumFrameHeight());
|
|
m_internalY = 0; // internal Y is recalculated
|
|
setZOrder(frm->zOrder());
|
|
setCopy(frm->isCopy());
|
|
m_drawFootNoteLine = false; // recalculated
|
|
setBackgroundColor( frm->backgroundColor() );
|
|
setLeftBorder(frm->leftBorder());
|
|
setRightBorder(frm->rightBorder());
|
|
setTopBorder(frm->topBorder());
|
|
setBottomBorder(frm->bottomBorder());
|
|
}
|
|
|
|
void KWFrame::frameBordersChanged() {
|
|
if (frameSet()->isFloating())
|
|
frameSet()->anchorFrameset()->invalidate();
|
|
}
|
|
|
|
|
|
void KWFrame::updateRulerHandles(){
|
|
// TODO
|
|
#if 0
|
|
if(! isSelected())
|
|
{
|
|
KWDocument *doc = frameSet()->kWordDocument();
|
|
if(doc)
|
|
doc->updateRulerFrameStartEnd();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
TQRect KWFrame::outerRect( KWViewMode* viewMode ) const
|
|
{
|
|
KWDocument *doc = m_frameSet->kWordDocument();
|
|
TQRect outerRect( doc->zoomRect( *this ) );
|
|
if ( viewMode && !m_frameSet->groupmanager() ) {
|
|
int minBorder = viewMode->drawFrameBorders() ? 1 : 0;
|
|
KWFrame* settingsFrame = m_frameSet->settingsFrame( this );
|
|
outerRect.rLeft() -= KoBorder::zoomWidthX( settingsFrame->leftBorder().width(), doc, minBorder );
|
|
outerRect.rTop() -= KoBorder::zoomWidthY( settingsFrame->topBorder().width(), doc, minBorder );
|
|
outerRect.rRight() += KoBorder::zoomWidthX( settingsFrame->rightBorder().width(), doc, minBorder );
|
|
outerRect.rBottom() += KoBorder::zoomWidthY( settingsFrame->bottomBorder().width(), doc, minBorder );
|
|
}
|
|
return outerRect;
|
|
}
|
|
|
|
KoRect KWFrame::outerKoRect() const
|
|
{
|
|
KoRect outerRect = *this;
|
|
KWDocument *doc = m_frameSet->kWordDocument();
|
|
KWFrame* settingsFrame = m_frameSet->settingsFrame( this );
|
|
outerRect.rLeft() -= KoBorder::zoomWidthX( settingsFrame->leftBorder().width(), doc, 1 ) / doc->zoomedResolutionX();
|
|
outerRect.rTop() -= KoBorder::zoomWidthY( settingsFrame->topBorder().width(), doc, 1 ) / doc->zoomedResolutionY();
|
|
outerRect.rRight() += KoBorder::zoomWidthX( settingsFrame->rightBorder().width(), doc, 1 ) / doc->zoomedResolutionX();
|
|
outerRect.rBottom() += KoBorder::zoomWidthY( settingsFrame->bottomBorder().width(), doc, 1 ) / doc->zoomedResolutionY();
|
|
return outerRect;
|
|
}
|
|
|
|
KoRect KWFrame::runAroundRect() const
|
|
{
|
|
KoRect raRect = outerKoRect();
|
|
raRect.rLeft() -= m_runAroundLeft;
|
|
raRect.rRight() += m_runAroundRight;
|
|
raRect.rTop() -= m_runAroundTop;
|
|
raRect.rBottom() += m_runAroundBottom;
|
|
return raRect;
|
|
}
|
|
|
|
void KWFrame::save( TQDomElement &frameElem )
|
|
{
|
|
// setAttribute( double ) uses a default precision of 6, and this seems
|
|
// to be 6 digits, even like '123.123' !
|
|
frameElem.setAttribute( "left", TQString::number( left(), 'g', DBL_DIG ) );
|
|
frameElem.setAttribute( "top", TQString::number( top(), 'g', DBL_DIG ) );
|
|
frameElem.setAttribute( "right", TQString::number( right(), 'g', DBL_DIG ) );
|
|
frameElem.setAttribute( "bottom", TQString::number( bottom(), 'g', DBL_DIG ) );
|
|
if ( minimumFrameHeight() > 0 )
|
|
frameElem.setAttribute( "min-height", TQString::number( minimumFrameHeight(), 'g', DBL_DIG ) );
|
|
|
|
if ( !m_frameSet->isHeaderOrFooter() && !m_frameSet->isMainFrameset() )
|
|
{
|
|
if(runAround()!=RA_NO)
|
|
{
|
|
frameElem.setAttribute( "runaround", static_cast<int>( runAround() ) );
|
|
if (runAround() == RA_BOUNDINGRECT)
|
|
{
|
|
if (runAroundSide()==RA_LEFT)
|
|
frameElem.setAttribute( "runaroundSide", "left" );
|
|
else if (runAroundSide()==RA_RIGHT)
|
|
frameElem.setAttribute( "runaroundSide", "right" );
|
|
else
|
|
frameElem.setAttribute( "runaroundSide", "biggest" );
|
|
}
|
|
}
|
|
if(runAroundLeft()!=0 || runAroundRight()!=0 || runAroundTop()!=0 || runAroundBottom()!=0) {
|
|
frameElem.setAttribute( "runaroundLeft", m_runAroundLeft );
|
|
frameElem.setAttribute( "runaroundRight", m_runAroundRight );
|
|
frameElem.setAttribute( "runaroundTop", m_runAroundTop );
|
|
frameElem.setAttribute( "runaroundBottom", m_runAroundBottom );
|
|
// The old file format had only one value, keep compat
|
|
double runAroundGap = TQMAX( TQMAX( m_runAroundLeft, m_runAroundRight ), TQMAX( m_runAroundTop, m_runAroundBottom ) );
|
|
frameElem.setAttribute( "runaroundGap", runAroundGap );
|
|
}
|
|
}
|
|
|
|
if(leftBorder().penWidth()!=0)
|
|
frameElem.setAttribute( "lWidth", leftBorder().penWidth() );
|
|
|
|
if(leftBorder().color.isValid())
|
|
{
|
|
frameElem.setAttribute( "lRed", leftBorder().color.red() );
|
|
frameElem.setAttribute( "lGreen", leftBorder().color.green() );
|
|
frameElem.setAttribute( "lBlue", leftBorder().color.blue() );
|
|
}
|
|
if(leftBorder().getStyle() != KoBorder::SOLID)
|
|
frameElem.setAttribute( "lStyle", static_cast<int>( leftBorder().getStyle()) );
|
|
|
|
if(rightBorder().penWidth()!=0)
|
|
frameElem.setAttribute( "rWidth", rightBorder().penWidth() );
|
|
|
|
if(rightBorder().color.isValid())
|
|
{
|
|
frameElem.setAttribute( "rRed", rightBorder().color.red() );
|
|
frameElem.setAttribute( "rGreen", rightBorder().color.green() );
|
|
frameElem.setAttribute( "rBlue", rightBorder().color.blue() );
|
|
}
|
|
if(rightBorder().getStyle() != KoBorder::SOLID)
|
|
frameElem.setAttribute( "rStyle", static_cast<int>( rightBorder().getStyle() ) );
|
|
|
|
if(topBorder().penWidth()!=0)
|
|
frameElem.setAttribute( "tWidth", topBorder().penWidth() );
|
|
|
|
if(topBorder().color.isValid())
|
|
{
|
|
frameElem.setAttribute( "tRed", topBorder().color.red() );
|
|
frameElem.setAttribute( "tGreen", topBorder().color.green() );
|
|
frameElem.setAttribute( "tBlue", topBorder().color.blue() );
|
|
}
|
|
if(topBorder().getStyle() != KoBorder::SOLID)
|
|
frameElem.setAttribute( "tStyle", static_cast<int>( topBorder().getStyle() ) );
|
|
|
|
if(bottomBorder().penWidth()!=0) {
|
|
frameElem.setAttribute( "bWidth", bottomBorder().penWidth() );
|
|
}
|
|
if(bottomBorder().color.isValid()) {
|
|
frameElem.setAttribute( "bRed", bottomBorder().color.red() );
|
|
frameElem.setAttribute( "bGreen", bottomBorder().color.green() );
|
|
frameElem.setAttribute( "bBlue", bottomBorder().color.blue() );
|
|
}
|
|
if(bottomBorder().getStyle() != KoBorder::SOLID)
|
|
frameElem.setAttribute( "bStyle", static_cast<int>( bottomBorder().getStyle() ) );
|
|
|
|
if(backgroundColor().color().isValid())
|
|
{
|
|
frameElem.setAttribute( "bkRed", backgroundColor().color().red() );
|
|
frameElem.setAttribute( "bkGreen", backgroundColor().color().green() );
|
|
frameElem.setAttribute( "bkBlue", backgroundColor().color().blue() );
|
|
frameElem.setAttribute( "bkStyle", (int)backgroundColor().style ());
|
|
}
|
|
if(paddingLeft() != 0)
|
|
frameElem.setAttribute( "bleftpt", paddingLeft() );
|
|
|
|
if(paddingRight()!=0)
|
|
frameElem.setAttribute( "brightpt", paddingRight() );
|
|
|
|
if(paddingTop()!=0)
|
|
frameElem.setAttribute( "btoppt", paddingTop() );
|
|
|
|
if(paddingBottom()!=0)
|
|
frameElem.setAttribute( "bbottompt", paddingBottom() );
|
|
|
|
if(frameBehavior()!=AutoCreateNewFrame)
|
|
frameElem.setAttribute( "autoCreateNewFrame", static_cast<int>( frameBehavior()) );
|
|
|
|
//if(newFrameBehavior()!=Reconnect) // always save this one, since the default value depends on the type of frame, etc.
|
|
frameElem.setAttribute( "newFrameBehavior", static_cast<int>( newFrameBehavior()) );
|
|
|
|
//same reason
|
|
frameElem.setAttribute( "copy", static_cast<int>( m_bCopy ) );
|
|
|
|
if(sheetSide()!= AnySide)
|
|
frameElem.setAttribute( "sheetSide", static_cast<int>( sheetSide()) );
|
|
|
|
frameElem.setAttribute( "z-index", zOrder() );
|
|
}
|
|
|
|
void KWFrame::load( TQDomElement &frameElem, KWFrameSet* frameSet, int syntaxVersion )
|
|
{
|
|
m_minFrameHeight = KWDocument::getAttribute( frameElem, "min-height", 0.0 );
|
|
m_runAround = static_cast<RunAround>( KWDocument::getAttribute( frameElem, "runaround", RA_NO ) );
|
|
TQString str = frameElem.attribute( "runaroundSide" );
|
|
if ( str == "left" )
|
|
m_runAroundSide = RA_LEFT;
|
|
else if ( str == "right" )
|
|
m_runAroundSide = RA_RIGHT;
|
|
else
|
|
m_runAroundSide = RA_BIGGEST;
|
|
|
|
double runAroundGap = ( frameElem.hasAttribute( "runaroundGap" ) )
|
|
? frameElem.attribute( "runaroundGap" ).toDouble()
|
|
: frameElem.attribute( "runaGapPT" ).toDouble();
|
|
setRunAroundGap( KWDocument::getAttribute( frameElem, "runaroundLeft", runAroundGap ),
|
|
KWDocument::getAttribute( frameElem, "runaroundRight", runAroundGap ),
|
|
KWDocument::getAttribute( frameElem, "runaroundTop", runAroundGap ),
|
|
KWDocument::getAttribute( frameElem, "runaroundBottom", runAroundGap ) );
|
|
|
|
m_sheetSide = static_cast<SheetSide>( KWDocument::getAttribute( frameElem, "sheetSide", AnySide ) );
|
|
m_frameBehavior = static_cast<FrameBehavior>( KWDocument::getAttribute( frameElem, "autoCreateNewFrame", AutoCreateNewFrame ) );
|
|
// Old documents had no "NewFrameBehavior" for footers/headers -> default to Copy.
|
|
NewFrameBehavior defaultValue = frameSet->isHeaderOrFooter() ? Copy : Reconnect;
|
|
// for old document we used the British spelling (newFrameBehaviour), so this is for backwards compatibility.
|
|
defaultValue = static_cast<NewFrameBehavior>( KWDocument::getAttribute( frameElem, "newFrameBehaviour", defaultValue ) );
|
|
m_newFrameBehavior = static_cast<NewFrameBehavior>( KWDocument::getAttribute( frameElem, "newFrameBehavior", defaultValue ) );
|
|
if ( frameSet->isFootEndNote() ) // note that isFootNote/isEndNote are not possible yet
|
|
m_newFrameBehavior = NoFollowup;
|
|
|
|
KoBorder l, r, t, b;
|
|
l.setPenWidth( KWDocument::getAttribute( frameElem, "lWidth", 0.0 ));
|
|
r.setPenWidth(KWDocument::getAttribute( frameElem, "rWidth", 0.0 ));
|
|
t.setPenWidth(KWDocument::getAttribute( frameElem, "tWidth", 0.0 ));
|
|
b.setPenWidth(KWDocument::getAttribute( frameElem, "bWidth", 0.0 ));
|
|
if ( frameElem.hasAttribute("lRed") )
|
|
l.color.setRgb(
|
|
KWDocument::getAttribute( frameElem, "lRed", 0 ),
|
|
KWDocument::getAttribute( frameElem, "lGreen", 0 ),
|
|
KWDocument::getAttribute( frameElem, "lBlue", 0 ) );
|
|
if ( frameElem.hasAttribute("rRed") )
|
|
r.color.setRgb(
|
|
KWDocument::getAttribute( frameElem, "rRed", 0 ),
|
|
KWDocument::getAttribute( frameElem, "rGreen", 0 ),
|
|
KWDocument::getAttribute( frameElem, "rBlue", 0 ) );
|
|
if ( frameElem.hasAttribute("tRed") )
|
|
t.color.setRgb(
|
|
KWDocument::getAttribute( frameElem, "tRed", 0 ),
|
|
KWDocument::getAttribute( frameElem, "tGreen", 0 ),
|
|
KWDocument::getAttribute( frameElem, "tBlue", 0 ) );
|
|
if ( frameElem.hasAttribute("bRed") )
|
|
b.color.setRgb(
|
|
KWDocument::getAttribute( frameElem, "bRed", 0 ),
|
|
KWDocument::getAttribute( frameElem, "bGreen", 0 ),
|
|
KWDocument::getAttribute( frameElem, "bBlue", 0 ) );
|
|
l.setStyle(static_cast<KoBorder::BorderStyle>( KWDocument::getAttribute( frameElem, "lStyle", KoBorder::SOLID ) ));
|
|
r.setStyle(static_cast<KoBorder::BorderStyle>( KWDocument::getAttribute( frameElem, "rStyle", KoBorder::SOLID ) ));
|
|
t.setStyle(static_cast<KoBorder::BorderStyle>( KWDocument::getAttribute( frameElem, "tStyle", KoBorder::SOLID ) ));
|
|
b.setStyle( static_cast<KoBorder::BorderStyle>( KWDocument::getAttribute( frameElem, "bStyle", KoBorder::SOLID ) ));
|
|
TQColor c;
|
|
if ( frameElem.hasAttribute("bkRed") )
|
|
c.setRgb(
|
|
KWDocument::getAttribute( frameElem, "bkRed", 0 ),
|
|
KWDocument::getAttribute( frameElem, "bkGreen", 0 ),
|
|
KWDocument::getAttribute( frameElem, "bkBlue", 0 ) );
|
|
|
|
if ( syntaxVersion < 2 ) // Activate old "white border == no border" conversion
|
|
{
|
|
if(c==l.color && l.penWidth()==1 && l.getStyle()==0 )
|
|
l.setPenWidth(0);
|
|
if(c==r.color && r.penWidth()==1 && r.getStyle()==0)
|
|
r.setPenWidth(0);
|
|
if(c==t.color && t.penWidth()==1 && t.getStyle()==0 )
|
|
t.setPenWidth(0);
|
|
if(c==b.color && b.penWidth()==1 && b.getStyle()==0 )
|
|
b.setPenWidth(0);
|
|
}
|
|
m_borderLeft = l;
|
|
m_borderRight = r;
|
|
m_borderTop = t;
|
|
m_borderBottom = b;
|
|
m_backgroundColor = TQBrush( c );
|
|
|
|
|
|
if( frameElem.hasAttribute("bkStyle"))
|
|
m_backgroundColor.setStyle (static_cast<Qt::BrushStyle>(KWDocument::getAttribute( frameElem, "bkStyle", TQt::SolidPattern )));
|
|
|
|
m_paddingLeft = frameElem.attribute( "bleftpt" ).toDouble();
|
|
m_paddingRight = frameElem.attribute( "brightpt" ).toDouble();
|
|
m_paddingTop = frameElem.attribute( "btoppt" ).toDouble();
|
|
m_paddingBottom = frameElem.attribute( "bbottompt" ).toDouble();
|
|
m_bCopy = KWDocument::getAttribute( frameElem, "copy", frameSet->isHeaderOrFooter() /* default to true for h/f */ );
|
|
m_zOrder = frameElem.attribute( "z-index" ).toInt();
|
|
}
|
|
|
|
// This is shared with table cells - so, no runaround and newframebehavior etc.
|
|
// Only background, borders, padding.
|
|
void KWFrame::loadBorderProperties( KoStyleStack& styleStack )
|
|
{
|
|
// padding. fo:padding for 4 values or padding-left/right/top/bottom
|
|
m_paddingLeft = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding", "left" ) );
|
|
m_paddingRight = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding", "right" ) );
|
|
m_paddingTop = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding", "top" ) );
|
|
m_paddingBottom = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding", "bottom" ) );
|
|
|
|
// background color
|
|
if ( styleStack.hasAttributeNS( KoXmlNS::fo, "background-color" ) ) {
|
|
TQString color = styleStack.attributeNS( KoXmlNS::fo, "background-color" );
|
|
if ( color == "transparent" )
|
|
m_backgroundColor = TQBrush( TQColor(), TQt::NoBrush );
|
|
else
|
|
{
|
|
m_backgroundColor = TQBrush( TQColor( color ) /*, brush style is a dead feature, ignored */ );
|
|
}
|
|
}
|
|
// OOo compatibility: it uses background-transparency=100% instead of background-color="transparent"
|
|
if ( styleStack.hasAttributeNS( KoXmlNS::fo, "background-transparency" ) ) {
|
|
TQString transp = styleStack.attributeNS( KoXmlNS::fo, "background-transparency" );
|
|
if ( transp == "100%" )
|
|
m_backgroundColor.setStyle( Qt::NoBrush );
|
|
}
|
|
|
|
// borders (3.11.27)
|
|
// can be none/hidden, solid and double. General form is the XSL/FO "width|style|color"
|
|
{
|
|
m_borderLeft.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "left") );
|
|
m_borderRight.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "right") );
|
|
m_borderTop.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "top") );
|
|
m_borderBottom.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "bottom") );
|
|
}
|
|
// TODO more refined border spec for double borders (3.11.28)
|
|
}
|
|
|
|
void KWFrame::loadCommonOasisProperties( KoOasisContext& context, KWFrameSet* frameSet, const char* typeProperties )
|
|
{
|
|
KoStyleStack& styleStack = context.styleStack();
|
|
styleStack.setTypeProperties( typeProperties );
|
|
|
|
loadBorderProperties( styleStack );
|
|
|
|
// Background color is now done with fill-color.
|
|
// loadBorderProperties loads fo:background-color for compatibility (and for table cells),
|
|
// but the correct way for text boxes is draw:fill-color
|
|
if ( styleStack.hasAttributeNS( KoXmlNS::draw, "fill-color" ) ) {
|
|
TQString color = styleStack.attributeNS( KoXmlNS::draw, "fill-color" );
|
|
if ( color == "transparent" )
|
|
m_backgroundColor = TQBrush( TQColor(), TQt::NoBrush );
|
|
else
|
|
{
|
|
m_backgroundColor = TQBrush( TQColor( color ) /*, brush style is a dead feature, ignored */ );
|
|
}
|
|
}
|
|
|
|
#if 0 // not allowed in the current OASIS spec
|
|
// margins, i.e. runAroundGap. fo:margin for 4 values or padding-left/right/top/bottom
|
|
m_runAroundLeft = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "left" ) );
|
|
m_runAroundRight = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "right" ) );
|
|
m_runAroundTop = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "top" ) );
|
|
m_runAroundBottom = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "bottom" ) );
|
|
#endif
|
|
// margins, i.e. runAroundGap. fo:margin-left/right/top/bottom
|
|
m_runAroundLeft = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-left" ) );
|
|
m_runAroundRight = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-right" ) );
|
|
m_runAroundTop = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-top" ) );
|
|
m_runAroundBottom = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-bottom" ) );
|
|
|
|
// This attribute isn't part of the OASIS spec. Doesn't matter since it doesn't affect rendering
|
|
// of existing documents, only editing (and only KWord has this kind of option until now).
|
|
const TQCString frameBehaviorOnNewPage = styleStack.attributeNS( KoXmlNS::koffice, "frame-behavior-on-new-page" ).latin1();
|
|
if ( frameBehaviorOnNewPage == "followup" )
|
|
m_newFrameBehavior = Reconnect;
|
|
else if ( frameBehaviorOnNewPage == "copy" )
|
|
m_newFrameBehavior = Copy;
|
|
else if ( frameBehaviorOnNewPage == "none" )
|
|
m_newFrameBehavior = NoFollowup;
|
|
else { // Defaults for OASIS documents not created by KWord
|
|
m_newFrameBehavior = frameSet->isHeaderOrFooter() ? Copy : NoFollowup;
|
|
if ( !frameBehaviorOnNewPage.isEmpty() )
|
|
kdWarning(32001) << "Unknown value for koffice:frame-behavior-on-new-page: " << frameBehaviorOnNewPage << endl;
|
|
}
|
|
// Footnotes and endnotes are handled in a special way.
|
|
if ( frameSet->isFootEndNote() ) // note that isFootNote/isEndNote are not possible yet
|
|
m_newFrameBehavior = NoFollowup;
|
|
|
|
KWFrame::RunAround runAround = KWFrame::RA_BOUNDINGRECT;
|
|
KWFrame::RunAroundSide runAroundSide = KWFrame::RA_BIGGEST;
|
|
const TQCString oowrap = styleStack.attributeNS( KoXmlNS::style, "wrap" ).latin1();
|
|
if ( oowrap == "none" ) // 'no wrap' means 'avoid horizontal space'
|
|
runAround = KWFrame::RA_SKIP;
|
|
else if ( oowrap == "left" )
|
|
runAroundSide = KWFrame::RA_LEFT;
|
|
else if ( oowrap == "right" )
|
|
runAroundSide= KWFrame::RA_RIGHT;
|
|
else if ( oowrap == "run-through" )
|
|
runAround = KWFrame::RA_NO;
|
|
//if ( oowrap == "biggest" ) // OASIS extension
|
|
// ->( KWFrame::RA_BOUNDINGRECT, KWFrame::RA_BIGGEST ), already set above
|
|
//if ( oowrap == "parallel" || oowrap == "dynamic" )
|
|
// dynamic is called "optimal" in the OO GUI. It's different from biggest because it can lead to parallel.
|
|
// Those are not supported in KWord, let's use biggest instead
|
|
setRunAround( runAround );
|
|
setRunAroundSide( runAroundSide );
|
|
}
|
|
|
|
void KWFrame::startOasisFrame( KoXmlWriter &writer, KoGenStyles& mainStyles, const TQString& name, const TQString& lastFrameName ) const
|
|
{
|
|
writer.startElement( "draw:frame" );
|
|
writer.addAttribute( "draw:name", name );
|
|
writer.addAttribute( "draw:style-name", saveOasisFrameStyle( mainStyles ) );
|
|
|
|
if ( !frameSet()->isFloating() )
|
|
{ // non-inline frame, anchored to page
|
|
const int pgNum = pageNumber();
|
|
const double yInPage = top() - frameSet()->pageManager()->topOfPage(pgNum);
|
|
writer.addAttributePt( "svg:x", left() );
|
|
writer.addAttributePt( "svg:y", yInPage );
|
|
writer.addAttribute( "text:anchor-type", "page" );
|
|
writer.addAttribute( "text:anchor-page-number", pgNum );
|
|
writer.addAttribute( "draw:z-index", zOrder() );
|
|
}
|
|
writer.addAttributePt( "svg:width", width() );
|
|
writer.addAttributePt( "svg:height", height() );
|
|
if ( isCopy() )
|
|
writer.addAttribute( "draw:copy-of", lastFrameName );
|
|
}
|
|
|
|
// shared between startOasisFrame and table cells.
|
|
// Only background, borders, padding.
|
|
void KWFrame::saveBorderProperties( KoGenStyle& frameStyle ) const
|
|
{
|
|
// Background: color and transparency
|
|
// OOo seems to use style:background-transparency="100%", but the schema allows background-color=transparent
|
|
if ( m_backgroundColor.style() == TQt::NoBrush )
|
|
frameStyle.addProperty( "fo:background-color", "transparent" );
|
|
else if ( m_backgroundColor.color().isValid() )
|
|
frameStyle.addProperty( "fo:background-color", m_backgroundColor.color().name() );
|
|
|
|
// Borders
|
|
if ( ( m_borderLeft == m_borderRight )
|
|
&& ( m_borderLeft == m_borderTop )
|
|
&& ( m_borderLeft == m_borderBottom ) )
|
|
{
|
|
frameStyle.addProperty( "fo:border", m_borderLeft.saveFoBorder() );
|
|
}
|
|
else
|
|
{
|
|
frameStyle.addProperty( "fo:border-left", m_borderLeft.saveFoBorder() );
|
|
frameStyle.addProperty( "fo:border-right", m_borderRight.saveFoBorder() );
|
|
frameStyle.addProperty( "fo:border-top", m_borderTop.saveFoBorder() );
|
|
frameStyle.addProperty( "fo:border-bottom", m_borderBottom.saveFoBorder() );
|
|
}
|
|
|
|
if ( m_paddingLeft != 0 && ( ( m_paddingLeft == m_paddingRight )
|
|
&& ( m_paddingLeft == m_paddingTop )
|
|
&& ( m_paddingLeft == m_paddingBottom ) ) )
|
|
frameStyle.addPropertyPt( "fo:padding", m_paddingLeft );
|
|
else
|
|
{
|
|
if ( m_paddingLeft != 0 )
|
|
frameStyle.addPropertyPt( "fo:padding-left", m_paddingLeft );
|
|
if ( m_paddingRight != 0 )
|
|
frameStyle.addPropertyPt( "fo:padding-right", m_paddingRight );
|
|
if ( m_paddingTop != 0 )
|
|
frameStyle.addPropertyPt( "fo:padding-top", m_paddingTop );
|
|
if ( m_paddingBottom != 0 )
|
|
frameStyle.addPropertyPt( "fo:padding-bottom", m_paddingBottom );
|
|
}
|
|
}
|
|
|
|
void KWFrame::saveMarginAttributes( KoXmlWriter &writer ) const
|
|
{
|
|
if ( m_runAroundLeft != 0 )
|
|
writer.addAttributePt( "fo:margin-left", m_runAroundLeft );
|
|
if ( m_runAroundRight != 0 )
|
|
writer.addAttributePt( "fo:margin-right", m_runAroundRight );
|
|
if ( m_runAroundTop != 0 )
|
|
writer.addAttributePt( "fo:margin-top", m_runAroundTop );
|
|
if ( m_runAroundBottom != 0 )
|
|
writer.addAttributePt( "fo:margin-bottom", m_runAroundBottom );
|
|
}
|
|
|
|
void KWFrame::saveMarginProperties( KoGenStyle& frameStyle ) const
|
|
{
|
|
#if 0 // not allowed in the current OASIS spec
|
|
if ( m_runAroundLeft != 0 && ( ( m_runAroundLeft == m_runAroundRight )
|
|
&& ( m_runAroundLeft == m_runAroundTop )
|
|
&& ( m_runAroundLeft == m_runAroundBottom ) ) )
|
|
frameStyle.addPropertyPt( "fo:margin", m_runAroundLeft );
|
|
else
|
|
{
|
|
#endif
|
|
if ( m_runAroundLeft != 0 )
|
|
frameStyle.addPropertyPt( "fo:margin-left", m_runAroundLeft );
|
|
if ( m_runAroundRight != 0 )
|
|
frameStyle.addPropertyPt( "fo:margin-right", m_runAroundRight );
|
|
if ( m_runAroundTop != 0 )
|
|
frameStyle.addPropertyPt( "fo:margin-top", m_runAroundTop );
|
|
if ( m_runAroundBottom != 0 )
|
|
frameStyle.addPropertyPt( "fo:margin-bottom", m_runAroundBottom );
|
|
#if 0 // not allowed in the current OASIS spec
|
|
}
|
|
#endif
|
|
}
|
|
|
|
TQString KWFrame::saveOasisFrameStyle( KoGenStyles& mainStyles ) const
|
|
{
|
|
KoGenStyle frameStyle( KWDocument::STYLE_FRAME_AUTO, "graphic" );
|
|
TQString protect;
|
|
if ( frameSet()->protectContent() )
|
|
protect = "content";
|
|
if ( frameSet()->isProtectSize() ) // ## should be moved for frame
|
|
{
|
|
if ( !protect.isEmpty() )
|
|
protect+=" ";
|
|
protect+="size";
|
|
}
|
|
if ( !protect.isEmpty() )
|
|
frameStyle.addProperty( "style:protect", protect );
|
|
|
|
if ( !frameSet()->isFloating() )
|
|
{ // non-inline frame, anchored to page
|
|
frameStyle.addProperty( "style:horizontal-rel", "page" );
|
|
frameStyle.addProperty( "style:vertical-rel", "page" );
|
|
frameStyle.addProperty( "style:horizontal-pos", "from-left" );
|
|
frameStyle.addProperty( "style:vertical-pos", "from-top" );
|
|
}
|
|
|
|
// Background (KWFrame::saveBorderProperties saves as fo:background-color, but OOo-2.0.x uses draw:fill-color)
|
|
// So now we use draw:fill-color too, the text background color is in fact a paragraph feature.
|
|
if ( m_backgroundColor.style() == TQt::NoBrush )
|
|
frameStyle.addProperty( "draw:fill-color", "transparent" );
|
|
else if ( m_backgroundColor.color().isValid() )
|
|
frameStyle.addProperty( "draw:fill-color", m_backgroundColor.color().name() );
|
|
|
|
saveBorderProperties( frameStyle );
|
|
saveMarginProperties( frameStyle );
|
|
|
|
if ( runAround() == KWFrame::RA_SKIP )
|
|
frameStyle.addProperty( "style:wrap", "none" );
|
|
else if ( runAround() == KWFrame::RA_NO )
|
|
frameStyle.addProperty( "style:wrap", "run-through" );
|
|
else // RA_BOUNDINGRECT
|
|
{
|
|
if ( runAroundSide() == KWFrame::RA_LEFT )
|
|
frameStyle.addProperty( "style:wrap", "left" );
|
|
else if ( runAroundSide() == KWFrame::RA_RIGHT )
|
|
frameStyle.addProperty( "style:wrap", "right" );
|
|
else if ( runAroundSide() == KWFrame::RA_BIGGEST )
|
|
frameStyle.addProperty( "style:wrap", "biggest" );
|
|
}
|
|
|
|
// This attribute isn't part of the OASIS spec. Doesn't matter since it doesn't affect rendering
|
|
// of existing documents, only editing (and only KWord has this kind of option until now).
|
|
NewFrameBehavior defaultNfb = frameSet()->isHeaderOrFooter() ? Copy : NoFollowup;
|
|
if ( m_newFrameBehavior != defaultNfb ) {
|
|
const char* value = "none";
|
|
if ( m_newFrameBehavior == Reconnect )
|
|
value = "followup";
|
|
else if ( m_newFrameBehavior == Copy )
|
|
value = "copy";
|
|
else if ( m_newFrameBehavior == NoFollowup )
|
|
value = "none";
|
|
frameStyle.addProperty( "koffice:frame-behavior-on-new-page", value );
|
|
}
|
|
|
|
// The loading code for this one is in kwtextframeset, maybe this should be moved there too
|
|
const char* frameBehav = 0;
|
|
if ( m_frameBehavior == KWFrame::Ignore )
|
|
frameBehav = "clip";
|
|
else if ( m_frameBehavior == KWFrame::AutoCreateNewFrame )
|
|
frameBehav = "auto-create-new-frame";
|
|
// the third case, AutoExtendFrame is handled by min-height
|
|
if ( frameBehav )
|
|
frameStyle.addProperty( "style:overflow-behavior", frameBehav );
|
|
|
|
return mainStyles.lookup( frameStyle, "fr" );
|
|
}
|
|
|
|
bool KWFrame::frameAtPos( const TQPoint& point, bool borderOfFrameOnly) const {
|
|
// Forwarded to KWFrameSet to make it virtual
|
|
return frameSet()->isFrameAtPos( this, point, borderOfFrameOnly );
|
|
}
|
|
|
|
KoRect KWFrame::innerRect() const
|
|
{
|
|
KoRect inner( this->normalize());
|
|
inner.moveBy( paddingLeft(), paddingTop() );
|
|
inner.setWidth( innerWidth() );
|
|
inner.setHeight( innerHeight() );
|
|
return inner;
|
|
}
|
|
|
|
double KWFrame::innerWidth() const
|
|
{
|
|
return KMAX( 0.0, width() - m_paddingLeft - m_paddingRight );
|
|
}
|
|
|
|
double KWFrame::innerHeight() const
|
|
{
|
|
return KMAX( 0.0, height() - m_paddingTop - m_paddingBottom );
|
|
}
|
|
|
|
void KWFrame::setFramePadding( double left, double top, double right, double bottom)
|
|
{
|
|
m_paddingLeft = left;
|
|
m_paddingTop = top;
|
|
m_paddingRight = right;
|
|
m_paddingBottom = bottom;
|
|
}
|
|
|
|
bool KWFrame::compareFrameZOrder(KWFrame *f1, KWFrame *f2)
|
|
{
|
|
return f1->zOrder() < f2->zOrder();
|
|
}
|