-
-
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
javafx replacement for file dialog #3005
Changes from 16 commits
67ed3aa
f4a58c3
136a844
b6d43dc
b3d7641
24c35c5
8dca324
dfde523
6633d61
e099c2a
2296ea5
982b475
3b7e52d
dbca24f
9f5036d
5b797d4
81c25ec
d4aed9b
e71181a
d3daaa6
e326bcf
e64b406
32c3db2
3f85f65
34d4251
514cd49
5305d43
cb7096c
fbf8fdb
cc6f3b9
ae7af40
16f0b11
3f7c282
9d2df14
38e087e
298a28f
773d4cc
39a1092
058aaf6
210d645
ce8b9c2
3450c8d
b5816bc
e1f85fd
8cb812d
0be175c
45697c4
7d627ff
3189b33
f579772
95fdd2d
bb22a5e
035d9e2
ce3d5e6
c27c4d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package org.jabref.gui.filelist; | ||
|
||
import java.io.IOException; | ||
import java.util.Optional; | ||
|
||
import javax.inject.Inject; | ||
|
||
import javafx.event.ActionEvent; | ||
import javafx.fxml.FXML; | ||
import javafx.scene.control.Button; | ||
import javafx.scene.control.ComboBox; | ||
import javafx.scene.control.TextField; | ||
|
||
import org.jabref.gui.AbstractController; | ||
import org.jabref.gui.DialogService; | ||
import org.jabref.gui.StateManager; | ||
import org.jabref.gui.desktop.JabRefDesktop; | ||
import org.jabref.gui.externalfiletype.ExternalFileType; | ||
import org.jabref.model.entry.LinkedFile; | ||
import org.jabref.preferences.PreferencesService; | ||
|
||
import org.apache.commons.logging.Log; | ||
import org.apache.commons.logging.LogFactory; | ||
|
||
public class FileListDialogController extends AbstractController<FileListDialogViewModel> { | ||
|
||
private static final Log LOGGER = LogFactory.getLog(FileListDialogController.class); | ||
|
||
@FXML private TextField tfLink; | ||
@FXML private Button btnBrowse; | ||
@FXML private Button btnOpen; | ||
@FXML private TextField tfDescription; | ||
@FXML private ComboBox<ExternalFileType> cmbFileType; | ||
@FXML private Button btnOk; | ||
@FXML private Button btnCancel; | ||
|
||
@Inject private PreferencesService preferences; | ||
@Inject private DialogService dialogService; | ||
@Inject private StateManager stateManager; | ||
|
||
@FXML | ||
private void initialize() { | ||
viewModel = new FileListDialogViewModel(stateManager.getActiveDatabase().get(), dialogService); | ||
setBindings(); | ||
|
||
} | ||
|
||
private void setBindings() { | ||
|
||
cmbFileType.itemsProperty().bindBidirectional(viewModel.externalFileTypeProperty()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tobiasdiez Here the binding is created, a simple list property for the combobox There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this looks good! (a one-directional binding should suffice I think since it looks like the |
||
tfDescription.textProperty().bindBidirectional(viewModel.descriptionProperty()); | ||
tfLink.textProperty().bindBidirectional(viewModel.linkProperty()); | ||
|
||
cmbFileType.valueProperty().bindBidirectional(viewModel.getSelectedExternalFileType()); | ||
} | ||
|
||
@FXML | ||
private void browseFileDialog(ActionEvent event) { | ||
viewModel.browseFileDialog(); | ||
tfLink.requestFocus(); | ||
|
||
} | ||
|
||
@FXML | ||
private void cancel(ActionEvent event) { | ||
getStage().close(); | ||
} | ||
|
||
@FXML | ||
private void ok_clicked(ActionEvent event) { | ||
|
||
} | ||
|
||
private void setValues(LinkedFile entry) { | ||
viewModel.setValues(entry); | ||
} | ||
|
||
@FXML | ||
void openFile(ActionEvent event) { | ||
|
||
ExternalFileType type = cmbFileType.getSelectionModel().getSelectedItem(); | ||
if (type != null) { | ||
try { | ||
JabRefDesktop.openExternalFileAnyFormat(stateManager.getActiveDatabase().get(), viewModel.linkProperty().get(), Optional.of(type)); | ||
} catch (IOException e) { | ||
LOGGER.error("File could not be opened", e); | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package org.jabref.gui.filelist; | ||
|
||
import javafx.scene.control.Alert.AlertType; | ||
import javafx.scene.control.DialogPane; | ||
|
||
import org.jabref.gui.AbstractDialogView; | ||
import org.jabref.gui.FXDialog; | ||
|
||
public class FileListDialogView extends AbstractDialogView { | ||
|
||
@Override | ||
public void show() { | ||
FXDialog filelistDialog = new FXDialog(AlertType.INFORMATION, "FileLIstDialog "); | ||
filelistDialog.setDialogPane((DialogPane) this.getView()); | ||
filelistDialog.setResizable(true); | ||
filelistDialog.show(); | ||
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
package org.jabref.gui.filelist; | ||
|
||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.util.List; | ||
import java.util.Optional; | ||
import java.util.regex.Pattern; | ||
|
||
import javafx.beans.property.ListProperty; | ||
import javafx.beans.property.ObjectProperty; | ||
import javafx.beans.property.SimpleListProperty; | ||
import javafx.beans.property.SimpleObjectProperty; | ||
import javafx.beans.property.SimpleStringProperty; | ||
import javafx.beans.property.StringProperty; | ||
import javafx.collections.FXCollections; | ||
|
||
import org.jabref.Globals; | ||
import org.jabref.gui.AbstractViewModel; | ||
import org.jabref.gui.DialogService; | ||
import org.jabref.gui.externalfiletype.ExternalFileType; | ||
import org.jabref.gui.externalfiletype.ExternalFileTypes; | ||
import org.jabref.gui.externalfiletype.UnknownExternalFileType; | ||
import org.jabref.gui.util.FileDialogConfiguration; | ||
import org.jabref.logic.util.io.FileUtil; | ||
import org.jabref.model.database.BibDatabaseContext; | ||
import org.jabref.model.entry.LinkedFile; | ||
import org.jabref.model.util.FileHelper; | ||
import org.jabref.preferences.JabRefPreferences; | ||
|
||
public class FileListDialogViewModel extends AbstractViewModel { | ||
|
||
private static final Pattern REMOTE_LINK_PATTERN = Pattern.compile("[a-z]+://.*"); | ||
private final StringProperty linkProperty = new SimpleStringProperty(""); | ||
private final StringProperty descriptionProperty = new SimpleStringProperty(""); | ||
private final ListProperty<ExternalFileType> externalfilesTypes = new SimpleListProperty<>(FXCollections.emptyObservableList()); | ||
private final ObjectProperty<ExternalFileType> selectedExternalFileType = new SimpleObjectProperty<>(); | ||
private final BibDatabaseContext bibDatabaseContext; | ||
private final DialogService dialogService; | ||
|
||
private boolean showSaveDialog; | ||
|
||
public FileListDialogViewModel(BibDatabaseContext bibDatabaseContext, DialogService dialogService) { | ||
|
||
this.bibDatabaseContext = bibDatabaseContext; | ||
this.dialogService = dialogService; | ||
externalfilesTypes.set(FXCollections.observableArrayList(ExternalFileTypes.getInstance().getExternalFileTypeSelection())); | ||
} | ||
|
||
private void checkExtension() { | ||
|
||
if (!linkProperty.getValueSafe().isEmpty()) { | ||
|
||
// Check if this looks like a remote link: | ||
if (REMOTE_LINK_PATTERN.matcher(linkProperty.get()).matches()) { | ||
ExternalFileTypes.getInstance().getExternalFileTypeByExt("html").ifPresent(selectedExternalFileType::setValue); | ||
} | ||
|
||
// Try to guess the file type: | ||
String theLink = linkProperty.get().trim(); | ||
ExternalFileTypes.getInstance().getExternalFileTypeForName(theLink).ifPresent(selectedExternalFileType::setValue); | ||
} | ||
} | ||
|
||
public void browseFileDialog() { | ||
String fileText = linkProperty().get(); | ||
|
||
Optional<Path> file = FileHelper.expandFilename(bibDatabaseContext, fileText, | ||
Globals.prefs.getFileDirectoryPreferences()); | ||
|
||
Path workingDir = file.orElse(Paths.get(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY))); | ||
String fileName = Paths.get(fileText).getFileName().toString(); | ||
|
||
FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() | ||
.withInitialDirectory(workingDir) | ||
.withInitialFileName(fileName).build(); | ||
Optional<Path> path; | ||
|
||
if (showSaveDialog) { | ||
path = dialogService.showFileSaveDialog(fileDialogConfiguration); | ||
} else { | ||
path = dialogService.showFileOpenDialog(fileDialogConfiguration); | ||
} | ||
path.ifPresent(newFile -> { | ||
// Store the directory for next time: | ||
Globals.prefs.put(JabRefPreferences.WORKING_DIRECTORY, newFile.toString()); | ||
|
||
// If the file is below the file directory, make the path relative: | ||
List<Path> fileDirectories = bibDatabaseContext | ||
.getFileDirectoriesAsPaths(Globals.prefs.getFileDirectoryPreferences()); | ||
newFile = FileUtil.shortenFileName(newFile, fileDirectories); | ||
|
||
linkProperty().set(newFile.toString()); | ||
checkExtension(); | ||
}); | ||
} | ||
|
||
// | ||
public void setValues(LinkedFile entry) { | ||
descriptionProperty.set(entry.getDescription()); | ||
linkProperty.set(entry.getLink()); | ||
|
||
selectedExternalFileType.setValue(null); | ||
|
||
// See what is a reasonable selection for the type combobox: | ||
Optional<ExternalFileType> fileType = ExternalFileTypes.getInstance().fromLinkedFile(entry, false); | ||
if (fileType.isPresent() && !(fileType.get() instanceof UnknownExternalFileType)) { | ||
selectedExternalFileType.setValue(fileType.get()); | ||
} else if ((entry.getLink() != null) && (!entry.getLink().isEmpty())) { | ||
checkExtension(); | ||
} | ||
} | ||
|
||
public StringProperty linkProperty() { | ||
return linkProperty; | ||
} | ||
|
||
public StringProperty descriptionProperty() { | ||
return descriptionProperty; | ||
} | ||
|
||
public ListProperty<ExternalFileType> externalFileTypeProperty() { | ||
return externalfilesTypes; | ||
} | ||
|
||
public ObjectProperty<ExternalFileType> getSelectedExternalFileType() { | ||
return selectedExternalFileType; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
|
||
<?import javafx.geometry.Insets?> | ||
<?import javafx.scene.control.Button?> | ||
<?import javafx.scene.control.ButtonBar?> | ||
<?import javafx.scene.control.ComboBox?> | ||
<?import javafx.scene.control.DialogPane?> | ||
<?import javafx.scene.control.Label?> | ||
<?import javafx.scene.control.TextField?> | ||
<?import javafx.scene.layout.HBox?> | ||
<?import javafx.scene.layout.VBox?> | ||
|
||
<DialogPane prefHeight="100.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.jabref.gui.filelist.FileListDialogController"> | ||
<content> | ||
<VBox maxWidth="1.7976931348623157E308"> | ||
<children> | ||
<HBox prefHeight="100.0" spacing="10.0"> | ||
<children> | ||
<Label maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="95.0" text="Link"> | ||
<padding> | ||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> | ||
</padding> | ||
</Label> | ||
<TextField fx:id="tfLink" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" /> | ||
<Button fx:id="btnBrowse" minWidth="-Infinity" mnemonicParsing="false" onAction="#browseFileDialog" text="Browse" /> | ||
<Button fx:id="btnOpen" minWidth="-Infinity" mnemonicParsing="false" onAction="#openFile" text="Open"> | ||
<HBox.margin> | ||
<Insets /> | ||
</HBox.margin> | ||
</Button> | ||
</children> | ||
<padding> | ||
<Insets top="10.0" /> | ||
</padding> | ||
</HBox> | ||
<HBox layoutX="21.0" layoutY="21.0" prefHeight="100.0" spacing="10.0"> | ||
<children> | ||
<Label minWidth="95.0" text="Description"> | ||
<HBox.margin> | ||
<Insets /> | ||
</HBox.margin> | ||
<padding> | ||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> | ||
</padding> | ||
</Label> | ||
<TextField fx:id="tfDescription" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" /> | ||
</children> | ||
</HBox> | ||
<HBox prefHeight="100.0" prefWidth="200.0" spacing="10.0"> | ||
<children> | ||
<Label minWidth="95.0" text="File type"> | ||
<padding> | ||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> | ||
</padding> | ||
</Label> | ||
<ComboBox fx:id="cmbFileType" /> | ||
</children> | ||
</HBox> | ||
<ButtonBar> | ||
<buttons> | ||
<Button fx:id="btnOk" defaultButton="true" mnemonicParsing="false" onAction="#ok_clicked" text="OK" /> | ||
<Button fx:id="btnCancel" cancelButton="true" mnemonicParsing="false" onAction="#cancel" text="Cancel" /> | ||
</buttons> | ||
</ButtonBar> | ||
</children> | ||
</VBox> | ||
</content> | ||
</DialogPane> |
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.
@tobiasdiez How do I handle such cases in javafx? The check for a return value? Should I do a showAndWait?
My initial idea would be to pass the UndoManager to the javafx view model (state manager? or other injection)
There are some other clases in which a similar stuff is executed which seems to a bit more complicated, e.g. the
DownloadExternalFile 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.
Good question. I think the return value should be accessed per getters of the
FileListDialogView
(this seems to be the most flexible and easiest solution - you don't need to create "Dialog return value classes" for more complex scenarios). These getters in the view should ask the view model of the dialog about the values. You can get the controller withjabref/src/main/java/org/jabref/gui/AbstractView.java
Line 45 in 1172ed4
(just change the visibility) and then the view model with
jabref/src/main/java/org/jabref/gui/AbstractController.java
Line 20 in 1172ed4
For parameter injection, have a look at
CopyFilesDialogView
.