stock_arrow.dart 2.65 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6 7
import 'dart:math' as math;

import 'package:flutter/material.dart';
8

9
class StockArrowPainter extends CustomPainter {
10 11 12 13
  StockArrowPainter({
    required this.color,
    required this.percentChange,
  });
14 15 16 17

  final Color color;
  final double percentChange;

18
  @override
Adam Barth's avatar
Adam Barth committed
19
  void paint(Canvas canvas, Size size) {
20
    final Paint paint = Paint()..color = color;
21 22 23
    paint.strokeWidth = 1.0;
    const double padding = 2.0;
    assert(padding > paint.strokeWidth / 2.0); // make sure the circle remains inside the box
24 25 26
    final double r = (size.shortestSide - padding) / 2.0; // radius of the circle
    final double centerX = padding + r;
    final double centerY = padding + r;
27 28

    // Draw the arrow.
29
    const double w = 8.0;
30 31 32 33 34 35 36 37
    double h = 5.0;
    double arrowY;
    if (percentChange < 0.0) {
      h = -h;
      arrowY = centerX + 1.0;
    } else {
      arrowY = centerX - 1.0;
    }
38
    final Path path = Path();
39 40 41 42
    path.moveTo(centerX, arrowY - h); // top of the arrow
    path.lineTo(centerX + w, arrowY + h);
    path.lineTo(centerX - w, arrowY + h);
    path.close();
43
    paint.style = PaintingStyle.fill;
44 45 46
    canvas.drawPath(path, paint);

    // Draw a circle that circumscribes the arrow.
47
    paint.style = PaintingStyle.stroke;
48
    canvas.drawCircle(Offset(centerX, centerY), r, paint);
49 50
  }

51
  @override
52 53 54
  bool shouldRepaint(StockArrowPainter oldDelegate) {
    return oldDelegate.color != color
        || oldDelegate.percentChange != percentChange;
55 56 57
  }
}

58
class StockArrow extends StatelessWidget {
59
  const StockArrow({ Key? key, required this.percentChange }) : super(key: key);
60 61 62 63

  final double percentChange;

  int _colorIndexForPercentChange(double percentChange) {
64
    const double maxPercent = 10.0;
65
    final double normalizedPercentChange = math.min(percentChange.abs(), maxPercent) / maxPercent;
66 67 68 69 70
    return 100 + (normalizedPercentChange * 8.0).floor() * 100;
  }

  Color _colorForPercentChange(double percentChange) {
    if (percentChange > 0)
71 72
      return Colors.green[_colorIndexForPercentChange(percentChange)]!;
    return Colors.red[_colorIndexForPercentChange(percentChange)]!;
73 74
  }

75
  @override
76
  Widget build(BuildContext context) {
77
    return Container(
78 79
      width: 40.0,
      height: 40.0,
80
      margin: const EdgeInsets.symmetric(horizontal: 5.0),
81 82
      child: CustomPaint(
        painter: StockArrowPainter(
83 84
          // TODO(jackson): This should change colors with the theme
          color: _colorForPercentChange(percentChange),
85 86 87
          percentChange: percentChange,
        ),
      ),
88 89 90
    );
  }
}