-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Conversation
… CSS file, started on import functionality
…d of string concatenation
…ve since we don't need it
* 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
Created an issue for the missing documentation: JabRef/user-documentation#254 Also created a pull request that adds the documentation: JabRef/user-documentation#255 |
Could you take a look? @tobiasdiez 😃 |
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
|
There was a problem hiding this 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 ^^
src/main/java/org/jabref/gui/preferences/AppearanceTabViewModel.java
Outdated
Show resolved
Hide resolved
src/main/java/org/jabref/gui/preferences/ExportThemeDialog.java
Outdated
Show resolved
Hide resolved
src/main/java/org/jabref/gui/preferences/ExportThemeDialog.java
Outdated
Show resolved
Hide resolved
src/main/java/org/jabref/gui/preferences/AppearanceTabViewModel.java
Outdated
Show resolved
Hide resolved
How can I add a CSS? I would have expected an import button next to "Custom theme" 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 |
@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... |
My assumptions are:
|
@nilsstre Are this unused imports real? --> https://app.codacy.com/gh/JabRef/jabref/pullRequest?prid=5083392 |
dialogService.showWarningDialogAndWait(Localization.lang("Import CSS"), | ||
Localization.lang("You must restart JabRef for this to come into effect.")); |
There was a problem hiding this comment.
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()?
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); | ||
} | ||
}); | ||
} | ||
} |
There was a problem hiding this comment.
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.
private void writeThemeToFile(Path path, OutputStream os) throws IOException { | ||
Files.copy(path, os); | ||
} |
There was a problem hiding this comment.
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.
@koppor In that case, I would prefer to point users to |
There was a problem hiding this 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; |
There was a problem hiding this comment.
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" /> |
There was a problem hiding this comment.
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 = ""; |
There was a problem hiding this comment.
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"; |
There was a problem hiding this comment.
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?
b8ef7b7
to
21c6e5e
Compare
@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. |
There was a problem hiding this 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.
@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! |
@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. |
As this PR is abandoned, I'm going to finish this in #6725 and I'm closing this PR. |
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
Dialogue box for selecting which theme to export
JabRef with the root theme CSS property changed to green
JabRef with the root theme CSS property changed to red
closes #5790