Gauge card refactoring

This commit is contained in:
Yegor Vialov 2020-04-07 20:20:57 +00:00
parent ab398cbdc3
commit 62d07bf8b9
7 changed files with 165 additions and 120 deletions

2
.gitignore vendored
View File

@ -18,5 +18,5 @@ flutter_export_environment.sh
.flutter-plugins-dependencies .flutter-plugins-dependencies
key.properties key.properties
premium_features_manager.class.dart secrets_manager.class.dart
pubspec.lock pubspec.lock

View File

@ -14,10 +14,11 @@ class GaugeCardBody extends StatefulWidget {
class _GaugeCardBodyState extends State<GaugeCardBody> { class _GaugeCardBodyState extends State<GaugeCardBody> {
List<charts.Series> seriesList; @override
Widget build(BuildContext context) {
List<charts.Series<GaugeSegment, String>> _createData(double value) { EntityWrapper entityWrapper = EntityModel.of(context).entityWrapper;
double fixedValue; double fixedValue;
double value = entityWrapper.entity.doubleState;
if (value > widget.max) { if (value > widget.max) {
fixedValue = widget.max.toDouble(); fixedValue = widget.max.toDouble();
} else if (value < widget.min) { } else if (value < widget.min) {
@ -25,130 +26,151 @@ class _GaugeCardBodyState extends State<GaugeCardBody> {
} else { } else {
fixedValue = value; fixedValue = value;
} }
double toShow = ((fixedValue - widget.min) / (widget.max - widget.min)) * 100;
Color mainColor;
if (widget.severity != null) {
if (widget.severity["red"] is int && fixedValue >= widget.severity["red"]) {
mainColor = Colors.red;
} else if (widget.severity["yellow"] is int && fixedValue >= widget.severity["yellow"]) {
mainColor = Colors.amber;
} else {
mainColor = Colors.green;
}
} else {
mainColor = Colors.green;
}
final data = [
GaugeSegment('Main', toShow, mainColor),
GaugeSegment('Rest', 100 - toShow, Colors.black45),
];
return [ List<GaugeRange> ranges;
charts.Series<GaugeSegment, String>( if (widget.severity != null && widget.severity["green"] is int && widget.severity["red"] is int && widget.severity["yellow"] is int) {
id: 'Segments', List<RangeContainer> rangesList = <RangeContainer>[
domainFn: (GaugeSegment segment, _) => segment.segment, RangeContainer(widget.severity["green"], HAClientTheme().getGreenGaugeColor()),
measureFn: (GaugeSegment segment, _) => segment.value, RangeContainer(widget.severity["red"], HAClientTheme().getRedGaugeColor()),
colorFn: (GaugeSegment segment, _) => segment.color, RangeContainer(widget.severity["yellow"], HAClientTheme().getYellowGaugeColor())
// Set a label accessor to control the text of the arc label. ];
labelAccessorFn: (GaugeSegment segment, _) => rangesList.sort((current, next) {
segment.segment == 'Main' ? '${segment.value}' : null, if (current.startFrom > next.startFrom) {
data: data, return 1;
}
if (current.startFrom < next.startFrom) {
return -1;
}
return 0;
});
ranges = [
GaugeRange(
startValue: rangesList[0].startFrom.toDouble(),
endValue: rangesList[1].startFrom.toDouble(),
color: fixedValue < rangesList[1].startFrom ? rangesList[0].color : rangesList[0].color.withOpacity(0.3),
sizeUnit: GaugeSizeUnit.factor,
endWidth: 0.3,
startWidth: 0.3
),
GaugeRange(
startValue: rangesList[1].startFrom.toDouble(),
endValue: rangesList[2].startFrom.toDouble(),
color: (fixedValue < rangesList[2].startFrom && fixedValue >= rangesList[1].startFrom) ? rangesList[1].color : rangesList[1].color.withOpacity(0.3),
sizeUnit: GaugeSizeUnit.factor,
endWidth: 0.3,
startWidth: 0.3
),
GaugeRange(
startValue: rangesList[2].startFrom.toDouble(),
endValue: widget.max.toDouble(),
color: fixedValue >= rangesList[2].startFrom ? rangesList[2].color : rangesList[2].color.withOpacity(0.3),
sizeUnit: GaugeSizeUnit.factor,
endWidth: 0.3,
startWidth: 0.3
)
];
}
if (ranges == null) {
ranges = <GaugeRange>[
GaugeRange(
startValue: widget.min.toDouble(),
endValue: widget.max.toDouble(),
color: Theme.of(context).primaryColorDark,
sizeUnit: GaugeSizeUnit.factor,
endWidth: 0.3,
startWidth: 0.3
) )
]; ];
} }
@override
Widget build(BuildContext context) {
EntityWrapper entityWrapper = EntityModel.of(context).entityWrapper;
return InkWell( return InkWell(
onTap: () => entityWrapper.handleTap(), onTap: () => entityWrapper.handleTap(),
onLongPress: () => entityWrapper.handleHold(), onLongPress: () => entityWrapper.handleHold(),
onDoubleTap: () => entityWrapper.handleDoubleTap(), onDoubleTap: () => entityWrapper.handleDoubleTap(),
child: AspectRatio( child: AspectRatio(
aspectRatio: 1.5, aspectRatio: 2,
child: Stack(
fit: StackFit.expand,
overflow: Overflow.clip,
children: [
LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
double verticalOffset;
if(constraints.maxWidth > 150.0) {
verticalOffset = 0.2;
} else if (constraints.maxWidth > 100.0) {
verticalOffset = 0.3;
} else {
verticalOffset = 0.3;
}
return FractionallySizedBox(
heightFactor: 2,
widthFactor: 1,
alignment: FractionalOffset(0,verticalOffset),
child: charts.PieChart(
_createData(entityWrapper.entity.doubleState),
animate: false,
defaultRenderer: charts.ArcRendererConfig(
arcRatio: 0.4,
startAngle: pi,
arcLength: pi,
),
),
);
}
),
Align(
alignment: Alignment.bottomCenter,
child: LayoutBuilder( child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) { builder: (BuildContext context, BoxConstraints constraints) {
double fontSize = constraints.maxHeight / 7; double fontSizeFactor;
return Padding( if (constraints.maxWidth > 300.0) {
padding: EdgeInsets.only(bottom: 2*fontSize), fontSizeFactor = 1.6;
child: SimpleEntityState( } else if (constraints.maxWidth > 150.0) {
//textAlign: TextAlign.center, fontSizeFactor = 1;
} else if (constraints.maxWidth > 100.0) {
fontSizeFactor = 0.6;
} else {
fontSizeFactor = 0.4;
}
return SfRadialGauge(
axes: <RadialAxis>[
RadialAxis(
maximum: widget.max.toDouble(),
minimum: widget.min.toDouble(),
showLabels: false,
showTicks: false,
canScaleToFit: true,
ranges: ranges,
annotations: <GaugeAnnotation>[
GaugeAnnotation(
angle: -90,
positionFactor: 1.3,
//verticalAlignment: GaugeAlignment.far,
widget: EntityName(
textStyle: Theme.of(context).textTheme.body1.copyWith(
fontSize: Theme.of(context).textTheme.body1.fontSize * fontSizeFactor
),
),
),
GaugeAnnotation(
angle: 180,
positionFactor: 0,
verticalAlignment: GaugeAlignment.center,
widget: SimpleEntityState(
expanded: false, expanded: false,
maxLines: 1, maxLines: 1,
textAlign: TextAlign.center, textAlign: TextAlign.center,
padding: EdgeInsets.all(0.0) textStyle: Theme.of(context).textTheme.title.copyWith(
//padding: EdgeInsets.only(top: Sizes.rowPadding), fontSize: Theme.of(context).textTheme.title.fontSize * fontSizeFactor,
),
);
}
), ),
), ),
Align( )
alignment: Alignment.bottomCenter, ],
child: LayoutBuilder( axisLineStyle: AxisLineStyle(
builder: (BuildContext context, BoxConstraints constraints) { thickness: 0.3,
double fontSize = constraints.maxHeight / 7; thicknessUnit: GaugeSizeUnit.factor
return Padding(
padding: EdgeInsets.only(bottom: fontSize),
child: EntityName(
textStyle: Theme.of(context).textTheme.body1.copyWith(
fontSize: fontSize
),
maxLines: 1,
padding: EdgeInsets.all(0.0),
textAlign: TextAlign.center,
textOverflow: TextOverflow.ellipsis,
),
);
}
), ),
startAngle: 180,
endAngle: 0,
pointers: <GaugePointer>[
NeedlePointer(
value: fixedValue,
lengthUnit: GaugeSizeUnit.factor,
needleLength: 0.9,
needleColor: Theme.of(context).accentColor,
enableAnimation: true,
needleStartWidth: 1,
animationType: AnimationType.bounceOut,
needleEndWidth: 3,
knobStyle: KnobStyle(
sizeUnit: GaugeSizeUnit.factor,
color: Theme.of(context).buttonColor,
knobRadius: 0.1
)
) )
] ]
) )
],
);
},
),
), ),
); );
} }
} }
class GaugeSegment { class RangeContainer {
final String segment; final int startFrom;
final double value; Color color;
final charts.Color color;
GaugeSegment(this.segment, this.value, Color color) RangeContainer(this.startFrom, this.color);
: this.color = charts.Color(
r: color.red, g: color.green, b: color.blue, a: color.alpha);
} }

View File

@ -21,6 +21,8 @@ class EntityName extends StatelessWidget {
} else { } else {
tStyle = Theme.of(context).textTheme.body1; tStyle = Theme.of(context).textTheme.body1;
} }
} else {
tStyle = textStyle;
} }
return Padding( return Padding(
padding: padding, padding: padding,

View File

@ -7,9 +7,10 @@ class SimpleEntityState extends StatelessWidget {
final EdgeInsetsGeometry padding; final EdgeInsetsGeometry padding;
final int maxLines; final int maxLines;
final String customValue; final String customValue;
final TextStyle textStyle;
//final bool bold; //final bool bold;
const SimpleEntityState({Key key,/*this.bold: false,*/ this.maxLines: 10, this.expanded: true, this.textAlign: TextAlign.right, this.padding: const EdgeInsets.fromLTRB(0.0, 0.0, Sizes.rightWidgetPadding, 0.0), this.customValue}) : super(key: key); const SimpleEntityState({Key key,/*this.bold: false,*/ this.maxLines: 10, this.expanded: true, this.textAlign: TextAlign.right, this.textStyle, this.padding: const EdgeInsets.fromLTRB(0.0, 0.0, Sizes.rightWidgetPadding, 0.0), this.customValue}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -21,13 +22,15 @@ class SimpleEntityState extends StatelessWidget {
} else { } else {
state = customValue; state = customValue;
} }
TextStyle textStyle; TextStyle tStyle;
if (entityModel.entityWrapper.entity.statelessType == StatelessEntityType.CALL_SERVICE) { if (textStyle != null) {
textStyle = Theme.of(context).textTheme.subhead.copyWith( tStyle = textStyle;
} else if (entityModel.entityWrapper.entity.statelessType == StatelessEntityType.CALL_SERVICE) {
tStyle = Theme.of(context).textTheme.subhead.copyWith(
color: Colors.blue color: Colors.blue
); );
} else { } else {
textStyle = Theme.of(context).textTheme.body1; tStyle = Theme.of(context).textTheme.body1;
} }
/*if (this.bold) { /*if (this.bold) {
textStyle = textStyle.apply(fontWeightDelta: 100); textStyle = textStyle.apply(fontWeightDelta: 100);
@ -43,7 +46,7 @@ class SimpleEntityState extends StatelessWidget {
maxLines: maxLines, maxLines: maxLines,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
softWrap: true, softWrap: true,
style: textStyle style: tStyle
) )
); );
if (expanded) { if (expanded) {

View File

@ -34,8 +34,11 @@ import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart' as standaloneWebview; import 'package:flutter_webview_plugin/flutter_webview_plugin.dart' as standaloneWebview;
import 'package:webview_flutter/webview_flutter.dart'; import 'package:webview_flutter/webview_flutter.dart';
import 'package:video_player/video_player.dart'; import 'package:video_player/video_player.dart';
import 'package:syncfusion_flutter_core/core.dart';
import 'package:syncfusion_flutter_gauges/gauges.dart';
import 'utils/logger.dart'; import 'utils/logger.dart';
import 'managers/secrets_manager.class.dart';
part 'const.dart'; part 'const.dart';
part 'utils/launcher.dart'; part 'utils/launcher.dart';
@ -164,6 +167,7 @@ Future<void> _reportError(dynamic error, dynamic stackTrace) async {
void main() async { void main() async {
Crashlytics.instance.enableInDevMode = false; Crashlytics.instance.enableInDevMode = false;
SyncfusionLicense.registerLicense(SecretsManager.SYNCFUSION_LICENSE_KEY);
FlutterError.onError = (FlutterErrorDetails details) { FlutterError.onError = (FlutterErrorDetails details) {
Logger.e(" Caut Flutter runtime error: ${details.exception}"); Logger.e(" Caut Flutter runtime error: ${details.exception}");

View File

@ -154,6 +154,18 @@ class HAClientTheme {
} }
} }
Color getGreenGaugeColor() {
return Colors.green;
}
Color getYellowGaugeColor() {
return Colors.yellow;
}
Color getRedGaugeColor() {
return Colors.red;
}
TextStyle getLinkTextStyle(BuildContext context) { TextStyle getLinkTextStyle(BuildContext context) {
ThemeData theme = Theme.of(context); ThemeData theme = Theme.of(context);
return theme.textTheme.body1.copyWith( return theme.textTheme.body1.copyWith(

View File

@ -33,6 +33,8 @@ dependencies:
battery: ^0.3.1+7 battery: ^0.3.1+7
firebase_crashlytics: ^0.1.3+3 firebase_crashlytics: ^0.1.3+3
video_player: ^0.10.7 video_player: ^0.10.7
syncfusion_flutter_core: ^18.1.43
syncfusion_flutter_gauges: ^18.1.43
dev_dependencies: dev_dependencies: