Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(461)

Unified Diff: runtime/bin/vmstats/bargraph.dart

Issue 12377099: Added support for "bin-ified" vmstats web app source files (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Made model data immutable Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/bin/vmstats/bargraph.dart
===================================================================
--- runtime/bin/vmstats/bargraph.dart (revision 0)
+++ runtime/bin/vmstats/bargraph.dart (revision 0)
@@ -0,0 +1,223 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart.vmstats;
+
+class BarGraph {
+ CanvasElement _canvas;
+ GraphModel _model;
+ List<Element> _elements;
+ double scaleHeight = 0;
+
+ static const int SAMPLE_WIDTH = 5;
+ static const int LEFT_MARGIN = 50;
+ static const int RIGHT_MARGIN = 150;
+ static const int LEGEND_WIDTH = 130;
+ static const int LEGEND_Y = 20;
+ static const int INSIDE_MARGIN = 2;
+
+ static const int NUM_DIVIDERS = 5;
+ static const String FONT = "14px sans-serif";
+
+ BarGraph(this._canvas, this._elements) {
+ var maxElements =
+ (_canvas.width - LEFT_MARGIN - RIGHT_MARGIN) ~/ SAMPLE_WIDTH;
+ _model = new GraphModel(maxElements);
+ _model.addListener(drawGraph, null);
+ drawBarGraph();
+ }
+
+ void addSample(List<int> segments) {
+ if (segments.length != _elements.length) {
+ throw new RuntimeError('invalid sample size for graph');
+ }
+ _model.addSample(segments);
+ }
+
+ void drawBarGraph() {
+ // Draw chart's outer box.
+ var context = _canvas.context2d;
+ context.beginPath();
+ context.strokeStyle = 'black';
+ // The '2's are the width of the line, even though 1 is specified.
+ context.strokeRect(
+ LEFT_MARGIN - 2, 1, _canvas.width - LEFT_MARGIN - RIGHT_MARGIN + 2,
+ _canvas.height - 2, 1);
+
+ // Draw legend.
+ var x = _canvas.width - LEGEND_WIDTH;
+ var y = LEGEND_Y;
+ context.font = FONT;
+ for (var i = 0; i < _elements.length; i++) {
+ context.fillStyle = _elements[i].color;
+ context.fillRect(x, y, 20, 20);
+ context.fillStyle = 'black';
+ context.fillText(_elements[i].name, x + 30, y + 15);
+ y += 30;
+ }
+ }
+
+ void drawGraph(var model) {
siva 2013/03/06 06:32:20 model parameter doesn't seem to have a type is it
Tom Ball 2013/03/06 17:47:17 Yes, updated.
+ var graphHeight = model.maxTotal;
+ var width = _canvas.clientWidth;
+ var height = _canvas.clientHeight;
+ if (graphHeight >= scaleHeight) {
+ // Make scale height a bit higher to allow for growth, and
+ // round to nearest 100.
+ scaleHeight = graphHeight * 1.2;
+ scaleHeight = ((scaleHeight / 100).ceil() * 100);
+ }
+ var scale = height / scaleHeight;
+ drawValues(scaleHeight, scale);
+ drawChart(scaleHeight, scale);
+ }
+
+ void drawChart(int maxHeight, double scale) {
+ var dividerHeight = maxHeight ~/ NUM_DIVIDERS;
+ var context = _canvas.context2d;
+ context.beginPath();
+ var height = maxHeight.toInt();
+ var scaledY = dividerHeight * scale;
+
+ // Draw the vertical axis values and lines.
+ for (var i = 1; i < NUM_DIVIDERS; i++) {
+ height -= (dividerHeight ~/ 100) * 100;
+ context.font = FONT;
+ context.fillStyle = 'black';
+ context.textAlign = 'right';
+ context.textBaseline = 'middle';
+ context.fillText(height.toString(), LEFT_MARGIN - 10, scaledY);
+ context.moveTo(LEFT_MARGIN - 2, scaledY);
+ context.strokeStyle = 'grey';
+ context.lineWidth = 0.5;
+ context.lineTo(_canvas.width - RIGHT_MARGIN, scaledY);
+ context.stroke();
+ scaledY += dividerHeight * scale;
+ }
+ }
+
+ void drawValues(int maxHeight, num scale) {
+ Iterator<Sample> iterator = _model.iterator;
+ var x = LEFT_MARGIN + INSIDE_MARGIN;
+
+ while (iterator.moveNext()) {
+ Sample s = iterator.current;
+ var y = INSIDE_MARGIN;
+ if (s != null) {
+ var blankHeight = scaleHeight - s.total();
+ drawVerticalSegment(x, y, SAMPLE_WIDTH, blankHeight, 'white', scale);
+ y += blankHeight;
+ for (int i = s.length - 1; i >= 0; i--) {
+ var h = s[i];
+ drawVerticalSegment(x, y, SAMPLE_WIDTH, h, _elements[i].color, scale);
+ y += s[i];
+ }
+ } else {
+ drawVerticalSegment(x, INSIDE_MARGIN, SAMPLE_WIDTH,
+ maxHeight, 'white', scale);
+ }
+ x += SAMPLE_WIDTH ;
+ }
+ }
+
+ void drawVerticalSegment(int x, int y, int w, int h, String color,
+ num scale) {
+ var context = _canvas.context2d;
+ y = (y * scale).floor();
+ h = (h * scale).ceil();
+ context.beginPath();
+ context.lineWidth = w;
+ context.fillStyle = color;
+ context.strokeStyle = color;
+ if (x < INSIDE_MARGIN) {
+ x = INSIDE_MARGIN;
+ }
+ if (y < INSIDE_MARGIN) {
+ y = INSIDE_MARGIN;
+ }
+ var max = _canvas.width - INSIDE_MARGIN;
+ if ((x + w) > max) {
+ w = max - x;
+ }
+ max = _canvas.height - INSIDE_MARGIN;
+ if ((y + h) > max) {
+ h = max - y;
+ }
+ context.moveTo(x, y);
+ context.lineTo(x, y + h);
+ context.stroke();
+ }
+}
+
+class GraphModel extends ObservableModel {
+ List<Sample> _samples = new List<Sample>();
+ int _maxSize;
+
+ static const int _LARGE_LENGTH = 999999999;
+
+ GraphModel(this._maxSize) {}
+
+ void addSample(List<int> segments) {
+ var len = _samples.length;
+ if (_samples.length >= _maxSize) {
+ _samples.remove(_samples.first);
+ }
+ _samples.add(new Sample(segments));
+ notifySuccess();
+ }
+
+ int get maxSize => _maxSize;
+
+ Iterator<Sample> get iterator => _samples.iterator;
+
+ Sample operator[](int i) => _samples[i];
+
+ /**
+ * Returns the minimum total from all the samples.
+ */
+ int get minTotal {
+ var min = _LARGE_LENGTH;
+ _samples.forEach((Sample s) => min = (s.total() < min ? s.total() : min));
+ return min;
+ }
+
+ /**
+ * Returns the maximum total from all the samples.
+ */
+ int get maxTotal {
+ var max = 0;
+ _samples.forEach((Sample s) => max = (s.total() > max ? s.total() : max));
+ return max;
+ }
+}
+
+/**
+ * An element is a data type that gets charted. Each element has a name for
+ * the legend, and a color for the bar graph. The number of elements in a
+ * graph should match the number of segments in each sample.
+ */
+class Element {
+ final String name;
+ final String color; // Any description the DOM will accept, like "red".
+
+ Element(this.name, this.color) {}
+}
+
+/**
+ * A sample is a list of segment lengths.
+ */
+class Sample {
+ List<int> _segments;
+
+ Sample(this._segments) {}
+
+ int get length => _segments.length;
+ int operator[](int i) => _segments[i];
+
+ Iterator<int> get iterator => _segments.iterator;
+
+ int total() {
+ return _segments.reduce(0, (int prev, int element) => prev + element);
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698