Skip to content

Commit 251c44d

Browse files
authored
Toggle enable status of menu items (#4872)
* Toggle enable status of menu items (prototype) * Use for pushtoapplication * Improve code around push to applications * Set enable status for all actions * Fix tests and checkstyle
1 parent d8b2c7e commit 251c44d

File tree

79 files changed

+691
-631
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+691
-631
lines changed

src/main/java/org/jabref/gui/BasePanel.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,20 @@
3030
import org.jabref.JabRefExecutorService;
3131
import org.jabref.gui.actions.Actions;
3232
import org.jabref.gui.actions.BaseAction;
33-
import org.jabref.gui.actions.CleanupAction;
34-
import org.jabref.gui.actions.CopyBibTeXKeyAndLinkAction;
35-
import org.jabref.gui.actions.GenerateBibtexKeyAction;
36-
import org.jabref.gui.actions.WriteXMPAction;
3733
import org.jabref.gui.autocompleter.AutoCompletePreferences;
3834
import org.jabref.gui.autocompleter.AutoCompleteUpdater;
3935
import org.jabref.gui.autocompleter.PersonNameSuggestionProvider;
4036
import org.jabref.gui.autocompleter.SuggestionProviders;
37+
import org.jabref.gui.bibtexkeypattern.GenerateBibtexKeyAction;
38+
import org.jabref.gui.cleanup.CleanupAction;
4139
import org.jabref.gui.collab.DatabaseChangeMonitor;
4240
import org.jabref.gui.collab.DatabaseChangePane;
4341
import org.jabref.gui.desktop.JabRefDesktop;
42+
import org.jabref.gui.edit.CopyBibTeXKeyAndLinkAction;
4443
import org.jabref.gui.edit.ReplaceStringAction;
4544
import org.jabref.gui.entryeditor.EntryEditor;
4645
import org.jabref.gui.exporter.SaveDatabaseAction;
46+
import org.jabref.gui.exporter.WriteXMPAction;
4747
import org.jabref.gui.externalfiles.FindFullTextAction;
4848
import org.jabref.gui.externalfiletype.ExternalFileMenuItem;
4949
import org.jabref.gui.externalfiletype.ExternalFileType;
@@ -294,7 +294,7 @@ private void setupActions() {
294294
// The action for cleaning up entry.
295295
actions.put(Actions.CLEANUP, cleanUpAction);
296296

297-
actions.put(Actions.MERGE_ENTRIES, () -> new MergeEntriesAction(frame).execute());
297+
actions.put(Actions.MERGE_ENTRIES, () -> new MergeEntriesAction(frame, Globals.stateManager).execute());
298298

299299
// The action for copying the selected entry's key.
300300
actions.put(Actions.COPY_KEY, this::copyKey);
@@ -432,7 +432,7 @@ private void delete(boolean cut, List<BibEntry> entries) {
432432
compound = new NamedCompound((entries.size() > 1 ? Localization.lang("delete entries") : Localization.lang("delete entry")));
433433
}
434434
for (BibEntry entry : entries) {
435-
compound.addEdit(new UndoableRemoveEntry(bibDatabaseContext.getDatabase(), entry, BasePanel.this));
435+
compound.addEdit(new UndoableRemoveEntry(bibDatabaseContext.getDatabase(), entry));
436436
bibDatabaseContext.getDatabase().removeEntry(entry);
437437
ensureNotShowingBottomPanel(entry);
438438
}

src/main/java/org/jabref/gui/EntryTypeViewModel.java

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import javafx.concurrent.Task;
1515
import javafx.concurrent.Worker;
1616

17+
import org.jabref.gui.duplicationFinder.DuplicateResolverDialog;
1718
import org.jabref.logic.bibtex.DuplicateCheck;
1819
import org.jabref.logic.bibtexkeypattern.BibtexKeyGenerator;
1920
import org.jabref.logic.importer.FetcherException;

src/main/java/org/jabref/gui/JabRefFrame.java

+92-208
Large diffs are not rendered by default.

src/main/java/org/jabref/gui/SaveOrderConfigDisplay.fxml

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
<?import javafx.scene.layout.ColumnConstraints?>
99
<?import javafx.scene.layout.GridPane?>
1010
<?import javafx.scene.layout.RowConstraints?>
11-
1211
<fx:root prefHeight="200.0" prefWidth="600.0" type="javafx.scene.layout.GridPane" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.jabref.gui.SaveOrderConfigDisplayView">
1312
<columnConstraints>
1413
<ColumnConstraints hgrow="SOMETIMES" minWidth="-Infinity" prefWidth="100.0" />

src/main/java/org/jabref/gui/StateManager.java

+6-11
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,19 @@
66
import java.util.stream.Collectors;
77

88
import javafx.beans.binding.Bindings;
9-
import javafx.beans.property.ObjectProperty;
109
import javafx.beans.property.ReadOnlyListProperty;
1110
import javafx.beans.property.ReadOnlyListWrapper;
12-
import javafx.beans.property.SimpleObjectProperty;
1311
import javafx.collections.FXCollections;
1412
import javafx.collections.ObservableList;
1513
import javafx.collections.ObservableMap;
1614

15+
import org.jabref.gui.util.OptionalObjectProperty;
1716
import org.jabref.logic.search.SearchQuery;
1817
import org.jabref.model.database.BibDatabaseContext;
1918
import org.jabref.model.entry.BibEntry;
2019
import org.jabref.model.groups.GroupTreeNode;
2120
import org.jabref.model.util.OptionalUtil;
2221

23-
import org.fxmisc.easybind.EasyBind;
24-
import org.fxmisc.easybind.monadic.MonadicBinding;
25-
2622
/**
2723
* This class manages the GUI-state of JabRef, including:
2824
* - currently selected database
@@ -33,22 +29,21 @@
3329
*/
3430
public class StateManager {
3531

36-
private final ObjectProperty<Optional<BibDatabaseContext>> activeDatabase = new SimpleObjectProperty<>(Optional.empty());
32+
private final OptionalObjectProperty<BibDatabaseContext> activeDatabase = OptionalObjectProperty.empty();
3733
private final ReadOnlyListWrapper<GroupTreeNode> activeGroups = new ReadOnlyListWrapper<>(FXCollections.observableArrayList());
3834
private final ObservableList<BibEntry> selectedEntries = FXCollections.observableArrayList();
3935
private final ObservableMap<BibDatabaseContext, ObservableList<GroupTreeNode>> selectedGroups = FXCollections.observableHashMap();
40-
private final ObjectProperty<Optional<SearchQuery>> activeSearchQuery = new SimpleObjectProperty<>(Optional.empty());
36+
private final OptionalObjectProperty<SearchQuery> activeSearchQuery = OptionalObjectProperty.empty();
4137

4238
public StateManager() {
43-
MonadicBinding<BibDatabaseContext> currentDatabase = EasyBind.map(activeDatabase, database -> database.orElse(null));
44-
activeGroups.bind(Bindings.valueAt(selectedGroups, currentDatabase));
39+
activeGroups.bind(Bindings.valueAt(selectedGroups, activeDatabase.orElse(null)));
4540
}
4641

47-
public ObjectProperty<Optional<BibDatabaseContext>> activeDatabaseProperty() {
42+
public OptionalObjectProperty<BibDatabaseContext> activeDatabaseProperty() {
4843
return activeDatabase;
4944
}
5045

51-
public ObjectProperty<Optional<SearchQuery>> activeSearchQueryProperty() {
46+
public OptionalObjectProperty<SearchQuery> activeSearchQueryProperty() {
5247
return activeSearchQuery;
5348
}
5449

src/main/java/org/jabref/gui/actions/ActionFactory.java

+65-4
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,35 @@
11
package org.jabref.gui.actions;
22

3+
import java.lang.reflect.InvocationTargetException;
4+
import java.lang.reflect.Method;
35
import java.util.Objects;
46

57
import javafx.scene.Node;
68
import javafx.scene.control.Button;
79
import javafx.scene.control.ButtonBase;
810
import javafx.scene.control.CheckMenuItem;
11+
import javafx.scene.control.Label;
912
import javafx.scene.control.Menu;
1013
import javafx.scene.control.MenuItem;
14+
import javafx.scene.control.Tooltip;
1115

1216
import org.jabref.gui.keyboard.KeyBindingRepository;
17+
import org.jabref.model.strings.StringUtil;
1318

19+
import com.sun.javafx.scene.control.skin.ContextMenuContent;
1420
import de.saxsys.mvvmfx.utils.commands.Command;
1521
import org.controlsfx.control.action.ActionUtils;
22+
import org.fxmisc.easybind.EasyBind;
23+
import org.slf4j.Logger;
24+
import org.slf4j.LoggerFactory;
1625

1726
/**
1827
* Helper class to create and style controls according to an {@link Action}.
1928
*/
2029
public class ActionFactory {
2130

31+
private static final Logger LOGGER = LoggerFactory.getLogger(ActionFactory.class);
32+
2233
private final KeyBindingRepository keyBindingRepository;
2334

2435
public ActionFactory(KeyBindingRepository keyBindingRepository) {
@@ -33,14 +44,64 @@ private static void setGraphic(MenuItem node, Action action) {
3344
action.getIcon().ifPresent(icon -> node.setGraphic(icon.getGraphicNode()));
3445
}
3546

36-
public MenuItem configureMenuItem(Action action, Command command, MenuItem menuItem) {
37-
return ActionUtils.configureMenuItem(new JabRefAction(action, command, keyBindingRepository), menuItem);
47+
/*
48+
* Returns MenuItemContainer node associated with this menu item
49+
* which can contain:
50+
* 1. label node of type Label for displaying menu item text,
51+
* 2. right node of type Label for displaying accelerator text,
52+
* or an arrow if it's a Menu,
53+
* 3. graphic node for displaying menu item icon, and
54+
* 4. left node for displaying either radio button or check box.
55+
*
56+
* This is basically rewritten impl_styleableGetNode() which
57+
* should not be used since it's marked as deprecated.
58+
*/
59+
private static Label getAssociatedNode(MenuItem menuItem) {
60+
ContextMenuContent.MenuItemContainer container = (ContextMenuContent.MenuItemContainer) menuItem.impl_styleableGetNode();
61+
62+
if (container == null) {
63+
return null;
64+
} else {
65+
// We have to use reflection to get the associated label
66+
try {
67+
Method getLabel = ContextMenuContent.MenuItemContainer.class.getDeclaredMethod("getLabel");
68+
getLabel.setAccessible(true);
69+
return (Label) getLabel.invoke(container);
70+
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
71+
LOGGER.warn("Could not get label of menu item", e);
72+
}
73+
}
74+
return null;
3875
}
3976

40-
public MenuItem createMenuItem(Action action, Command command) {
41-
MenuItem menuItem = ActionUtils.createMenuItem(new JabRefAction(action, command, keyBindingRepository));
77+
public MenuItem configureMenuItem(Action action, Command command, MenuItem menuItem) {
78+
ActionUtils.configureMenuItem(new JabRefAction(action, command, keyBindingRepository), menuItem);
4279
setGraphic(menuItem, action);
4380

81+
// Show tooltips
82+
if (command instanceof SimpleCommand) {
83+
EasyBind.subscribe(
84+
((SimpleCommand) command).statusMessageProperty(),
85+
message -> {
86+
Label label = getAssociatedNode(menuItem);
87+
if (label != null) {
88+
label.setMouseTransparent(false);
89+
if (StringUtil.isBlank(message)) {
90+
label.setTooltip(null);
91+
} else {
92+
label.setTooltip(new Tooltip(message));
93+
}
94+
}
95+
}
96+
);
97+
}
98+
99+
return menuItem;
100+
}
101+
102+
public MenuItem createMenuItem(Action action, Command command) {
103+
MenuItem menuItem = new MenuItem();
104+
configureMenuItem(action, command, menuItem);
44105
return menuItem;
45106
}
46107

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.jabref.gui.actions;
2+
3+
import javafx.beans.binding.Bindings;
4+
import javafx.beans.binding.BooleanExpression;
5+
6+
import org.jabref.gui.StateManager;
7+
8+
public class ActionHelper {
9+
public static BooleanExpression needsDatabase(StateManager stateManager) {
10+
return stateManager.activeDatabaseProperty().isPresent();
11+
}
12+
13+
public static BooleanExpression needsEntriesSelected(StateManager stateManager) {
14+
return Bindings.isNotEmpty(stateManager.getSelectedEntries());
15+
}
16+
}

src/main/java/org/jabref/gui/actions/Actions.java

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
/**
44
* Global String constants for GUI actions
55
*/
6+
@Deprecated
67
public enum Actions {
78

89
ABBREVIATE_ISO,

src/main/java/org/jabref/gui/actions/BaseAction.java

+3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
* BaseAction is used to define actions that are called from the
55
* base frame through runCommand(). runCommand() finds the
66
* appropriate BaseAction object, and runs its action() method.
7+
*
8+
* @deprecated use {@link SimpleCommand} instead
79
*/
810
@FunctionalInterface
11+
@Deprecated
912
public interface BaseAction {
1013

1114
void action() throws Exception;

src/main/java/org/jabref/gui/actions/BibtexKeyPatternAction.java

-18
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.jabref.gui.actions;
22

3+
import javafx.beans.binding.Bindings;
4+
35
import org.jabref.Globals;
46
import org.jabref.gui.keyboard.KeyBindingRepository;
57

@@ -10,7 +12,6 @@
1012
*/
1113
class JabRefAction extends org.controlsfx.control.action.Action {
1214

13-
1415
public JabRefAction(Action action, KeyBindingRepository keyBindingRepository) {
1516
super(action.getText());
1617
action.getIcon()
@@ -19,22 +20,34 @@ public JabRefAction(Action action, KeyBindingRepository keyBindingRepository) {
1920
.ifPresent(keyBinding -> setAccelerator(keyBindingRepository.getKeyCombination(keyBinding)));
2021

2122
setLongText(action.getDescription());
22-
2323
}
2424

2525
public JabRefAction(Action action, Command command, KeyBindingRepository keyBindingRepository) {
2626
this(action, keyBindingRepository);
2727

2828
setEventHandler(event -> {
2929
command.execute();
30-
trackExecute();
30+
trackExecute(getActionName(action, command));
3131
});
3232

3333
disabledProperty().bind(command.executableProperty().not());
34+
35+
if (command instanceof SimpleCommand) {
36+
SimpleCommand ourCommand = (SimpleCommand) command;
37+
longTextProperty().bind(Bindings.concat(action.getDescription(), ourCommand.statusMessageProperty()));
38+
}
39+
}
40+
41+
private String getActionName(Action action, Command command) {
42+
if (command.getClass().isAnonymousClass()) {
43+
return action.getText();
44+
} else {
45+
return command.getClass().getSimpleName();
46+
}
3447
}
3548

36-
private void trackExecute() {
49+
private void trackExecute(String actionName) {
3750
Globals.getTelemetryClient()
38-
.ifPresent(telemetryClient -> telemetryClient.trackEvent(getText()));
51+
.ifPresent(telemetryClient -> telemetryClient.trackEvent(actionName));
3952
}
4053
}

src/main/java/org/jabref/gui/actions/ManageContentSelectorAction.java

-29
This file was deleted.

src/main/java/org/jabref/gui/actions/OldCommandWrapper.java

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* This wraps the old Swing commands so that they fit into the new infrastructure.
1414
* In the long term, this class should be removed.
1515
*/
16+
@Deprecated
1617
public class OldCommandWrapper extends CommandBase {
1718

1819
private static final Logger LOGGER = LoggerFactory.getLogger(OldCommandWrapper.class);

src/main/java/org/jabref/gui/actions/OldCommandWrapperForActiveDatabase.java

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* This wraps the old Swing commands so that they fit into the new infrastructure.
1414
* In the long term, this class should be removed.
1515
*/
16+
@Deprecated
1617
public class OldCommandWrapperForActiveDatabase extends CommandBase {
1718

1819
private static final Logger LOGGER = LoggerFactory.getLogger(OldCommandWrapperForActiveDatabase.class);

src/main/java/org/jabref/gui/actions/SetupGeneralFieldsAction.java

-13
This file was deleted.

0 commit comments

Comments
 (0)