[Ermine] Added filled progress bar visualization

Change-Id: Ibf92880bec2accd0541b44fa86347e677f23d002
diff --git a/shell/ermine/BUILD.gn b/shell/ermine/BUILD.gn
index ec7d8f3..117bcba 100644
--- a/shell/ermine/BUILD.gn
+++ b/shell/ermine/BUILD.gn
@@ -61,7 +61,8 @@
     "src/widgets/tile_chrome.dart",
     "src/widgets/tile_sizer.dart",
     "src/widgets/tile_tab.dart",
-    "src/widgets/status_bar_visualizer.dart"
+    "src/widgets/status_tick_bar_visualizer.dart",
+    "src/widgets/status_progress_bar_visualizer.dart"
   ]
 
   deps = [
diff --git a/shell/ermine/lib/src/widgets/status.dart b/shell/ermine/lib/src/widgets/status.dart
index d04220d..4e8fb4f 100644
--- a/shell/ermine/lib/src/widgets/status.dart
+++ b/shell/ermine/lib/src/widgets/status.dart
@@ -8,7 +8,7 @@
 
 import '../models/status_model.dart';
 import '../utils/elevations.dart';
-import '../widgets/status_bar_visualizer.dart';
+import '../widgets/status_tick_bar_visualizer.dart';
 
 const _listItemHeight = 35.0;
 const _leadingStyle = TextStyle(
@@ -80,11 +80,14 @@
                     'CPU Usage',
                     style: _leadingStyle,
                   ),
-                  title: StatusBarVisualizer(
+                  title: StatusTickBarVisualizer(
                     barValue: model.getCpu(),
                     barFill: model.getCpuFill(),
                     barMax: model.getCpuMax(),
-                    barSize: 25,
+                    tickMax: 25,
+                    textStyle: _titleStyle,
+                    textAlignment: TextAlign.left,
+                    barFirst: true,
                   ),
                 ),
               ),
@@ -97,11 +100,14 @@
                     'Mem Usage',
                     style: _leadingStyle,
                   ),
-                  title: StatusBarVisualizer(
+                  title: StatusTickBarVisualizer(
                     barValue: model.getMem(),
                     barFill: model.getMemFill(),
                     barMax: model.getMemMax(),
-                    barSize: 25,
+                    tickMax: 25,
+                    textStyle: _titleStyle,
+                    textAlignment: TextAlign.left,
+                    barFirst: true,
                   ),
                 ),
               ),
@@ -159,4 +165,4 @@
       ),
     );
   }
-}
+}
\ No newline at end of file
diff --git a/shell/ermine/lib/src/widgets/status_bar_visualizer.dart b/shell/ermine/lib/src/widgets/status_bar_visualizer.dart
deleted file mode 100644
index da273b9..0000000
--- a/shell/ermine/lib/src/widgets/status_bar_visualizer.dart
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2019 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'dart:ui';
-
-import 'package:flutter/material.dart';
-
-// Builds bar visualization given a value, fill amount, and maximum amount.
-class StatusBarVisualizer extends StatelessWidget {
-  // Descriptive text displayed to the right of bar visualization.
-  final String _barValue;
-  // Amount the bar visualization will be filled.
-  final double _barFill;
-  // Maximum amount the bar visualization can be filled.
-  final double _barMax;
-  // Maximum amount of tick marks allowed to be in row.
-  final int _barSize;
-
-  const StatusBarVisualizer(
-      {@required String barValue,
-      @required double barFill,
-      @required double barMax,
-      @required int barSize})
-      : _barValue = barValue,
-        _barFill = barFill,
-        _barMax = barMax,
-        _barSize = barSize;
-
-  @override
-  Widget build(BuildContext context) {
-    return Row(
-      mainAxisAlignment: MainAxisAlignment.end,
-      children: <Widget>[
-        Text(
-          _drawTicks(_activeTicks()),
-          style: TextStyle(
-            color: Colors.white,
-            fontSize: 14,
-            letterSpacing: -4,
-            fontFamily: 'RobotoMono',
-            fontWeight: FontWeight.w400,
-          ),
-        ),
-        Text(
-          _drawTicks(_inactiveTicks()),
-          style: TextStyle(
-            color: Colors.grey[600],
-            fontSize: 14,
-            letterSpacing: -4,
-            fontFamily: 'RobotoMono',
-            fontWeight: FontWeight.w400,
-          ),
-        ),
-        SizedBox(width: _barSpace()),
-        Text(
-          _barValue,
-          textAlign: TextAlign.right,
-          style: TextStyle(
-            color: Colors.white,
-            fontSize: 14,
-            fontFamily: 'RobotoMono',
-            fontWeight: FontWeight.w400,
-          ),
-        ),
-      ],
-    );
-  }
-
-  // Determines how many active ticks to be drawn.
-  int _activeTicks() => ((_barFill / _barMax) * _maxTicks()).toInt();
-
-  // Determines how many inactive ticks to be drawn.
-  int _inactiveTicks() => (_maxTicks() - _activeTicks());
-
-  // Determines how many ticks can fit in row.
-  int _maxTicks() => _barSize - _barValue.length;
-
-  // Builds string of ticks.
-  String _drawTicks(int numTicks) => List.filled(numTicks + 1, '').join('| ');
-
-  // Adds space to align bar visualizations.
-  double _barSpace() => _barValue.length % 2 == 0 ? 9 : 6;
-}
diff --git a/shell/ermine/lib/src/widgets/status_progress_bar_visualizer.dart b/shell/ermine/lib/src/widgets/status_progress_bar_visualizer.dart
new file mode 100644
index 0000000..92ff49a
--- /dev/null
+++ b/shell/ermine/lib/src/widgets/status_progress_bar_visualizer.dart
@@ -0,0 +1,130 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:ui';
+
+import 'package:flutter/material.dart';
+
+// Builds bar visualization given a value, fill amount, and maximum amount.
+class StatusProgressBarVisualizer extends StatelessWidget {
+  // Descriptive text displayed on the side of the progress bar visualization.
+  final String _barValue;
+  // Amount the progress bar visualization will be filled.
+  final double _barFill;
+  // Maximum amount the progress bar visualization can be filled.
+  final double _barMax;
+  // Double between 0 - 1 that determines the ratio of bar to text in container.
+  final double _barSize;
+  // Height of bar visualization & text.
+  final double _barHeight;
+  // Determines style of text in visualiation.
+  final TextStyle _textStyle;
+  // Determines alignment of text on the side of the bar visualization.
+  final TextAlign _textAlignment;
+  // Determines if bar visualization is first in order in row.
+  final bool _barFirst;
+
+  const StatusProgressBarVisualizer(
+      {@required String barValue,
+      @required double barFill,
+      @required double barMax,
+      @required double barSize,
+      @required double barHeight,
+      @required TextStyle textStyle,
+      @required TextAlign textAlignment,
+      @required bool barFirst})
+      : _barValue = barValue,
+        _barFill = barFill,
+        _barMax = barMax,
+        _barSize = barSize,
+        _barHeight = barHeight,
+        _textStyle = textStyle,
+        _textAlignment = textAlignment,
+        _barFirst = barFirst;
+
+  @override
+  Widget build(BuildContext context) {
+    if (_barFirst)
+      return _buildBarLeft(context);
+    return _buildBarRight(context);
+  }
+
+  Widget _buildBarLeft(BuildContext context) {
+    return Flex(
+      direction: Axis.horizontal,
+      children: <Widget>[
+        // Progress Bar
+        Expanded(
+          flex: (_barSize * 100).toInt(),
+          child: Flex(
+            direction: Axis.horizontal,
+            children: <Widget>[
+              Expanded(
+                  flex: ((_barFill / _barMax) * 100).toInt(),
+                  child: Container(
+                    height: _barHeight,
+                    color: Colors.white,
+                  )),
+              Expanded(
+                flex: (((_barMax - _barFill) / _barMax) * 100).toInt(),
+                child: Container(
+                  height: _barHeight,
+                  color: Colors.grey[600],
+                ),
+              ),
+            ],
+          ),
+        ),
+        // Descriptive Text
+        Expanded(
+          flex: ((1 - _barSize) * 100).toInt(),
+          child: Text(
+            _barValue,
+            textAlign: _textAlignment,
+            style: _textStyle,
+          ),
+        ),
+      ],
+    );
+  }
+
+  Widget _buildBarRight(BuildContext context) {
+    return Flex(
+      direction: Axis.horizontal,
+      children: <Widget>[
+        // Descriptive Text
+        Expanded(
+          flex: ((1 - _barSize) * 100).toInt(),
+          child: Text(
+            _barValue,
+            textAlign: _textAlignment,
+            style: _textStyle,
+          ),
+        ),
+        // Progress Bar
+        Expanded(
+          flex: (_barSize * 100).toInt(),
+          child: Flex(
+            direction: Axis.horizontal,
+            children: <Widget>[
+              Expanded(
+                  flex: ((_barFill / _barMax) * 100).toInt(),
+                  child: Container(
+                    height: _barHeight,
+                    color: Colors.white,
+                  )),
+              Expanded(
+                flex: (((_barMax - _barFill) / _barMax) * 100).toInt(),
+                child: Container(
+                  height: _barHeight,
+                  color: Colors.grey[600],
+                ),
+              ),
+            ],
+          ),
+        ),
+      ],
+    );
+  }
+}
diff --git a/shell/ermine/lib/src/widgets/status_tick_bar_visualizer.dart b/shell/ermine/lib/src/widgets/status_tick_bar_visualizer.dart
new file mode 100644
index 0000000..4fea0fb
--- /dev/null
+++ b/shell/ermine/lib/src/widgets/status_tick_bar_visualizer.dart
@@ -0,0 +1,126 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:ui';
+
+import 'package:flutter/material.dart';
+
+// Builds bar visualization given a value, fill amount, and maximum amount.
+class StatusTickBarVisualizer extends StatelessWidget {
+  // Descriptive text displayed to the right of bar visualization.
+  final String _barValue;
+  // Amount the bar visualization will be filled.
+  final double _barFill;
+  // Maximum amount the bar visualization can be filled.
+  final double _barMax;
+  // Maximum amount of tick marks allowed to be in row.
+  final int _tickMax;
+  // Determines style of text in visualiation.
+  final TextStyle _textStyle;
+  // Determines alignment of text on the side of the bar visualization.
+  final TextAlign _textAlignment;
+  // Determines if bar visualization is first in order in row.
+  final bool _barFirst;
+
+  const StatusTickBarVisualizer(
+      {@required String barValue,
+      @required double barFill,
+      @required double barMax,
+      @required int tickMax,
+      @required TextStyle textStyle,
+      @required TextAlign textAlignment,
+      @required bool barFirst})
+      : _barValue = barValue,
+        _barFill = barFill,
+        _barMax = barMax,
+        _tickMax = tickMax,
+        _textStyle = textStyle,
+        _textAlignment = textAlignment,
+        _barFirst = barFirst;
+
+  @override
+  Widget build(BuildContext context) {
+    if (_barFirst)
+      return _buildBarLeft(context);
+    return _buildBarRight(context);
+  }
+
+  Widget _buildBarLeft(BuildContext context) {
+    return Row(
+      mainAxisAlignment: MainAxisAlignment.end,
+      children: <Widget>[
+        Text(
+          _drawTicks(_activeTicks()),
+          style: _setTickStyle(true)
+        ),
+        Text(
+          _drawTicks(_inactiveTicks()),
+          style: _setTickStyle(false),
+        ),
+        SizedBox(width: _barSpace()),
+        Text(
+          _barValue,
+          textAlign: _textAlignment,
+          style: _textStyle,
+        ),
+      ],
+    );
+  }
+
+  Widget _buildBarRight(BuildContext context) {
+    return Row(
+      mainAxisAlignment: MainAxisAlignment.end,
+      children: <Widget>[
+        Text(
+          _barValue,
+          textAlign: _textAlignment,
+          style: _textStyle,
+        ),
+        SizedBox(width: _barSpace()),
+        Text(
+          _drawTicks(_activeTicks()),
+          style: _setTickStyle(true),
+        ),
+        Text(
+          _drawTicks(_inactiveTicks()),
+          style: _setTickStyle(false)
+        ),
+      ],
+    );
+  }
+
+  TextStyle _setTickStyle(bool active) {
+    if (active) {
+      return TextStyle(
+        color: Colors.white,
+        fontSize: 14,
+        letterSpacing: -4,
+        fontFamily: 'RobotoMono',
+        fontWeight: FontWeight.w400,
+      );
+    }
+    return TextStyle(
+      color: Colors.grey[600],
+      fontSize: 14,
+      letterSpacing: -4,
+      fontFamily: 'RobotoMono',
+      fontWeight: FontWeight.w400,
+    );
+  }
+
+  // Determines how many active ticks to be drawn.
+  int _activeTicks() => ((_barFill / _barMax) * _maxTicks()).toInt();
+
+  // Determines how many inactive ticks to be drawn.
+  int _inactiveTicks() => (_maxTicks() - _activeTicks());
+
+  // Determines how many ticks can fit in row.
+  int _maxTicks() => _tickMax - _barValue.length;
+
+  // Builds string of ticks.
+  String _drawTicks(int numTicks) => List.filled(numTicks + 1, '').join('| ');
+
+  // Adds space to align bar visualizations.
+  double _barSpace() => _barValue.length % 2 == 0 ? 9 : 6;
+}