/* KDChart - a multi-platform charting engine */ /**************************************************************************** ** Copyright (C) 2001-2003 Klarälvdalens Datakonsult AB. All rights reserved. ** ** This file is part of the KDChart library. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid commercial KDChart licenses may use this file in ** accordance with the KDChart Commercial License Agreement provided with ** the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.klaralvdalens-datakonsult.se/?page=products for ** information about KDChart Commercial License Agreements. ** ** Contact info@klaralvdalens-datakonsult.se if any conditions of this ** licensing are not clear to you. ** **********************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include KDChartCustomBox::~KDChartCustomBox() { // Intentionally left blank for now. } void KDChartCustomBox::deepCopy( const KDChartCustomBox* source ) { if( !source || this == source ) return; _rotation = source->_rotation; _content.deepCopy( &source->_content); _fontSize = source->_fontSize; _fontScaleGlobal = source->_fontScaleGlobal; _deltaX = source->_deltaX; _deltaY = source->_deltaY; _width = source->_width; _height = source->_height; _color = source->_color; _paper = source->_paper; _anchorArea = source->_anchorArea; _anchorPos = source->_anchorPos; _anchorAlign = source->_anchorAlign; _dataRow = source->_dataRow; _dataCol = source->_dataCol; _data3rd = source->_data3rd; _deltaAlign = source->_deltaAlign; _deltaScaleGlobal = source->_deltaScaleGlobal; _anchorBeingCalculated = source->_anchorBeingCalculated; _parentAxisArea = source->_parentAxisArea; } const KDChartCustomBox* KDChartCustomBox::clone() const { KDChartCustomBox* newBox = new KDChartCustomBox(); newBox->deepCopy( this ); return newBox; } float KDChartCustomBox::trueFontSize( double areaWidthP1000, double areaHeightP1000, int rectHeight ) const { float size; if( 0 > _fontSize ) { if( _fontScaleGlobal ) { size = _fontSize * TQMIN(areaWidthP1000, areaHeightP1000) * -1.0;//(areaWidthP1000 + areaHeightP1000) / -2.0; } else { // calculate the exact size: float targetLineSpacing = (_fontSize * rectHeight)/ -1000; size = targetLineSpacing; // step #1 - try to make the right font size: TQFont font( content().font() ); font.setPointSizeFloat( size ); TQFontMetrics fm( font ); //tqDebug(TQString("\nsize : ")+TQString::number(size)); //tqDebug(TQString("(float)rectHeight : ")+TQString::number((float)rectHeight)); //tqDebug(TQString("(float)fm.lineSpacing(): ")+TQString::number((float)fm.lineSpacing())); size *= targetLineSpacing / fm.lineSpacing(); //tqDebug(TQString("size : ")+TQString::number(size)); // step #2 - make sure the font size is not too big: font.setPointSizeFloat( size ); TQFontMetrics fm2( font ); size *= targetLineSpacing / fm2.lineSpacing(); //tqDebug(TQString("(float)rectHeight : ")+TQString::number((float)rectHeight)); //tqDebug(TQString("(float)fm.lineSpacing(): ")+TQString::number((float)fm.lineSpacing())); //tqDebug(TQString("size : ")+TQString::number(size)); } } else { //tqDebug(TQString("\n_fontsize: ")+TQString::number(_fontSize)); if( _fontSize ) size = _fontSize; else{ size = content().font().pointSize(); if( -1 == size ) size = content().font().pixelSize(); if( -1 == size ) size = 10; } } return size; } int KDChartCustomBox::trueFontLineSpacing( double areaWidthP1000, double areaHeightP1000, int rectHeight ) const { TQFont font( content().font() ); font.setPointSizeFloat( trueFontSize( areaWidthP1000,areaHeightP1000, rectHeight ) ); TQFontMetrics fm( font ); return fm.lineSpacing(); } void KDChartCustomBox::getTrueShift( double areaWidthP1000, double areaHeightP1000, int rectHeight, int& dX, int& dY ) const { int x, y; if( _deltaScaleGlobal ){ x = (0 > _deltaX) ? static_cast < int > ( -areaWidthP1000 * _deltaX ) : _deltaX; y = (0 > _deltaY) ? static_cast < int > ( -areaHeightP1000 * _deltaY ) : _deltaY; }else{ int fontHeight = trueFontLineSpacing( areaWidthP1000, areaHeightP1000, rectHeight ); //tqDebug("\nfontHeight %i",fontHeight); x = (0 > _deltaX) ? static_cast < int > ( fontHeight * _deltaX / -100.0 ) : _deltaX; y = (0 > _deltaY) ? static_cast < int > ( fontHeight * _deltaY / -100.0 ) : _deltaY; //tqDebug("y %i",y); } uint deltaAlign = (KDCHART_AlignAuto == _deltaAlign) ? _anchorAlign : _deltaAlign; if ( TQt::AlignLeft == (TQt::AlignLeft & deltaAlign) ) dX = x; else if ( TQt::AlignRight == (TQt::AlignRight & deltaAlign) ) dX = -x; else dX = 0; // <-- so the _deltaX value becomes ineffective! if ( TQt::AlignTop == (TQt::AlignTop & deltaAlign) ) dY = y; else if ( TQt::AlignBottom == (TQt::AlignBottom & deltaAlign) ) dY = -y; else dY = 0; // <-- so the _deltaY value becomes ineffective! } TQRect KDChartCustomBox::trueRect( TQPainter * /*painter*/, TQPoint /*anchor*/, double /*areaWidthP1000*/, double /*areaHeightP1000*/ ) const { //temporary allow KDC_Presentation to compile tqDebug( "Sorry, not implemented yet: KDChartCustomBox::trueRect()" ); return TQRect( 1, 1, 2, 2 ); } //static TQPainter* pppainter=0; //static int pdWidth =1280; //static int pdHeight =1024; TQRect KDChartCustomBox::trueRect( TQPoint anchor, double areaWidthP1000, double areaHeightP1000 ) const { int w = (0 > _width ) ? static_cast < int > ( -areaWidthP1000 * _width ) : _width; int h = (0 > _height) ? static_cast < int > ( -areaHeightP1000 * _height ) : _height; //tqDebug("w: %i h: %i", w,h ); if( _fontScaleGlobal && 0 == w && 0 == h ){ //Now calculate the size of the box based upon the content! TQFont font( content().font() ); if ( _fontSize ) { font.setPointSizeFloat( (0 > _fontSize) ? (_fontSize * TQMIN(areaWidthP1000, areaHeightP1000) * -1.0)//(areaWidthP1000 + areaHeightP1000) / -2.0 : _fontSize ); //tqDebug("\n_fontSize * TQMIN(areaWidthP1000, areaHeightP1000) %i * TQMIN(%f, %f) text: %s", _fontSize , areaWidthP1000, areaHeightP1000, content().text().latin1()); } TQString txt( content().text() ); TQString txtTest( txt.stripWhiteSpace().lower() ); if( !txtTest.startsWith("" ) ) txt.prepend( "" ); if( !txtTest.endsWith( "") ) txt.append( ""); //tqDebug("\nw: %i h: %i", w,h ); TQSimpleRichText tmpContent( txt, font ); // tmpContent.setWidth(pdWidth); // tmpContent.setHeight(pdHeight); // tmpContent.adjustSize(); // if( pppainter ){ // tmpContent.setWidth(pppainter, 2000); // tmpContent.adjustSize(); // } w = tmpContent.widthUsed(); h = tmpContent.height(); //tqDebug("pdWidth: %i w: %i h %i",pdWidth,w,h); //tqDebug("w: %i h: %i", w,h ); } //tqDebug("\nw: %i h: %i", w,h ); int x,y; if ( TQt::AlignLeft == (TQt::AlignLeft & _anchorAlign) ) x = 0; else if ( TQt::AlignRight == (TQt::AlignRight & _anchorAlign) ) x = - w + 1; else x = - w / 2; if ( TQt::AlignTop == (TQt::AlignTop & _anchorAlign) ) y = 0; else if ( TQt::AlignBottom == (TQt::AlignBottom & _anchorAlign) ) y = - h + 1; else y = - h / 2; int dX,dY; getTrueShift( areaWidthP1000, areaHeightP1000, h, dX, dY ); //tqDebug("trueRect: x %i y %i w %i h %i text: %s", anchor.x()+x+dX, anchor.y()+y+dY, w,h, content().text().latin1()); return TQRect( anchor.x()+x+dX, anchor.y()+y+dY, w, h ); } int KDChartCustomBox::trueRectAlignX(const TQRect& rect) const { int ret = rect.center().x(); if ( TQt::AlignLeft == (TQt::AlignLeft & _anchorAlign) ) ret -= rect.width(); else if ( TQt::AlignRight == (TQt::AlignRight & _anchorAlign) ) ret += rect.width(); return ret; } int KDChartCustomBox::trueRectAlignY(const TQRect& rect) const { int ret = rect.center().y(); if ( TQt::AlignTop == (TQt::AlignTop & _anchorAlign) ) ret -= rect.height(); else if ( TQt::AlignBottom == (TQt::AlignBottom & _anchorAlign) ) ret += rect.height(); return ret; } void KDChartCustomBox::paint( TQPainter* painter, TQPoint anchor, double areaWidthP1000, double areaHeightP1000, const KDFrame* frame, const TQRect& frameRect, const TQColor * color, const TQBrush * paper ) const { painter->save(); int rotDX = 0; int rotDY = 0; /* //pppainter=painter; const TQPaintDeviceMetrics metrics(painter->device()); pdWidth = metrics.width(); const int aWidthP1000 = metrics.width() /1000; const int aHeightP1000 = metrics.height()/1000; //pdHeight = metrics.height(); */ TQRect myRect( trueRect( anchor, areaWidthP1000, areaHeightP1000 ) ); /* TQPaintDeviceMetrics metrics(painter->device()); int pdWidth = metrics.width(); int dpiY = metrics.logicalDpiY(); int dpiX = metrics.logicalDpiX(); tqDebug("dpiY: %i dpiX: %i",dpiY,dpiX); tqDebug("pdWidth: %i box myRect w: %i h %i",pdWidth,myRect.width(),myRect.height()); */ //myRect.setSize(myRect.size()*6); TQRect myFrameRect( frameRect ); if ( myRect.isValid() ) { //tqDebug("box myRect center: x %i y %i",myRect.center().x(),myRect.center().y()); if( _rotation ){ getTrueShift( areaWidthP1000, areaHeightP1000, myRect.height(), rotDX, rotDY ); myRect.moveBy( -rotDX, -rotDY ); if( frame ) myFrameRect.moveBy( -rotDX, -rotDY ); //tqDebug("\nrotDelta: x %i y %i",rotDX,rotDY); //tqDebug("\nbox myRect center: x %i y %i",myRect.center().x(),myRect.center().y()); myRect.moveCenter( TQPoint( anchor.x() - trueRectAlignX(myRect), anchor.y() - trueRectAlignY(myRect) ) ); if( frame ) myFrameRect.moveCenter( TQPoint( anchor.x() - trueRectAlignX(myFrameRect), anchor.y() - trueRectAlignY(myFrameRect) ) ); //tqDebug("box myRect center: x %i y %i",myRect.center().x(),myRect.center().y()); painter->translate( anchor.x(), anchor.y() ); painter->rotate( _rotation ); painter->translate( rotDX, rotDY ); } if( frame ) frame->paint( painter, KDFrame::PaintAll, myFrameRect ); if ( _fontSize ) { TQFont font( content().font() ); float trueSize = trueFontSize(areaWidthP1000,areaHeightP1000, myRect.height() ); font.setPointSizeFloat( trueSize ); //adjust the area height related to the font size myRect.setHeight( (int)(trueSize )+ (int)(trueSize*0.5)); const KDChartTextPiece tmpTextPiece( painter, content().text(), font ); tmpTextPiece.draw( painter, myRect.x(), myRect.y(), myRect, color ? *color : _color, paper ? paper : &_paper ); }else{ content().draw( painter, myRect.x(), myRect.y(), myRect, color ? *color : _color, paper ? paper : &_paper ); } } painter->restore(); } void KDChartCustomBox::createCustomBoxNode( TQDomDocument& document, TQDomNode& parent, const TQString& elementName, const KDChartCustomBox* custombox ) { TQDomElement customBoxElement = document.createElement( elementName ); parent.appendChild( customBoxElement ); KDXML::createIntNode( document, customBoxElement, "Rotation", custombox->_rotation ); KDXML::createStringNode( document, customBoxElement, "ContentText", custombox->_content.text() ); KDXML::createFontNode( document, customBoxElement, "ContentFont", custombox->_content.font() ); KDXML::createIntNode( document, customBoxElement, "FontSize", custombox->_fontSize ); KDXML::createBoolNode( document, customBoxElement, "FontScaleGlobal", custombox->_fontScaleGlobal ); KDXML::createIntNode( document, customBoxElement, "DeltaX", custombox->_deltaX ); KDXML::createIntNode( document, customBoxElement, "DeltaY", custombox->_deltaY ); KDXML::createIntNode( document, customBoxElement, "Width", custombox->_width ); KDXML::createIntNode( document, customBoxElement, "Height", custombox->_height ); KDXML::createColorNode( document, customBoxElement, "Color", custombox->_color ); KDXML::createBrushNode( document, customBoxElement, "Paper", custombox->_paper ); KDXML::createIntNode( document, customBoxElement, "AnchorArea", custombox->_anchorArea ); KDXML::createStringNode( document, customBoxElement, "AnchorPos", KDChartEnums::positionFlagToString( custombox->_anchorPos ) ); KDXML::createIntNode( document, customBoxElement, "AnchorAlign", custombox->_anchorAlign ); KDXML::createIntNode( document, customBoxElement, "DataRow", custombox->_dataRow ); KDXML::createIntNode( document, customBoxElement, "DataCol", custombox->_dataCol ); KDXML::createIntNode( document, customBoxElement, "Data3rd", custombox->_data3rd ); KDXML::createIntNode( document, customBoxElement, "DeltaAlign", custombox->_deltaAlign ); KDXML::createBoolNode( document, customBoxElement, "DeltaScaleGlobal", custombox->_deltaScaleGlobal ); KDXML::createIntNode( document, customBoxElement, "ParentAxisArea", custombox->_parentAxisArea ); } bool KDChartCustomBox::readCustomBoxNode( const TQDomElement& element, KDChartCustomBox& custombox ) { bool ok = true; TQString tempContentText; TQFont tempContentFont; int tempRotation = 0; // must be initialized: new parameter, not present in old versions of KDChart int tempDeltaAlign = KDCHART_AlignAuto; // must be initialized too: new parameter bool tempDeltaScaleGlobal = true; // must be initialized too: new parameter int tempFontSize, tempDeltaX, tempDeltaY, tempWidth, tempHeight, tempAnchorArea, tempParentAxisArea, tempAnchorAlign, tempDataRow, tempDataCol, tempData3rd; bool tempFontScaleGlobal; TQColor tempColor; TQBrush tempPaper; KDChartEnums::PositionFlag tempAnchorPos = KDChartEnums::PosTopLeft; TQDomNode node = element.firstChild(); while( !node.isNull() ) { TQDomElement element = node.toElement(); if( !element.isNull() ) { // was really an element TQString tagName = element.tagName(); if( tagName == "Rotation" ) { ok = ok & KDXML::readIntNode( element, tempRotation ); } else if( tagName == "ContentText" ) { ok = ok & KDXML::readStringNode( element, tempContentText ); } else if( tagName == "ContentFont" ) { ok = ok & KDXML::readFontNode( element, tempContentFont ); } else if( tagName == "FontSize" ) { ok = ok & KDXML::readIntNode( element, tempFontSize ); } else if( tagName == "FontScaleGlobal" ) { ok = ok & KDXML::readBoolNode( element, tempFontScaleGlobal ); } else if( tagName == "DeltaX" ) { ok = ok & KDXML::readIntNode( element, tempDeltaX ); } else if( tagName == "DeltaY" ) { ok = ok & KDXML::readIntNode( element, tempDeltaY ); } else if( tagName == "Width" ) { ok = ok & KDXML::readIntNode( element, tempWidth ); } else if( tagName == "Height" ) { ok = ok & KDXML::readIntNode( element, tempHeight ); } else if( tagName == "Color" ) { ok = ok & KDXML::readColorNode( element, tempColor ); } else if( tagName == "Paper" ) { ok = ok & KDXML::readBrushNode( element, tempPaper ); } else if( tagName == "AnchorArea" ) { ok = ok & KDXML::readIntNode( element, tempAnchorArea ); } else if( tagName == "AnchorPos" ) { TQString value; ok = ok & KDXML::readStringNode( element, value ); tempAnchorPos = KDChartEnums::stringToPositionFlag( value ); } else if( tagName == "AnchorAlign" ) { ok = ok & KDXML::readIntNode( element, tempAnchorAlign ); } else if( tagName == "DataRow" ) { ok = ok & KDXML::readIntNode( element, tempDataRow ); } else if( tagName == "DataCol" ) { ok = ok & KDXML::readIntNode( element, tempDataCol ); } else if( tagName == "Data3rd" ) { ok = ok & KDXML::readIntNode( element, tempData3rd ); } else if( tagName == "DeltaAlign" ) { ok = ok & KDXML::readIntNode( element, tempDeltaAlign ); } else if( tagName == "DeltaScaleGlobal" ) { ok = ok & KDXML::readBoolNode( element, tempDeltaScaleGlobal ); } else if ( tagName == "ParentAxisArea" ) { ok = ok & KDXML::readIntNode( element, tempParentAxisArea ); } else { tqDebug( "Unknown tag in custom box" ); } } node = node.nextSibling(); } if( ok ) { const KDChartTextPiece piece( 0, tempContentText, tempContentFont ); custombox._content.deepCopy( &piece ); custombox._rotation = tempRotation; custombox._fontSize = tempFontSize; custombox._fontScaleGlobal = tempFontScaleGlobal; custombox._deltaX = tempDeltaX; custombox._deltaY = tempDeltaY; custombox._width = tempWidth; custombox._height = tempHeight; custombox._color = tempColor; custombox._paper = tempPaper; custombox._anchorArea = tempAnchorArea; custombox._anchorPos = tempAnchorPos; custombox._anchorAlign = tempAnchorAlign; custombox._dataRow = tempDataRow; custombox._dataCol = tempDataCol; custombox._data3rd = tempData3rd; custombox._deltaAlign = tempDeltaAlign; custombox._deltaScaleGlobal = tempDeltaScaleGlobal; custombox._parentAxisArea = tempParentAxisArea; } return ok; } #include "KDChartCustomBox.moc"