-
-
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
Live reloading when switching themes #7336
Conversation
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, this already looks extremely nice. The new Stylesheet
classes are a good idea, they make things a lot clearer.
I'm not sure if it works, but it would be nice to profit even more from the introduction of these classes and further simplify the Theme / ThemeImpl / ThemePreference classes. The following would be my idea:
- Add
Optional<Stylesheet> getAdditonialStylesheet
inAppearencePreference
. The preference class usesStylesheet.create(...)
to create one based on the string stored in the preferences. - The Theme class uses this method to determine the additional stylesheets to install.
- You can now remove ThemeState, ThemeImpl and ThemePreferences.
What do you think?
|
||
private final ThemePreference themePreference; | ||
|
||
private final StyleSheet additionalStylesheet; |
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.
Maybe make this an Optional<StyleSheet>
? Than you would not need to introduce the "EmptyStylesheet" class.
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.
The idea here is to have an invariant: "there is always an additional stylesheet".
This is so that it is much simpler to transition between states where an additional stylesheet is available, and states where it is not (either because it is missing, or because the theme does not require one).
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.
ok, but "there is always an additional stylesheet" doesn't seem to be valid from a business logic (the light theme doesn't have additional css) as well as from the current implementation (EmptyStylesheet is not a a stylesheet, it's something that pretends to be one).
On the other hand, the current solution works and is fine codewise so take my comment as a suggestion that doesn't necessarily need to be implemented.
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.
Ah, perhaps it wasn't clear! EmptyStylesheet loaded a real resource called Empty.css so it wasn't pretending!
However, given it is confusing, I've updated to remove StyleSheetEmpty and rename Empty.css to Light.css, which has a comment in it explaining that it doesn't have to add anything over Base.css
This is meaningful, because we could add something specific to Light.css. A practical example would be theming for Preview. That can't be done in Base.css, because WebEngine (which preview uses) can only take one style sheet and that is the additional one. So Light.css would be the place for that.
So hopefully that clears things up (and removes a class) while keeping the useful invariant.
src/main/java/org/jabref/preferences/AppearancePreferences.java
Outdated
Show resolved
Hide resolved
I have gone somewhat in this direction, just pushed a change that cleans up the AppearancePreferences and eliminates ThemeState, by having the Stylesheet created by the ThemePreference. Theme no longer has a circular relationship with the PreferenceService. Instead it just needs AppearancePreferences and this is the state object. It might be a bit cleaner still if I can move AppreancePreferences into the theme package, at the moment all the preference objects sit together but we really want it to live with ThemePreference so it can have some package-private methods to help ThemeImpl. Not sure I could go further with removing the added classes without compromising the Single Responsibility Principle which are the rationale behind them:
If we for example combined Stylesheet and ThemePreference into a single class, then Stylesheet would no longer be useable for the base stylesheet, it would be coupled to the additional stylesheet. The general stylesheet handling doesn't need to be impacted when we get to #7322, which really only concerns how ThemePreference interacts with the appearance tab and settings storage. Stylesheet shouldn't have to care about such things, especially as it is also used by the base CSS. |
That looks really good. Thanks! Based on your description of the responsibilities of the classes, one might consider to rename |
Great work so far, however, please keep in mind that the |
Hi @docrjp , do you have any updates on this PR? We are so impressed of your work you already contributed in such a short period of time in this and the other PR. |
Hi! So, I'm somewhat undecided about how to finish up the PR. Eliminating ThemeState, and moving the Stylesheet static factory to the XxxPreferences, conflicts to some extent with the principle that the preferences are just data holder objects. Since now, the static factory Stylesheet.create() is called from the preferences. On the other hand, maybe that's taking the principle too literally. It's not too much different from java NIO Path. If we used Path in a preference class, then we're using static factory methods i.e. Path.of() and these static factories have a lot of file system logic behind them, with Path itself being an interface. I think it depends on the goal behind the preference classes being data holders. If it is so that we can deserialize by reflection with a library (e.g. Jackson), where it helps to not have complex factory or constructor logic, then I think it safest to move this logic back out of ThemePreference and reintroduce ThemeState as per the initial PR commit. Doing so eliminates the static factory from the ThemePreference and will keep that class really plain and simple. On the other hand, if the purpose of keeping the preferences as data holder objects is to encourage loose coupling -- i.e. avoid the preferences needing application services injecting into them -- then the Stylesheet.create() static factory itself is harmless. It doesn't need to depend upon any other services, less so even than Path.of() which depends on file system providers. However, what remains not so great is that Stylesheet is in the theme package but the factory is used from the preference package -- and the preference is in turn used by the ThemeManager in the .theme package. So that's a cyclic dependency of packages. My instinct is to keep ThemePreference, and keep Stylesheet.create() as being called by ThemePreference, and then move ThemePreference into its own sub-package of the preferences package along with Stylesheet. But I don't want to do that if it messes up other plans with preferences. |
Thanks for your very quick response! My idea was to collect the xxxPreferences classes in the model package unbound to any concrete implementation either of the preferences or the gui. On the other hand I think that the theme preferences definitely are part of the gui implementation. |
That's their main goal as of now. Personally, I don't mind if a bit of logic is needed to construct a preference object.
I don't think this is a big deal. For unit tests, you can mock the preferences and still create a ThemeManager. I think, this is the most important thing that one desires from the architecture. |
Did anything come out of the devcall that is worth taking into consideration? If not, then based on discussion above, I think we can just stick with what we've got for now, and I finish up the outstanding work of fixing the unit tests. I'll also update the tracked master to make sure that the PR is clean. With the related follow up issues #7322 and #7323. there will be some more natural opportunities to refactor and discuss :) |
Sorry, I was a bit buried in work today. We had a brief discussion yesterday, but no quick response, so it's more or less up to me, since I'm currently refactoring the whole preferences complex. I believe there was a misunderstanding on my side: I thought that Please keep the naming convention ( I know, Thank you for your patience and all your impressive work! As soon as you are ready, we are doing the regular double review and can then merge. |
# Conflicts: # src/main/java/org/jabref/gui/preferences/appearance/AppearanceTabViewModel.java # src/main/java/org/jabref/gui/preferences/preview/PreviewTab.java
@docrjp could you please implement the last remaining changes so that we can get this merged? Thanks! |
Sorry! My spare time has been unusually lacking this last month but I hope
to get to it soon!
All the best
Rob
…On Wed, 10 Mar 2021, 09:59 Tobias Diez, ***@***.***> wrote:
@docrjp <https://github.com/docrjp> could you please implement the last
remaining changes so that we can get this merged? Thanks!
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#7336 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACIZMN3X3VZ2V33CKJORJPTTC47G3ANCNFSM4V7P6JVQ>
.
|
Hi, I took the liberty to dive into this PR a bit last week and made some commits regarding the remaining issues. If you don't mind I'll push them on your branch? |
@calixtus What's the status here? You still had the OutOfBounds Exception? |
There still seems to be a concurrency bug producing the exception, and the ThemeManagerTest not completely working. Had to put work on this pr on hold because of more pressing matters, both private and jabref-related |
# Conflicts: # src/main/java/org/jabref/gui/LibraryTab.java # src/main/java/org/jabref/gui/entryeditor/OptionalFields2Tab.java # src/main/java/org/jabref/gui/entryeditor/OptionalFieldsTab.java # src/main/java/org/jabref/gui/preferences/preview/PreviewTab.java # src/main/java/org/jabref/gui/preview/PreviewViewer.java # src/main/java/org/jabref/gui/slr/ExistingStudySearchAction.java # src/main/java/org/jabref/preferences/JabRefPreferences.java
# Conflicts: # src/main/java/org/jabref/gui/entryeditor/DeprecatedFieldsTab.java # src/main/java/org/jabref/gui/entryeditor/EntryEditor.java # src/main/java/org/jabref/gui/entryeditor/FieldsEditorTab.java # src/main/java/org/jabref/gui/entryeditor/OptionalFields2Tab.java # src/main/java/org/jabref/gui/entryeditor/OptionalFieldsTab.java # src/main/java/org/jabref/gui/entryeditor/OptionalFieldsTabBase.java # src/main/java/org/jabref/gui/entryeditor/OtherFieldsTab.java # src/main/java/org/jabref/gui/entryeditor/PreviewTab.java # src/main/java/org/jabref/gui/entryeditor/RequiredFieldsTab.java # src/main/java/org/jabref/gui/entryeditor/UserDefinedFieldsTab.java # src/main/java/org/jabref/gui/preview/PreviewPanel.java
src/main/java/org/jabref/gui/preferences/appearance/AppearanceTabViewModel.java
Show resolved
Hide resolved
* upstream/main: Observable Preferences J (Preview) and minor refactor (#8370) quickfix (#8383) Live reloading when switching themes (#7336) FIX NPE on Merge Dialog (#8380) Bump org.eclipse.jgit from 5.13.0.202109080827-r to 6.0.0.202111291000-r (#8378) Bump jackson-dataformat-yaml from 2.13.0 to 2.13.1 (#8379) Bump tika-core from 2.2.0 to 2.2.1 (#8377) Update turabian-fullnote-bibliography-no-ibid.csl Squashed 'buildres/csl/csl-locales/' changes from d5ee85de8e..c38205618f Squashed 'buildres/csl/csl-styles/' changes from 60bf7d5..f78c707
Is this feature ready now? I'm trying to make themes and would like to have this. |
Well, live reloading worked once when it was implemented, and I believe there are some test ensuring it works. Be aware that currently the css is a bit of a mess, as there are some styles still hidden in the source, especially measurements are not yet scaling. But most of jabref should be customizeable. |
This resolves enhancement #7335 ( fixes #7335 )
Theme preferences can be changed without reloading. Supporting the enhancement is a refactoring of Theme which lays the groundwork for further enhancements #7322 and #7323.
This is a draft PR, for visibility and Continuous Integration purposes. Some code changes are outstanding:
Followed by standard PR tasks: