#2559 User Preference setting to use complementary alias colors when dark mode causes the default alias color (black) to have no contrast on background (#2565)

Co-authored-by: denny <dennis.sheirer@gmail.com>
This commit is contained in:
Denny Sheirer
2026-11-02 03:41:35 -05:00
committed by GitHub
parent 14c77c4926
commit 0b3ce66cad
3 changed files with 71 additions and 3 deletions

View File

@@ -25,6 +25,7 @@ import io.github.dsheirer.preference.application.ApplicationPreference;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.Separator;
@@ -45,6 +46,7 @@ public class AppearancePreferenceEditor extends HBox
private final ApplicationPreference mApplicationPreference;
private GridPane mEditorPane;
private VBox mThemeRadioGroup;
private CheckBox mComplementaryAliasColorsCheckBox;
private Slider mGuiScaleSlider;
private Label mGuiScaleValueLabel;
@@ -74,6 +76,12 @@ public class AppearancePreferenceEditor extends HBox
mEditorPane.add(new Label("Theme"), 0, row, 3, 1);
mEditorPane.add(getThemeRadioGroup(), 0, ++row, 3, 1);
mEditorPane.add(getComplementaryAliasColorsCheckBox(), 0, ++row, 3, 1);
Label aliasColorHint = new Label("Dark themes only. Replaces alias colors that are hard to read against " +
"the background with a complementary color.");
aliasColorHint.setWrapText(true);
mEditorPane.add(aliasColorHint, 0, ++row, 3, 1);
Separator separator = new Separator(Orientation.HORIZONTAL);
GridPane.setHgrow(separator, Priority.ALWAYS);
@@ -139,6 +147,22 @@ public class AppearancePreferenceEditor extends HBox
return mThemeRadioGroup;
}
/**
* Check box to opt in to replacing hard to read alias colors with a complementary color in dark themes.
*/
private CheckBox getComplementaryAliasColorsCheckBox()
{
if(mComplementaryAliasColorsCheckBox == null)
{
mComplementaryAliasColorsCheckBox = new CheckBox("Use Complementary Alias Colors");
mComplementaryAliasColorsCheckBox.setSelected(mApplicationPreference.isComplementaryAliasColors());
mComplementaryAliasColorsCheckBox.setOnAction(e -> mApplicationPreference
.setComplementaryAliasColors(mComplementaryAliasColorsCheckBox.isSelected()));
}
return mComplementaryAliasColorsCheckBox;
}
/**
* Slider to adjust the global GUI zoom factor. The slider snaps to 10% increments and only
* persists the value when the user releases the slider so we do not thrash a LAF reinstall on

View File

@@ -74,6 +74,7 @@ public class ThemeManager
private volatile UserPreferences mUserPreferences;
private volatile Theme mCurrentTheme = Theme.LIGHT;
private volatile double mCurrentGuiScale = 1.0d;
private volatile boolean mComplementaryAliasColors = false;
/** Data URL of the currently-active per-theme accent stylesheet, or null. */
private volatile String mAccentStylesheetUrl;
@@ -109,6 +110,7 @@ public class ThemeManager
mUserPreferences = userPreferences;
mCurrentTheme = userPreferences.getApplicationPreference().getTheme();
mCurrentGuiScale = userPreferences.getApplicationPreference().getGuiScale();
mComplementaryAliasColors = userPreferences.getApplicationPreference().isComplementaryAliasColors();
if(firstBind)
{
@@ -225,12 +227,12 @@ public class ThemeManager
* Provides the color to render user-selected content (e.g. an alias) against a background in the current theme.
* @param color selected by the user.
* @param background that the color is rendered against.
* @return the color, or a readable alternative when dark mode is active and the color lacks contrast with the
* background.
* @return the color, or a readable alternative when the user enabled complementary alias colors, dark mode is
* active and the color lacks contrast with the background.
*/
public Color getReadableColor(Color color, Color background)
{
return isDarkMode() ? ColorContrast.getReadable(color, background) : color;
return mComplementaryAliasColors && isDarkMode() ? ColorContrast.getReadable(color, background) : color;
}
public void register(Scene scene)
@@ -288,6 +290,20 @@ public class ThemeManager
Theme updated = mUserPreferences.getApplicationPreference().getTheme();
double updatedScale = mUserPreferences.getApplicationPreference().getGuiScale();
boolean updatedComplementary = mUserPreferences.getApplicationPreference().isComplementaryAliasColors();
if(updatedComplementary != mComplementaryAliasColors)
{
mComplementaryAliasColors = updatedComplementary;
//The Swing table renderers look up the alias color each time they paint.
EventQueue.invokeLater(() -> {
for(Window window: Window.getWindows())
{
window.repaint();
}
});
}
if(updated == mCurrentTheme && Math.abs(updatedScale - mCurrentGuiScale) < 1e-6)
{

View File

@@ -37,6 +37,7 @@ public class ApplicationPreference extends Preference
private static final String PREFERENCE_KEY_DARK_MODE = "dark.mode";
private static final String PREFERENCE_KEY_THEME = "ui.theme";
private static final String PREFERENCE_KEY_GUI_SCALE = "ui.gui.scale";
private static final String PREFERENCE_KEY_COMPLEMENTARY_ALIAS_COLORS = "ui.complementary.alias.colors";
/** Hard bounds for the GUI zoom factor. */
public static final double MIN_GUI_SCALE = 0.5d;
@@ -49,6 +50,7 @@ public class ApplicationPreference extends Preference
private Boolean mAutomaticDiagnosticMonitoring;
private Theme mTheme;
private Double mGuiScale;
private Boolean mComplementaryAliasColors;
/**
* Constructs an instance
@@ -167,6 +169,32 @@ public class ApplicationPreference extends Preference
return getTheme().isDark();
}
/**
* Indicates if alias colors that lack contrast with the background are replaced with a complementary color when a
* dark theme is active.
* @return true if enabled. Default is false, so that aliases display the color selected by the user.
*/
public boolean isComplementaryAliasColors()
{
if(mComplementaryAliasColors == null)
{
mComplementaryAliasColors = mPreferences.getBoolean(PREFERENCE_KEY_COMPLEMENTARY_ALIAS_COLORS, false);
}
return mComplementaryAliasColors;
}
/**
* Sets the enabled state for using complementary alias colors in dark themes.
* @param enabled true to replace alias colors that lack contrast with the background.
*/
public void setComplementaryAliasColors(boolean enabled)
{
mComplementaryAliasColors = enabled;
mPreferences.putBoolean(PREFERENCE_KEY_COMPLEMENTARY_ALIAS_COLORS, enabled);
notifyPreferenceUpdated();
}
/**
* Returns the GUI zoom factor. 1.0 = 100% (default). Bounded to
* [{@link #MIN_GUI_SCALE}, {@link #MAX_GUI_SCALE}].