Skip to content

Commit

Permalink
Provide access to dark theme in preferences (#4372)
Browse files Browse the repository at this point in the history
Fixes #4130.
  • Loading branch information
Ali96kz authored and tobiasdiez committed Oct 17, 2018
1 parent c2d9832 commit 453e7b5
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 21 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#
- We add auto url formatting when user paste link to URL field in entry editor. [#254](https://github.com/koppor/jabref/issues/254)
- We added a minimal height for the entry editor so that it can no longer be hidden by accident. [#4279](https://github.com/JabRef/jabref/issues/4279)
- We added a new keyboard shortcut so that the entry editor could be closed by <kbd>Ctrl<kbd> + <kbd>E<kbd>. [#4222] (https://github.com/JabRef/jabref/issues/4222)

- We added an option in the preference dialog box, that allows user to pick the dark or light theme option. [#4130] (https://github.com/JabRef/jabref/issues/4130)



Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/jabref/Globals.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ public static synchronized KeyBindingRepository getKeyPrefs() {
}

// Background tasks
public static void startBackgroundTasks() {
public static void startBackgroundTasks() throws JabRefException {
Globals.fileUpdateMonitor = new DefaultFileUpdateMonitor();
JabRefExecutorService.INSTANCE.executeInterruptableTask(Globals.fileUpdateMonitor, "FileUpdateMonitor");

themeLoader = new ThemeLoader(fileUpdateMonitor);
themeLoader = new ThemeLoader(fileUpdateMonitor, prefs);

if (Globals.prefs.shouldCollectTelemetry() && !GraphicsEnvironment.isHeadless()) {
startTelemetryClient();
Expand Down
36 changes: 32 additions & 4 deletions src/main/java/org/jabref/gui/preferences/AppearancePrefsTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import javafx.scene.Node;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
Expand All @@ -16,12 +18,16 @@

class AppearancePrefsTab extends Pane implements PrefsTab {

public static final String BASE_CSS = "Base.css";
public static final String DARK_CSS = "Dark.css";
private final JabRefPreferences prefs;
private final CheckBox fontTweaksLAF;
private final TextField fontSize;
private final CheckBox overrideFonts;
private final VBox container = new VBox();
private final DialogService dialogService;
private final RadioButton lightTheme;
private final RadioButton darkTheme;

/**
* Customization of appearance parameters.
Expand All @@ -41,7 +47,18 @@ public AppearancePrefsTab(DialogService dialogService, JabRefPreferences prefs)
fontSizeContainer.disableProperty().bind(overrideFonts.selectedProperty().not());
fontTweaksLAF = new CheckBox(Localization.lang("Tweak font rendering for entry editor on Linux"));

container.getChildren().addAll(overrideFonts, fontSizeContainer, fontTweaksLAF);
ToggleGroup themeGroup = new ToggleGroup();
lightTheme = new RadioButton("Light theme");
lightTheme.setToggleGroup(themeGroup);
darkTheme = new RadioButton("Dark theme");
darkTheme.setToggleGroup(themeGroup);

if (prefs.get(JabRefPreferences.FX_THEME).equals(BASE_CSS))
lightTheme.setSelected(true);
else if (prefs.get(JabRefPreferences.FX_THEME).equals(DARK_CSS))
darkTheme.setSelected(true);

container.getChildren().addAll(overrideFonts, fontSizeContainer, fontTweaksLAF, lightTheme, darkTheme);

}

Expand All @@ -68,10 +85,21 @@ public void storeSettings() {
int newFontSize = Integer.parseInt(fontSize.getText());
prefs.putInt(JabRefPreferences.MAIN_FONT_SIZE, newFontSize);

boolean isThemeChanged = false;

if (lightTheme.isSelected() && !prefs.get(JabRefPreferences.FX_THEME).equals(BASE_CSS)) {
prefs.put(JabRefPreferences.FX_THEME, BASE_CSS);
isThemeChanged = true;
} else if (darkTheme.isSelected() && !prefs.get(JabRefPreferences.FX_THEME).equals(DARK_CSS)) {
prefs.put(JabRefPreferences.FX_THEME, DARK_CSS);
isThemeChanged = true;
}

boolean isRestartRequired =
oldFxTweakValue != fontTweaksLAF.isSelected()
|| oldOverrideDefaultFontSize != overrideFonts.isSelected()
|| oldFontSize != newFontSize;
(oldFxTweakValue != fontTweaksLAF.isSelected())
|| (oldOverrideDefaultFontSize != overrideFonts.isSelected())
|| (oldFontSize != newFontSize)
|| isThemeChanged;
if (isRestartRequired) {
dialogService.showWarningDialogAndWait(Localization.lang("Settings"),
Localization.lang("Some appearance settings you changed require to restart JabRef to come into effect."));
Expand Down
36 changes: 24 additions & 12 deletions src/main/java/org/jabref/gui/util/ThemeLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import javafx.scene.Parent;
import javafx.scene.Scene;

import org.jabref.JabRefException;
import org.jabref.gui.JabRefFrame;
import org.jabref.model.strings.StringUtil;
import org.jabref.model.util.FileUpdateMonitor;
Expand All @@ -21,28 +22,39 @@

/**
* Installs the style file and provides live reloading.
*
* <p>
* The live reloading has to be turned on by setting the <code>-Djabref.theme.css</code> property.
* There two possible modes:
* (1) When only <code>-Djabref.theme.css</code> is specified, then the standard <code>Base.css</code> that is found will be watched
* and on changes in that file, the style-sheet will be reloaded and changes are immediately visible.
* (2) When a path to a css file is passed to <code>-Djabref.theme.css</code>, then the given style is loaded in addition to the base css file.
* Changes in the specified css file lead to an immediate redraw of the interface.
*
* (1) When only <code>-Djabref.theme.css</code> is specified, then the standard <code>Base.css</code> that is found will be watched
* and on changes in that file, the style-sheet will be reloaded and changes are immediately visible.
* (2) When a path to a css file is passed to <code>-Djabref.theme.css</code>, then the given style is loaded in addition to the base css file.
* Changes in the specified css file lead to an immediate redraw of the interface.
* <p>
* When working from an IDE, this usually means that the <code>Base.css</code> is located in the build folder.
* To use the css-file that is located in the sources directly, the full path can be given as value for the "VM option":
* <code>-Djabref.theme.css="/path/to/src/Base.css"</code>
*
*/
public class ThemeLoader {

private static final String DEFAULT_PATH_MAIN_CSS = JabRefFrame.class.getResource("Base.css").toExternalForm();
private static final String CSS_SYSTEM_PROPERTY = System.getProperty("jabref.theme.css");
private static final Logger LOGGER = LoggerFactory.getLogger(ThemeLoader.class);
private String cssProperty = System.getProperty("jabref.theme.css");
private final FileUpdateMonitor fileUpdateMonitor;

public ThemeLoader(FileUpdateMonitor fileUpdateMonitor) {
public ThemeLoader(FileUpdateMonitor fileUpdateMonitor, JabRefPreferences jabRefPreferences) throws JabRefException {
this.fileUpdateMonitor = Objects.requireNonNull(fileUpdateMonitor);

if (StringUtil.isNullOrEmpty(cssProperty)) {
String cssFileName = jabRefPreferences.get(JabRefPreferences.FX_THEME);
if (cssFileName != null) {
try {
cssProperty = Paths.get(JabRefFrame.class.getResource(cssFileName).toURI()).toString();
} catch (URISyntaxException e) {
LOGGER.warn("can't get css file URI");
throw new JabRefException("can't set custom theme");
}
}
}
}

/**
Expand All @@ -52,8 +64,8 @@ public ThemeLoader(FileUpdateMonitor fileUpdateMonitor) {
public void installBaseCss(Scene scene, JabRefPreferences preferences) {
addAndWatchForChanges(scene, DEFAULT_PATH_MAIN_CSS, 0);

if (StringUtil.isNotBlank(CSS_SYSTEM_PROPERTY)) {
final Path path = Paths.get(CSS_SYSTEM_PROPERTY);
if (StringUtil.isNotBlank(cssProperty)) {
final Path path = Paths.get(cssProperty);
if (Files.isReadable(path)) {
String cssUrl = path.toUri().toString();
addAndWatchForChanges(scene, cssUrl, 1);
Expand All @@ -69,7 +81,7 @@ private void addAndWatchForChanges(Scene scene, String cssUrl, int index) {
try {
// If -Djabref.theme.css is defined and the resources are not part of a .jar bundle,
// we watch the file for changes and turn on live reloading
if (!cssUrl.startsWith("jar:") && CSS_SYSTEM_PROPERTY != null) {
if (!cssUrl.startsWith("jar:") && cssProperty != null) {
Path cssFile = Paths.get(new URL(cssUrl).toURI());
LOGGER.info("Enabling live reloading of " + cssFile);
fileUpdateMonitor.addListenerForFile(cssFile, () -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ public class JabRefPreferences implements PreferencesService {
public static final String EXTERNAL_FILE_TYPES = "externalFileTypes";
public static final String FONT_FAMILY = "fontFamily";
public static final String FX_FONT_RENDERING_TWEAK = "fxFontRenderingTweak";
public static final String FX_THEME = "fxTheme";
public static final String LANGUAGE = "language";
public static final String NAMES_LAST_ONLY = "namesLastOnly";
public static final String ABBR_AUTHOR_NAMES = "abbrAuthorNames";
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/org/jabref/styletester/StyleTesterMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import javafx.scene.Scene;
import javafx.stage.Stage;

import org.jabref.JabRefException;
import org.jabref.JabRefExecutorService;
import org.jabref.gui.icon.IconTheme;
import org.jabref.gui.util.DefaultFileUpdateMonitor;
Expand All @@ -20,7 +21,7 @@ public static void main(String[] args) {
}

@Override
public void start(Stage stage) {
public void start(Stage stage) throws JabRefException {
StyleTesterView view = new StyleTesterView();

IconTheme.loadFonts();
Expand All @@ -29,7 +30,7 @@ public void start(Stage stage) {
JabRefExecutorService.INSTANCE.executeInterruptableTask(fileUpdateMonitor, "FileUpdateMonitor");

Scene scene = new Scene(view.getContent());
new ThemeLoader(fileUpdateMonitor).installBaseCss(scene, JabRefPreferences.getInstance());
new ThemeLoader(fileUpdateMonitor, JabRefPreferences.getInstance()).installBaseCss(scene, JabRefPreferences.getInstance());
stage.setScene(scene);
stage.show();
}
Expand Down

0 comments on commit 453e7b5

Please sign in to comment.