kword

KWFrame.cpp
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>
5
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.
10
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.
15
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.
20*/
21
22#include "KWFrame.h"
23#include "KWFrameSet.h"
24#include "KWFrameList.h"
25#include "KWDocument.h"
26#include "KWPageManager.h"
27#include "KWTextFrameSet.h"
28#include "KWViewMode.h"
29#include "KWCanvas.h"
30
31#include <KoOasisContext.h>
32#include <KoXmlNS.h>
33#include <KoXmlWriter.h>
34#include <KoStyleStack.h>
35
36#include <kcommand.h>
37#include <kdebug.h>
38
39#include <float.h> // for DBL_DIG
40
41//#define DEBUG_DRAW
42
43/******************************************************************/
44/* Class: ZOrderedFrameList */
45/******************************************************************/
46
47int ZOrderedFrameList::compareItems(TQPtrCollection::Item a, TQPtrCollection::Item b)
48{
49 int za = ((KWFrame *)a)->zOrder();
50 int zb = ((KWFrame *)b)->zOrder();
51 if (za == zb) return 0;
52 if (za < zb) return -1;
53 return 1;
54}
55
56
57/******************************************************************/
58/* Class: KWFrame */
59/******************************************************************/
60
62{
63 m_runAround = RA_NO;
64 //kdDebug(32001) << "KWFrame::KWFrame this=" << this << " frame=" << frame << endl;
65 copySettings( frame );
66 m_minFrameHeight=0;
67 m_frameStack = 0; // lazy initialisation.
68}
69
70KWFrame::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 ),
75 m_runAround( ra ),
76 m_runAroundSide( RA_BIGGEST ),
77 m_frameBehavior( AutoExtendFrame ),
78 m_newFrameBehavior( ( fs && fs->type() == FT_TEXT ) ? Reconnect : NoFollowup ),
79 m_bCopy( false ),
80 m_drawFootNoteLine( false ),
81 m_runAroundLeft( 1.0 ),
82 m_runAroundRight( 1.0 ),
83 m_runAroundTop( 1.0 ),
84 m_runAroundBottom( 1.0 ),
85 m_paddingLeft( 0 ),
86 m_paddingRight( 0 ),
87 m_paddingTop( 0 ),
88 m_paddingBottom( 0 ),
89 m_minFrameHeight( 0.01 ), // not 0, since AutoExtendFrame means min-height in odt
90 m_internalY( 0 ),
91 m_zOrder( 0 ),
92 m_backgroundColor( (fs && (fs->type() == FT_PICTURE || fs->type() == FT_PART)) ? TQBrush( TQColor(), TQt::NoBrush) : TQBrush( TQColor() ) ), // valid brush with invalid color ( default )
93 m_borderLeft( TQColor(), KoBorder::SOLID, 0 ),
94 m_borderRight( TQColor(), KoBorder::SOLID, 0 ),
95 m_borderTop( TQColor(), KoBorder::SOLID, 0 ),
96 m_borderBottom( TQColor(), KoBorder::SOLID, 0 ),
97 m_frameSet( fs )
98{
99 //kdDebug(32001) << "KWFrame::KWFrame " << this << " left=" << left << " top=" << top << endl;
100 m_frameStack = 0; // lazy initialisation.
101}
102
104{
105 //kdDebug(32001) << "KWFrame::~KWFrame " << this << endl;
106 delete m_frameStack;
107 m_frameStack = 0;
108}
109
110void KWFrame::setBackgroundColor( const TQBrush &color )
111{
112 m_backgroundColor = color;
113}
114
115
117{
118 Q_ASSERT( m_frameSet );
119 if( !m_frameSet ) {
120 kdDebug() << k_funcinfo << this << " has no frameset!" << endl;
121 return 0;
122 }
123 if( !m_frameSet->pageManager() ) {
124 kdWarning() << k_funcinfo << this << " is not a frame that is in use; misses a pageManager!" << endl;
125 return -1;
126 }
127 return frameSet()->pageManager()->pageNumber(this);
128}
129
130int KWFrame::pageNumber( KWDocument* doc ) const
131{
132 return doc->pageManager()->pageNumber(this);
133}
134
136 /* returns a deep copy of self */
137 return new KWFrame(this);
138}
139
140void KWFrame::copySettings(KWFrame *frm)
141{
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());
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());
165}
166
168 if (frameSet()->isFloating())
170}
171
172
173void KWFrame::updateRulerHandles(){
174// TODO
175#if 0
176 if(! isSelected())
177 {
178 KWDocument *doc = frameSet()->kWordDocument();
179 if(doc)
180 doc->updateRulerFrameStartEnd();
181 }
182#endif
183}
184
185TQRect KWFrame::outerRect( KWViewMode* viewMode ) const
186{
187 KWDocument *doc = m_frameSet->kWordDocument();
188 TQRect 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 );
196 }
197 return outerRect;
198}
199
201{
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();
209 return outerRect;
210}
211
213{
214 KoRect raRect = outerKoRect();
215 raRect.rLeft() -= m_runAroundLeft;
216 raRect.rRight() += m_runAroundRight;
217 raRect.rTop() -= m_runAroundTop;
218 raRect.rBottom() += m_runAroundBottom;
219 return raRect;
220}
221
222void KWFrame::save( TQDomElement &frameElem )
223{
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", TQString::number( left(), 'g', DBL_DIG ) );
227 frameElem.setAttribute( "top", TQString::number( top(), 'g', DBL_DIG ) );
228 frameElem.setAttribute( "right", TQString::number( right(), 'g', DBL_DIG ) );
229 frameElem.setAttribute( "bottom", TQString::number( bottom(), 'g', DBL_DIG ) );
230 if ( minimumFrameHeight() > 0 )
231 frameElem.setAttribute( "min-height", TQString::number( minimumFrameHeight(), 'g', DBL_DIG ) );
232
233 if ( !m_frameSet->isHeaderOrFooter() && !m_frameSet->isMainFrameset() )
234 {
235 if(runAround()!=RA_NO)
236 {
237 frameElem.setAttribute( "runaround", static_cast<int>( runAround() ) );
238 if (runAround() == RA_BOUNDINGRECT)
239 {
240 if (runAroundSide()==RA_LEFT)
241 frameElem.setAttribute( "runaroundSide", "left" );
242 else if (runAroundSide()==RA_RIGHT)
243 frameElem.setAttribute( "runaroundSide", "right" );
244 else
245 frameElem.setAttribute( "runaroundSide", "biggest" );
246 }
247 }
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 = TQMAX( TQMAX( m_runAroundLeft, m_runAroundRight ), TQMAX( m_runAroundTop, m_runAroundBottom ) );
255 frameElem.setAttribute( "runaroundGap", runAroundGap );
256 }
257 }
258
259 if(leftBorder().penWidth()!=0)
260 frameElem.setAttribute( "lWidth", leftBorder().penWidth() );
261
262 if(leftBorder().color.isValid())
263 {
264 frameElem.setAttribute( "lRed", leftBorder().color.red() );
265 frameElem.setAttribute( "lGreen", leftBorder().color.green() );
266 frameElem.setAttribute( "lBlue", leftBorder().color.blue() );
267 }
268 if(leftBorder().getStyle() != KoBorder::SOLID)
269 frameElem.setAttribute( "lStyle", static_cast<int>( leftBorder().getStyle()) );
270
271 if(rightBorder().penWidth()!=0)
272 frameElem.setAttribute( "rWidth", rightBorder().penWidth() );
273
274 if(rightBorder().color.isValid())
275 {
276 frameElem.setAttribute( "rRed", rightBorder().color.red() );
277 frameElem.setAttribute( "rGreen", rightBorder().color.green() );
278 frameElem.setAttribute( "rBlue", rightBorder().color.blue() );
279 }
280 if(rightBorder().getStyle() != KoBorder::SOLID)
281 frameElem.setAttribute( "rStyle", static_cast<int>( rightBorder().getStyle() ) );
282
283 if(topBorder().penWidth()!=0)
284 frameElem.setAttribute( "tWidth", topBorder().penWidth() );
285
286 if(topBorder().color.isValid())
287 {
288 frameElem.setAttribute( "tRed", topBorder().color.red() );
289 frameElem.setAttribute( "tGreen", topBorder().color.green() );
290 frameElem.setAttribute( "tBlue", topBorder().color.blue() );
291 }
292 if(topBorder().getStyle() != KoBorder::SOLID)
293 frameElem.setAttribute( "tStyle", static_cast<int>( topBorder().getStyle() ) );
294
295 if(bottomBorder().penWidth()!=0) {
296 frameElem.setAttribute( "bWidth", bottomBorder().penWidth() );
297 }
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() );
302 }
303 if(bottomBorder().getStyle() != KoBorder::SOLID)
304 frameElem.setAttribute( "bStyle", static_cast<int>( bottomBorder().getStyle() ) );
305
306 if(backgroundColor().color().isValid())
307 {
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 ());
312 }
313 if(paddingLeft() != 0)
314 frameElem.setAttribute( "bleftpt", paddingLeft() );
315
316 if(paddingRight()!=0)
317 frameElem.setAttribute( "brightpt", paddingRight() );
318
319 if(paddingTop()!=0)
320 frameElem.setAttribute( "btoppt", paddingTop() );
321
322 if(paddingBottom()!=0)
323 frameElem.setAttribute( "bbottompt", paddingBottom() );
324
325 if(frameBehavior()!=AutoCreateNewFrame)
326 frameElem.setAttribute( "autoCreateNewFrame", static_cast<int>( frameBehavior()) );
327
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()) );
330
331 //same reason
332 frameElem.setAttribute( "copy", static_cast<int>( m_bCopy ) );
333
334 if(sheetSide()!= AnySide)
335 frameElem.setAttribute( "sheetSide", static_cast<int>( sheetSide()) );
336
337 frameElem.setAttribute( "z-index", zOrder() );
338}
339
340void KWFrame::load( TQDomElement &frameElem, KWFrameSet* frameSet, int syntaxVersion )
341{
342 m_minFrameHeight = KWDocument::getAttribute( frameElem, "min-height", 0.0 );
343 m_runAround = static_cast<RunAround>( KWDocument::getAttribute( frameElem, "runaround", RA_NO ) );
344 TQString str = frameElem.attribute( "runaroundSide" );
345 if ( str == "left" )
346 m_runAroundSide = RA_LEFT;
347 else if ( str == "right" )
348 m_runAroundSide = RA_RIGHT;
349 else
350 m_runAroundSide = RA_BIGGEST;
351
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 ) );
359
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;
369
370 KoBorder l, r, t, b;
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") )
376 l.color.setRgb(
377 KWDocument::getAttribute( frameElem, "lRed", 0 ),
378 KWDocument::getAttribute( frameElem, "lGreen", 0 ),
379 KWDocument::getAttribute( frameElem, "lBlue", 0 ) );
380 if ( frameElem.hasAttribute("rRed") )
381 r.color.setRgb(
382 KWDocument::getAttribute( frameElem, "rRed", 0 ),
383 KWDocument::getAttribute( frameElem, "rGreen", 0 ),
384 KWDocument::getAttribute( frameElem, "rBlue", 0 ) );
385 if ( frameElem.hasAttribute("tRed") )
386 t.color.setRgb(
387 KWDocument::getAttribute( frameElem, "tRed", 0 ),
388 KWDocument::getAttribute( frameElem, "tGreen", 0 ),
389 KWDocument::getAttribute( frameElem, "tBlue", 0 ) );
390 if ( frameElem.hasAttribute("bRed") )
391 b.color.setRgb(
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 ) ));
399 TQColor c;
400 if ( frameElem.hasAttribute("bkRed") )
401 c.setRgb(
402 KWDocument::getAttribute( frameElem, "bkRed", 0 ),
403 KWDocument::getAttribute( frameElem, "bkGreen", 0 ),
404 KWDocument::getAttribute( frameElem, "bkBlue", 0 ) );
405
406 if ( syntaxVersion < 2 ) // Activate old "white border == no border" conversion
407 {
408 if(c==l.color && l.penWidth()==1 && l.getStyle()==0 )
409 l.setPenWidth(0);
410 if(c==r.color && r.penWidth()==1 && r.getStyle()==0)
411 r.setPenWidth(0);
412 if(c==t.color && t.penWidth()==1 && t.getStyle()==0 )
413 t.setPenWidth(0);
414 if(c==b.color && b.penWidth()==1 && b.getStyle()==0 )
415 b.setPenWidth(0);
416 }
417 m_borderLeft = l;
418 m_borderRight = r;
419 m_borderTop = t;
420 m_borderBottom = b;
421 m_backgroundColor = TQBrush( c );
422
423
424 if( frameElem.hasAttribute("bkStyle"))
425 m_backgroundColor.setStyle (static_cast<TQt::BrushStyle>(KWDocument::getAttribute( frameElem, "bkStyle", TQt::SolidPattern )));
426
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();
433}
434
435// This is shared with table cells - so, no runaround and newframebehavior etc.
436// Only background, borders, padding.
437void KWFrame::loadBorderProperties( KoStyleStack& styleStack )
438{
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" ) );
444
445 // background color
446 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "background-color" ) ) {
447 TQString color = styleStack.attributeNS( KoXmlNS::fo, "background-color" );
448 if ( color == "transparent" )
449 m_backgroundColor = TQBrush( TQColor(), TQt::NoBrush );
450 else
451 {
452 m_backgroundColor = TQBrush( TQColor( color ) /*, brush style is a dead feature, ignored */ );
453 }
454 }
455 // OOo compatibility: it uses background-transparency=100% instead of background-color="transparent"
456 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "background-transparency" ) ) {
457 TQString transp = styleStack.attributeNS( KoXmlNS::fo, "background-transparency" );
458 if ( transp == "100%" )
459 m_backgroundColor.setStyle( TQt::NoBrush );
460 }
461
462 // borders (3.11.27)
463 // can be none/hidden, solid and double. General form is the XSL/FO "width|style|color"
464 {
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") );
469 }
470 // TODO more refined border spec for double borders (3.11.28)
471}
472
473void KWFrame::loadCommonOasisProperties( KoOasisContext& context, KWFrameSet* frameSet, const char* typeProperties )
474{
475 KoStyleStack& styleStack = context.styleStack();
476 styleStack.setTypeProperties( typeProperties );
477
478 loadBorderProperties( styleStack );
479
480 // Background color is now done with fill-color.
481 // loadBorderProperties loads fo:background-color for compatibility (and for table cells),
482 // but the correct way for text boxes is draw:fill-color
483 if ( styleStack.hasAttributeNS( KoXmlNS::draw, "fill-color" ) ) {
484 TQString color = styleStack.attributeNS( KoXmlNS::draw, "fill-color" );
485 if ( color == "transparent" )
486 m_backgroundColor = TQBrush( TQColor(), TQt::NoBrush );
487 else
488 {
489 m_backgroundColor = TQBrush( TQColor( color ) /*, brush style is a dead feature, ignored */ );
490 }
491 }
492
493#if 0 // not allowed in the current OASIS spec
494 // margins, i.e. runAroundGap. fo:margin for 4 values or padding-left/right/top/bottom
495 m_runAroundLeft = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "left" ) );
496 m_runAroundRight = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "right" ) );
497 m_runAroundTop = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "top" ) );
498 m_runAroundBottom = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "bottom" ) );
499#endif
500 // margins, i.e. runAroundGap. fo:margin-left/right/top/bottom
501 m_runAroundLeft = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-left" ) );
502 m_runAroundRight = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-right" ) );
503 m_runAroundTop = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-top" ) );
504 m_runAroundBottom = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-bottom" ) );
505
506 // This attribute isn't part of the OASIS spec. Doesn't matter since it doesn't affect rendering
507 // of existing documents, only editing (and only KWord has this kind of option until now).
508 const TQCString frameBehaviorOnNewPage = styleStack.attributeNS( KoXmlNS::koffice, "frame-behavior-on-new-page" ).latin1();
509 if ( frameBehaviorOnNewPage == "followup" )
510 m_newFrameBehavior = Reconnect;
511 else if ( frameBehaviorOnNewPage == "copy" )
512 m_newFrameBehavior = Copy;
513 else if ( frameBehaviorOnNewPage == "none" )
514 m_newFrameBehavior = NoFollowup;
515 else { // Defaults for OASIS documents not created by KWord
516 m_newFrameBehavior = frameSet->isHeaderOrFooter() ? Copy : NoFollowup;
517 if ( !frameBehaviorOnNewPage.isEmpty() )
518 kdWarning(32001) << "Unknown value for koffice:frame-behavior-on-new-page: " << frameBehaviorOnNewPage << endl;
519 }
520 // Footnotes and endnotes are handled in a special way.
521 if ( frameSet->isFootEndNote() ) // note that isFootNote/isEndNote are not possible yet
522 m_newFrameBehavior = NoFollowup;
523
524 KWFrame::RunAround runAround = KWFrame::RA_BOUNDINGRECT;
525 KWFrame::RunAroundSide runAroundSide = KWFrame::RA_BIGGEST;
526 const TQCString oowrap = styleStack.attributeNS( KoXmlNS::style, "wrap" ).latin1();
527 if ( oowrap == "none" ) // 'no wrap' means 'avoid horizontal space'
528 runAround = KWFrame::RA_SKIP;
529 else if ( oowrap == "left" )
530 runAroundSide = KWFrame::RA_LEFT;
531 else if ( oowrap == "right" )
532 runAroundSide= KWFrame::RA_RIGHT;
533 else if ( oowrap == "run-through" )
534 runAround = KWFrame::RA_NO;
535 //if ( oowrap == "biggest" ) // OASIS extension
536 // ->( KWFrame::RA_BOUNDINGRECT, KWFrame::RA_BIGGEST ), already set above
537 //if ( oowrap == "parallel" || oowrap == "dynamic" )
538 // dynamic is called "optimal" in the OO GUI. It's different from biggest because it can lead to parallel.
539 // Those are not supported in KWord, let's use biggest instead
540 setRunAround( runAround );
541 setRunAroundSide( runAroundSide );
542}
543
544void KWFrame::startOasisFrame( KoXmlWriter &writer, KoGenStyles& mainStyles, const TQString& name, const TQString& lastFrameName ) const
545{
546 writer.startElement( "draw:frame" );
547 writer.addAttribute( "draw:name", name );
548 writer.addAttribute( "draw:style-name", saveOasisFrameStyle( mainStyles ) );
549
550 if ( !frameSet()->isFloating() )
551 { // non-inline frame, anchored to page
552 const int pgNum = pageNumber();
553 const double yInPage = top() - frameSet()->pageManager()->topOfPage(pgNum);
554 writer.addAttributePt( "svg:x", left() );
555 writer.addAttributePt( "svg:y", yInPage );
556 writer.addAttribute( "text:anchor-type", "page" );
557 writer.addAttribute( "text:anchor-page-number", pgNum );
558 writer.addAttribute( "draw:z-index", zOrder() );
559 }
560 writer.addAttributePt( "svg:width", width() );
561 writer.addAttributePt( "svg:height", height() );
562 if ( isCopy() )
563 writer.addAttribute( "draw:copy-of", lastFrameName );
564}
565
566// shared between startOasisFrame and table cells.
567// Only background, borders, padding.
568void KWFrame::saveBorderProperties( KoGenStyle& frameStyle ) const
569{
570 // Background: color and transparency
571 // OOo seems to use style:background-transparency="100%", but the schema allows background-color=transparent
572 if ( m_backgroundColor.style() == TQt::NoBrush )
573 frameStyle.addProperty( "fo:background-color", "transparent" );
574 else if ( m_backgroundColor.color().isValid() )
575 frameStyle.addProperty( "fo:background-color", m_backgroundColor.color().name() );
576
577 // Borders
578 if ( ( m_borderLeft == m_borderRight )
579 && ( m_borderLeft == m_borderTop )
580 && ( m_borderLeft == m_borderBottom ) )
581 {
582 frameStyle.addProperty( "fo:border", m_borderLeft.saveFoBorder() );
583 }
584 else
585 {
586 frameStyle.addProperty( "fo:border-left", m_borderLeft.saveFoBorder() );
587 frameStyle.addProperty( "fo:border-right", m_borderRight.saveFoBorder() );
588 frameStyle.addProperty( "fo:border-top", m_borderTop.saveFoBorder() );
589 frameStyle.addProperty( "fo:border-bottom", m_borderBottom.saveFoBorder() );
590 }
591
592 if ( m_paddingLeft != 0 && ( ( m_paddingLeft == m_paddingRight )
593 && ( m_paddingLeft == m_paddingTop )
594 && ( m_paddingLeft == m_paddingBottom ) ) )
595 frameStyle.addPropertyPt( "fo:padding", m_paddingLeft );
596 else
597 {
598 if ( m_paddingLeft != 0 )
599 frameStyle.addPropertyPt( "fo:padding-left", m_paddingLeft );
600 if ( m_paddingRight != 0 )
601 frameStyle.addPropertyPt( "fo:padding-right", m_paddingRight );
602 if ( m_paddingTop != 0 )
603 frameStyle.addPropertyPt( "fo:padding-top", m_paddingTop );
604 if ( m_paddingBottom != 0 )
605 frameStyle.addPropertyPt( "fo:padding-bottom", m_paddingBottom );
606 }
607}
608
609void KWFrame::saveMarginAttributes( KoXmlWriter &writer ) const
610{
611 if ( m_runAroundLeft != 0 )
612 writer.addAttributePt( "fo:margin-left", m_runAroundLeft );
613 if ( m_runAroundRight != 0 )
614 writer.addAttributePt( "fo:margin-right", m_runAroundRight );
615 if ( m_runAroundTop != 0 )
616 writer.addAttributePt( "fo:margin-top", m_runAroundTop );
617 if ( m_runAroundBottom != 0 )
618 writer.addAttributePt( "fo:margin-bottom", m_runAroundBottom );
619}
620
621void KWFrame::saveMarginProperties( KoGenStyle& frameStyle ) const
622{
623#if 0 // not allowed in the current OASIS spec
624 if ( m_runAroundLeft != 0 && ( ( m_runAroundLeft == m_runAroundRight )
625 && ( m_runAroundLeft == m_runAroundTop )
626 && ( m_runAroundLeft == m_runAroundBottom ) ) )
627 frameStyle.addPropertyPt( "fo:margin", m_runAroundLeft );
628 else
629 {
630#endif
631 if ( m_runAroundLeft != 0 )
632 frameStyle.addPropertyPt( "fo:margin-left", m_runAroundLeft );
633 if ( m_runAroundRight != 0 )
634 frameStyle.addPropertyPt( "fo:margin-right", m_runAroundRight );
635 if ( m_runAroundTop != 0 )
636 frameStyle.addPropertyPt( "fo:margin-top", m_runAroundTop );
637 if ( m_runAroundBottom != 0 )
638 frameStyle.addPropertyPt( "fo:margin-bottom", m_runAroundBottom );
639#if 0 // not allowed in the current OASIS spec
640 }
641#endif
642}
643
644TQString KWFrame::saveOasisFrameStyle( KoGenStyles& mainStyles ) const
645{
646 KoGenStyle frameStyle( KWDocument::STYLE_FRAME_AUTO, "graphic" );
647 TQString protect;
648 if ( frameSet()->protectContent() )
649 protect = "content";
650 if ( frameSet()->isProtectSize() ) // ## should be moved for frame
651 {
652 if ( !protect.isEmpty() )
653 protect+=" ";
654 protect+="size";
655 }
656 if ( !protect.isEmpty() )
657 frameStyle.addProperty( "style:protect", protect );
658
659 if ( !frameSet()->isFloating() )
660 { // non-inline frame, anchored to page
661 frameStyle.addProperty( "style:horizontal-rel", "page" );
662 frameStyle.addProperty( "style:vertical-rel", "page" );
663 frameStyle.addProperty( "style:horizontal-pos", "from-left" );
664 frameStyle.addProperty( "style:vertical-pos", "from-top" );
665 }
666
667 // Background (KWFrame::saveBorderProperties saves as fo:background-color, but OOo-2.0.x uses draw:fill-color)
668 // So now we use draw:fill-color too, the text background color is in fact a paragraph feature.
669 if ( m_backgroundColor.style() == TQt::NoBrush )
670 frameStyle.addProperty( "draw:fill-color", "transparent" );
671 else if ( m_backgroundColor.color().isValid() )
672 frameStyle.addProperty( "draw:fill-color", m_backgroundColor.color().name() );
673
674 saveBorderProperties( frameStyle );
675 saveMarginProperties( frameStyle );
676
677 if ( runAround() == KWFrame::RA_SKIP )
678 frameStyle.addProperty( "style:wrap", "none" );
679 else if ( runAround() == KWFrame::RA_NO )
680 frameStyle.addProperty( "style:wrap", "run-through" );
681 else // RA_BOUNDINGRECT
682 {
683 if ( runAroundSide() == KWFrame::RA_LEFT )
684 frameStyle.addProperty( "style:wrap", "left" );
685 else if ( runAroundSide() == KWFrame::RA_RIGHT )
686 frameStyle.addProperty( "style:wrap", "right" );
687 else if ( runAroundSide() == KWFrame::RA_BIGGEST )
688 frameStyle.addProperty( "style:wrap", "biggest" );
689 }
690
691 // This attribute isn't part of the OASIS spec. Doesn't matter since it doesn't affect rendering
692 // of existing documents, only editing (and only KWord has this kind of option until now).
693 NewFrameBehavior defaultNfb = frameSet()->isHeaderOrFooter() ? Copy : NoFollowup;
694 if ( m_newFrameBehavior != defaultNfb ) {
695 const char* value = "none";
696 if ( m_newFrameBehavior == Reconnect )
697 value = "followup";
698 else if ( m_newFrameBehavior == Copy )
699 value = "copy";
700 else if ( m_newFrameBehavior == NoFollowup )
701 value = "none";
702 frameStyle.addProperty( "koffice:frame-behavior-on-new-page", value );
703 }
704
705 // The loading code for this one is in kwtextframeset, maybe this should be moved there too
706 const char* frameBehav = 0;
707 if ( m_frameBehavior == KWFrame::Ignore )
708 frameBehav = "clip";
709 else if ( m_frameBehavior == KWFrame::AutoCreateNewFrame )
710 frameBehav = "auto-create-new-frame";
711 // the third case, AutoExtendFrame is handled by min-height
712 if ( frameBehav )
713 frameStyle.addProperty( "style:overflow-behavior", frameBehav );
714
715 return mainStyles.lookup( frameStyle, "fr" );
716}
717
718bool KWFrame::frameAtPos( const TQPoint& point, bool borderOfFrameOnly) const {
719 // Forwarded to KWFrameSet to make it virtual
720 return frameSet()->isFrameAtPos( this, point, borderOfFrameOnly );
721}
722
723KoRect KWFrame::innerRect() const
724{
725 KoRect inner( this->normalize());
726 inner.moveBy( paddingLeft(), paddingTop() );
727 inner.setWidth( innerWidth() );
728 inner.setHeight( innerHeight() );
729 return inner;
730}
731
732double KWFrame::innerWidth() const
733{
734 return KMAX( 0.0, width() - m_paddingLeft - m_paddingRight );
735}
736
737double KWFrame::innerHeight() const
738{
739 return KMAX( 0.0, height() - m_paddingTop - m_paddingBottom );
740}
741
742void KWFrame::setFramePadding( double left, double top, double right, double bottom)
743{
744 m_paddingLeft = left;
745 m_paddingTop = top;
746 m_paddingRight = right;
747 m_paddingBottom = bottom;
748}
749
751{
752 return f1->zOrder() < f2->zOrder();
753}
Class: KWFrameSet Base type, a frameset holds content as well as frames to show that content.
Definition KWFrameSet.h:62
static KWFrame * settingsFrame(const KWFrame *frame)
Returns the original frame that the param frame is a copy off, or the frame itself.
KWTableFrameSet * groupmanager() const
returns the groupManager this frameset belongs to.
Definition KWFrameSet.h:408
KWTextFrameSet * anchorFrameset() const
Return the frameset in which our anchor is - assuming isFloating()
Definition KWFrameSet.h:374
bool isFrameAtPos(const KWFrame *frame, const TQPoint &nPoint, bool borderOfFrameOnly=false) const
Return if the point is on the frame.
This class represents a single frame.
Definition KWFrame.h:68
bool frameAtPos(const TQPoint &nPoint, bool borderOfFrameOnly=false) const
Return if the point is on the frame.
Definition KWFrame.cpp:718
NewFrameBehavior
What happens on new page (create a new frame and reconnect, no followup, make copy)
Definition KWFrame.h:132
TQRect outerRect(KWViewMode *viewMode) const
Return the zoomed rectangle for this frame, including the border - for drawing.
Definition KWFrame.cpp:185
double minimumFrameHeight(void) const
Definition KWFrame.h:284
KWFrameSet * frameSet() const
Data stucture methods.
Definition KWFrame.h:143
double paddingTop() const
get top padding
Definition KWFrame.h:240
double paddingBottom() const
get bottom padding
Definition KWFrame.h:242
void setPaddingLeft(double b)
set left padding (distance between frame contents and frame border)
Definition KWFrame.h:227
void setMinimumFrameHeight(double h)
The property minimum frame height is used to make the automatic frame shrinking code stop.
Definition KWFrame.h:279
static bool compareFrameZOrder(KWFrame *f1, KWFrame *f2)
This is a method used to sort a list using the STL sorting methods.
Definition KWFrame.cpp:750
virtual ~KWFrame()
Destructor.
Definition KWFrame.cpp:103
void setPaddingRight(double b)
set right padding
Definition KWFrame.h:229
FrameBehavior
what should happen when the frame is full
Definition KWFrame.h:116
void setZOrder(int z)
The z-order of the frame, relative to the other frames on the same page.
Definition KWFrame.h:155
void save(TQDomElement &frameElem)
create XML to describe yourself
Definition KWFrame.cpp:222
RunAround
Runaround types RA_NO = No run around, all text is just printed.
Definition KWFrame.h:75
void setPaddingBottom(double b)
set bottom padding
Definition KWFrame.h:233
double paddingLeft() const
get left padding
Definition KWFrame.h:236
bool isCopy() const
Drawing property: if isCopy, this frame is a copy of the previous frame in the frameset.
Definition KWFrame.h:138
double paddingRight() const
get right padding
Definition KWFrame.h:238
void setPaddingTop(double b)
set top padding
Definition KWFrame.h:231
int pageNumber() const
The page on which this frame is.
Definition KWFrame.cpp:116
const KoBorder & leftBorder() const
All borders can be custom drawn with their own colors etc.
Definition KWFrame.h:170
KoRect outerKoRect() const
Return the unzoomed rectangle, including the border, for the frames-on-top list.
Definition KWFrame.cpp:200
void startOasisFrame(KoXmlWriter &xmlWriter, KoGenStyles &mainStyles, const TQString &name, const TQString &lastFrameName=TQString()) const
Write out a draw:frame element and its style.
Definition KWFrame.cpp:544
void load(TQDomElement &frameElem, KWFrameSet *frameSet, int syntaxVersion)
read attributes from XML.
Definition KWFrame.cpp:340
RunAroundSide
Runaround side - only meaningful when RA_BOUNDINGRECT is used.
Definition KWFrame.h:79
KoRect runAroundRect() const
Return the rectangle for this frame including the border and the runaround gap.
Definition KWFrame.cpp:212
KWFrame(KWFrameSet *fs, double left, double top, double width, double height, RunAround ra=RA_BOUNDINGRECT)
Constructor.
Definition KWFrame.cpp:70
KWFrame * getCopy()
returns a copy of self
Definition KWFrame.cpp:135
SheetSide
This frame will only be copied to: AnySide, OddSide or EvenSide.
Definition KWFrame.h:126
void frameBordersChanged()
Marks a frame to have changed position/borders.
Definition KWFrame.cpp:167
double topOfPage(int pageNumber) const
Return the y-offset in this document of the top of page with pageNumber Note that pageNumber is NOT a...
int pageNumber(const KoRect *rect) const
return pageNumber of frame, pagenumbers for a normal document start at 1.
virtual void invalidate()
Invalidate all paragraphs (causes a re-flow of the text upon next redraw)
Abstract base class for KWCanvas's view modes.
Definition KWViewMode.h:48
bool drawFrameBorders() const
Should we see frame borders? This setting doesn't always come from KWView...
Definition KWViewMode.h:105