1
/* This file is part of the KDE project
2
Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@kde.org>
3
Copyright (C) 2000-2006 David Faure <faure@kde.org>
4
Copyright (C) 2005 Thomas Zander <zander@kde.org>
6
This library is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Library General Public
8
License as published by the Free Software Foundation; either
9
version 2 of the License, or (at your option) any later version.
11
This library is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
Library General Public License for more details.
16
You should have received a copy of the GNU Library General Public License
17
along with this library; see the file COPYING.LIB. If not, write to
18
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19
* Boston, MA 02110-1301, USA.
23
#include "KWFrameSet.h"
24
#include "KWFrameList.h"
25
#include "KWDocument.h"
26
#include "KWPageManager.h"
27
#include "KWTextFrameSet.h"
28
#include "KWViewMode.h"
31
#include <KoOasisContext.h>
33
#include <KoXmlWriter.h>
34
#include <KoStyleStack.h>
39
#include <float.h> // for DBL_DIG
43
/******************************************************************/
44
/* Class: ZOrderedFrameList */
45
/******************************************************************/
47
int ZOrderedFrameList::compareItems(QPtrCollection::Item a, QPtrCollection::Item b)
49
int za = ((KWFrame *)a)->zOrder();
50
int zb = ((KWFrame *)b)->zOrder();
51
if (za == zb) return 0;
52
if (za < zb) return -1;
57
/******************************************************************/
59
/******************************************************************/
61
KWFrame::KWFrame(KWFrame * frame)
64
//kdDebug(32001) << "KWFrame::KWFrame this=" << this << " frame=" << frame << endl;
65
copySettings( frame );
67
m_frameStack = 0; // lazy initialisation.
70
KWFrame::KWFrame(KWFrameSet *fs, double left, double top, double width, double height, RunAround ra )
71
: KoRect( left, top, width, height ),
72
// Initialize member vars here. This ensures they are all initialized, since it's
73
// easier to compare this list with the member vars list (compiler ensures order).
74
m_sheetSide( AnySide ),
76
m_runAroundSide( RA_BIGGEST ),
77
m_frameBehavior( AutoExtendFrame ),
78
m_newFrameBehavior( ( fs && fs->type() == FT_TEXT ) ? Reconnect : NoFollowup ),
80
m_drawFootNoteLine( false ),
81
m_runAroundLeft( 1.0 ),
82
m_runAroundRight( 1.0 ),
83
m_runAroundTop( 1.0 ),
84
m_runAroundBottom( 1.0 ),
89
m_minFrameHeight( 0 ),
92
m_backgroundColor( (fs && (fs->type() == FT_PICTURE || fs->type() == FT_PART)) ? QBrush( QColor(), Qt::NoBrush) : QBrush( QColor() ) ), // valid brush with invalid color ( default )
93
m_borderLeft( QColor(), KoBorder::SOLID, 0 ),
94
m_borderRight( QColor(), KoBorder::SOLID, 0 ),
95
m_borderTop( QColor(), KoBorder::SOLID, 0 ),
96
m_borderBottom( QColor(), KoBorder::SOLID, 0 ),
99
//kdDebug(32001) << "KWFrame::KWFrame " << this << " left=" << left << " top=" << top << endl;
100
m_frameStack = 0; // lazy initialisation.
105
//kdDebug(32001) << "KWFrame::~KWFrame " << this << endl;
110
void KWFrame::setBackgroundColor( const QBrush &color )
112
m_backgroundColor = color;
116
int KWFrame::pageNumber() const
118
Q_ASSERT( m_frameSet );
120
kdDebug() << k_funcinfo << this << " has no frameset!" << endl;
123
if( !m_frameSet->pageManager() ) {
124
kdWarning() << k_funcinfo << this << " is not a frame that is in use; misses a pageManager!" << endl;
127
return frameSet()->pageManager()->pageNumber(this);
130
int KWFrame::pageNumber( KWDocument* doc ) const
132
return doc->pageManager()->pageNumber(this);
135
KWFrame *KWFrame::getCopy() {
136
/* returns a deep copy of self */
137
return new KWFrame(this);
140
void KWFrame::copySettings(KWFrame *frm)
142
setFrameSet( frm->frameSet() ); // do this first in case of debug output in the methods below
143
setRect(frm->x(), frm->y(), frm->width(), frm->height());
144
// Keep order identical as member var order (and init in ctor)
145
setSheetSide(frm->sheetSide());
146
setRunAround(frm->runAround());
147
setRunAroundSide(frm->runAroundSide());
148
setFrameBehavior(frm->frameBehavior());
149
setNewFrameBehavior(frm->newFrameBehavior());
150
setRunAroundGap(frm->runAroundLeft(), frm->runAroundRight(), frm->runAroundTop(), frm->runAroundBottom());
151
setPaddingLeft(frm->paddingLeft());
152
setPaddingRight(frm->paddingRight());
153
setPaddingTop(frm->paddingTop());
154
setPaddingBottom(frm->paddingBottom());
155
setMinimumFrameHeight(frm->minimumFrameHeight());
156
m_internalY = 0; // internal Y is recalculated
157
setZOrder(frm->zOrder());
158
setCopy(frm->isCopy());
159
m_drawFootNoteLine = false; // recalculated
160
setBackgroundColor( frm->backgroundColor() );
161
setLeftBorder(frm->leftBorder());
162
setRightBorder(frm->rightBorder());
163
setTopBorder(frm->topBorder());
164
setBottomBorder(frm->bottomBorder());
167
void KWFrame::frameBordersChanged() {
168
if (frameSet()->isFloating())
169
frameSet()->anchorFrameset()->invalidate();
173
void KWFrame::updateRulerHandles(){
178
KWDocument *doc = frameSet()->kWordDocument();
180
doc->updateRulerFrameStartEnd();
185
QRect KWFrame::outerRect( KWViewMode* viewMode ) const
187
KWDocument *doc = m_frameSet->kWordDocument();
188
QRect outerRect( doc->zoomRect( *this ) );
189
if ( viewMode && !m_frameSet->groupmanager() ) {
190
int minBorder = viewMode->drawFrameBorders() ? 1 : 0;
191
KWFrame* settingsFrame = m_frameSet->settingsFrame( this );
192
outerRect.rLeft() -= KoBorder::zoomWidthX( settingsFrame->leftBorder().width(), doc, minBorder );
193
outerRect.rTop() -= KoBorder::zoomWidthY( settingsFrame->topBorder().width(), doc, minBorder );
194
outerRect.rRight() += KoBorder::zoomWidthX( settingsFrame->rightBorder().width(), doc, minBorder );
195
outerRect.rBottom() += KoBorder::zoomWidthY( settingsFrame->bottomBorder().width(), doc, minBorder );
200
KoRect KWFrame::outerKoRect() const
202
KoRect outerRect = *this;
203
KWDocument *doc = m_frameSet->kWordDocument();
204
KWFrame* settingsFrame = m_frameSet->settingsFrame( this );
205
outerRect.rLeft() -= KoBorder::zoomWidthX( settingsFrame->leftBorder().width(), doc, 1 ) / doc->zoomedResolutionX();
206
outerRect.rTop() -= KoBorder::zoomWidthY( settingsFrame->topBorder().width(), doc, 1 ) / doc->zoomedResolutionY();
207
outerRect.rRight() += KoBorder::zoomWidthX( settingsFrame->rightBorder().width(), doc, 1 ) / doc->zoomedResolutionX();
208
outerRect.rBottom() += KoBorder::zoomWidthY( settingsFrame->bottomBorder().width(), doc, 1 ) / doc->zoomedResolutionY();
212
KoRect KWFrame::runAroundRect() const
214
KoRect raRect = outerKoRect();
215
raRect.rLeft() -= m_runAroundLeft;
216
raRect.rRight() += m_runAroundRight;
217
raRect.rTop() -= m_runAroundTop;
218
raRect.rBottom() += m_runAroundBottom;
222
void KWFrame::save( QDomElement &frameElem )
224
// setAttribute( double ) uses a default precision of 6, and this seems
225
// to be 6 digits, even like '123.123' !
226
frameElem.setAttribute( "left", QString::number( left(), 'g', DBL_DIG ) );
227
frameElem.setAttribute( "top", QString::number( top(), 'g', DBL_DIG ) );
228
frameElem.setAttribute( "right", QString::number( right(), 'g', DBL_DIG ) );
229
frameElem.setAttribute( "bottom", QString::number( bottom(), 'g', DBL_DIG ) );
230
if ( minimumFrameHeight() > 0 )
231
frameElem.setAttribute( "min-height", QString::number( minimumFrameHeight(), 'g', DBL_DIG ) );
233
if ( !m_frameSet->isHeaderOrFooter() && !m_frameSet->isMainFrameset() )
235
if(runAround()!=RA_NO)
237
frameElem.setAttribute( "runaround", static_cast<int>( runAround() ) );
238
if (runAround() == RA_BOUNDINGRECT)
240
if (runAroundSide()==RA_LEFT)
241
frameElem.setAttribute( "runaroundSide", "left" );
242
else if (runAroundSide()==RA_RIGHT)
243
frameElem.setAttribute( "runaroundSide", "right" );
245
frameElem.setAttribute( "runaroundSide", "biggest" );
248
if(runAroundLeft()!=0 || runAroundRight()!=0 || runAroundTop()!=0 || runAroundBottom()!=0) {
249
frameElem.setAttribute( "runaroundLeft", m_runAroundLeft );
250
frameElem.setAttribute( "runaroundRight", m_runAroundRight );
251
frameElem.setAttribute( "runaroundTop", m_runAroundTop );
252
frameElem.setAttribute( "runaroundBottom", m_runAroundBottom );
253
// The old file format had only one value, keep compat
254
double runAroundGap = QMAX( QMAX( m_runAroundLeft, m_runAroundRight ), QMAX( m_runAroundTop, m_runAroundBottom ) );
255
frameElem.setAttribute( "runaroundGap", runAroundGap );
259
if(leftBorder().penWidth()!=0)
260
frameElem.setAttribute( "lWidth", leftBorder().penWidth() );
262
if(leftBorder().color.isValid())
264
frameElem.setAttribute( "lRed", leftBorder().color.red() );
265
frameElem.setAttribute( "lGreen", leftBorder().color.green() );
266
frameElem.setAttribute( "lBlue", leftBorder().color.blue() );
268
if(leftBorder().getStyle() != KoBorder::SOLID)
269
frameElem.setAttribute( "lStyle", static_cast<int>( leftBorder().getStyle()) );
271
if(rightBorder().penWidth()!=0)
272
frameElem.setAttribute( "rWidth", rightBorder().penWidth() );
274
if(rightBorder().color.isValid())
276
frameElem.setAttribute( "rRed", rightBorder().color.red() );
277
frameElem.setAttribute( "rGreen", rightBorder().color.green() );
278
frameElem.setAttribute( "rBlue", rightBorder().color.blue() );
280
if(rightBorder().getStyle() != KoBorder::SOLID)
281
frameElem.setAttribute( "rStyle", static_cast<int>( rightBorder().getStyle() ) );
283
if(topBorder().penWidth()!=0)
284
frameElem.setAttribute( "tWidth", topBorder().penWidth() );
286
if(topBorder().color.isValid())
288
frameElem.setAttribute( "tRed", topBorder().color.red() );
289
frameElem.setAttribute( "tGreen", topBorder().color.green() );
290
frameElem.setAttribute( "tBlue", topBorder().color.blue() );
292
if(topBorder().getStyle() != KoBorder::SOLID)
293
frameElem.setAttribute( "tStyle", static_cast<int>( topBorder().getStyle() ) );
295
if(bottomBorder().penWidth()!=0) {
296
frameElem.setAttribute( "bWidth", bottomBorder().penWidth() );
298
if(bottomBorder().color.isValid()) {
299
frameElem.setAttribute( "bRed", bottomBorder().color.red() );
300
frameElem.setAttribute( "bGreen", bottomBorder().color.green() );
301
frameElem.setAttribute( "bBlue", bottomBorder().color.blue() );
303
if(bottomBorder().getStyle() != KoBorder::SOLID)
304
frameElem.setAttribute( "bStyle", static_cast<int>( bottomBorder().getStyle() ) );
306
if(backgroundColor().color().isValid())
308
frameElem.setAttribute( "bkRed", backgroundColor().color().red() );
309
frameElem.setAttribute( "bkGreen", backgroundColor().color().green() );
310
frameElem.setAttribute( "bkBlue", backgroundColor().color().blue() );
311
frameElem.setAttribute( "bkStyle", (int)backgroundColor().style ());
313
if(paddingLeft() != 0)
314
frameElem.setAttribute( "bleftpt", paddingLeft() );
316
if(paddingRight()!=0)
317
frameElem.setAttribute( "brightpt", paddingRight() );
320
frameElem.setAttribute( "btoppt", paddingTop() );
322
if(paddingBottom()!=0)
323
frameElem.setAttribute( "bbottompt", paddingBottom() );
325
if(frameBehavior()!=AutoCreateNewFrame)
326
frameElem.setAttribute( "autoCreateNewFrame", static_cast<int>( frameBehavior()) );
328
//if(newFrameBehavior()!=Reconnect) // always save this one, since the default value depends on the type of frame, etc.
329
frameElem.setAttribute( "newFrameBehavior", static_cast<int>( newFrameBehavior()) );
332
frameElem.setAttribute( "copy", static_cast<int>( m_bCopy ) );
334
if(sheetSide()!= AnySide)
335
frameElem.setAttribute( "sheetSide", static_cast<int>( sheetSide()) );
337
frameElem.setAttribute( "z-index", zOrder() );
340
void KWFrame::load( QDomElement &frameElem, KWFrameSet* frameSet, int syntaxVersion )
342
m_minFrameHeight = KWDocument::getAttribute( frameElem, "min-height", 0.0 );
343
m_runAround = static_cast<RunAround>( KWDocument::getAttribute( frameElem, "runaround", RA_NO ) );
344
QString str = frameElem.attribute( "runaroundSide" );
346
m_runAroundSide = RA_LEFT;
347
else if ( str == "right" )
348
m_runAroundSide = RA_RIGHT;
350
m_runAroundSide = RA_BIGGEST;
352
double runAroundGap = ( frameElem.hasAttribute( "runaroundGap" ) )
353
? frameElem.attribute( "runaroundGap" ).toDouble()
354
: frameElem.attribute( "runaGapPT" ).toDouble();
355
setRunAroundGap( KWDocument::getAttribute( frameElem, "runaroundLeft", runAroundGap ),
356
KWDocument::getAttribute( frameElem, "runaroundRight", runAroundGap ),
357
KWDocument::getAttribute( frameElem, "runaroundTop", runAroundGap ),
358
KWDocument::getAttribute( frameElem, "runaroundBottom", runAroundGap ) );
360
m_sheetSide = static_cast<SheetSide>( KWDocument::getAttribute( frameElem, "sheetSide", AnySide ) );
361
m_frameBehavior = static_cast<FrameBehavior>( KWDocument::getAttribute( frameElem, "autoCreateNewFrame", AutoCreateNewFrame ) );
362
// Old documents had no "NewFrameBehavior" for footers/headers -> default to Copy.
363
NewFrameBehavior defaultValue = frameSet->isHeaderOrFooter() ? Copy : Reconnect;
364
// for old document we used the British spelling (newFrameBehaviour), so this is for backwards compatibility.
365
defaultValue = static_cast<NewFrameBehavior>( KWDocument::getAttribute( frameElem, "newFrameBehaviour", defaultValue ) );
366
m_newFrameBehavior = static_cast<NewFrameBehavior>( KWDocument::getAttribute( frameElem, "newFrameBehavior", defaultValue ) );
367
if ( frameSet->isFootEndNote() ) // note that isFootNote/isEndNote are not possible yet
368
m_newFrameBehavior = NoFollowup;
371
l.setPenWidth( KWDocument::getAttribute( frameElem, "lWidth", 0.0 ));
372
r.setPenWidth(KWDocument::getAttribute( frameElem, "rWidth", 0.0 ));
373
t.setPenWidth(KWDocument::getAttribute( frameElem, "tWidth", 0.0 ));
374
b.setPenWidth(KWDocument::getAttribute( frameElem, "bWidth", 0.0 ));
375
if ( frameElem.hasAttribute("lRed") )
377
KWDocument::getAttribute( frameElem, "lRed", 0 ),
378
KWDocument::getAttribute( frameElem, "lGreen", 0 ),
379
KWDocument::getAttribute( frameElem, "lBlue", 0 ) );
380
if ( frameElem.hasAttribute("rRed") )
382
KWDocument::getAttribute( frameElem, "rRed", 0 ),
383
KWDocument::getAttribute( frameElem, "rGreen", 0 ),
384
KWDocument::getAttribute( frameElem, "rBlue", 0 ) );
385
if ( frameElem.hasAttribute("tRed") )
387
KWDocument::getAttribute( frameElem, "tRed", 0 ),
388
KWDocument::getAttribute( frameElem, "tGreen", 0 ),
389
KWDocument::getAttribute( frameElem, "tBlue", 0 ) );
390
if ( frameElem.hasAttribute("bRed") )
392
KWDocument::getAttribute( frameElem, "bRed", 0 ),
393
KWDocument::getAttribute( frameElem, "bGreen", 0 ),
394
KWDocument::getAttribute( frameElem, "bBlue", 0 ) );
395
l.setStyle(static_cast<KoBorder::BorderStyle>( KWDocument::getAttribute( frameElem, "lStyle", KoBorder::SOLID ) ));
396
r.setStyle(static_cast<KoBorder::BorderStyle>( KWDocument::getAttribute( frameElem, "rStyle", KoBorder::SOLID ) ));
397
t.setStyle(static_cast<KoBorder::BorderStyle>( KWDocument::getAttribute( frameElem, "tStyle", KoBorder::SOLID ) ));
398
b.setStyle( static_cast<KoBorder::BorderStyle>( KWDocument::getAttribute( frameElem, "bStyle", KoBorder::SOLID ) ));
400
if ( frameElem.hasAttribute("bkRed") )
402
KWDocument::getAttribute( frameElem, "bkRed", 0 ),
403
KWDocument::getAttribute( frameElem, "bkGreen", 0 ),
404
KWDocument::getAttribute( frameElem, "bkBlue", 0 ) );
406
if ( syntaxVersion < 2 ) // Activate old "white border == no border" conversion
408
if(c==l.color && l.penWidth()==1 && l.getStyle()==0 )
410
if(c==r.color && r.penWidth()==1 && r.getStyle()==0)
412
if(c==t.color && t.penWidth()==1 && t.getStyle()==0 )
414
if(c==b.color && b.penWidth()==1 && b.getStyle()==0 )
421
m_backgroundColor = QBrush( c );
424
if( frameElem.hasAttribute("bkStyle"))
425
m_backgroundColor.setStyle (static_cast<Qt::BrushStyle>(KWDocument::getAttribute( frameElem, "bkStyle", Qt::SolidPattern )));
427
m_paddingLeft = frameElem.attribute( "bleftpt" ).toDouble();
428
m_paddingRight = frameElem.attribute( "brightpt" ).toDouble();
429
m_paddingTop = frameElem.attribute( "btoppt" ).toDouble();
430
m_paddingBottom = frameElem.attribute( "bbottompt" ).toDouble();
431
m_bCopy = KWDocument::getAttribute( frameElem, "copy", frameSet->isHeaderOrFooter() /* default to true for h/f */ );
432
m_zOrder = frameElem.attribute( "z-index" ).toInt();
435
// This is shared with table cells - so, no runaround and newframebehavior etc.
436
// Only background, borders, padding.
437
void KWFrame::loadBorderProperties( KoStyleStack& styleStack )
439
// padding. fo:padding for 4 values or padding-left/right/top/bottom
440
m_paddingLeft = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding", "left" ) );
441
m_paddingRight = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding", "right" ) );
442
m_paddingTop = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding", "top" ) );
443
m_paddingBottom = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding", "bottom" ) );
445
// background color (3.11.25)
446
if ( styleStack.hasAttributeNS( KoXmlNS::fo, "background-color" ) ) {
447
QString color = styleStack.attributeNS( KoXmlNS::fo, "background-color" );
448
if ( color == "transparent" )
449
m_backgroundColor = QBrush( QColor(), Qt::NoBrush );
452
m_backgroundColor = QBrush( QColor( color ) /*, brush style is a dead feature, ignored */ );
455
// OOo compatibility: it uses background-transparency=100% instead of background-color="transparent"
456
if ( styleStack.hasAttributeNS( KoXmlNS::fo, "background-transparency" ) ) {
457
QString transp = styleStack.attributeNS( KoXmlNS::fo, "background-transparency" );
458
if ( transp == "100%" )
459
m_backgroundColor.setStyle( Qt::NoBrush );
463
// can be none/hidden, solid and double. General form is the XSL/FO "width|style|color"
465
m_borderLeft.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "left") );
466
m_borderRight.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "right") );
467
m_borderTop.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "top") );
468
m_borderBottom.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "bottom") );
470
// TODO more refined border spec for double borders (3.11.28)
473
void KWFrame::loadCommonOasisProperties( KoOasisContext& context, KWFrameSet* frameSet, const char* typeProperties )
475
KoStyleStack& styleStack = context.styleStack();
476
styleStack.setTypeProperties( typeProperties );
478
loadBorderProperties( styleStack );
480
#if 0 // not allowed in the current OASIS spec
481
// margins, i.e. runAroundGap. fo:margin for 4 values or padding-left/right/top/bottom
482
m_runAroundLeft = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "left" ) );
483
m_runAroundRight = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "right" ) );
484
m_runAroundTop = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "top" ) );
485
m_runAroundBottom = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "bottom" ) );
487
// margins, i.e. runAroundGap. fo:margin-left/right/top/bottom
488
m_runAroundLeft = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-left" ) );
489
m_runAroundRight = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-right" ) );
490
m_runAroundTop = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-top" ) );
491
m_runAroundBottom = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-bottom" ) );
493
// This attribute isn't part of the OASIS spec. Doesn't matter since it doesn't affect rendering
494
// of existing documents, only editing (and only KWord has this kind of option until now).
495
const QCString frameBehaviorOnNewPage = styleStack.attributeNS( KoXmlNS::koffice, "frame-behavior-on-new-page" ).latin1();
496
if ( frameBehaviorOnNewPage == "followup" )
497
m_newFrameBehavior = Reconnect;
498
else if ( frameBehaviorOnNewPage == "copy" )
499
m_newFrameBehavior = Copy;
500
else if ( frameBehaviorOnNewPage == "none" )
501
m_newFrameBehavior = NoFollowup;
502
else { // Defaults for OASIS documents not created by KWord
503
m_newFrameBehavior = frameSet->isHeaderOrFooter() ? Copy : NoFollowup;
504
if ( !frameBehaviorOnNewPage.isEmpty() )
505
kdWarning(32001) << "Unknown value for koffice:frame-behavior-on-new-page: " << frameBehaviorOnNewPage << endl;
507
// Footnotes and endnotes are handled in a special way.
508
if ( frameSet->isFootEndNote() ) // note that isFootNote/isEndNote are not possible yet
509
m_newFrameBehavior = NoFollowup;
511
KWFrame::RunAround runAround = KWFrame::RA_BOUNDINGRECT;
512
KWFrame::RunAroundSide runAroundSide = KWFrame::RA_BIGGEST;
513
const QCString oowrap = styleStack.attributeNS( KoXmlNS::style, "wrap" ).latin1();
514
if ( oowrap == "none" ) // 'no wrap' means 'avoid horizontal space'
515
runAround = KWFrame::RA_SKIP;
516
else if ( oowrap == "left" )
517
runAroundSide = KWFrame::RA_LEFT;
518
else if ( oowrap == "right" )
519
runAroundSide= KWFrame::RA_RIGHT;
520
else if ( oowrap == "run-through" )
521
runAround = KWFrame::RA_NO;
522
//if ( oowrap == "biggest" ) // OASIS extension
523
// ->( KWFrame::RA_BOUNDINGRECT, KWFrame::RA_BIGGEST ), already set above
524
//if ( oowrap == "parallel" || oowrap == "dynamic" )
525
// dynamic is called "optimal" in the OO GUI. It's different from biggest because it can lead to parallel.
526
// Those are not supported in KWord, let's use biggest instead
527
setRunAround( runAround );
528
setRunAroundSide( runAroundSide );
531
void KWFrame::startOasisFrame( KoXmlWriter &writer, KoGenStyles& mainStyles, const QString& name, const QString& lastFrameName ) const
533
writer.startElement( "draw:frame" );
534
writer.addAttribute( "draw:name", name );
535
writer.addAttribute( "draw:style-name", saveOasisFrameStyle( mainStyles ) );
537
if ( !frameSet()->isFloating() )
538
{ // non-inline frame, anchored to page
539
const int pgNum = pageNumber();
540
const double yInPage = top() - frameSet()->pageManager()->topOfPage(pgNum);
541
writer.addAttributePt( "svg:x", left() );
542
writer.addAttributePt( "svg:y", yInPage );
543
writer.addAttribute( "text:anchor-type", "page" );
544
writer.addAttribute( "text:anchor-page-number", pgNum );
545
writer.addAttribute( "draw:z-index", zOrder() );
547
writer.addAttributePt( "svg:width", width() );
548
writer.addAttributePt( "svg:height", height() );
550
writer.addAttribute( "draw:copy-of", lastFrameName );
553
// shared between startOasisFrame and table cells.
554
// Only background, borders, padding.
555
void KWFrame::saveBorderProperties( KoGenStyle& frameStyle ) const
557
// Background: color and transparency
558
// OOo seems to use style:background-transparency="100%", but the schema allows background-color=transparent
559
if ( m_backgroundColor.style() == Qt::NoBrush )
560
frameStyle.addProperty( "fo:background-color", "transparent" );
561
else if ( m_backgroundColor.color().isValid() )
562
frameStyle.addProperty( "fo:background-color", m_backgroundColor.color().name() );
565
if ( ( m_borderLeft == m_borderRight )
566
&& ( m_borderLeft == m_borderTop )
567
&& ( m_borderLeft == m_borderBottom ) )
569
frameStyle.addProperty( "fo:border", m_borderLeft.saveFoBorder() );
573
frameStyle.addProperty( "fo:border-left", m_borderLeft.saveFoBorder() );
574
frameStyle.addProperty( "fo:border-right", m_borderRight.saveFoBorder() );
575
frameStyle.addProperty( "fo:border-top", m_borderTop.saveFoBorder() );
576
frameStyle.addProperty( "fo:border-bottom", m_borderBottom.saveFoBorder() );
579
if ( m_paddingLeft != 0 && ( ( m_paddingLeft == m_paddingRight )
580
&& ( m_paddingLeft == m_paddingTop )
581
&& ( m_paddingLeft == m_paddingBottom ) ) )
582
frameStyle.addPropertyPt( "fo:padding", m_paddingLeft );
585
if ( m_paddingLeft != 0 )
586
frameStyle.addPropertyPt( "fo:padding-left", m_paddingLeft );
587
if ( m_paddingRight != 0 )
588
frameStyle.addPropertyPt( "fo:padding-right", m_paddingRight );
589
if ( m_paddingTop != 0 )
590
frameStyle.addPropertyPt( "fo:padding-top", m_paddingTop );
591
if ( m_paddingBottom != 0 )
592
frameStyle.addPropertyPt( "fo:padding-bottom", m_paddingBottom );
596
void KWFrame::saveMarginAttributes( KoXmlWriter &writer ) const
598
if ( m_runAroundLeft != 0 )
599
writer.addAttributePt( "fo:margin-left", m_runAroundLeft );
600
if ( m_runAroundRight != 0 )
601
writer.addAttributePt( "fo:margin-right", m_runAroundRight );
602
if ( m_runAroundTop != 0 )
603
writer.addAttributePt( "fo:margin-top", m_runAroundTop );
604
if ( m_runAroundBottom != 0 )
605
writer.addAttributePt( "fo:margin-bottom", m_runAroundBottom );
608
void KWFrame::saveMarginProperties( KoGenStyle& frameStyle ) const
610
#if 0 // not allowed in the current OASIS spec
611
if ( m_runAroundLeft != 0 && ( ( m_runAroundLeft == m_runAroundRight )
612
&& ( m_runAroundLeft == m_runAroundTop )
613
&& ( m_runAroundLeft == m_runAroundBottom ) ) )
614
frameStyle.addPropertyPt( "fo:margin", m_runAroundLeft );
618
if ( m_runAroundLeft != 0 )
619
frameStyle.addPropertyPt( "fo:margin-left", m_runAroundLeft );
620
if ( m_runAroundRight != 0 )
621
frameStyle.addPropertyPt( "fo:margin-right", m_runAroundRight );
622
if ( m_runAroundTop != 0 )
623
frameStyle.addPropertyPt( "fo:margin-top", m_runAroundTop );
624
if ( m_runAroundBottom != 0 )
625
frameStyle.addPropertyPt( "fo:margin-bottom", m_runAroundBottom );
626
#if 0 // not allowed in the current OASIS spec
631
QString KWFrame::saveOasisFrameStyle( KoGenStyles& mainStyles ) const
633
KoGenStyle frameStyle( KWDocument::STYLE_FRAME_AUTO, "graphic" );
635
if ( frameSet()->protectContent() )
637
if ( frameSet()->isProtectSize() ) // ## should be moved for frame
639
if ( !protect.isEmpty() )
643
if ( !protect.isEmpty() )
644
frameStyle.addProperty( "style:protect", protect );
646
if ( !frameSet()->isFloating() )
647
{ // non-inline frame, anchored to page
648
frameStyle.addProperty( "style:horizontal-rel", "page" );
649
frameStyle.addProperty( "style:vertical-rel", "page" );
650
frameStyle.addProperty( "style:horizontal-pos", "from-left" );
651
frameStyle.addProperty( "style:vertical-pos", "from-top" );
654
saveBorderProperties( frameStyle );
655
saveMarginProperties( frameStyle );
657
if ( runAround() == KWFrame::RA_SKIP )
658
frameStyle.addProperty( "style:wrap", "none" );
659
else if ( runAround() == KWFrame::RA_NO )
660
frameStyle.addProperty( "style:wrap", "run-through" );
661
else // RA_BOUNDINGRECT
663
if ( runAroundSide() == KWFrame::RA_LEFT )
664
frameStyle.addProperty( "style:wrap", "left" );
665
else if ( runAroundSide() == KWFrame::RA_RIGHT )
666
frameStyle.addProperty( "style:wrap", "right" );
667
else if ( runAroundSide() == KWFrame::RA_BIGGEST )
668
frameStyle.addProperty( "style:wrap", "biggest" );
671
// This attribute isn't part of the OASIS spec. Doesn't matter since it doesn't affect rendering
672
// of existing documents, only editing (and only KWord has this kind of option until now).
673
NewFrameBehavior defaultNfb = frameSet()->isHeaderOrFooter() ? Copy : NoFollowup;
674
if ( m_newFrameBehavior != defaultNfb ) {
675
const char* value = "none";
676
if ( m_newFrameBehavior == Reconnect )
678
else if ( m_newFrameBehavior == Copy )
680
else if ( m_newFrameBehavior == NoFollowup )
682
frameStyle.addProperty( "koffice:frame-behavior-on-new-page", value );
685
// The loading code for this one is in kwtextframeset, maybe this should be moved there too
686
const char* frameBehav = 0;
687
if ( m_frameBehavior == KWFrame::Ignore )
689
else if ( m_frameBehavior == KWFrame::AutoCreateNewFrame )
690
frameBehav = "auto-create-new-frame";
691
// the third case, AutoExtendFrame is handled by min-height
693
frameStyle.addProperty( "style:overflow-behavior", frameBehav );
695
return mainStyles.lookup( frameStyle, "fr" );
698
bool KWFrame::frameAtPos( const QPoint& point, bool borderOfFrameOnly) const {
699
// Forwarded to KWFrameSet to make it virtual
700
return frameSet()->isFrameAtPos( this, point, borderOfFrameOnly );
703
KoRect KWFrame::innerRect() const
705
KoRect inner( this->normalize());
706
inner.moveBy( paddingLeft(), paddingTop() );
707
inner.setWidth( innerWidth() );
708
inner.setHeight( innerHeight() );
712
double KWFrame::innerWidth() const
714
return KMAX( 0.0, width() - m_paddingLeft - m_paddingRight );
717
double KWFrame::innerHeight() const
719
return KMAX( 0.0, height() - m_paddingTop - m_paddingBottom );
722
void KWFrame::setFramePadding( double left, double top, double right, double bottom)
724
m_paddingLeft = left;
726
m_paddingRight = right;
727
m_paddingBottom = bottom;
730
bool KWFrame::compareFrameZOrder(KWFrame *f1, KWFrame *f2)
732
return f1->zOrder() < f2->zOrder();