kchart

KDChart.cpp
1/*
2 KDChart - a multi-platform charting engine
3 */
4
5/****************************************************************************
6 ** Copyright (C) 2001-2003 Klarälvdalens Datakonsult AB. All rights reserved.
7 **
8 ** This file is part of the KDChart library.
9 **
10 ** This file may be distributed and/or modified under the terms of the
11 ** GNU General Public License version 2 as published by the Free Software
12 ** Foundation and appearing in the file LICENSE.GPL included in the
13 ** packaging of this file.
14 **
15 ** Licensees holding valid commercial KDChart licenses may use this file in
16 ** accordance with the KDChart Commercial License Agreement provided with
17 ** the Software.
18 **
19 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
20 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 **
22 ** See http://www.klaralvdalens-datakonsult.se/?page=products for
23 ** information about KDChart Commercial License Agreements.
24 **
25 ** Contact info@klaralvdalens-datakonsult.se if any conditions of this
26 ** licensing are not clear to you.
27 **
28 **********************************************************************/
29#if defined KDAB_EVAL
30#include "../evaldialog/evaldialog.h"
31#endif
32
36#include <KDChart.h>
37#include <KDChartPainter.h>
38#include <KDChartParams.h>
39#include <KDChartGlobal.h>
40#include <KDChartAxisParams.h>
41
42#include <tqglobal.h>
43#include <tqpainter.h>
44#include <tqpaintdevice.h>
45#include <tqpaintdevicemetrics.h>
46
47#ifdef TQSA
48#if 0 // Disabled by ingwa to make it compile
49#include <tqsinterpreter.h>
50#include "KDChartWrapperFactory.h"
51#include "KDChartObjectFactory.h"
52#endif
53#endif
54
74
75KDChartParams* KDChart::oldParams = 0;
76KDChartPainter* KDChart::cpainter = 0;
77KDChartPainter* KDChart::cpainter2 = 0;
78KDChartParams::ChartType KDChart::cpainterType = KDChartParams::NoType;
79KDChartParams::ChartType KDChart::cpainterType2 = KDChartParams::NoType;
80
85void cleanupPainter();
86
87
88bool hasCartesianAxes( KDChartParams::ChartType chartType )
89{
90 switch( chartType ){
91 case KDChartParams::NoType: return false;
92 case KDChartParams::Bar: return true;
93 case KDChartParams::Line: return true;
94 case KDChartParams::Area: return true;
95 case KDChartParams::Pie: return false;
96 case KDChartParams::HiLo: return true;
97 case KDChartParams::Ring: return false;
98 case KDChartParams::Polar: return false; // Polar axes are NO cartesian axes!
99 case KDChartParams::BoxWhisker: return true;
100 default:
101 tqDebug("\n\n\n\nKDCHART ERROR: Type missing in KDChart.cpp hasCartesianAxes()\n"
102 "=============================================================\n"
103 "=============================================================\n\n\n\n");
104 }
105 return false;
106}
107
108
122bool KDChart::painterToDrawRect( TQPainter* painter, TQRect& drawRect )
123{
124 if( painter ){
125 TQPaintDeviceMetrics painterMetrics( painter->device() );
126 drawRect = TQRect( 0, 0, painterMetrics.width(), painterMetrics.height() );
127 drawRect.setWidth( drawRect.width() -2 );
128 drawRect.setHeight( drawRect.height()-2 );
129 return true;
130 }else{
131 drawRect = TQRect( TQPoint(0,0), TQSize(0,0) );
132 tqDebug("ERROR: KDChartPainter::painterToDrawRect() was called with *no* painter.");
133 return false;
134 }
135}
136
137
156bool KDChart::setupGeometry( TQPainter* painter,
157 KDChartParams* params,
159 const TQRect& drawRect )
160{
161//tqDebug("INVOKING: KDChart::setupGeometry()");
162 if( !params ){
163 tqDebug("ERROR: setupGeometry::paint() was called with *no* params.");
164 return false;
165 }
166 if( !data ){
167 tqDebug("ERROR: setupGeometry::paint() was called with *no* data.");
168 return false;
169 }
170 // don't crash due to memory problems when running on windows
171#ifdef TQ_WS_WIN
172 TQPixmap::setDefaultOptimization(TQPixmap::MemoryOptim);
173#endif
174
175 // Install a cleanup routine that is called when the TQt
176 // application shuts down and cleans up any potentially still
177 // existing painters. Only do this once.
178 static bool bFirstCleanUpInstall = true;
179 if( bFirstCleanUpInstall ) {
180 bFirstCleanUpInstall = false;
181 tqAddPostRoutine( cleanupPainter );
182 }
183
184 // Check whether last call of this methode gave us the same params pointer.
185 // If params changed we must create new painter(s).
186 bool paramsHasChanged = ( params != oldParams );
187 if( paramsHasChanged )
188 oldParams = params;
189
190 // Check whether there already is painter and, if that is the
191 // case, whether the painter still has the correct type (the chart
192 // type might have changed in the meantime).
193 if ( paramsHasChanged || !cpainter || cpainterType != params->chartType() )
194 {
195 delete cpainter; /* save, since always 0 if there was not yet
196 a chart painter */
197 // create a new painter
198 cpainter = KDChartPainter::create( params, false );
199 cpainterType = params->chartType();
200 }
201
202 // Check whether there already is a 2nd painter and, if that is the
203 // case, whether the painter still has the correct type (the
204 // additional chart type might have changed in the meantime).
205 if ( paramsHasChanged || !cpainter2 || cpainterType2 != params->additionalChartType() )
206 {
207 delete cpainter2; /* save, since always 0 if there was not yet
208 a chart painter */
209 // create a new painter
210 if( hasCartesianAxes( params->chartType() )
211 && hasCartesianAxes( params->additionalChartType() ) ){
212 cpainter2 = KDChartPainter::create( params, true );
213 cpainterType2 = params->additionalChartType();
214 }else{
215 cpainter2 = 0;
216 cpainterType2 = KDChartParams::NoType;
217 }
218 }
219
220 if ( cpainter ){ // can be 0 if no exceptions are used
221 cpainter->setupGeometry( painter, data, drawRect );
222 }
223
224 if ( cpainter2 ){ // can be 0 if no exceptions are used
225 cpainter2->setupGeometry( painter, data, drawRect );
226 }
227
228 return true;
229}
230
256void KDChart::paint( TQPainter* painter,
257 KDChartParams* paraParams,
258 KDChartTableDataBase* paraData,
259 KDChartDataRegionList* regions,
260 const TQRect* rect,
261 bool mustCalculateGeometry )
262{
263//tqDebug("KDChart::paint() mustCalculateGeometry: "+TQString(mustCalculateGeometry?"true":"false") );
264#if defined KDAB_EVAL
265 EvalDialog::checkEvalLicense( "KD Chart" );
266#endif
267
268 // delete old contents, to avoid the region from constantly growing
269 if( regions )
270 regions->clear();
271
272 KDChartParams* params = paraParams;
273 KDChartTableDataBase* data = paraData;
274 if( !paraParams && !paraData ){
275 tqDebug("-----");
276 tqDebug("Note: KDChart::paint() was called without \"params\" and without \"data\".");
277 tqDebug("----- Showing a default bar chart.");
278 params = new KDChartParams();
279 params->setDatasetGap(3 * params->valueBlockGap());
280 params->setPrintDataValues( false );
281 params->setLegendPosition( KDChartParams::NoLegend );
282 params->setAxisLabelsVisible( KDChartAxisParams::AxisPosBottom, false );
283 params->setAxisShowGrid( KDChartAxisParams::AxisPosBottom, false );
284 params->setHeader1Text( "KDChartWidget" );
285 data = new KDChartTableData( 3, 1 );
286 // 1st series
287 data->setCell( 0, 0, 12.5 );
288 // 2nd series
289 data->setCell( 1, 0, 8.0 );
290 // 3rd series
291 data->setCell( 2, 0, 15.0 );
292 }
293
294 TQRect drawRect;
295 bool bOk = true;
296 if( mustCalculateGeometry || !cpainter || cpainter->outermostRect().isNull() ){
297 if( rect )
298 drawRect = *rect;
299 else if( !painterToDrawRect( painter, drawRect ) ){
300 tqDebug("ERROR: KDChart::paint() could not calculate a drawing area.");
301 bOk = false;
302 }
303 //tqDebug("xxx" );
304 if( (params || data) && !setupGeometry( painter, params, data, drawRect ) ){
305 tqDebug("ERROR: KDChart::paint() could not calculate the chart geometry.");
306 bOk = false;
307 }
308 }else{
309 drawRect = cpainter->outermostRect();
310 }
311
312 //tqDebug("yyy" );
313
314 if( bOk ){
315 // Note: the following *must* paint the main-chart first
316 // and the additional chart afterwards
317 // since all axes computations are only done when
318 // the first chart is painted but will be needed for both of course.
319 //
320 bool paintFirst = true;
321 bool paintLast = ! ( cpainter && cpainter2 );
322 if ( cpainter ) { // can be 0 if no exceptions are used
323 //tqDebug("zzz" );
324 cpainter->paint( painter, data, paintFirst, paintLast, regions, &drawRect, false );
325
326 paintFirst = false;
327 }
328 paintLast = true;
329 if ( cpainter2 ) // can be 0 if no exceptions are used
330 cpainter2->paint( painter, data, paintFirst, paintLast, regions, &drawRect, false );
331 }
332
333 if( !paraParams && !paraData ){
334 delete params;
335 delete data;
336 }
337 KDChartAutoColor::freeInstance(); // stuff that memory leak
338}
339
340
354void KDChart::print( TQPainter* painter, KDChartParams* params,
356 KDChartDataRegionList* regions,
357 const TQRect* rect,
358 bool mustCalculateGeometry )
359{
360 bool oldOpt=true;
361 if( params ){
362 oldOpt = params->optimizeOutputForScreen();
363 params->setOptimizeOutputForScreen( false );
364 }
365 paint( painter, params, data, regions, rect, mustCalculateGeometry );
366 if( params )
367 params->setOptimizeOutputForScreen( oldOpt );
368}
369
370
371/*
372 This method is called at application shut-down and cleans up the
373 last created painter.
374 */
376{
377 delete KDChart::cpainter;
378 delete KDChart::cpainter2;
379 KDChart::oldParams = 0;
380}
381
382#ifdef TQSA
383void KDChart::initInterpreter( TQSInterpreter* interpreter )
384{
385 privateInitInterpreter( interpreter );
386 interpreter->evaluate( globals() );
387}
388
389void KDChart::initProject( TQSProject* project )
390{
391 project->createScript( TQString::fromLatin1( "KDCHART_Globals" ), globals() );
392 privateInitInterpreter( project->interpreter() );
393}
394
395TQString KDChart::globals()
396{
397 TQString globals;
398 TQMap<char*, double> intMap;
399
400 intMap.insert( "KDCHART_POS_INFINITE", KDCHART_POS_INFINITE );
401 intMap.insert( "KDCHART_NEG_INFINITE", KDCHART_NEG_INFINITE );
402 intMap.insert( "KDCHART_AlignAuto", KDCHART_AlignAuto );
403 intMap.insert( "KDCHART_ALL_AXES", KDCHART_ALL_AXES );
404 intMap.insert( "KDCHART_NO_AXIS", KDCHART_NO_AXIS );
405 intMap.insert( "KDCHART_ALL_DATASETS", KDCHART_ALL_DATASETS );
406 intMap.insert( "KDCHART_NO_DATASET", KDCHART_NO_DATASET );
407 intMap.insert( "KDCHART_UNKNOWN_CHART", KDCHART_UNKNOWN_CHART );
408 intMap.insert( "KDCHART_ALL_CHARTS", KDCHART_ALL_CHARTS );
409 intMap.insert( "KDCHART_NO_CHART", KDCHART_NO_CHART );
410 intMap.insert( "KDCHART_GLOBAL_LINE_STYLE", KDCHART_GLOBAL_LINE_STYLE );
411 intMap.insert( "KDCHART_AUTO_SIZE", KDCHART_AUTO_SIZE );
412 intMap.insert( "KDCHART_DATA_VALUE_AUTO_DIGITS", KDCHART_DATA_VALUE_AUTO_DIGITS );
413 intMap.insert( "KDCHART_SAGITTAL_ROTATION", KDCHART_SAGITTAL_ROTATION );
414 intMap.insert( "KDCHART_TANGENTIAL_ROTATION", KDCHART_TANGENTIAL_ROTATION );
415 intMap.insert( "KDCHART_PROPSET_NORMAL_DATA", KDCHART_PROPSET_NORMAL_DATA );
416 intMap.insert( "KDCHART_PROPSET_TRANSPARENT_DATA", KDCHART_PROPSET_TRANSPARENT_DATA );
417 intMap.insert( "KDCHART_PROPSET_HORI_LINE", KDCHART_PROPSET_HORI_LINE );
418 intMap.insert( "KDCHART_PROPSET_VERT_LINE", KDCHART_PROPSET_VERT_LINE );
419 intMap.insert( "KDCHART_SAGGITAL_ROTATION", KDCHART_SAGGITAL_ROTATION );
420 intMap.insert( "KDCHART_CNT_ORDINATES", KDCHART_CNT_ORDINATES );
421 intMap.insert( "KDCHART_MAX_POLAR_DELIMS_AND_LABELS_POS", KDCHART_MAX_POLAR_DELIMS_AND_LABELS_POS );
422 intMap.insert( "KDCHART_MAX_AXES", KDCHART_MAX_AXES );
423 intMap.insert( "KDCHART_AXIS_LABELS_AUTO_DELTA", KDCHART_AXIS_LABELS_AUTO_DELTA );
424 intMap.insert( "KDCHART_AXIS_LABELS_AUTO_LEAVEOUT", KDCHART_AXIS_LABELS_AUTO_LEAVEOUT );
425 intMap.insert( "KDCHART_AXIS_LABELS_AUTO_DIGITS", KDCHART_AXIS_LABELS_AUTO_DIGITS );
426 intMap.insert( "KDCHART_AXIS_GRID_AUTO_LINEWIDTH", KDCHART_AXIS_GRID_AUTO_LINEWIDTH );
427 intMap.insert( "KDCHART_AXIS_IGNORE_EMPTY_INNER_SPAN", KDCHART_AXIS_IGNORE_EMPTY_INNER_SPAN );
428 intMap.insert( "KDCHART_DONT_CHANGE_EMPTY_INNER_SPAN_NOW", KDCHART_DONT_CHANGE_EMPTY_INNER_SPAN_NOW );
429 intMap.insert( "DBL_MIN", DBL_MIN );
430 intMap.insert( "DBL_MAX", DBL_MAX );
431
432 for( TQMapIterator<char*,double> it= intMap.begin(); it != intMap.end(); ++it ) {
433 // This is written this way to be efficient
434 globals += TQString::fromLatin1( "const " );
435 globals += it.key();
436 globals += " = ";
437 globals += TQString::number( it.data() );
438 globals += ";\n";
439 }
440
441 globals += TQString::fromLatin1( "const KDCHART_AXIS_LABELS_AUTO_DATETIME_FORMAT=\"%1\";\n" )
442 .arg( TQString::fromLatin1( KDCHART_AXIS_LABELS_AUTO_DATETIME_FORMAT ) );
443 globals += TQString::fromLatin1( "const KDCHART_AXIS_LABELS_AUTO_LIMIT = 140319.64;\n" );
444 globals += TQString::fromLatin1( "const KDCHART_DEFAULT_AXIS_GRID_COLOR = new Color(\"%1\");\n" )
446 globals += TQString::fromLatin1( "const KDCHART_DATA_VALUE_AUTO_COLOR = new Color(\"%1\");\n" )
447 .arg( (KDCHART_DATA_VALUE_AUTO_COLOR)->name());
448
449
450 TQMap<char*,TQColor> colorMap;
451 colorMap.insert( "TQt.color0", TQt::color0 );
452 colorMap.insert( "TQt.color1", TQt::color1 );
453 colorMap.insert( "TQt.black", TQt::black );
454 colorMap.insert( "TQt.white", TQt::white );
455 colorMap.insert( "TQt.darkGray", TQt::darkGray );
456 colorMap.insert( "TQt.gray", TQt::gray );
457 colorMap.insert( "TQt.lightGray", TQt::lightGray );
458 colorMap.insert( "TQt.red", TQt::red );
459 colorMap.insert( "TQt.green", TQt::green );
460 colorMap.insert( "TQt.blue", TQt::blue );
461 colorMap.insert( "TQt.cyan", TQt::cyan );
462 colorMap.insert( "TQt.magenta", TQt::magenta );
463 colorMap.insert( "TQt.yellow", TQt::yellow );
464 colorMap.insert( "TQt.darkRed", TQt::darkRed );
465 colorMap.insert( "TQt.darkGreen", TQt::darkGreen );
466 colorMap.insert( "TQt.darkBlue", TQt::darkBlue );
467 colorMap.insert( "TQt.darkCyan", TQt::darkCyan );
468 colorMap.insert( "TQt.darkMagenta", TQt::darkMagenta );
469 colorMap.insert( "TQt.darkYellow", TQt::darkYellow );
470 for( TQMapIterator<char*,TQColor> it2= colorMap.begin(); it2 != colorMap.end(); ++it2 ) {
471 // This is written this way to be efficient
472 globals += TQString::fromLatin1( it2.key() );
473 globals += TQString::fromLatin1( " = new Color( " );
474 globals += TQString::number( it2.data().red() );
475 globals += ',';
476 globals += TQString::number( it2.data().green() );
477 globals += ',';
478 globals += TQString::number( it2.data().blue() );
479 globals += TQString::fromLatin1( " );\n" );
480 }
481 //tqDebug( "%s",globals.latin1() );
482 return globals;
483}
484
485void KDChart::privateInitInterpreter( TQSInterpreter* interpreter )
486{
487 interpreter->addWrapperFactory( new KDChartWrapperFactory );
488 interpreter->addObjectFactory ( new KDChartObjectFactory );
489}
490
491#endif
Provide access to the chart axis parameters.
#define KDCHART_DEFAULT_AXIS_GRID_COLOR
Use this to reset the grid colour to its default value for re-doing changes made by calling setAxisGr...
#define KDCHART_AXIS_LABELS_AUTO_DELTA
Use this to specify that the step-width from one label to the other shall be calculated automatically...
#define KDCHART_AXIS_GRID_AUTO_LINEWIDTH
Use this to specify that the width of the axis grid lines shall be equal to the width of the axis lin...
#define KDCHART_AXIS_LABELS_AUTO_DATETIME_FORMAT
Use this to specify that date/time format to be used for displaying the axis labels is to be determin...
#define KDCHART_DONT_CHANGE_EMPTY_INNER_SPAN_NOW
Use this to prevent setAxisValues from changing the current setting of _axisMaxEmptyInnerSpan.
#define KDCHART_AXIS_IGNORE_EMPTY_INNER_SPAN
Use this to specify that the zero-line shall NOT be omitted in case all of the data are grouped far a...
#define KDCHART_AXIS_LABELS_AUTO_LEAVEOUT
Use this to specify that an automatically computed amount of axis labels are to be skipped if there i...
#define KDCHART_AXIS_LABELS_AUTO_DIGITS
Use this to specify that the number of digits to be shown on the axis labels behind the comma is to b...
Header for all common chart parameters.
#define KDCHART_PROPSET_VERT_LINE
Predefined (build-in) property ID.
#define KDCHART_PROPSET_NORMAL_DATA
Default (built-in) property ID, used for data cells without any special properties.
#define KDCHART_PROPSET_HORI_LINE
Predefined (build-in) property ID.
#define KDCHART_CNT_ORDINATES
Our charts may have up to 4 ordinate axes: 2 left ones and 2 right ones.
#define KDCHART_PROPSET_TRANSPARENT_DATA
Predefined (build-in) property ID.
#define KDCHART_MAX_AXES
Charts have up to 12 axes: up to two axes on both sides for X, Y and Z (if data is 3-dimensional).
#define KDCHART_NEG_INFINITE
Use special value KDCHART_NEG_INFINITE to indicate negative infinite values.
#define KDCHART_POS_INFINITE
Use special value KDCHART_POS_INFINITE to indicate positive infinite values.
Definition of a single entry-point to the charting engine for applications that wish to provide their...
The collection class used by KD Chart to store data region information.
An abstract base class that defines an interface for classes that implement chart drawing.
static KDChartPainter * create(KDChartParams *params, bool make2nd=false)
Creates an object of a concrete subclass of KDChartPainter that KDChart::paint() (and consequently,...
Bundles the display parameters of a chart.
void setOptimizeOutputForScreen(bool screenOutput)
Specify whether drawing should be optimized for (low resolution) screen output or whether other routi...
ChartType additionalChartType() const
Returns the additional chart type configured in this params object.
void setLegendPosition(LegendPosition position)
Specifies where the legend should be shown.
void setHeader1Text(const TQString &text)
Specifies the text to be displayed as the first header line.
void setDatasetGap(int gap)
Specifies the number of pixels between two dataset values.
int valueBlockGap() const
Returns the number of pixels between each value block.
ChartType
The chart type.
bool optimizeOutputForScreen() const
Returns whether drawing is optimized for (low resolution) screen output (this is the default) or whet...
void setAxisLabelsVisible(uint n, bool axisLabelsVisible)
Specifies whether the axis labels of an axis are to be shown.
void setPrintDataValues(bool active, uint chart=KDCHART_ALL_CHARTS, int divPow10=0, int digitsBehindComma=KDCHART_DATA_VALUE_AUTO_DIGITS, TQFont *font=0, uint size=UINT_MAX, const TQColor *color=KDCHART_DATA_VALUE_AUTO_COLOR, KDChartEnums::PositionFlag negativePosition=KDChartEnums::PosCenter, uint negativeAlign=TQt::AlignCenter, int negativeDeltaX=0, int negativeDeltaY=0, int negativeRotation=0, KDChartEnums::PositionFlag positivePosition=KDChartEnums::PosCenter, uint positiveAlign=TQt::AlignCenter, int positiveDeltaX=0, int positiveDeltaY=0, int positiveRotation=0, KDChartEnums::TextLayoutPolicy policy=KDChartEnums::LayoutPolicyRotate)
Specifies if and how a chart will print the data value texts near their respective entries.
void setAxisShowGrid(uint n, bool axisShowGrid)
Specifies whether a grid should be drawn at the chart data area.
ChartType chartType() const
Returns the chart type configured in this params object.
KD Chart's build-in table data for an easy way of storing data values.
virtual void setCell(uint _row, uint _col, const TQVariant &_value1, const TQVariant &_value2=TQVariant())=0
Stores data in a cell.
friend void cleanupPainter()
A global function that cleans up possible KDChartPainter objects at application shutdown.
Definition KDChart.cpp:375
static bool setupGeometry(TQPainter *painter, KDChartParams *params, KDChartTableDataBase *data, const TQRect &drawRect)
Calculates the axis and data area rects of a chart with the specified parameters on the specified pai...
Definition KDChart.cpp:156
static bool painterToDrawRect(TQPainter *painter, TQRect &drawRect)
Calculates the drawing area from a given TQPainter.
Definition KDChart.cpp:122
static void paint(TQPainter *, KDChartParams *, KDChartTableDataBase *, KDChartDataRegionList *regions=0, const TQRect *rect=0, bool mustCalculateGeometry=true)
Paints a chart with the specified parameters on the specified painter.
Definition KDChart.cpp:256
static void print(TQPainter *, KDChartParams *, KDChartTableDataBase *, KDChartDataRegionList *regions=0, const TQRect *rect=0, bool mustCalculateGeometry=true)
Paints a chart with the specified parameters on the specified painter which should use a TQPrinter as...
Definition KDChart.cpp:354