App 2.23.1: Retro style also in the accent colour
"Retro (accent colour)" draws the display in the chosen paint colour and the labels in its light shade; regeneration stays green, a low battery turns amber. Listed under Retro. Emulator only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
This commit is contained in:
@@ -69,7 +69,7 @@ Repository: `ssh://git@git.stinnesbeck.com:2222/nils/mg4.git` (remote `origin`),
|
|||||||
|
|
||||||
| Tab | Contents |
|
| Tab | Contents |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Overview | value tiles (battery, range, range/usage/energy since start, 5-min averages of range, usage, power, speed), vehicle info (odometer, lease allowance and the odometer against it), tyre pressures; read every 0.2 s on a background thread. Five styles (Settings → Overview style): Tiles, Gauges (`GaugeView` needles), Cockpit (`RingView` rings, `TraceView` power trace), Retro (`RetroView`, seven-segment VFD), Futuristic (`FlowView`, animated energy flow) |
|
| Overview | value tiles (battery, range, range/usage/energy since start, 5-min averages of range, usage, power, speed), vehicle info (odometer, lease allowance and the odometer against it), tyre pressures; read every 0.2 s on a background thread. Styles (Settings → Overview style): Tiles, Gauges (`GaugeView` needles), Cockpit (`RingView` rings, `TraceView` power trace), Retro (`RetroView`, seven-segment VFD, classic or in the accent colour), Futuristic (`FlowView`, animated energy flow) |
|
||||||
| Consumption / Charging | period totals, daily log, charging sessions and curve |
|
| Consumption / Charging | period totals, daily log, charging sessions and curve |
|
||||||
| Live data | on/off, ABRP API key and user token, upload frequency |
|
| Live data | on/off, ABRP API key and user token, upload frequency |
|
||||||
| Server | URL, pairing by QR, ingest token, installation ID (read-only), config import |
|
| Server | URL, pairing by QR, ingest token, installation ID (read-only), config import |
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ with the server using a token of its own, obtained by pairing with a phone (belo
|
|||||||
|
|
||||||
| Tab | What it shows |
|
| Tab | What it shows |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **Overview** | Battery, range, power and speed; range, usage and energy since start; 5-minute averages of range, usage, power and speed; vehicle info (odometer, climate setpoint) and tyre pressures. Read five times a second. Five looks to choose from in Settings → Overview style: Tiles, Gauges, Cockpit, Retro and Futuristic |
|
| **Overview** | Battery, range, power and speed; range, usage and energy since start; 5-minute averages of range, usage, power and speed; vehicle info (odometer, climate setpoint) and tyre pressures. Read five times a second. Looks to choose from in Settings → Overview style: Tiles, Gauges, Cockpit, Retro (classic turquoise or in your accent colour) and Futuristic |
|
||||||
| **Consumption** | Lifetime, last 7 and 30 days, Trip A and B (distance, energy, average consumption and speed, SOC change), and a daily log of the last four months |
|
| **Consumption** | Lifetime, last 7 and 30 days, Trip A and B (distance, energy, average consumption and speed, SOC change), and a daily log of the last four months |
|
||||||
| **Charging** | The current session (SOC, voltage, current, power, energy into the battery and from the grid, time, cost) and its SOC/power curve |
|
| **Charging** | The current session (SOC, voltage, current, power, energy into the battery and from the grid, time, cost) and its SOC/power curve |
|
||||||
| **Live data** | Live data on/off, ABRP credentials for sending directly from the car, upload frequency |
|
| **Live data** | Live data on/off, ABRP credentials for sending directly from the car, upload frequency |
|
||||||
|
|||||||
@@ -131,6 +131,12 @@ tyre pressures, GPS (lat, lon, elevation, heading) and the is_* flags. It does *
|
|||||||
confirmed car facts, app structure, UI conventions, build/test/ship, documents. It replaces
|
confirmed car facts, app structure, UI conventions, build/test/ship, documents. It replaces
|
||||||
upstream's EVABRPUploader text. The test emulator is now in the flake: `nix run .#car-emulator`
|
upstream's EVABRPUploader text. The test emulator is now in the flake: `nix run .#car-emulator`
|
||||||
(Android 9 AOSP at 1920×720, 160 dpi; the car build installs as the system user — checked).
|
(Android 9 AOSP at 1920×720, 160 dpi; the car build installs as the system user — checked).
|
||||||
|
- 2026-10-24 — App 2.23.1 (branch `styles-retro-future`): "Retro (accent colour)", the Retro
|
||||||
|
style in the chosen paint colour — display in `evAccent`, labels in `evAccentLight`;
|
||||||
|
regeneration stays green, a low battery turns amber (not red, so it never looks like Dynamic
|
||||||
|
Red). Same `RetroView`, `setAccentPalette`; listed under Retro, stored as `RETRO_ACCENT`.
|
||||||
|
Checked on the emulator in Dynamic Red with sample values
|
||||||
|
(`screenshots/nilsmg4-2.23.1-retro-accent.png`). Not tried on the car.
|
||||||
- 2026-10-24 — App 2.23.0 (branch `styles-retro-future`): two more Overview styles, each one
|
- 2026-10-24 — App 2.23.0 (branch `styles-retro-future`): two more Overview styles, each one
|
||||||
Canvas view fed a `ClusterValues` per reading. **Retro** (`RetroView`): an 80s digital cluster
|
Canvas view fed a `ClusterValues` per reading. **Retro** (`RetroView`): an 80s digital cluster
|
||||||
as a vacuum fluorescent display — slanted seven-segment digits (`SevenSegment`, unit-tested)
|
as a vacuum fluorescent display — slanted seven-segment digits (`SevenSegment`, unit-tested)
|
||||||
|
|||||||
+2
-2
@@ -34,8 +34,8 @@ android {
|
|||||||
applicationId "com.stinnesbeck.nilsmg4"
|
applicationId "com.stinnesbeck.nilsmg4"
|
||||||
minSdk 27
|
minSdk 27
|
||||||
targetSdk 36
|
targetSdk 36
|
||||||
versionCode 115
|
versionCode 116
|
||||||
versionName "2.23.0"
|
versionName "2.23.1"
|
||||||
|
|
||||||
// Nothing about the server ships in the APK: its URL and ingest token are entered in
|
// Nothing about the server ships in the APK: its URL and ingest token are entered in
|
||||||
// the app's Server tab (ServerConfig), and the database is only reachable by the server.
|
// the app's Server tab (ServerConfig), and the database is only reachable by the server.
|
||||||
|
|||||||
@@ -1442,7 +1442,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
private Double dashTripKm;
|
private Double dashTripKm;
|
||||||
|
|
||||||
/** The stored values of the Overview styles, in the order of the drop-down. */
|
/** The stored values of the Overview styles, in the order of the drop-down. */
|
||||||
private static final String[] OVERVIEW_STYLES = { "TILES", "GAUGES", "COCKPIT", "RETRO", "FUTURISTIC" };
|
private static final String[] OVERVIEW_STYLES = { "TILES", "GAUGES", "COCKPIT", "RETRO", "RETRO_ACCENT", "FUTURISTIC" };
|
||||||
|
|
||||||
/** The chosen style's index in {@link #OVERVIEW_STYLES}; anything unknown is Tiles. */
|
/** The chosen style's index in {@link #OVERVIEW_STYLES}; anything unknown is Tiles. */
|
||||||
private int overviewStyle() {
|
private int overviewStyle() {
|
||||||
@@ -1457,15 +1457,17 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
vehiclePane.setVisibility(style == 0 ? View.VISIBLE : View.GONE);
|
vehiclePane.setVisibility(style == 0 ? View.VISIBLE : View.GONE);
|
||||||
gaugesPane.setVisibility(style == 1 ? View.VISIBLE : View.GONE);
|
gaugesPane.setVisibility(style == 1 ? View.VISIBLE : View.GONE);
|
||||||
cockpitPane.setVisibility(style == 2 ? View.VISIBLE : View.GONE);
|
cockpitPane.setVisibility(style == 2 ? View.VISIBLE : View.GONE);
|
||||||
retroPane.setVisibility(style == 3 ? View.VISIBLE : View.GONE);
|
// Retro in either palette: one pane, the view told which.
|
||||||
futuristicPane.setVisibility(style == 4 ? View.VISIBLE : View.GONE);
|
retroPane.setVisibility(style == 3 || style == 4 ? View.VISIBLE : View.GONE);
|
||||||
|
((RetroView) retroPane.findViewById(R.id.retro_view)).setAccentPalette(style == 4);
|
||||||
|
futuristicPane.setVisibility(style == 5 ? View.VISIBLE : View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Tiles, Gauges, Cockpit, Retro or Futuristic; all are fed on every reading. */
|
/** Tiles, Gauges, Cockpit, Retro (classic or accent colour) or Futuristic; all are fed on every reading. */
|
||||||
private void bindOverviewStyle() {
|
private void bindOverviewStyle() {
|
||||||
String[] labels = { getString(R.string.overview_style_tiles), getString(R.string.overview_style_gauges),
|
String[] labels = { getString(R.string.overview_style_tiles), getString(R.string.overview_style_gauges),
|
||||||
getString(R.string.overview_style_cockpit), getString(R.string.overview_style_retro),
|
getString(R.string.overview_style_cockpit), getString(R.string.overview_style_retro),
|
||||||
getString(R.string.overview_style_futuristic) };
|
getString(R.string.overview_style_retro_accent), getString(R.string.overview_style_futuristic) };
|
||||||
bindChoices(settingsPane.findViewById(R.id.overview_style_choices), labels, overviewStyle(),
|
bindChoices(settingsPane.findViewById(R.id.overview_style_choices), labels, overviewStyle(),
|
||||||
position -> {
|
position -> {
|
||||||
prefs.edit().putString(PREF_OVERVIEW_STYLE, OVERVIEW_STYLES[position]).apply();
|
prefs.edit().putString(PREF_OVERVIEW_STYLE, OVERVIEW_STYLES[position]).apply();
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ import java.util.Locale;
|
|||||||
* Left: charge as a bar, the percentage and range. Right: 5-minute usage, the average since
|
* Left: charge as a bar, the percentage and range. Right: 5-minute usage, the average since
|
||||||
* start and the distance. Bottom: climate, clock, odometer. Unread values show dashes and light
|
* start and the distance. Bottom: climate, clock, odometer. Unread values show dashes and light
|
||||||
* no bar segments. The whole pane is one Canvas, redrawn only when a reading arrives.
|
* no bar segments. The whole pane is one Canvas, redrawn only when a reading arrives.
|
||||||
|
*
|
||||||
|
* Two palettes: the classic one (turquoise display, amber labels), or the chosen accent colour
|
||||||
|
* for the display and its light shade for the labels ({@link #setAccentPalette}). Regeneration
|
||||||
|
* stays green in both; a low battery is red in the classic palette and amber in the accent one,
|
||||||
|
* so it never looks like the accent itself.
|
||||||
*/
|
*/
|
||||||
public final class RetroView extends View {
|
public final class RetroView extends View {
|
||||||
|
|
||||||
@@ -33,24 +38,36 @@ public final class RetroView extends View {
|
|||||||
private final Paint bezel = new Paint(Paint.ANTI_ALIAS_FLAG);
|
private final Paint bezel = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
private final Path path = new Path();
|
private final Path path = new Path();
|
||||||
private final RectF rect = new RectF();
|
private final RectF rect = new RectF();
|
||||||
private final int lit, regen, amber, warn;
|
private final int classicLit, classicLabel, classicWarn, accentLit, accentLabel, regen;
|
||||||
|
private int lit, amber, warn;
|
||||||
private ClusterValues v = new ClusterValues();
|
private ClusterValues v = new ClusterValues();
|
||||||
|
|
||||||
public RetroView(Context context, AttributeSet attrs) {
|
public RetroView(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
lit = context.getColor(R.color.retro_lit);
|
classicLit = context.getColor(R.color.retro_lit);
|
||||||
|
classicLabel = context.getColor(R.color.retro_label);
|
||||||
|
classicWarn = context.getColor(R.color.retro_warn);
|
||||||
|
accentLit = AccentColor.resolve(context, R.attr.evAccent);
|
||||||
|
accentLabel = AccentColor.resolve(context, R.attr.evAccentLight);
|
||||||
regen = context.getColor(R.color.retro_regen);
|
regen = context.getColor(R.color.retro_regen);
|
||||||
amber = context.getColor(R.color.retro_label);
|
|
||||||
warn = context.getColor(R.color.retro_warn);
|
|
||||||
ghost.setColor(AccentColor.withAlpha(lit, 0x14));
|
|
||||||
glow.setStyle(Paint.Style.STROKE);
|
glow.setStyle(Paint.Style.STROKE);
|
||||||
glow.setStrokeJoin(Paint.Join.ROUND);
|
glow.setStrokeJoin(Paint.Join.ROUND);
|
||||||
label.setColor(amber);
|
|
||||||
label.setTypeface(Typeface.create(Typeface.MONOSPACE, Typeface.BOLD));
|
label.setTypeface(Typeface.create(Typeface.MONOSPACE, Typeface.BOLD));
|
||||||
label.setLetterSpacing(0.12f);
|
label.setLetterSpacing(0.12f);
|
||||||
panel.setColor(context.getColor(R.color.retro_panel));
|
panel.setColor(context.getColor(R.color.retro_panel));
|
||||||
bezel.setStyle(Paint.Style.STROKE);
|
bezel.setStyle(Paint.Style.STROKE);
|
||||||
bezel.setColor(context.getColor(R.color.retro_bezel));
|
bezel.setColor(context.getColor(R.color.retro_bezel));
|
||||||
|
setAccentPalette(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The chosen accent colour instead of the classic turquoise and amber. */
|
||||||
|
void setAccentPalette(boolean accent) {
|
||||||
|
lit = accent ? accentLit : classicLit;
|
||||||
|
amber = accent ? accentLabel : classicLabel;
|
||||||
|
warn = accent ? classicLabel : classicWarn;
|
||||||
|
ghost.setColor(AccentColor.withAlpha(lit, 0x14));
|
||||||
|
label.setColor(amber);
|
||||||
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setValues(ClusterValues values) {
|
void setValues(ClusterValues values) {
|
||||||
|
|||||||
@@ -130,6 +130,7 @@
|
|||||||
<string name="overview_style_cockpit">Cockpit</string>
|
<string name="overview_style_cockpit">Cockpit</string>
|
||||||
<string name="overview_style_retro">Retro</string>
|
<string name="overview_style_retro">Retro</string>
|
||||||
<string name="overview_style_futuristic">Futuristic</string>
|
<string name="overview_style_futuristic">Futuristic</string>
|
||||||
|
<string name="overview_style_retro_accent">Retro (accent colour)</string>
|
||||||
<string name="cockpit_battery">BATTERY</string>
|
<string name="cockpit_battery">BATTERY</string>
|
||||||
<string name="cockpit_usage">USAGE · 5 MIN</string>
|
<string name="cockpit_usage">USAGE · 5 MIN</string>
|
||||||
<string name="cockpit_usage_unit">kWh/100 km</string>
|
<string name="cockpit_usage_unit">kWh/100 km</string>
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 226 KiB |
Reference in New Issue
Block a user