blob: 90715301996b84c3f53ae425563fc28aceb8b6f8 [file] [log] [blame]
// 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 {
// Determines style of text in visualiation.
final TextStyle textStyle;
// Determines alignment of text on the side of the bar visualization.
final TextAlign textAlignment;
// Model to manage data for StatusTickBarVisualizerModel.
final StatusTickBarVisualizerModel model;
const StatusTickBarVisualizer({
@required this.model,
@required this.textStyle,
@required this.textAlignment,
});
@override
Widget build(BuildContext context) {
if (model.barFirst)
return AnimatedBuilder(
animation: model,
builder: (BuildContext context, Widget child) {
return _buildBarLeft(context);
});
return AnimatedBuilder(
animation: model,
builder: (BuildContext context, Widget child) {
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(
model.barValue,
textAlign: textAlignment,
style: textStyle,
),
],
);
}
Widget _buildBarRight(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(
model.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() {
return ((model.barFill / model.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() => model.tickMax - model.barValue.length;
// Builds string of ticks.
String _drawTicks(int numTicks) {
if (numTicks < 0 || numTicks == null)
return List.filled(1, '').join('| ');
return List.filled(numTicks + 1, '').join('| ');
}
// Adds space to align bar visualizations.
double _barSpace() => model.barValue.length % 2 == 0 ? 9 : 6;
}
class StatusTickBarVisualizerModel extends ChangeNotifier {
// Descriptive text displayed to the right of bar visualization.
String _barValue;
// Amount the bar visualization will be filled.
double _barFill;
// Maximum amount the bar visualization can be filled.
double _barMax;
// Maximum amount of tick marks allowed to be in row.
final int _tickMax;
// Determines if bar visualization is first in order in row.
final bool _barFirst;
set barFill(double updatedBarFill) {
_barFill = updatedBarFill;
notifyListeners();
}
set barMax(double updatedBarMax) {
_barMax = updatedBarMax;
notifyListeners();
}
set barValue(String updatedBarValue) {
_barValue = updatedBarValue;
notifyListeners();
}
String get barValue => _barValue;
double get barFill => _barFill;
double get barMax => _barMax;
int get tickMax => _tickMax;
bool get barFirst => _barFirst;
StatusTickBarVisualizerModel({
String barValue = 'loading...',
double barFill = 1,
double barMax = 2,
int tickMax = 25,
bool barFirst = true,
}) : _barValue = barValue,
_barFill = barFill,
_barMax = barMax,
_tickMax = tickMax,
_barFirst = barFirst;
}