|
|
@@ -0,0 +1,93 @@
|
|
|
+import 'package:flutter/material.dart';
|
|
|
+
|
|
|
+class LineChartTitle {
|
|
|
+ const LineChartTitle({required this.title, this.width, this.flex});
|
|
|
+
|
|
|
+ final Widget title;
|
|
|
+ final double? width;
|
|
|
+ final int? flex;
|
|
|
+}
|
|
|
+
|
|
|
+class LineChartElem {
|
|
|
+ const LineChartElem(this.cols);
|
|
|
+
|
|
|
+ final Iterable<Widget> cols;
|
|
|
+}
|
|
|
+
|
|
|
+class LineChart extends StatelessWidget {
|
|
|
+ const LineChart(
|
|
|
+ {super.key,
|
|
|
+ required this.titles,
|
|
|
+ required this.children,
|
|
|
+ this.lineHeight});
|
|
|
+
|
|
|
+ final Iterable<LineChartTitle> titles;
|
|
|
+ final Iterable<LineChartElem> children;
|
|
|
+ final double? lineHeight;
|
|
|
+ final dividerWidth = 0.71;
|
|
|
+ final borderWidth = 0.71;
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget build(BuildContext context) {
|
|
|
+ final lineHeight = this.lineHeight ?? 38.5;
|
|
|
+ final titlesChildren = <Widget>[];
|
|
|
+ for (var (i, e) in titles.indexed) {
|
|
|
+ titlesChildren.add(e.width != null
|
|
|
+ ? Container(
|
|
|
+ alignment: Alignment.center, width: e.width!, child: e.title)
|
|
|
+ : Expanded(
|
|
|
+ flex: e.flex!,
|
|
|
+ child: Center(child: e.title),
|
|
|
+ ));
|
|
|
+ if (i < titles.length - 1) {
|
|
|
+ titlesChildren.add(SizedBox(
|
|
|
+ width: dividerWidth,
|
|
|
+ ));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ final title = Container(
|
|
|
+ margin: EdgeInsets.all(borderWidth),
|
|
|
+ height: lineHeight,
|
|
|
+ child: Row(
|
|
|
+ children: titlesChildren,
|
|
|
+ ));
|
|
|
+ final children = <Widget>[
|
|
|
+ title,
|
|
|
+ ];
|
|
|
+
|
|
|
+ children.addAll(this.children.map((e) {
|
|
|
+ final row = <Widget>[];
|
|
|
+ for (var (i, one) in e.cols.indexed) {
|
|
|
+ final t = titles.elementAt(i);
|
|
|
+ row.add(t.width != null
|
|
|
+ ? Container(
|
|
|
+ width: t.width!, alignment: Alignment.center, child: one)
|
|
|
+ : Expanded(flex: t.flex!, child: Center(child: one)));
|
|
|
+ if (i != e.cols.length - 1) {
|
|
|
+ row.add(SizedBox(
|
|
|
+ height: 17.78, child: VerticalDivider(width: dividerWidth)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return Container(
|
|
|
+ margin: const EdgeInsets.only(top: 2),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color: Colors.white,
|
|
|
+ border: Border.all(
|
|
|
+ color: const Color(0xffe9e9e9), width: borderWidth),
|
|
|
+ boxShadow: const [
|
|
|
+ BoxShadow(color: Color(0x4d000000), blurRadius: 0.71)
|
|
|
+ ]),
|
|
|
+ height: lineHeight,
|
|
|
+ child: Row(
|
|
|
+ children: row,
|
|
|
+ ));
|
|
|
+ }));
|
|
|
+
|
|
|
+ return Column(
|
|
|
+ mainAxisSize: MainAxisSize.min,
|
|
|
+ children: children,
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|