23 #include "KDChartStockDiagram_p.h" 25 #include "KDChartPainterSaver_p.h" 30 class StockDiagram::Private::ThreeDPainter
33 struct ThreeDProperties {
39 ThreeDPainter( QPainter *p )
42 QPolygonF drawTwoDLine(
const QLineF &line,
const QPen &
pen,
43 const ThreeDProperties &props );
44 QPolygonF drawThreeDLine(
const QLineF &line,
const QBrush &
brush,
45 const QPen &
pen,
const ThreeDProperties &props );
46 QPolygonF drawThreeDRect(
const QRectF &rect,
const QBrush &
brush,
47 const QPen &
pen,
const ThreeDProperties &props );
50 QPointF projectPoint(
const QPointF &point, qreal depth, qreal angle )
const;
51 QColor calcShadowColor(
const QColor &color, qreal angle )
const;
62 QPointF StockDiagram::Private::ThreeDPainter::projectPoint(
const QPointF &point, qreal depth, qreal angle )
const 64 const qreal angleInRad = DEGTORAD( angle );
65 const qreal distX = depth * cos( angleInRad );
67 const qreal distY = depth * -sin( angleInRad );
69 return QPointF( point.x() + distX, point.y() + distY );
78 QColor StockDiagram::Private::ThreeDPainter::calcShadowColor(
const QColor &color, qreal angle )
const 83 const qreal shadowFactor = 0.5;
84 const qreal sinAngle = 1.0 - qAbs( sin( DEGTORAD( angle ) ) ) * shadowFactor;
85 return QColor( qRound( color.red() * sinAngle ),
86 qRound( color.green() * sinAngle ),
87 qRound( color.blue() * sinAngle ) );
98 QPolygonF StockDiagram::Private::ThreeDPainter::drawTwoDLine(
const QLineF &line,
const QPen &
pen,
99 const ThreeDProperties &props )
102 PainterSaver painterSaver( painter );
105 const qreal z = props.depth / 2.0;
108 const QPointF deepP1 = projectPoint( line.p1(), z, props.angle );
109 const QPointF deepP2 = projectPoint( line.p2(), z, props.angle );
112 QPolygonF threeDArea;
114 const QPointF offset( 0.0, 1.0 );
115 threeDArea << deepP1 - offset << deepP2 - offset
116 << deepP1 + offset << deepP2 + offset << deepP1 - offset;
118 painter->setPen( pen );
119 painter->drawLine( QLineF( deepP1, deepP2 ) );
133 QPolygonF StockDiagram::Private::ThreeDPainter::drawThreeDLine(
const QLineF &line,
const QBrush &
brush,
134 const QPen &pen,
const ThreeDProperties &props )
137 PainterSaver painterSaver( painter );
139 const QPointF p1 = line.p1();
140 const QPointF p2 = line.p2();
143 const QPointF deepP1 = projectPoint( p1, props.depth, props.angle );
144 const QPointF deepP2 = projectPoint( p2, props.depth, props.angle );
147 QPolygonF threeDArea;
148 threeDArea << p1 << p2 << deepP2 << deepP1 << p1;
152 if ( props.useShadowColors ) {
153 QBrush shadowBrush( brush );
154 QPen shadowPen( pen );
155 shadowBrush.setColor( calcShadowColor( brush.color(), props.angle ) );
156 shadowPen.setColor( calcShadowColor( pen.color(), props.angle ) );
157 painter->setBrush( shadowBrush );
158 painter->setPen( shadowPen );
160 painter->setBrush( brush );
161 painter->setPen( pen );
164 painter->drawPolygon( threeDArea );
178 QPolygonF StockDiagram::Private::ThreeDPainter::drawThreeDRect(
const QRectF &rect,
const QBrush &brush,
179 const QPen &pen,
const ThreeDProperties &props )
182 PainterSaver painterSaver( painter );
185 const QRectF normalizedRect = rect.normalized();
188 const QLineF topSide = QLineF( normalizedRect.topLeft(), normalizedRect.topRight() );
189 const QLineF bottomSide = QLineF( normalizedRect.bottomLeft(), normalizedRect.bottomRight() );
190 const QLineF leftSide = QLineF( normalizedRect.topLeft(), normalizedRect.bottomLeft() );
191 const QLineF rightSide = QLineF( normalizedRect.topRight(), normalizedRect.bottomRight() );
193 QPolygonF drawnPolygon;
196 const qreal angle = props.angle;
199 if ( angle >= 0.0 && angle < 90.0 ) {
200 drawnPolygon = drawnPolygon.united( drawThreeDLine( topSide, brush, pen, props ) );
201 drawnPolygon = drawnPolygon.united( drawThreeDLine( rightSide, brush, pen, props ) );
203 }
else if ( angle >= 90.0 && angle < 180.0 ) {
204 drawnPolygon = drawnPolygon.united( drawThreeDLine( topSide, brush, pen, props ) );
205 drawnPolygon = drawnPolygon.united( drawThreeDLine( leftSide, brush, pen, props ) );
207 }
else if ( angle >= 180.0 && angle < 270.0 ) {
208 drawnPolygon = drawnPolygon.united( drawThreeDLine( bottomSide, brush, pen, props ) );
209 drawnPolygon = drawnPolygon.united( drawThreeDLine( leftSide, brush, pen, props ) );
211 }
else if ( angle >= 270.0 && angle <= 360.0 ) {
212 drawnPolygon = drawnPolygon.united( drawThreeDLine( bottomSide, brush, pen, props ) );
213 drawnPolygon = drawnPolygon.united( drawThreeDLine( rightSide, brush, pen, props ) );
217 painter->setPen( pen );
218 painter->setBrush( brush );
219 painter->drawRect( normalizedRect );
225 StockDiagram::Private::Private()
230 StockDiagram::Private::Private(
const Private& r )
235 StockDiagram::Private::~Private()
246 QPointF StockDiagram::Private::projectPoint(
PaintContext *context,
const QPointF &point )
const 257 QRectF StockDiagram::Private::projectCandlestick(
PaintContext *context,
const QPointF &open,
const QPointF &close, qreal width )
const 259 const QPointF leftHighPoint = context->
coordinatePlane()->
translate( QPointF( close.x() + 0.5 - width / 2.0, close.y() ) );
260 const QPointF rightLowPoint = context->
coordinatePlane()->
translate( QPointF( open.x() + 0.5 + width / 2.0, open.y() ) );
261 const QPointF rightHighPoint = context->
coordinatePlane()->
translate( QPointF( close.x() + 0.5 + width / 2.0, close.y() ) );
263 return QRectF( leftHighPoint, QSizeF( rightHighPoint.x() - leftHighPoint.x(),
264 rightLowPoint.y() - leftHighPoint.y() ) );
267 void StockDiagram::Private::drawOHLCBar(
int dataset,
const CartesianDiagramDataCompressor::DataPoint &open,
268 const CartesianDiagramDataCompressor::DataPoint &high,
269 const CartesianDiagramDataCompressor::DataPoint &low,
270 const CartesianDiagramDataCompressor::DataPoint &close,
274 const int col = low.index.row();
280 const QPointF leftOpenPoint( open.key + 0.5 - tickLength, open.value );
281 const QPointF rightOpenPoint( open.key + 0.5, open.value );
282 const QPointF highPoint( high.key + 0.5, high.value );
283 const QPointF lowPoint( low.key + 0.5, low.value );
284 const QPointF leftClosePoint( close.key + 0.5, close.value );
285 const QPointF rightClosePoint( close.key + 0.5 + tickLength, close.value );
287 bool reversedOrder =
false;
290 const int angle = threeDAttr.
angle();
292 if ( ( angle >= 0 && angle < 90 ) || ( angle >= 180 && angle < 270 ) )
293 reversedOrder =
true;
295 if ( ( angle >= 90 && angle < 180 ) || ( angle >= 270 && angle <= 360 ) )
296 reversedOrder =
false;
299 if ( reversedOrder ) {
301 drawLine( dataset, col, leftOpenPoint, rightOpenPoint, context );
302 if ( !low.hidden && !high.hidden )
303 drawLine( dataset, col, lowPoint, highPoint, context );
305 drawLine( dataset, col, leftClosePoint, rightClosePoint, context );
308 drawLine( dataset, col, leftClosePoint, rightClosePoint, context );
309 if ( !low.hidden && !high.hidden )
310 drawLine( dataset, col, lowPoint, highPoint, context );
312 drawLine( dataset, col, leftOpenPoint, rightOpenPoint, context );
316 if ( !open.hidden ) {
317 addLabel( &lpc, diagram->attributesModel()->mapToSource( open.index ), 0,
320 if ( !high.hidden ) {
321 addLabel( &lpc, diagram->attributesModel()->mapToSource( high.index ), 0,
325 addLabel( &lpc, diagram->attributesModel()->mapToSource( low.index ), 0,
328 if ( !close.hidden ) {
329 addLabel( &lpc, diagram->attributesModel()->mapToSource( close.index ), 0,
332 paintDataValueTextsAndMarkers( context, lpc,
false );
342 void StockDiagram::Private::drawCandlestick(
int ,
const CartesianDiagramDataCompressor::DataPoint &open,
343 const CartesianDiagramDataCompressor::DataPoint &high,
344 const CartesianDiagramDataCompressor::DataPoint &low,
345 const CartesianDiagramDataCompressor::DataPoint &close,
348 PainterSaver painterSaver( context->
painter() );
351 const int row = low.index.row();
352 const int col = low.index.column();
354 QPointF bottomCandlestickPoint;
355 QPointF topCandlestickPoint;
359 bool drawCandlestick = !open.hidden && !close.hidden;
365 if ( open.value <= close.value ) {
366 pen = stockDiagram()->upTrendCandlestickPen( row );
367 brush = stockDiagram()->upTrendCandlestickBrush( row );
368 bottomCandlestickPoint = QPointF( open.key, open.value );
369 topCandlestickPoint = QPointF( close.key, close.value );
370 drawLowerLine = !low.hidden && !open.hidden;
371 drawUpperLine = !low.hidden && !close.hidden;
373 pen = stockDiagram()->downTrendCandlestickPen( row );
374 brush = stockDiagram()->downTrendCandlestickBrush( row );
375 bottomCandlestickPoint = QPointF( close.key, close.value );
376 topCandlestickPoint = QPointF( open.key, open.value );
377 drawLowerLine = !low.hidden && !close.hidden;
378 drawUpperLine = !low.hidden && !open.hidden;
384 const QPointF lowPoint = projectPoint( context, QPointF( low.key, low.value ) );
385 const QPointF highPoint = projectPoint( context, QPointF( high.key, high.value ) );
386 const QLineF lowerLine = QLineF( lowPoint, projectPoint( context, bottomCandlestickPoint ) );
387 const QLineF upperLine = QLineF( projectPoint( context, topCandlestickPoint ), highPoint );
390 QRectF candlestick = projectCandlestick( context, bottomCandlestickPoint,
394 QPolygonF drawnPolygon;
398 ThreeDPainter threeDPainter( context->
painter() );
400 ThreeDPainter::ThreeDProperties threeDProps;
401 threeDProps.depth = threeDAttr.
depth();
402 threeDProps.angle = threeDAttr.
angle();
407 if ( threeDProps.angle > 0.0 && threeDProps.angle < 180.0 ) {
409 drawnPolygon = threeDPainter.drawTwoDLine( lowerLine, pen, threeDProps );
410 if ( drawCandlestick )
411 drawnPolygon = threeDPainter.drawThreeDRect( candlestick, brush, pen, threeDProps );
413 drawnPolygon = threeDPainter.drawTwoDLine( upperLine, pen, threeDProps );
416 drawnPolygon = threeDPainter.drawTwoDLine( upperLine, pen, threeDProps );
417 if ( drawCandlestick )
418 drawnPolygon = threeDPainter.drawThreeDRect( candlestick, brush, pen, threeDProps );
420 drawnPolygon = threeDPainter.drawTwoDLine( lowerLine, pen, threeDProps );
423 QPainter *
const painter = context->
painter();
424 painter->setBrush( brush );
425 painter->setPen( pen );
427 painter->drawLine( lowerLine );
429 painter->drawLine( upperLine );
430 if ( drawCandlestick )
431 painter->drawRect( candlestick );
434 drawnPolygon = candlestick;
441 addLabel( &lpc, diagram->attributesModel()->mapToSource( low.index ), 0,
443 if ( drawCandlestick ) {
445 reverseMapper.addPolygon( row, openValueColumn(), drawnPolygon );
446 reverseMapper.addPolygon( row, closeValueColumn(), drawnPolygon );
448 addLabel( &lpc, diagram->attributesModel()->mapToSource( open.index ), 0,
449 PositionPoints( candlestick.bottomRight() ), Position::South, Position::South, open.value );
450 addLabel( &lpc, diagram->attributesModel()->mapToSource( close.index ), 0,
451 PositionPoints( candlestick.topRight() ), Position::South, Position::South, close.value );
454 addLabel( &lpc, diagram->attributesModel()->mapToSource( high.index ), 0,
457 paintDataValueTextsAndMarkers( context, lpc,
false );
468 void StockDiagram::Private::drawLine(
int dataset,
int col,
const QPointF &point1,
const QPointF &point2,
PaintContext *context )
470 PainterSaver painterSaver( context->
painter() );
473 const int modelRow = col;
474 const int modelCol = 0;
476 const QPen pen = diagram->pen( dataset );
477 const QBrush brush = diagram->brush( dataset );
482 QLineF line = QLineF( transP1, transP2 );
485 ThreeDPainter::ThreeDProperties threeDProps;
486 threeDProps.angle = threeDBarAttr.
angle();
487 threeDProps.depth = threeDBarAttr.
depth();
490 ThreeDPainter painter( context->
painter() );
491 reverseMapper.addPolygon( modelCol, modelRow, painter.drawThreeDLine( line, brush, pen, threeDProps ) );
493 context->
painter()->setPen( pen );
495 reverseMapper.addLine( modelCol, modelRow, transP1, transP2 );
496 context->
painter()->drawLine( line );
505 int StockDiagram::Private::openValueColumn()
const 516 int StockDiagram::Private::highValueColumn()
const 526 int StockDiagram::Private::lowValueColumn()
const 536 int StockDiagram::Private::closeValueColumn()
const KDChartEnums::PositionValue value() const
Returns an integer value corresponding to this Position.
virtual const QPointF translate(const QPointF &diagramPoint) const =0
Translate the given point in value space coordinates to a position in pixel space.
AbstractCoordinatePlane * coordinatePlane() const
static const Position & South
QPainter * painter() const
qreal candlestickWidth() const
QBrush brush() const
Retrieve the brush to be used for painting datapoints globally.
bool useShadowColors() const
Base class for diagrams based on a cartesian coordianate system.
Stores information about painting diagrams.
A set of 3D bar attributes.
Stores the absolute target points of a Position.
QPen pen() const
Retrieve the pen to be used for painting datapoints globally.
Attributes to customize the appearance of a column in a stock chart.