Commit ce808319 authored by Nicolas Richard Walter Boeckh's avatar Nicolas Richard Walter Boeckh 💬

Moving files to hierarchical structure, UI tweaks

- Graph : Added Axis Titles
- NavBar : Migrated to "cicular_bottom_navigation"
- Battery Indicator : Rounded corners + Color lerping
- Data Tile :  resized text
parent cb6b9f53
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"android":[{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"macos":[{"name":"shared_preferences_macos","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_macos-0.0.1+8\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"shared_preferences_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_web-0.1.2+5\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_blue","dependencies":[]},{"name":"geolocator","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","dependencies":[]},{"name":"location_permissions","dependencies":[]},{"name":"path_provider","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2020-08-21 09:20:35.704809","version":"1.21.0-10.0.pre.212"}
\ No newline at end of file
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"android":[{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"macos":[{"name":"shared_preferences_macos","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_macos-0.0.1+8\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"shared_preferences_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_web-0.1.2+5\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_blue","dependencies":[]},{"name":"geolocator","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","dependencies":[]},{"name":"location_permissions","dependencies":[]},{"name":"path_provider","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2020-08-26 17:00:48.008588","version":"1.22.0-2.0.pre.18"}
\ No newline at end of file
import 'package:carousel_slider/carousel_slider.dart';
import 'package:circular_bottom_navigation/circular_bottom_navigation.dart';
import 'package:flutter/cupertino.dart';
import 'package:logair_application/ui/routes/home.dart';
......@@ -13,10 +14,24 @@ class HomeController {
/// The controller for the [CarouselSlider].
PageController _pageController;
/// The controller for the [CircularBottomNavigation]
CircularBottomNavigationController _navigationController;
/// Sets the [PageController] for the [CarouselSlider]
set carouselController(PageController carouselController) => this._pageController = carouselController;
get carouselController => this._pageController;
/// Sets the [CircularBottomNavigationController] for the [CircularBottomNavigation]
set navigationController(CircularBottomNavigationController navController) => this._navigationController = navController;
/// Force the [CarouselSlider] to navigate to another page.
void gotoPage(int page) => (this._pageController != null) ? this._pageController.jumpToPage(page) : {};
void gotoPage(int page) {
if (this._pageController != null)
this._pageController.jumpToPage(page);
}
/// Forces the [CircularBottomNavigation] to the correct position.
void navbarToPage(int page) {
if (this._navigationController != null)
this._navigationController.value = (page + 1) % 3;
}
}
\ No newline at end of file
......@@ -9,7 +9,7 @@ import 'package:logair_application/logic/handlers/network_handler.dart';
import 'package:logair_application/logic/data_header.dart';
import 'package:logair_application/logic/data_packet.dart';
import 'package:logair_application/logic/handlers/position_handler.dart';
import 'package:logair_application/utils/pm_symbol.dart';
import 'package:logair_application/utils/enums/pm_symbol.dart';
/// The [MapDisplayController] is a [Singleton] that handles the mapping of information.
class MapDisplayController {
......@@ -85,7 +85,8 @@ class MapDisplayController {
if (this._pmMarkers.length > maxPoints)
this._pmMarkers.removeRange(0, this._pmMarkers.length - 200);
this._pmMarkers.add(_buildPMMarker(position, value));
if (value != null)
this._pmMarkers.add(_buildPMMarker(position, value));
}
/// This function is executed on first initialization of the [MapDisplayController]
......
......@@ -105,6 +105,7 @@ class DataHandler {
}
}
/// This destroys the elements it depends on to avoid duplication or wrong information
void dispose() {
DataHeader().dispose();
this._data.removeWhere((element) => true);
......
......@@ -11,7 +11,7 @@ import 'package:logair_application/logic/handlers/data_handler.dart';
import 'package:logair_application/logic/handlers/database_handler.dart';
import 'package:tuple/tuple.dart';
/// Singleton data structure that contains services enabling the application to send data to a webserver.
/// This singleton data structure that contains services enabling the application to send data to a webserver.
class NetworkHandler {
factory NetworkHandler() => _singleton;
......@@ -24,6 +24,7 @@ class NetworkHandler {
static final NetworkHandler _singleton = new NetworkHandler._internal();
DateTime _lastServerTransmission;
/// Method to send acquired data packets by using a POST requests.
......@@ -32,7 +33,6 @@ class NetworkHandler {
String url = 'https://api.logair.unige.ch/v1/service';
/// Break conditions ([DataHeader] unset or no [DataPacket] available).
// TODO add url to db,
if (!DataHeader().headerSet || DataHandler().getData().length == 0)
return;
......@@ -55,13 +55,18 @@ class NetworkHandler {
postData.addAll(packetList);
/// Attempt to send the data to the endpoint via HTTP POST request.
http.Response response = await http.post(
url,
headers: { "accept": "application/json", "content-type": "application/json" },
body: json.encode(postData)
)
http.Response response;
try {
response = await http.post(
url,
headers: { "accept": "application/json", "content-type": "application/json" },
body: json.encode(postData)
);
/// On error, the error should be ignored and not break the thread.
.catchError((e) => print("${e.toString()} COULDN'T CONNECT"));
} catch (e) {
print("${e.toString()} COULDN'T CONNECT");
response = null;
}
/// If the response is defined as an instance of [http.Response], check it's status code and remove all of the packets from the log.
if (response != null && response.statusCode == 200) {
......@@ -79,12 +84,17 @@ class NetworkHandler {
/// The default endpoint.
String url = 'https://api.logair.unige.ch/v1/geo/bounds?device_id=$deviceId&lat1=${bounds.northEast.latitude}&lng1=${bounds.northEast.longitude}&lat2=${bounds.southWest.latitude}&lng2=${bounds.southWest.longitude}&age=${300000}&limit=${200}';
/// Attempt to send the data to the endpoint via HTTP POST request.
http.Response response = await http.get(
url,
headers: { "accept": "application/json", "content-type": "application/json" },
)
http.Response response;
try {
response = await http.get(
url,
headers: { "accept": "application/json", "content-type": "application/json" },
);
/// On error, the error should be ignored and not break the thread.
.catchError((e) => print('COULDN\'T CONNECT'));
} catch (e) {
print("${e.toString()} COULDN'T CONNECT");
response = null;
}
if (response != null && response.statusCode == 200) {
// TODO Complete
......
import 'package:flutter/material.dart';
class CardPainter extends CustomPainter {
CardPainter({@required this.isLeft, @required this.battery, @required this.color});
final bool isLeft;
int battery;
Color color;
setColor(Color newColor) {
this.color = newColor;
}
@override
void paint(Canvas canvas, Size size) {
final shapeBounds = Rect.fromLTRB(0, 0, size.width, size.height);
_drawBackground(canvas, shapeBounds);
}
@override
bool shouldRepaint(CardPainter oldDelegate) {
return color != oldDelegate.color;
}
void _drawBackground(Canvas canvas, Rect shapeBounds) {
final Paint paint = Paint()..color = color;
final rectWidth = shapeBounds.width * this.battery / 100;
final backgroundPath = (this.isLeft) ?
(Path()
..moveTo(shapeBounds.left, shapeBounds.top)
..lineTo(shapeBounds.bottomLeft.dx, shapeBounds.bottomLeft.dy)
..lineTo(shapeBounds.bottomLeft.dx + rectWidth, shapeBounds.bottomRight.dy)
..lineTo(shapeBounds.bottomLeft.dx + rectWidth, shapeBounds.topRight.dy) //7
..close()) :
(Path()
..moveTo(shapeBounds.right, shapeBounds.top) //3
..lineTo(shapeBounds.bottomRight.dx, shapeBounds.bottomRight.dy)
..lineTo(shapeBounds.bottomRight.dx - rectWidth, shapeBounds.bottomRight.dy)
..lineTo(shapeBounds.topRight.dx - rectWidth, shapeBounds.topRight.dy) //7
..close()); //8
canvas.drawPath(backgroundPath, paint);
}
}
\ No newline at end of file
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:logair_application/logic/handlers/data_handler.dart';
import 'package:logair_application/ui/carousel_card.dart';
import 'package:logair_application/ui/components/data_tile.dart';
import 'package:logair_application/ui/components/graph/graph.dart';
class DataWidget extends StatelessWidget {
DataWidget();
@override
Widget build(BuildContext context) {
Widget widget = Center(
child: Column(
children: [
// Local data (Chart + Data points)
Graph(),
DataTile(DataHandler().getDataStream(), false, ''),
// Bar (Locations + Add new -> Pop to new route)
Container(
color: Colors.grey,
child: Row(
children: [
Expanded(
child: Text(
'Other Locations',
textAlign: TextAlign.center,
),
),
IconButton(
onPressed: () => {},
icon: Icon(Icons.add),
)
],
),
),
Column(
children: [
DataTile(DataHandler().getMockDataStream(), true, 'Home'),
DataTile(DataHandler().getMockDataStream(), true, 'Work'),
DataTile(DataHandler().getMockDataStream(), true, 'C'),
DataTile(DataHandler().getMockDataStream(), true, 'D'),
DataTile(DataHandler().getMockDataStream(), true, 'E'),
DataTile(DataHandler().getMockDataStream(), true, 'F'),
DataTile(DataHandler().getMockDataStream(), true, 'G'),
DataTile(DataHandler().getMockDataStream(), true, 'H'),
DataTile(DataHandler().getMockDataStream(), true, 'I'),
],
),
],
)
);
return CarouselCard(child: widget);
}
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:logair_application/logic/handlers/data_handler.dart';
import 'package:logair_application/ui/components/common/carousel_card.dart';
import 'package:logair_application/ui/components/body/data/graph/graph.dart';
import 'package:logair_application/ui/components/body/data/tiles/data_tile.dart';
class DataWidget extends StatelessWidget {
DataWidget();
@override
Widget build(BuildContext context) {
Widget widget = Center(
child: Column(
children: [
// Local data (Chart + Data points)
Graph(),
DataTile(DataHandler().getDataStream(), false, ''),
SizedBox(height: 10,),
// Bar (Locations + Add new -> Pop to new route)
Container(
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.only(topLeft: Radius.circular(5), topRight: Radius.circular(5))
),
child: Row(
children: [
Expanded(
child: Text(
'Locations of Interest',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 18
),
),
),
IconButton(
onPressed: () => {},
icon: Icon(Icons.add),
)
],
),
),
Column(
children: [
DataTile(DataHandler().getMockDataStream(), true, 'Home'),
DataTile(DataHandler().getMockDataStream(), true, 'Work'),
DataTile(DataHandler().getMockDataStream(), true, 'C'),
DataTile(DataHandler().getMockDataStream(), true, 'D'),
DataTile(DataHandler().getMockDataStream(), true, 'E'),
DataTile(DataHandler().getMockDataStream(), true, 'F'),
DataTile(DataHandler().getMockDataStream(), true, 'G'),
DataTile(DataHandler().getMockDataStream(), true, 'H'),
DataTile(DataHandler().getMockDataStream(), true, 'I'),
SizedBox(height: 30,)
],
),
],
)
);
return CarouselCard(child: widget);
}
}
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:logair_application/ui/components/graph/graph_colors.dart';
import 'package:logair_application/ui/components/graph/graph_controller.dart';
import 'package:logair_application/ui/components/graph/indicator.dart';
import 'package:logair_application/ui/components/body/data/graph/graph_colors.dart';
import 'package:logair_application/ui/components/body/data/graph/graph_controller.dart';
import 'package:logair_application/ui/components/body/data/graph/indicator.dart';
/// WIP
/// TODO Add axis titles
/// This graph should display the average quality of the air in 5 second increments.
/// This graph displays the average quality of the air in 5 second increments.
class Graph extends StatefulWidget {
Graph({Key key}) : super(key: key);
......@@ -16,8 +15,24 @@ class Graph extends StatefulWidget {
}
class _GraphState extends State<Graph> {
/// The first registered timestamp.
double start;
/// The current timestamp.
double now;
/// The maximum y-axis coordinate.
double yMax = 0;
List<FlSpot> spotsPM1 = [FlSpot(0, 0)];
List<FlSpot> spotsPM2_5 = [FlSpot(0, 0)];
List<FlSpot> spotsPM4 = [FlSpot(0, 0)];
List<FlSpot> spotsPM10 = [FlSpot(0, 0)];
_GraphState() {
/// This gets the average PM data for the last 5 seconds and modifies the graph state with this data.
GraphController().getGraphData().listen((Map<String, dynamic> newData) {
/// Focus guard
if (this.mounted) {
setState(() {
start = newData['start'];
......@@ -25,25 +40,15 @@ class _GraphState extends State<Graph> {
spotsPM2_5 = newData['spotsPM2_5'];
spotsPM4 = newData['spotsPM4'];
spotsPM10 = newData['spotsPM10'];
max = newData['max'];
yMax = newData['max'];
now = newData['now'];
});
}
});
}
closeTo(double value, double reference, double delta) => reference - delta <= value && value <= reference + delta;
double start;
double now;
double max = 0;
List<FlSpot> spotsPM1 = [FlSpot(0, 0)];
List<FlSpot> spotsPM2_5 = [FlSpot(0, 0)];
List<FlSpot> spotsPM4 = [FlSpot(0, 0)];
List<FlSpot> spotsPM10 = [FlSpot(0, 0)];
generateLine(List<FlSpot> data, Color color) => LineChartBarData(
/// This creates a line of [FlSpot] of the specific [color]
_generateLine(List<FlSpot> data, Color color) => LineChartBarData(
spots: data,
isCurved: false,
colors: [color],
......@@ -63,9 +68,7 @@ class _GraphState extends State<Graph> {
child: LineChart(
LineChartData(
lineTouchData: LineTouchData(
touchCallback: (lineTouchResponse) => {
print(lineTouchResponse.lineBarSpots.map((e) => e.props))
},
touchCallback: (lineTouchResponse) => { },
handleBuiltInTouches: true,
),
gridData: FlGridData(
......@@ -73,7 +76,7 @@ class _GraphState extends State<Graph> {
drawHorizontalLine: true,
horizontalInterval: 5,
),
// Build from DataPacket would enable getting every 10 seconds add HH:mm:ss
// Build data with timestamp.
titlesData: FlTitlesData(
bottomTitles: SideTitles(
showTitles: true,
......@@ -93,7 +96,6 @@ class _GraphState extends State<Graph> {
return '';
},
),
// TODO Set values for PM
leftTitles: SideTitles(
showTitles: true,
interval: 10,
......@@ -120,21 +122,32 @@ class _GraphState extends State<Graph> {
),
minX: (now ?? 0) - 130,
maxX: (now ?? 0) + 10,
maxY: (this.max ?? 0) + 10,
maxY: (this.yMax ?? 0) + 10,
minY: 0,
clipToBorder: true,
lineBarsData: [
generateLine(spotsPM1, GraphColors.PM1.color),
generateLine(spotsPM2_5, GraphColors.PM2_5.color),
generateLine(spotsPM4, GraphColors.PM4.color),
generateLine(spotsPM10, GraphColors.PM10.color),
_generateLine(spotsPM1, GraphColors.PM1.color),
_generateLine(spotsPM2_5, GraphColors.PM2_5.color),
_generateLine(spotsPM4, GraphColors.PM4.color),
_generateLine(spotsPM10, GraphColors.PM10.color),
],
axisTitleData: FlAxisTitleData(
show: true,
leftTitle: AxisTitle(
showTitle: true,
titleText: 'PM density µg/m³',
margin: 0,
textStyle: TextStyle(
fontSize: 12,
color: Colors.black
)
),
bottomTitle: AxisTitle(
showTitle: true,
titleText: 'Time',
margin: 0,
textStyle: TextStyle(
fontSize: 12,
color: Colors.black
)
)
)
......@@ -150,7 +163,7 @@ class _GraphState extends State<Graph> {
crossAxisAlignment: CrossAxisAlignment.center,
children: GraphColors.list.map((GraphColors gc) =>
Indicator(
text: gc.text,
text: gc.label,
color: gc.color,
isSquare: true,
)
......
import 'package:flutter/material.dart';
import 'package:logair_application/ui/components/graph/graph.dart';
import 'package:logair_application/ui/components/body/data/graph/graph.dart';
/// Enumeration of representative colors for the different [Graph] lines.
class GraphColors {
/// Reference Key (for display)
final String _key;
/// The color that represents the [_key]
final Color _value;
/// Enum constructor with a <K, V>
const GraphColors._internal(this._key, this._value);
/// Overriden [toString] method, this helps with debugging the values.
toString() => 'Enum.$_key ~> $_value';
String get text => _key;
/// This is a getter for the label
String get label => _key;
/// This is a getter for the color associated to the label
Color get color => _value;
/// [GraphColors] representation for PM 1
static const PM1 = const GraphColors._internal('PM 1', Color(0xff0293ee));
/// [GraphColors] representation for PM 2.5
static const PM2_5 = const GraphColors._internal('PM 2.5', Color(0xfff8b250));
/// [GraphColors] representation for PM 4
static const PM4 = const GraphColors._internal('PM 4', Color(0xff845bef));
/// [GraphColors] representation for PM 10
static const PM10 = const GraphColors._internal('PM 10', Color(0xff13d38e));
/// This is a getter for the list of all [GraphColors] represented by this "enum"
static List<GraphColors> get list => [PM1, PM2_5, PM4, PM10];
}
\ No newline at end of file
import 'package:fl_chart/fl_chart.dart';
import 'package:logair_application/logic/handlers/database_handler.dart';
import 'package:logair_application/ui/data_widget.dart';
import 'package:logair_application/ui/components/body/data/data_widget.dart';
/// This Controller type class serves to remove the data aspect of the [LineChart] from Flutter's build tree,
/// therefore reducing memory usage to paint the graph when cycling back to the [DataWidget]..
......
import 'package:flutter/material.dart';
import 'package:logair_application/ui/components/graph/graph.dart';
/// Small label [Widget] that serves as Caption for the [Graph]
class Indicator extends StatelessWidget {
......
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:logair_application/logic/data_packet.dart';
import 'package:logair_application/utils/pm_symbol.dart';
import 'package:logair_application/utils/enums/pm_symbol.dart';
//TODO Add weather ?
/// Widget that displays the data specific to a specific place, depending on the stream provided.
......@@ -90,7 +90,7 @@ class _DataTileState extends State<DataTile> {
Text(
cellTitle.key,
style: TextStyle(
fontSize: 12
fontSize: 14
),
),
Text(
......@@ -115,7 +115,7 @@ class _DataTileState extends State<DataTile> {
child: Text(
title,
style: TextStyle(
fontSize: 14,
fontSize: 15,
),
),
)
......
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:logair_application/logic/controllers/map_display_controller.dart';
import 'package:logair_application/ui/base_widget.dart';
import 'package:logair_application/ui/carousel_card.dart';
import 'package:logair_application/utils/pm_symbol.dart';
class MapContainer extends BaseWidget {
MapContainer();
FlutterMap _buildMap() {
return FlutterMap(
mapController: MapDisplayController().controller(),
options: new MapOptions(
onPositionChanged: (position, hasGesture) => MapDisplayController().setControllerChange(position.center, position.zoom),
center: MapDisplayController().currentPosition(),
zoom: 13.0,
),
layers: [
TileLayerOptions(
urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
subdomains: ['a', 'b', 'c']
),
PolylineLayerOptions(
polylines: MapDisplayController().polylines,
),
CircleLayerOptions(
circles: MapDisplayController().pmMarkers,
),
MarkerLayerOptions(
markers: [
MapDisplayController().marker,
],
),
],
);
}
@override
Widget build(BuildContext context) {
TextEditingController _fromController = TextEditingController();
TextEditingController _toController = TextEditingController();
Expanded _buildMapLayerSelection(String text, Function onPressed) =>
Expanded(
child: RaisedButton(
onPressed: onPressed,
child: Text(text)
),
);
return CarouselCard(
child: Center(