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

javafx replacement for file dialog #3005

Merged
merged 55 commits into from
Mar 26, 2018
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
67ed3aa
javafx replacement for file dialog
Siedlerchr Jul 6, 2017
f4a58c3
Merge remote-tracking branch 'upstream/master' into selectFilesDlg
Siedlerchr Jul 15, 2017
136a844
Add some core structure for selectFilesDialog
Siedlerchr Jul 15, 2017
b6d43dc
Merge remote-tracking branch 'upstream/master' into selectFilesDlg
Siedlerchr Jul 31, 2017
b3d7641
Add Properties for binding
Siedlerchr Jul 31, 2017
24c35c5
add getters
Siedlerchr Jul 31, 2017
8dca324
Merge remote-tracking branch 'upstream/master' into selectFilesDlg
Siedlerchr Aug 6, 2017
dfde523
Renaming, use properties in controller
Siedlerchr Aug 6, 2017
6633d61
Merge remote-tracking branch 'upstream/master' into selectFilesDlg
Siedlerchr Sep 23, 2017
e099c2a
port some more code
Siedlerchr Sep 23, 2017
2296ea5
Merge remote-tracking branch 'upstream/master' into selectFilesDlg
Siedlerchr Nov 1, 2017
982b475
Asssign combobox selected value property
Siedlerchr Nov 1, 2017
3b7e52d
Merge remote-tracking branch 'upstream/master' into selectFilesDlg
Siedlerchr Nov 3, 2017
dbca24f
Merge remote-tracking branch 'upstream/master' into selectFilesDlg
Siedlerchr Nov 19, 2017
9f5036d
fix some formatting
Siedlerchr Nov 19, 2017
5b797d4
Merge remote-tracking branch 'upstream/master' into selectFilesDlg
Siedlerchr Dec 29, 2017
81c25ec
make getController public to get viewModel
Siedlerchr Dec 29, 2017
d4aed9b
Merge remote-tracking branch 'upstream/master' into selectFilesDlg
Siedlerchr Jan 2, 2018
e71181a
Merge remote-tracking branch 'upstream/master' into selectFilesDlg
Siedlerchr Jan 2, 2018
d3daaa6
Merge remote-tracking branch 'upstream/master' into selectFilesDlg
Siedlerchr Jan 2, 2018
e326bcf
add enum with config values instead of booleans
Siedlerchr Jan 3, 2018
e64b406
Merge remote-tracking branch 'upstream/master' into selectFilesDlg
Siedlerchr Jan 14, 2018
32c3db2
Fix depdendency injection
Siedlerchr Jan 14, 2018
3f85f65
Merge remote-tracking branch 'upstream/master' into selectFilesDlg
Siedlerchr Jan 24, 2018
34d4251
Merge remote-tracking branch 'origin/master' into selectFilesDlg
tobiasdiez Feb 6, 2018
514cd49
Rework
tobiasdiez Feb 6, 2018
5305d43
Merge remote-tracking branch 'upstream/maintable-beta' into selectFil…
Siedlerchr Mar 17, 2018
cb7096c
Merge remote-tracking branch 'upstream/master' into maintable-beta
Siedlerchr Mar 17, 2018
fbf8fdb
Create Wrapper to pass LinkedFile around
Siedlerchr Mar 17, 2018
cc6f3b9
fix some indentations
Siedlerchr Mar 17, 2018
ae7af40
remove open unknown external file type dialog
Siedlerchr Mar 17, 2018
16f0b11
Merge remote-tracking branch 'upstream/maintable-beta' into selectFil…
Siedlerchr Mar 18, 2018
3f7c282
fix indentation
Siedlerchr Mar 18, 2018
9d2df14
convert attachFileDialog to javafx
Siedlerchr Mar 18, 2018
38e087e
reformat
Siedlerchr Mar 18, 2018
298a28f
Mark old filelist as deprecated
Siedlerchr Mar 19, 2018
773d4cc
Merge remote-tracking branch 'upstream/maintable-beta' into selectFil…
Siedlerchr Mar 19, 2018
39a1092
fix checkstyle
Siedlerchr Mar 19, 2018
058aaf6
fix checkstyle again
Siedlerchr Mar 19, 2018
210d645
add changelog
Siedlerchr Mar 19, 2018
ce8b9c2
adjust indentation
Siedlerchr Mar 20, 2018
3450c8d
Merge remote-tracking branch 'upstream/maintable-beta' into selectFil…
Siedlerchr Mar 24, 2018
b5816bc
convert to new FXML dialog model funcionality
Siedlerchr Mar 24, 2018
e1f85fd
fix empty lines
Siedlerchr Mar 24, 2018
8cb812d
fix checkstyle
Siedlerchr Mar 24, 2018
0be175c
Fix viewModel NPE in copyFiles Action and linkedfilesEditDialog
Siedlerchr Mar 24, 2018
45697c4
Add close button in copy linked files
Siedlerchr Mar 24, 2018
7d627ff
fix checkstyle
Siedlerchr Mar 24, 2018
3189b33
Rename and reformat
Siedlerchr Mar 25, 2018
f579772
remove changelog
Siedlerchr Mar 25, 2018
95fdd2d
remove close method
Siedlerchr Mar 25, 2018
bb22a5e
change some odd looking assigments
Siedlerchr Mar 25, 2018
035d9e2
renaming
Siedlerchr Mar 25, 2018
ce3d5e6
forgotten rename
Siedlerchr Mar 25, 2018
c27c4d2
Merge remote-tracking branch 'upstream/maintable-beta' into selectFil…
Siedlerchr Mar 26, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions src/main/java/org/jabref/gui/filelist/AttachFileAction.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package org.jabref.gui.filelist;

import java.util.Optional;
import javafx.application.Platform;

import org.jabref.gui.BasePanel;
import org.jabref.gui.actions.BaseAction;
import org.jabref.gui.undo.UndoableFieldChange;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.FieldChange;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.FieldName;
import org.jabref.model.entry.LinkedFile;

public class AttachFileAction implements BaseAction {
Expand All @@ -27,9 +24,14 @@ public void action() {
}
BibEntry entry = panel.getSelectedEntries().get(0);
LinkedFile flEntry = new LinkedFile("", "", "");
FileListEntryEditor editor = new FileListEntryEditor(flEntry, false, true,

FileListDialogView dlg = new FileListDialogView();

Platform.runLater(() -> dlg.show());
/* FileListEntryEditor editor = new FileListEntryEditor(flEntry, false, true,
panel.getBibDatabaseContext());
editor.setVisible(true, true);

if (editor.okPressed()) {
Copy link
Member Author

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

Copy link
Member

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 with

private Optional<AbstractController> getController() {

(just change the visibility) and then the view model with

For parameter injection, have a look at CopyFilesDialogView.

Optional<FieldChange> fieldChange = entry.addFile(flEntry);

Expand All @@ -39,6 +41,6 @@ public void action() {
panel.getUndoManager().addEdit(ce);
panel.markBaseChanged();
}
}
}*/
}
}
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());
Copy link
Member Author

Choose a reason for hiding this comment

The 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

Copy link
Member

Choose a reason for hiding this comment

The 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 itemsProperty is never changed directly.)

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);
}
}
}
}
19 changes: 19 additions & 0 deletions src/main/java/org/jabref/gui/filelist/FileListDialogView.java
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();

}
}
128 changes: 128 additions & 0 deletions src/main/java/org/jabref/gui/filelist/FileListDialogViewModel.java
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
Expand Up @@ -84,6 +84,9 @@ public class FileListEntryEditor {
//Do not make this variable final, as then the lambda action listener will fail on compiöe
private BibDatabaseContext databaseContext;
private final ActionListener browsePressed = e -> {



String fileText = link.getText().trim();
Optional<Path> file = FileHelper.expandFilename(this.databaseContext, fileText,
Globals.prefs.getFileDirectoryPreferences());
Expand Down
68 changes: 68 additions & 0 deletions src/main/resources/org/jabref/gui/filelist/FileListDialog.fxml
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>