diff options
Diffstat (limited to 'examples/chart/chartform_canvas.cpp')
-rw-r--r-- | examples/chart/chartform_canvas.cpp | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/examples/chart/chartform_canvas.cpp b/examples/chart/chartform_canvas.cpp new file mode 100644 index 000000000..842c04e6f --- /dev/null +++ b/examples/chart/chartform_canvas.cpp @@ -0,0 +1,226 @@ +#include "canvastext.h" +#include "chartform.h" + +#include <qbrush.h> +#include <qcanvas.h> + +#include <math.h> // sin, cos + +#ifndef M_PI +#define M_PI 3.1415 +#endif + +void ChartForm::drawElements() +{ + TQCanvasItemList list = m_canvas->allItems(); + for ( TQCanvasItemList::iterator it = list.begin(); it != list.end(); ++it ) + delete *it; + + // 360 * 16 for pies; TQt works with 16ths of degrees + int scaleFactor = m_chartType == PIE ? 5760 : + m_chartType == VERTICAL_BAR ? m_canvas->height() : + m_canvas->width(); + double biggest = 0.0; + int count = 0; + double total = 0.0; + static double scales[MAX_ELEMENTS]; + + for ( int i = 0; i < MAX_ELEMENTS; ++i ) { + if ( m_elements[i].isValid() ) { + double value = m_elements[i].value(); + count++; + total += value; + if ( value > biggest ) + biggest = value; + scales[i] = m_elements[i].value() * scaleFactor; + } + } + + if ( count ) { + // 2nd loop because of total and biggest + for ( int i = 0; i < MAX_ELEMENTS; ++i ) + if ( m_elements[i].isValid() ) + if ( m_chartType == PIE ) + scales[i] = (m_elements[i].value() * scaleFactor) / total; + else + scales[i] = (m_elements[i].value() * scaleFactor) / biggest; + + switch ( m_chartType ) { + case PIE: + drawPieChart( scales, total, count ); + break; + case VERTICAL_BAR: + drawVerticalBarChart( scales, total, count ); + break; + case HORIZONTAL_BAR: + drawHorizontalBarChart( scales, total, count ); + break; + } + } + + m_canvas->update(); +} + + +void ChartForm::drawPieChart( const double scales[], double total, int ) +{ + double width = m_canvas->width(); + double height = m_canvas->height(); + int size = int(width > height ? height : width); + int x = int(width / 2); + int y = int(height / 2); + int angle = 0; + + for ( int i = 0; i < MAX_ELEMENTS; ++i ) { + if ( m_elements[i].isValid() ) { + int extent = int(scales[i]); + TQCanvasEllipse *arc = new TQCanvasEllipse( + size, size, angle, extent, m_canvas ); + arc->setX( x ); + arc->setY( y ); + arc->setZ( 0 ); + arc->setBrush( TQBrush( m_elements[i].valueColor(), + BrushStyle(m_elements[i].valuePattern()) ) ); + arc->show(); + angle += extent; + TQString label = m_elements[i].label(); + if ( !label.isEmpty() || m_addValues != NO ) { + label = valueLabel( label, m_elements[i].value(), total ); + CanvasText *text = new CanvasText( i, label, m_font, m_canvas ); + double proX = m_elements[i].proX( PIE ); + double proY = m_elements[i].proY( PIE ); + if ( proX < 0 || proY < 0 ) { + // Find the centre of the pie segment + TQRect rect = arc->boundingRect(); + proX = ( rect.width() / 2 ) + rect.x(); + proY = ( rect.height() / 2 ) + rect.y(); + // Centre text over the centre of the pie segment + rect = text->boundingRect(); + proX -= ( rect.width() / 2 ); + proY -= ( rect.height() / 2 ); + // Make proportional + proX /= width; + proY /= height; + } + text->setColor( m_elements[i].labelColor() ); + text->setX( proX * width ); + text->setY( proY * height ); + text->setZ( 1 ); + text->show(); + m_elements[i].setProX( PIE, proX ); + m_elements[i].setProY( PIE, proY ); + } + } + } +} + + +void ChartForm::drawVerticalBarChart( + const double scales[], double total, int count ) +{ + double width = m_canvas->width(); + double height = m_canvas->height(); + int prowidth = int(width / count); + int x = 0; + TQPen pen; + pen.setStyle( NoPen ); + + for ( int i = 0; i < MAX_ELEMENTS; ++i ) { + if ( m_elements[i].isValid() ) { + int extent = int(scales[i]); + int y = int(height - extent); + TQCanvasRectangle *rect = new TQCanvasRectangle( + x, y, prowidth, extent, m_canvas ); + rect->setBrush( TQBrush( m_elements[i].valueColor(), + BrushStyle(m_elements[i].valuePattern()) ) ); + rect->setPen( pen ); + rect->setZ( 0 ); + rect->show(); + TQString label = m_elements[i].label(); + if ( !label.isEmpty() || m_addValues != NO ) { + double proX = m_elements[i].proX( VERTICAL_BAR ); + double proY = m_elements[i].proY( VERTICAL_BAR ); + if ( proX < 0 || proY < 0 ) { + proX = x / width; + proY = y / height; + } + label = valueLabel( label, m_elements[i].value(), total ); + CanvasText *text = new CanvasText( i, label, m_font, m_canvas ); + text->setColor( m_elements[i].labelColor() ); + text->setX( proX * width ); + text->setY( proY * height ); + text->setZ( 1 ); + text->show(); + m_elements[i].setProX( VERTICAL_BAR, proX ); + m_elements[i].setProY( VERTICAL_BAR, proY ); + } + x += prowidth; + } + } +} + + +void ChartForm::drawHorizontalBarChart( + const double scales[], double total, int count ) +{ + double width = m_canvas->width(); + double height = m_canvas->height(); + int proheight = int(height / count); + int y = 0; + TQPen pen; + pen.setStyle( NoPen ); + + for ( int i = 0; i < MAX_ELEMENTS; ++i ) { + if ( m_elements[i].isValid() ) { + int extent = int(scales[i]); + TQCanvasRectangle *rect = new TQCanvasRectangle( + 0, y, extent, proheight, m_canvas ); + rect->setBrush( TQBrush( m_elements[i].valueColor(), + BrushStyle(m_elements[i].valuePattern()) ) ); + rect->setPen( pen ); + rect->setZ( 0 ); + rect->show(); + TQString label = m_elements[i].label(); + if ( !label.isEmpty() || m_addValues != NO ) { + double proX = m_elements[i].proX( HORIZONTAL_BAR ); + double proY = m_elements[i].proY( HORIZONTAL_BAR ); + if ( proX < 0 || proY < 0 ) { + proX = 0; + proY = y / height; + } + label = valueLabel( label, m_elements[i].value(), total ); + CanvasText *text = new CanvasText( i, label, m_font, m_canvas ); + text->setColor( m_elements[i].labelColor() ); + text->setX( proX * width ); + text->setY( proY * height ); + text->setZ( 1 ); + text->show(); + m_elements[i].setProX( HORIZONTAL_BAR, proX ); + m_elements[i].setProY( HORIZONTAL_BAR, proY ); + } + y += proheight; + } + } +} + + +TQString ChartForm::valueLabel( + const TQString& label, double value, double total ) +{ + if ( m_addValues == NO ) + return label; + + TQString newLabel = label; + if ( !label.isEmpty() ) + if ( m_chartType == VERTICAL_BAR ) + newLabel += '\n'; + else + newLabel += ' '; + if ( m_addValues == YES ) + newLabel += TQString::number( value, 'f', m_decimalPlaces ); + else if ( m_addValues == AS_PERCENTAGE ) + newLabel += TQString::number( (value / total) * 100, 'f', m_decimalPlaces ) + + '%'; + return newLabel; +} + |