-
-
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
[WIP] Convert Exporter Customization Dialog to javafx #4394
Conversation
@@ -35,4 +35,8 @@ | |||
|
|||
public void updateEntryEditorTabList(); | |||
|
|||
List<String> getStringList(String key); |
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 no generic methods here, create specific ones for the cases you need, e.g. get CustomExporters or getExporterormat... Or you create CustomExporter preferences which has all the needed information inside.
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 Swing version has a class CustomExportList which holds a list of custom exporters and associated data. I was going to move some of the code here into the ExporterViewModel and other code into the ExporterCustomizationDialogViewModel. Do you recommend keeping the CustomExportList as it is?
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 PreferencesService should only contain usecase-specific preference methods and the caller shouldn't care about how these information are stored in the preferences. So, here, the method would look like List<Exporter> getCustomExportFormats()
and then in the implementation there would be calls like preferences.getStringList(JabRefPreferences.CUSTOM_EXPORT_FORMAT + i))
.
Thus, most of the code in CustomExportList
should go into JabrefPreferences
.
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.
Shouldn't the methods in preferencesService
match those invoked in ExportCustomizationDialogViewModel
as exporters.add(preferences.X)
where X is the method, rather than using preferences.getStringList
?
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.
Sorry, I don't really understand what you mean. The PreferencesService should provide an interface to the preferences that hide the exact semantics of how the object is serialized. So abstractly, X getX()
and putX(X newValue)
, where X
is the (model) object. The implementation in JabRefPreferences
than has to worry about (de)serialization.
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.
Quick question: Do you recommend writing tests for the view model? The dialog is simple, but not as simple as the previous one I wrote.
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'm not a big fan of writing tests for the sake of it. My strategy is usually to program everything and when I discover a problem in the logic during testing, I'll write a test for it. Hence, if the dialog is simple enough that you don't make any errors, then you don't need to write tests ;-).
An exception is when there is really complex logic that is definitely worth testing.
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.
Most of your comments in the code make sense to me. I've added some further remarks.
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public class ExportCustomizationDialogViewModel extends BaseDialog<Void> { |
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 View
/Dialog class should derive from BaseDialog
and not the view model.
@@ -35,4 +35,8 @@ | |||
|
|||
public void updateEntryEditorTabList(); | |||
|
|||
List<String> getStringList(String key); |
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 PreferencesService should only contain usecase-specific preference methods and the caller shouldn't care about how these information are stored in the preferences. So, here, the method would look like List<Exporter> getCustomExportFormats()
and then in the implementation there would be calls like preferences.getStringList(JabRefPreferences.CUSTOM_EXPORT_FORMAT + i))
.
Thus, most of the code in CustomExportList
should go into JabrefPreferences
.
} | ||
|
||
//possibly not necessary, and if so getSortedList will have to return the correct type, not Eventlist<List<String>> | ||
public List<ExporterViewModel> loadExporters() { |
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.
You might don't need the gui-wrapper ExporterViewModel
around Exporter
. In general such a wrapper is needed to adapt the properties of the model to display it to the user. But, here, the data of an exporter is relatively simple and the already in a suitable format for the gui.
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 have put the data in the GUI wrapper ExporterViewModel
for now. How would I create the TableView
and TableColumns
without a ViewModel
for the data? All the examples I could find in JabRef and online had some sort of ViewModel
.
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.
You can also simply use Exporter
as the datatype for the TableView. But if you have already created a ViewModel for it, keep it. It is probably the cleaner approach and more versatile for the future.
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.
Okay. I've finished, but not tested, most of the ViewModel
. I just have to add the dialog to add or modify the exporter, and then create the View and FXML. Unless there's something I forgot...
At this point, I've refactored most of the code from the dialogs. The reasoning is mostly implemented already or in the comments. Take a look if you have time and let me know what you think! Otherwise, I can keep going and let you know when I'm done. |
.addExtensionFilter(Localization.lang("Custom layout file"), StandardFileType.LAYOUT) | ||
.withDefaultExtension(Localization.lang("Custom layout file"), StandardFileType.LAYOUT) | ||
.withInitialDirectory(getExportWorkingDirectory()).build(); | ||
dialogService.showFileOpenDialog(fileDialogConfiguration).ifPresent(f -> setText(f.toAbsolutePath().toString())); //implement setting the text |
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.
To set the text, you would create a StringProperty here, e.g. selectedPath and then bind that property to a textfield in the View
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.
Fixed it. I think I had the property, but I hadn't realized this is what I needed here. Thanks for your recommendation!
|
||
} | ||
|
||
public void modifyExporter(int row) { |
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.
Do you really need an int here? It would be generally better if you just operate on the row object
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 don't think I need it. I changed it to use a property selectedExporters
.
Hi, I am having trouble using EasyBind to bind a |
@NorwayMaple No need to complex binding. Just use setItems. Another thing I just noticed, for the SimpleXYZProperty in javafx, there exists always an interface, e.g. XYZ Property. Always use that. |
Thank you! I took a brief look at it, and it looks good. In the future, how can I decide when to use EasyBind? |
@NorwayMaple Easybind is only needed in rare cases. I would go with the rule of thumb, if you can't achieve your goal with normal javafx bindings, try Easbindings. |
I finished the View and am trying to load it from the JabRef menu, but Afterburner throws an error:
etc... I grepped |
I made a number of the changes. For some reason, the cancel button is not showing up in the subdialog. Also, I tried to use a try/catch block to catch an |
try { | ||
exporterToModify = selectedExporters.get(0); | ||
dialog = new CreateModifyExporterDialogView(exporterToModify, dialogService, preferences, loader); | ||
} catch (IndexOutOfBoundsException 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.
normally isEmpty should work. Does the indexoutofbounds exception realy targets to this line?
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.
It's not clear. I put debug breakpoints on lines 56, 57, 59, and 60. I also put one in the line viewModel.modifyExporter()
in ExporterCustomizationDialogView
. That one is the only one it stops at before it throws the exception, but I don't understand how that is possible, since there should be no intervening lines. Also I find it odd that it should throw the very same exception that I was trying to catch.
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.
You can try to make selectedExporters
a normal array list.
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 don't think it has to do with selectedExporters
because it returns at line 59 when none are selected. Something else may be going on.
@Siedlerchr @tobiasdiez I think I have finished the corrections you guys recommended. Do you think anything remains to be changed? Thanks, |
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 for the followup. The code looks very good to me. Please remove the outdated comments (I only marked a few, there might be more) and maybe run the code formatter on the files (also on the fxml ones), then this is good to go.
|
||
@Inject private DialogService dialogService; | ||
@Inject private PreferencesService preferences; | ||
@Inject private JournalAbbreviationLoader loader; // Should this be injected? |
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.
e.g here
} | ||
|
||
private void loadExporters() { | ||
List<TemplateExporter> exportersLogic = preferences.getCustomExportFormats(loader); //Var exportersLogic may need more descriptive name |
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.
or here
I removed most of the comments - let me know if I need to remove the last few. For the code formatter, I ran it, then |
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.
Looks good to me. Thanks a lot for all the work you put in this PR. I will now press the magic button 😃
* upstream/master: Bump applicationinsights-logging-log4j2 from 2.2.1 to 2.3.0 (#4540) Bump antlr4-runtime from 4.7.1 to 4.7.2 (#4542) Bump applicationinsights-core from 2.2.1 to 2.3.0 (#4541) Bump antlr4 from 4.7.1 to 4.7.2 (#4543) Fix journal name "Astronomy Journal" to "Astronomical Journal" fix-for-issue-4489 (#4538) Sorting of read-status isn't working as expected #4521 (#4536) Add preselect last used export format in export to clipboard dialog (#4533) fixed 4365 put html in clipboard (#4519) [WIP] Convert Exporter Customization Dialog to javafx (#4394) Fixes #4437 (#4531) Bump checkstyle from 8.14 to 8.15 (#4528) # Conflicts: # src/main/java/org/jabref/preferences/PreferencesService.java
* upstream/master: (49 commits) improve styling of preferences side menu (#4556) Cleanup interfaces (#4553) Bump fontbox from 2.0.12 to 2.0.13 (#4552) Bump pdfbox from 2.0.12 to 2.0.13 (#4551) Bump wiremock from 2.19.0 to 2.20.0 (#4550) Fixes that renaming a group did not change the group name in the interface (#4549) Bump applicationinsights-logging-log4j2 from 2.2.1 to 2.3.0 (#4540) Bump antlr4-runtime from 4.7.1 to 4.7.2 (#4542) Bump applicationinsights-core from 2.2.1 to 2.3.0 (#4541) Bump antlr4 from 4.7.1 to 4.7.2 (#4543) Fix journal name "Astronomy Journal" to "Astronomical Journal" fix-for-issue-4489 (#4538) Sorting of read-status isn't working as expected #4521 (#4536) Add preselect last used export format in export to clipboard dialog (#4533) fixed 4365 put html in clipboard (#4519) [WIP] Convert Exporter Customization Dialog to javafx (#4394) Fixes #4437 (#4531) Bump checkstyle from 8.14 to 8.15 (#4528) Correct PNAS abbrev. (#4524) Create test (#4518) ...
This is my work so far. I am just beginning the dialog conversion and wanted to share my reasoning so far. What I am doing is listed in the comments in class
ExportCustomizationDialogViewModel
.