|
6 | 6 | import java.util.ArrayList;
|
7 | 7 | import java.util.LinkedList;
|
8 | 8 | import java.util.List;
|
| 9 | +import java.util.Objects; |
9 | 10 | import java.util.Optional;
|
10 | 11 | import java.util.stream.Collectors;
|
11 | 12 |
|
12 |
| -import javax.inject.Inject; |
13 |
| - |
14 | 13 | import javafx.application.Platform;
|
15 | 14 | import javafx.beans.property.ObjectProperty;
|
16 | 15 | import javafx.css.PseudoClass;
|
17 |
| -import javafx.fxml.FXML; |
18 | 16 | import javafx.scene.control.Button;
|
19 | 17 | import javafx.scene.control.ContextMenu;
|
20 | 18 | import javafx.scene.control.Control;
|
|
23 | 21 | import javafx.scene.control.SelectionMode;
|
24 | 22 | import javafx.scene.control.SeparatorMenuItem;
|
25 | 23 | import javafx.scene.control.TextField;
|
| 24 | +import javafx.scene.control.Tooltip; |
26 | 25 | import javafx.scene.control.TreeItem;
|
27 | 26 | import javafx.scene.control.TreeTableColumn;
|
28 | 27 | import javafx.scene.control.TreeTableRow;
|
|
32 | 31 | import javafx.scene.input.MouseButton;
|
33 | 32 | import javafx.scene.input.MouseEvent;
|
34 | 33 | import javafx.scene.input.TransferMode;
|
| 34 | +import javafx.scene.layout.BorderPane; |
| 35 | +import javafx.scene.layout.HBox; |
| 36 | +import javafx.scene.layout.Priority; |
35 | 37 | import javafx.scene.layout.StackPane;
|
36 | 38 | import javafx.scene.text.Text;
|
37 | 39 |
|
|
57 | 59 | import org.slf4j.Logger;
|
58 | 60 | import org.slf4j.LoggerFactory;
|
59 | 61 |
|
60 |
| -public class GroupTreeView { |
| 62 | +public class GroupTreeView extends BorderPane { |
61 | 63 |
|
62 | 64 | private static final Logger LOGGER = LoggerFactory.getLogger(GroupTreeView.class);
|
63 | 65 |
|
64 |
| - @FXML private TreeTableView<GroupNodeViewModel> groupTree; |
65 |
| - @FXML private TreeTableColumn<GroupNodeViewModel, GroupNodeViewModel> mainColumn; |
66 |
| - @FXML private TreeTableColumn<GroupNodeViewModel, GroupNodeViewModel> numberColumn; |
67 |
| - @FXML private TreeTableColumn<GroupNodeViewModel, GroupNodeViewModel> expansionNodeColumn; |
68 |
| - @FXML private CustomTextField searchField; |
69 |
| - @FXML private Button addNewGroup; |
| 66 | + private TreeTableView<GroupNodeViewModel> groupTree; |
| 67 | + private TreeTableColumn<GroupNodeViewModel, GroupNodeViewModel> mainColumn; |
| 68 | + private TreeTableColumn<GroupNodeViewModel, GroupNodeViewModel> numberColumn; |
| 69 | + private TreeTableColumn<GroupNodeViewModel, GroupNodeViewModel> expansionNodeColumn; |
| 70 | + private CustomTextField searchField; |
| 71 | + private Button addNewGroup; |
70 | 72 |
|
71 |
| - @Inject private StateManager stateManager; |
72 |
| - @Inject private DialogService dialogService; |
73 |
| - @Inject private TaskExecutor taskExecutor; |
74 |
| - @Inject private PreferencesService preferencesService; |
| 73 | + private final StateManager stateManager; |
| 74 | + private final DialogService dialogService; |
| 75 | + private final TaskExecutor taskExecutor; |
| 76 | + private final PreferencesService preferencesService; |
75 | 77 |
|
76 | 78 | private GroupTreeViewModel viewModel;
|
77 | 79 | private CustomLocalDragboard localDragboard;
|
78 | 80 |
|
79 | 81 | private DragExpansionHandler dragExpansionHandler;
|
80 | 82 |
|
81 |
| - @FXML |
82 |
| - public void initialize() { |
| 83 | + /** |
| 84 | + * The groups panel |
| 85 | + * |
| 86 | + * Note: This panel is deliberately not created in FXML, since parsing of this took about 500 msecs. In an attempt |
| 87 | + * to speed up the startup time of JabRef, this has been rewritten to plain java. |
| 88 | + */ |
| 89 | + public GroupTreeView(TaskExecutor taskExecutor, StateManager stateManager, PreferencesService preferencesService, DialogService dialogService) { |
| 90 | + this.taskExecutor = taskExecutor; |
| 91 | + this.stateManager = stateManager; |
| 92 | + this.preferencesService = preferencesService; |
| 93 | + this.dialogService = dialogService; |
| 94 | + |
| 95 | + createNodes(); |
| 96 | + this.getStylesheets().add(Objects.requireNonNull(GroupTreeView.class.getResource("GroupTree.css")).toExternalForm()); |
| 97 | + initialize(); |
| 98 | + } |
| 99 | + |
| 100 | + private void createNodes() { |
| 101 | + searchField = new CustomTextField(); |
| 102 | + |
| 103 | + searchField.setPromptText(Localization.lang("Filter groups")); |
| 104 | + searchField.setId("searchField"); |
| 105 | + HBox.setHgrow(searchField, Priority.ALWAYS); |
| 106 | + HBox groupFilterBar = new HBox(searchField); |
| 107 | + groupFilterBar.setId("groupFilterBar"); |
| 108 | + this.setTop(groupFilterBar); |
| 109 | + |
| 110 | + mainColumn = new TreeTableColumn<>(); |
| 111 | + mainColumn.setId("mainColumn"); |
| 112 | + numberColumn = new TreeTableColumn<>(); |
| 113 | + numberColumn.getStyleClass().add("numberColumn"); |
| 114 | + numberColumn.setMinWidth(50d); |
| 115 | + numberColumn.setMaxWidth(70d); |
| 116 | + numberColumn.setPrefWidth(60d); |
| 117 | + expansionNodeColumn = new TreeTableColumn<>(); |
| 118 | + expansionNodeColumn.getStyleClass().add("expansionNodeColumn"); |
| 119 | + expansionNodeColumn.setMaxWidth(25d); |
| 120 | + expansionNodeColumn.setMinWidth(25d); |
| 121 | + |
| 122 | + groupTree = new TreeTableView<>(); |
| 123 | + groupTree.setId("groupTree"); |
| 124 | + groupTree.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY); |
| 125 | + groupTree.getColumns().addAll(List.of(mainColumn, numberColumn, expansionNodeColumn)); |
| 126 | + this.setCenter(groupTree); |
| 127 | + |
| 128 | + addNewGroup = new Button(Localization.lang("Add group")); |
| 129 | + addNewGroup.setId("addNewGroup"); |
| 130 | + addNewGroup.setMaxWidth(Double.MAX_VALUE); |
| 131 | + HBox.setHgrow(addNewGroup, Priority.ALWAYS); |
| 132 | + addNewGroup.setTooltip(new Tooltip(Localization.lang("New group"))); |
| 133 | + addNewGroup.setOnAction(event -> addNewGroup()); |
| 134 | + |
| 135 | + HBox groupBar = new HBox(addNewGroup); |
| 136 | + groupBar.setId("groupBar"); |
| 137 | + this.setBottom(groupBar); |
| 138 | + } |
| 139 | + |
| 140 | + private void initialize() { |
83 | 141 | this.localDragboard = stateManager.getLocalDragboard();
|
84 | 142 | viewModel = new GroupTreeViewModel(stateManager, dialogService, preferencesService, taskExecutor, localDragboard);
|
85 | 143 |
|
@@ -396,13 +454,12 @@ private ContextMenu createContextMenuForGroup(GroupNodeViewModel group) {
|
396 | 454 | return menu;
|
397 | 455 | }
|
398 | 456 |
|
399 |
| - @FXML |
400 | 457 | private void addNewGroup() {
|
401 | 458 | viewModel.addNewGroupToRoot();
|
402 | 459 | }
|
403 | 460 |
|
404 | 461 | /**
|
405 |
| - * Workaround taken from https://bitbucket.org/controlsfx/controlsfx/issues/330/making-textfieldssetupclearbuttonfield |
| 462 | + * Workaround taken from https://github.com/controlsfx/controlsfx/issues/330 |
406 | 463 | */
|
407 | 464 | private void setupClearButtonField(CustomTextField customTextField) {
|
408 | 465 | try {
|
|
0 commit comments