App 2.27.2: Terminal in the accent colour; Original as a colour choice

Retro and Terminal are one entry each; the accent colour drop-down
offers "Original" first for them, remembered per style. The old
"Retro (accent colour)" entry is folded in and its stored value
migrated. 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:
2026-10-24 21:38:01 +02:00
co-authored by Claude Opus 5.5
parent ef2ba89fba
commit 1c85fd2d9f
10 changed files with 137 additions and 51 deletions
@@ -68,6 +68,7 @@ public class MainActivity extends AppCompatActivity {
private OctagonView octagonView;
/** The styles built on {@link ClusterCanvasView}, fed together. */
private final java.util.List<ClusterCanvasView> canvasStyles = new java.util.ArrayList<>();
private TerminalView terminalView;
/** The pane of each Overview style, by its {@link OverviewStyle} ordinal. */
private View[] stylePanes;
private View consumptionPane;
@@ -282,11 +283,12 @@ public class MainActivity extends AppCompatActivity {
octagonView = new OctagonView(this, null);
View sciFiPane = drawnPane(sciFiView), cartoonPane = drawnPane(cartoonView),
blueprintPane = drawnPane(blueprintView), mgPane = drawnPane(octagonView);
java.util.Collections.addAll(canvasStyles, new MinimalView(this), new TerminalView(this),
terminalView = new TerminalView(this);
java.util.Collections.addAll(canvasStyles, new MinimalView(this), terminalView,
new AviationView(this), new NixieView(this), new ChronographView(this));
View[] canvasPanes = new View[canvasStyles.size()];
for (int i = 0; i < canvasPanes.length; i++) canvasPanes[i] = drawnPane(canvasStyles.get(i));
stylePanes = new View[] { vehiclePane, gaugesPane, cockpitPane, retroPane, retroPane,
stylePanes = new View[] { vehiclePane, gaugesPane, cockpitPane, retroPane,
futuristicPane, sciFiPane, cartoonPane, blueprintPane, mgPane,
canvasPanes[0], canvasPanes[1], canvasPanes[2], canvasPanes[3], canvasPanes[4] };
// The Overview page holds every style; Settings → Overview style picks the one shown.
@@ -1216,14 +1218,32 @@ public class MainActivity extends AppCompatActivity {
}
/** The accent colour; a change recreates the activity so every view takes it. */
/**
* The accent colour; a change recreates the activity so every view takes it. For a style
* with an original palette, "Original colours" comes first: it keeps the style in its own
* colours and leaves the app's accent as it is.
*/
private void bindAccentColor() {
OverviewStyle style = overviewStyle();
AccentColor[] colors = AccentColor.values();
String[] labels = new String[colors.length];
for (int i = 0; i < colors.length; i++) labels[i] = colors[i].label;
int offset = style.hasOriginal ? 1 : 0;
String[] labels = new String[colors.length + offset];
if (offset == 1) labels[0] = getString(R.string.accent_original);
for (int i = 0; i < colors.length; i++) labels[i + offset] = colors[i].label;
AccentColor current = AccentColor.fromPref(prefs.getString(AccentColor.PREF_KEY, null));
bindChoices(settingsPane.findViewById(R.id.accent_choices), labels, current.ordinal(), position -> {
if (colors[position] == current) return;
prefs.edit().putString(AccentColor.PREF_KEY, colors[position].name()).apply();
int selected = originalColours(style) ? 0 : current.ordinal() + offset;
bindChoices(settingsPane.findViewById(R.id.accent_choices), labels, selected, position -> {
if (style.hasOriginal) prefs.edit().putBoolean(style.originalKey(), position == 0).apply();
if (position < offset) {
applyOverviewStyle();
return;
}
AccentColor picked = colors[position - offset];
if (picked == current) {
applyOverviewStyle();
return;
}
prefs.edit().putString(AccentColor.PREF_KEY, picked.name()).apply();
recreate();
});
applyAccentAvailability();
@@ -1488,15 +1508,28 @@ public class MainActivity extends AppCompatActivity {
private Double dashTripKm;
private OverviewStyle overviewStyle() {
return OverviewStyle.fromPref(prefs.getString(PREF_OVERVIEW_STYLE, null));
String stored = prefs.getString(PREF_OVERVIEW_STYLE, null);
OverviewStyle style = OverviewStyle.fromPref(stored);
if (OverviewStyle.wasAccentEntry(stored)) {
// "Retro (accent colour)" before 2.27.2: now Retro, in the accent colour.
prefs.edit().putString(PREF_OVERVIEW_STYLE, style.name()).putBoolean(style.originalKey(), false).apply();
}
return style;
}
/** Whether a style with an original palette shows it (the default) or the accent colour. */
private boolean originalColours(OverviewStyle style) {
return style.hasOriginal && prefs.getBoolean(style.originalKey(), true);
}
private void applyOverviewStyle() {
OverviewStyle style = overviewStyle();
for (View pane : stylePanes) pane.setVisibility(pane == stylePanes[style.ordinal()] ? View.VISIBLE : View.GONE);
// Retro in either palette: one pane, the view told which.
retroView.setAccentPalette(style == OverviewStyle.RETRO_ACCENT);
applyAccentAvailability();
// Retro and Terminal: their original palette or the accent colour, as chosen for each.
retroView.setAccentPalette(!originalColours(OverviewStyle.RETRO));
terminalView.setAccentPalette(!originalColours(OverviewStyle.TERMINAL));
// The accent choices depend on the style ("Original colours" for Retro and Terminal).
if (settingsPane != null) bindAccentColor();
}
/**
@@ -1520,7 +1553,7 @@ public class MainActivity extends AppCompatActivity {
private String[] styleLabels() {
return new String[] { 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_retro_accent), getString(R.string.overview_style_futuristic),
getString(R.string.overview_style_futuristic),
getString(R.string.overview_style_scifi), getString(R.string.overview_style_cartoon),
getString(R.string.overview_style_blueprint), getString(R.string.overview_style_mg),
getString(R.string.overview_style_minimal), getString(R.string.overview_style_terminal),
@@ -1533,8 +1566,8 @@ public class MainActivity extends AppCompatActivity {
OverviewStyle[] styles = OverviewStyle.values();
com.google.android.material.textfield.MaterialAutoCompleteTextView field =
settingsPane.findViewById(R.id.overview_style_choices);
// Wider than its field, which shares a row with the accent colour: "Retro (accent colour)".
field.setDropDownWidth(Math.round(360 * getResources().getDisplayMetrics().density));
// Wider than its field, which shares a row with the accent colour.
field.setDropDownWidth(Math.round(320 * getResources().getDisplayMetrics().density));
bindChoices(field, styleLabels(), overviewStyle().ordinal(),
position -> {
prefs.edit().putString(PREF_OVERVIEW_STYLE, styles[position].name()).apply();
@@ -2,43 +2,65 @@ package com.evsuite.abrp;
/**
* The Overview styles in the order of the Settings drop-down, the value each is stored as, and
* whether it is drawn in the chosen accent colour. Styles with their own fixed palette (Retro's
* display, the starship console, the cartoon, the blueprint, the terminal, the flight display,
* the nixie tubes) ignore it, so Settings only offers the accent colour for the others. Pure
* Java, unit-tested.
* how it takes colour:
*
* - {@link #usesAccent}: drawn in the chosen accent colour, so Settings offers the accent
* colour for it. Styles with only their own fixed palette (the starship console, the cartoon,
* the blueprint, the flight display, the nixie tubes) ignore it and Settings greys it out.
* - {@link #hasOriginal}: has an original palette of its own as well (Retro's turquoise
* display, the terminal's green phosphor); Settings then offers "Original colours" above the
* accent colours, remembered per style under {@link #originalKey()}.
*
* Pure Java, unit-tested.
*/
enum OverviewStyle {
TILES(true),
GAUGES(true),
COCKPIT(true),
RETRO(false),
RETRO_ACCENT(true),
FUTURISTIC(true),
SCIFI(false),
CARTOON(false),
BLUEPRINT(false),
MG(true),
MINIMAL(true),
TERMINAL(false),
AVIATION(false),
NIXIE(false),
CHRONOGRAPH(true);
TILES(true, false),
GAUGES(true, false),
COCKPIT(true, false),
RETRO(true, true),
FUTURISTIC(true, false),
SCIFI(false, false),
CARTOON(false, false),
BLUEPRINT(false, false),
MG(true, false),
MINIMAL(true, false),
TERMINAL(true, true),
AVIATION(false, false),
NIXIE(false, false),
CHRONOGRAPH(true, false);
static final String PREF_KEY = "overview_style";
/** Drawn in the accent colour, so the accent choice changes how it looks. */
final boolean usesAccent;
final boolean hasOriginal;
OverviewStyle(boolean usesAccent) {
OverviewStyle(boolean usesAccent, boolean hasOriginal) {
this.usesAccent = usesAccent;
this.hasOriginal = hasOriginal;
}
/** The stored style; "DASHBOARD" (Gauges before 2.22.3) and anything unknown handled. */
/** Where the choice between the original palette and the accent colour is kept. */
String originalKey() {
return "original_colours_" + name();
}
/**
* The stored style. Older values: "DASHBOARD" (Gauges before 2.22.3), and "RETRO_ACCENT" /
* "TERMINAL_ACCENT" (separate entries before 2.27.2, now the style in the accent colour —
* see {@link #wasAccentEntry}). Anything unknown is Tiles.
*/
static OverviewStyle fromPref(String stored) {
if ("DASHBOARD".equals(stored)) return GAUGES;
if ("RETRO_ACCENT".equals(stored)) return RETRO;
if ("TERMINAL_ACCENT".equals(stored)) return TERMINAL;
for (OverviewStyle style : values()) {
if (style.name().equals(stored)) return style;
}
return TILES;
}
/** A stored value from when the accent-coloured variant was its own entry. */
static boolean wasAccentEntry(String stored) {
return "RETRO_ACCENT".equals(stored) || "TERMINAL_ACCENT".equals(stored);
}
}
@@ -14,6 +14,10 @@ import java.util.Locale;
* a prompt with a blinking cursor (it blinks because readings redraw the view; it does not
* animate on its own). A low battery turns its row amber. Unread values show "—" and an empty
* bar.
*
* Two palettes: green phosphor, or the chosen accent colour ({@link #setAccentPalette}) — the
* text in its light shade, the command line in the accent itself, on plain black. The low
* battery stays amber in both.
*/
final class TerminalView extends ClusterCanvasView {
@@ -21,23 +25,33 @@ final class TerminalView extends ClusterCanvasView {
private final Paint text = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint scan = new Paint();
private final int green, dim, amber;
private final int accentText, accentDim;
private final int amber = 0xFFFFB000;
private int green, dim, background;
TerminalView(Context context) {
super(context);
green = 0xFF33FF66;
dim = 0xFF1C8A3A;
amber = 0xFFFFB000;
accentText = AccentColor.resolve(context, R.attr.evAccentLight);
accentDim = AccentColor.resolve(context, R.attr.evAccent);
setAccentPalette(false);
text.setTypeface(Typeface.MONOSPACE);
scan.setColor(0x0CFFFFFF);
}
/** The chosen accent colour instead of green phosphor. */
void setAccentPalette(boolean accent) {
green = accent ? accentText : 0xFF33FF66;
dim = accent ? accentDim : 0xFF1C8A3A;
background = accent ? 0xFF050505 : 0xFF020A04;
invalidate();
}
@Override
protected void onDraw(Canvas c) {
super.onDraw(c);
float w = getWidth(), h = getHeight();
if (w <= 0 || h <= 0) return;
c.drawColor(0xFF020A04);
c.drawColor(background);
// About 14 rows at 1.32 em each plus margins; monospace is about 0.6 em wide and the
// longest row about 58 characters.
+1 -1
View File
@@ -126,7 +126,6 @@
<string name="overview_style_cockpit">Cockpit</string>
<string name="overview_style_retro">Retro</string>
<string name="overview_style_futuristic">Futuristic</string>
<string name="overview_style_retro_accent">Retro (accent colour)</string>
<string name="overview_style_scifi">Sci-fi</string>
<string name="overview_style_cartoon">Cartoon</string>
<string name="overview_style_blueprint">Blueprint</string>
@@ -136,6 +135,7 @@
<string name="overview_fullscreen_exit">Show the navigation again</string>
<string name="overview_style_minimal">Minimal</string>
<string name="overview_style_terminal">Terminal</string>
<string name="accent_original">Original</string>
<string name="overview_style_aviation">Aviation</string>
<string name="overview_style_nixie">Nixie tubes</string>
<string name="overview_style_chronograph">Chronograph</string>
@@ -19,17 +19,23 @@ public class OverviewStyleTest {
@Test
public void oldAndUnknownValues() {
assertEquals(OverviewStyle.GAUGES, OverviewStyle.fromPref("DASHBOARD"));
assertEquals(OverviewStyle.RETRO, OverviewStyle.fromPref("RETRO_ACCENT"));
assertEquals(OverviewStyle.TERMINAL, OverviewStyle.fromPref("TERMINAL_ACCENT"));
assertTrue(OverviewStyle.wasAccentEntry("RETRO_ACCENT"));
assertFalse(OverviewStyle.wasAccentEntry("RETRO"));
assertEquals(OverviewStyle.TILES, OverviewStyle.fromPref(null));
assertEquals(OverviewStyle.TILES, OverviewStyle.fromPref("NOPE"));
}
@Test
public void onlyStylesDrawnInTheAccentOfferIt() {
public void colourOptions() {
assertTrue(OverviewStyle.TILES.usesAccent);
assertTrue(OverviewStyle.RETRO_ACCENT.usesAccent);
assertTrue(OverviewStyle.MG.usesAccent);
assertFalse(OverviewStyle.RETRO.usesAccent);
assertFalse(OverviewStyle.TILES.hasOriginal);
assertTrue(OverviewStyle.RETRO.usesAccent);
assertTrue(OverviewStyle.RETRO.hasOriginal);
assertTrue(OverviewStyle.TERMINAL.hasOriginal);
assertFalse(OverviewStyle.CARTOON.usesAccent);
assertFalse(OverviewStyle.NIXIE.usesAccent);
assertEquals("original_colours_RETRO", OverviewStyle.RETRO.originalKey());
}
}