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

Let user load customized CSS #6036

Closed
wants to merge 20 commits into from

Conversation

nilsstre
Copy link
Contributor

@nilsstre nilsstre commented Feb 27, 2020

I have added functionality that lets the user import and export CSS files, this pull request is related to issue #5790

I have added a button in the PreferencesDialog that lets the user import a CSS file, the user then has to set the radio button in the Appearance tab -> Visual theme to custom theme and restart for the changes to take effect.

I have also added a button in the PreferencesDialog that lets the user export either the base, the dark or the custom theme (if previously imported) as CSS. The reason for adding this button was that I thought it would be easier for the user to create a custom theme if they could use one of the originals as a base.

I added a third radio button for toggling the custom theme to the Visual theme section in the Appearance tab, the button is disabled if the user has not imported a CSS file

New radio and import/export buttons
Screenshot 2020-02-27 at 15 05 42

Dialogue box for selecting which theme to export
Screenshot 2020-02-27 at 15 05 18

JabRef with the root theme CSS property changed to green
Screenshot 2020-02-26 at 17 51 13

JabRef with the root theme CSS property changed to red
Screenshot 2020-02-26 at 17 50 27

closes #5790

… CSS file, started on import functionality
* Add CSS file type, add button in preferences to import a custom CSS file, started on import functionality

* Change so that the log uses format specifiers instead of string concatenation

* Add RadioButton for toggling custom theme

* Add preference for setting the path to custom CSS theme

* Load custom CSS if toggled

* Add missing language keys

* Remove check if the current theme is applied again, the check is removed since we don't need it

* Save path to the custom CSS file in program preferences
… once, disable custom theme radio button i no custom theme has been imported
* Add method for saving theme to file

* Add modal for selection witch theme to export as CSS
@nilsstre
Copy link
Contributor Author

Created an issue for the missing documentation: JabRef/user-documentation#254

Also created a pull request that adds the documentation: JabRef/user-documentation#255

@nilsstre
Copy link
Contributor Author

nilsstre commented Feb 27, 2020

Could you take a look? @tobiasdiez 😃

@koppor
Copy link
Member

koppor commented Feb 27, 2020

Please ensure that you loaded the correct IntelliJ configuration and the you pressed Ctrl+Alt+O to Optimize the imports. Then everyhting is sorted correctly

 [ant:checkstyle] [ERROR] /home/runner/work/jabref/jabref/src/main/java/org/jabref/gui/preferences/ExportThemeDialog.java:5: Wrong order for 'javafx.beans.property.SimpleStringProperty' import. [ImportOrder]

Copy link
Member

@koppor koppor left a comment

Choose a reason for hiding this comment

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

Some nitpicks, but looks good otherwise ^^

@nilsstre nilsstre requested a review from koppor February 27, 2020 20:29
@koppor
Copy link
Member

koppor commented Feb 27, 2020

How can I add a CSS? I would have expected an import button next to "Custom theme"

grafik

I would also expect an "Export" button there.

"Import theme" and "Export theme" at the lower left corner is not intuitive for me: The context of the "Visual Theme" heading indicates that everything what has to do with the Theme is found there. Just move the buttons here below the radio group.

@nilsstre
Copy link
Contributor Author

nilsstre commented Feb 27, 2020

How can I add a CSS? I would have expected an import button next to "Custom theme"

grafik

I would also expect an "Export" button there.

"Import theme" and "Export theme" at the lower left corner is not intuitive for me: The context of the "Visual Theme" heading indicates that everything what has to do with the Theme is found there. Just move the buttons here below the radio group.

Okay I will move the buttons, I thought that it would be a good idea to group them with the other import/export buttons

@nilsstre
Copy link
Contributor Author

New button design

Screenshot 2020-02-27 at 23 17 36

@tobiasdiez
Copy link
Member

@koppor what's the use case for the export theme? The way the themes work, you don't need to change an existing theme file but specify only the differences (ie you build a top of the current light theme). Moreover, both source files for the light and dark theme are in this repository...

@koppor
Copy link
Member

koppor commented Feb 28, 2020

My assumptions are:

  • This is the only way where I get information about the available CSS classes.
  • As a user not familiar with GitHub, I am still familiar with text editors. Thus, import/export is an easy way for me to edit the CSS.

@koppor
Copy link
Member

koppor commented Feb 28, 2020

@nilsstre Are this unused imports real? --> https://app.codacy.com/gh/JabRef/jabref/pullRequest?prid=5083392

Comment on lines +139 to +140
dialogService.showWarningDialogAndWait(Localization.lang("Import CSS"),
Localization.lang("You must restart JabRef for this to come into effect."));
Copy link
Member

Choose a reason for hiding this comment

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

Why don't you deal with this by restartWarnings.add()?

Comment on lines +1 to +107
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.KeyCode;

import org.jabref.JabRefException;
import org.jabref.gui.DialogService;
import org.jabref.gui.util.BaseDialog;
import org.jabref.gui.util.FileDialogConfiguration;
import org.jabref.gui.util.ThemeLoader;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.util.StandardFileType;
import org.jabref.preferences.JabRefPreferences;

import com.airhacks.afterburner.views.ViewLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ExportThemeDialog extends BaseDialog<Void> {

private static final Logger LOGGER = LoggerFactory.getLogger(ExportThemeDialog.class);

@FXML
private TableView<Theme> table;
@FXML
private TableColumn<Theme, String> columnName;
@FXML
private TableColumn<Theme, String> columnPath;

private JabRefPreferences preferences;
private DialogService dialogService;

public ExportThemeDialog(DialogService dialogService, JabRefPreferences preferences) {
this.dialogService = dialogService;
this.preferences = preferences;

ViewLoader
.view(this)
.load()
.setAsDialogPane(this);

this.setTitle(Localization.lang("Export Theme"));
}

@FXML
public void initialize() {
columnName.setCellValueFactory(new PropertyValueFactory<>("name"));
columnPath.setCellValueFactory(new PropertyValueFactory<>("path"));

ObservableList<Theme> data =
FXCollections.observableArrayList(new Theme("Light theme", ThemeLoader.MAIN_CSS), new Theme("Dark theme", ThemeLoader.DARK_CSS));

if (!(ThemeLoader.getCustomCss().isBlank())) {
data.add(new Theme("Custom theme", ThemeLoader.getCustomCss()));
}

table.setItems(data);

table.setOnKeyPressed(event -> {
TablePosition tablePosition;
if (event.getCode().equals(KeyCode.ENTER)) {
tablePosition = table.getFocusModel().getFocusedCell();
final int row = tablePosition.getRow();
ObservableList<Theme> list = table.getItems();
Theme theme = list.get(row);
exportCSSFile(theme.getPath());
}
});

table.setRowFactory(tv -> {
TableRow<Theme> row = new TableRow<>();
row.setOnMouseClicked(event -> handleSelectedRowEvent(row));
return row;
});
}

private void handleSelectedRowEvent(TableRow<Theme> row) {
if (!row.isEmpty()) {
exportCSSFile(row.getItem().getPath());
}
}

private void exportCSSFile(String theme) {
FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder()
.addExtensionFilter(StandardFileType.CSS)
.withDefaultExtension(StandardFileType.CSS)
.withInitialDirectory(preferences.setLastPreferencesExportPath())
.build();

dialogService.showFileSaveDialog(fileDialogConfiguration)
.ifPresent(exportFile -> {
try {
preferences.exportTheme(exportFile.getFileName(), theme);
} catch (JabRefException ex) {
LOGGER.warn(ex.getMessage(), ex);
dialogService.showErrorDialogAndWait(Localization.lang("Export theme"), ex);
}
});
}
}
Copy link
Member

Choose a reason for hiding this comment

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

This class can be divided according to the mvvm-pattern.
This means: put exportCSSFile, handleSelectedRowEvent and the logic to initialize the list into a ViewModel class und communicate between the View and the ViewModel via Properties. Basic idea is that the ViewModel should be useable, even if no gui is loaded.
Have a look at the implementation of other PreferencesTabs or dialogs.
It's very easy.

Comment on lines +1411 to +1413
private void writeThemeToFile(Path path, OutputStream os) throws IOException {
Files.copy(path, os);
}
Copy link
Member

Choose a reason for hiding this comment

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

In this case, writeThemeToFile is just an alias for Files.copy with the exact arguments. Just inline it. "exportTheme" should be clear enough.

@tobiasdiez
Copy link
Member

@koppor In that case, I would prefer to point users to themes.jabref.org which points to a new repository where we then explain a bit how themes are designed (and maybe let users upload new themes as PRs?). The normal user will not touch the css but might download it from someone else. And for this normal user flow, no export functionality is needed.

Copy link
Member

@tobiasdiez tobiasdiez left a comment

Choose a reason for hiding this comment

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

Thanks a lot for your contribution. Overall the code looks good and I've only a few comments. The are concerned mainly with simplifying the user experience and streamline the code flow.
Concerning the later, the flow of information should be like this: preference dialog sets preference object, theme loader sets correct theme based on preferences. There should be no direct interaction between the preference dialog and the theme loader.

Finally, I'm still of the opinion that the export functionality is not necessary. Instead I would add a sentence like "You can find custom themes and information about how to create them on themes.jabref.org" below the "Custom theme option". On this site we can then give more detailed information on how to create custom themes and have a collection of user-provided ones. I let @koppor decide on this one.

import org.jabref.gui.util.TaskExecutor;
import org.jabref.logic.l10n.Localization;
Copy link
Member

Choose a reason for hiding this comment

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

These new imports don't seem to be necessary.

@@ -29,4 +31,18 @@
<Label styleClass="sectionHeader" text="%Visual theme"/>
<RadioButton fx:id="themeLight" text="%Light theme" toggleGroup="$theme"/>
<RadioButton fx:id="themeDark" text="%Dark theme" toggleGroup="$theme"/>
<RadioButton fx:id="customTheme" text="%Custom theme" toggleGroup="$theme"/>

<Label styleClass="sectionHeader" text="%Import custom theme" />
Copy link
Member

Choose a reason for hiding this comment

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

I would prefer if the "Import custom CSS file" button is directly grouped with the above radio button option (since it doesn't make sense to import a custom theme but don't select it). Moreover, I would add a text field showing the currently selected custom css file. So in summary it should look like "Execute program" under "External programs" (also in the preferences).

Finally, I think "Select/Choose custom theme" is more appropriate. Import suggest that I can delete the file afterwards because JabRef imported it.

@@ -38,6 +39,7 @@

public static final String MAIN_CSS = "Base.css";
public static final String DARK_CSS = "Dark.css";
private static String CUSTOM_CSS = "";
Copy link
Member

Choose a reason for hiding this comment

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

This field is not really required for this class. I would prefer if only the preferences know about the current custom theme (in form of the FX_Theme field).

@@ -403,6 +405,8 @@
private static final int EXPORTER_FILENAME_INDEX = 1;
private static final int EXPORTER_EXTENSION_INDEX = 2;

private static final String PATH_TO_CUSTOM_THEME = "pathToCustomTheme";
Copy link
Member

Choose a reason for hiding this comment

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

Is this field really required? Can we not simply point FX_Theme to the external css file?

@koppor koppor force-pushed the master branch 5 times, most recently from b8ef7b7 to 21c6e5e Compare March 4, 2020 17:02
@koppor
Copy link
Member

koppor commented Mar 6, 2020

@nilsstre I finally brought up https://themes.jabref.org. Is it possible for you to address the comments by @tobiasdiez? We would really like to get this in.

@koppor koppor changed the title Let user load customized css [WIP] Let user load customized CSS Mar 6, 2020
Copy link
Member

@koppor koppor left a comment

Choose a reason for hiding this comment

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

Please include the link to http://themes.jabref.org/ and address the review comments.

@tobiasdiez
Copy link
Member

@nilsstre Any update on this? Would be nice to gives this PR a final polish. Otherwise we have to close your PR unmerged and your work would be lost - which would be very sad for the time and energy you already spent on this. Thanks!

@tobiasdiez tobiasdiez marked this pull request as draft April 17, 2020 15:57
@koppor koppor changed the title [WIP] Let user load customized CSS Let user load customized CSS Apr 23, 2020
@koppor
Copy link
Member

koppor commented Jul 7, 2020

@nilsstre We would really like to see that this features comes into JabRef. May I ask whether you can find some time to finish this PR? It seems to be close to get it done. We have resources to provide timely feedback.

@calixtus calixtus mentioned this pull request Jul 30, 2020
5 tasks
@calixtus
Copy link
Member

As this PR is abandoned, I'm going to finish this in #6725 and I'm closing this PR.
Thanks for your contribution so far, your work is marked by your name in the git log and you should be mentioned in future releases of JabRef.

@calixtus calixtus closed this Jul 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow to load customized css
4 participants