Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4130 provide dark theme #4372

Merged
merged 17 commits into from
Oct 17, 2018
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
40 changes: 25 additions & 15 deletions src/main/java/org/jabref/gui/util/ThemeLoader.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.jabref.gui.util;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
Expand All @@ -11,6 +12,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 +23,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 final Path CSS_SYSTEM_PROPERTY;
private final FileUpdateMonitor fileUpdateMonitor;

public ThemeLoader(FileUpdateMonitor fileUpdateMonitor) {
public ThemeLoader(FileUpdateMonitor fileUpdateMonitor, JabRefPreferences jabRefPreferences) throws JabRefException {
this.fileUpdateMonitor = Objects.requireNonNull(fileUpdateMonitor);
Siedlerchr marked this conversation as resolved.
Show resolved Hide resolved

String cssFileName = jabRefPreferences.get(JabRefPreferences.FX_THEME);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First and foremost CSS_SYSTEM_PROPERTY should be System.getProperty("jabref.theme.css"), if the latter is not empty /null (StringUtil.isBlank) so that one can override the theme from the preference using command line arguments (mainly for developers). The preference should be consulted only if the system property is empty.
Please also rename CSS_SYSTEM_PROPERTY to userCss or something like this.

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

} else
CSS_SYSTEM_PROPERTY = null;
}

/**
Expand All @@ -52,12 +65,9 @@ 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 (Files.isReadable(path)) {
String cssUrl = path.toUri().toString();
addAndWatchForChanges(scene, cssUrl, 1);
}
if (CSS_SYSTEM_PROPERTY != null && Files.isReadable(CSS_SYSTEM_PROPERTY)) {
String cssUrl = CSS_SYSTEM_PROPERTY.toUri().toString();
addAndWatchForChanges(scene, cssUrl, 1);
}

preferences.getFontSize().ifPresent(size -> scene.getRoot().setStyle("-fx-font-size: " + size + "pt;"));
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/jabref/preferences/JabRefPreferences.java
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 Expand Up @@ -472,6 +473,7 @@ private JabRefPreferences() {
}

defaults.put(FX_FONT_RENDERING_TWEAK, OS.LINUX); //we turn this on per default on Linux
defaults.put(FX_THEME, "Base.css");
defaults.put(EMACS_ADDITIONAL_PARAMETERS, "-n -e");

defaults.put(PUSH_TO_APPLICATION, "TeXstudio");
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