ui: gps compass widget layout changes
- angular direction (0-359) + 16ths compassrose - documented in ui README
This commit is contained in:
@@ -34,6 +34,7 @@ All services use singleton pattern with `ServiceName.instance`.
|
|||||||
|--------|---------|
|
|--------|---------|
|
||||||
| `NavigatorWidget` | Animated character with emotion states (images precached at startup) |
|
| `NavigatorWidget` | Animated character with emotion states (images precached at startup) |
|
||||||
| `AccelGraph` | Real-time accelerometer visualization with gravity compensation |
|
| `AccelGraph` | Real-time accelerometer visualization with gravity compensation |
|
||||||
|
| `GpsCompass` | GPS heading compass with rotating navigation icon and degree readout |
|
||||||
| `WhiskeyMark` | Gimbal-style horizon indicator using IMU roll/pitch |
|
| `WhiskeyMark` | Gimbal-style horizon indicator using IMU roll/pitch |
|
||||||
| `SystemBar` | Top status bar (time, connection, Pi temp) |
|
| `SystemBar` | Top status bar (time, connection, Pi temp) |
|
||||||
| `StatBox` | Reusable metric display box |
|
| `StatBox` | Reusable metric display box |
|
||||||
|
|||||||
@@ -7,11 +7,21 @@ class GpsCompass extends StatelessWidget {
|
|||||||
|
|
||||||
const GpsCompass({super.key, this.heading});
|
const GpsCompass({super.key, this.heading});
|
||||||
|
|
||||||
bool get _hasSignal => heading != null && !heading!.isNaN && heading! >= 0 && heading! < 360;
|
bool get _hasSignal => heading != null;
|
||||||
|
|
||||||
String get _displayHeading {
|
String get _displayHeading {
|
||||||
if (!_hasSignal) return '—-'; // Intentional double dash
|
if (!_hasSignal) return 'N/A'; // Just make it clear; redundant anyways, this only gets called when _hasSignal
|
||||||
return '${heading!.round()}°';
|
return '${(heading! % 360).round()}'; // No need for the degree symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
String get _compassDirection {
|
||||||
|
if (!_hasSignal) return '';
|
||||||
|
final directions = [
|
||||||
|
'N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE',
|
||||||
|
'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW'
|
||||||
|
];
|
||||||
|
final index = ((heading! % 360) / 22.5).round() % 16;
|
||||||
|
return directions[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -19,7 +29,7 @@ class GpsCompass extends StatelessWidget {
|
|||||||
final theme = AppTheme.of(context);
|
final theme = AppTheme.of(context);
|
||||||
|
|
||||||
// No signal = subdued color, valid = foreground
|
// No signal = subdued color, valid = foreground
|
||||||
final color = _hasSignal ? theme.foreground : theme.subdued;
|
final iconColour = _hasSignal ? theme.foreground : theme.highlight;
|
||||||
|
|
||||||
// Convert to radians, 0 = no rotation when no signal
|
// Convert to radians, 0 = no rotation when no signal
|
||||||
final angle = _hasSignal ? (heading! * math.pi / 180.0) : 0.0;
|
final angle = _hasSignal ? (heading! * math.pi / 180.0) : 0.0;
|
||||||
@@ -35,8 +45,8 @@ class GpsCompass extends StatelessWidget {
|
|||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
child: Icon(
|
child: Icon(
|
||||||
_hasSignal ? Icons.navigation : Icons.navigation_outlined,
|
_hasSignal ? Icons.navigation : Icons.navigation_outlined,
|
||||||
size: 80,
|
size: 120,
|
||||||
color: color,
|
color: iconColour,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -46,10 +56,10 @@ class GpsCompass extends StatelessWidget {
|
|||||||
child: FittedBox(
|
child: FittedBox(
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
child: Text(
|
child: Text(
|
||||||
_displayHeading,
|
_hasSignal ? "${_displayHeading} ${_compassDirection}" : "N/A",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 60,
|
fontSize: 80,
|
||||||
color: color,
|
color: theme.subdued,
|
||||||
fontFamily: 'DIN1451',
|
fontFamily: 'DIN1451',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user