package bluej.editor.moe;

import bluej.Config;
import bluej.editor.moe.MoeActions.Category;
import bluej.editor.moe.MoeActions.MoeAbstractAction;
import bluej.pkgmgr.Project;
import bluej.prefmgr.PrefPanelListener;
import bluej.utility.DialogManager;
import bluej.utility.Utility;
import bluej.utility.javafx.FXPlatformSupplier;
import bluej.utility.javafx.JavaFXUtil;
import javafx.animation.RotateTransition;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.TextFieldListCell;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination.ModifierValue;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Window;
import javafx.util.Duration;
import javafx.util.StringConverter;
import threadchecker.OnThread;
import threadchecker.Tag;

import java.util.List;
import java.util.Optional;
import java.util.Properties;
import java.util.stream.Collectors;


| KeyBindingsPanel panel for the key bindings in preferences | @author Marion Zalk | @OnThread(Tag.FXPlatform) public class KeyBindingsPanel extends GridPane implements PrefPanelListener{ static final String title = Config.getString("editor.functions.title"); static final String close = Config.getString("close"); static final String defaultsLabel = Config.getString("editor.functions.defaults"); static final String categoriesLabel = Config.getString("editor.functions.categories"); static final String keyLabel = Config.getString("editor.functions.keys"); static final String addKeyLabel = Config.getString("editor.functions.addkey"); static final String delKeyLabel = Config.getString("editor.functions.delkey"); private final FXPlatformSupplier<Window> parent; private final Button defaultsButton; private final Button addKeyButton; private final Button delKeyButton; private final ComboBox<Category> categoryMenu; private final ListView<String> functionList; private final ListView<KeyCodeCombination> keyList; private final Text helpLabel; private MoeActions actions; private Properties help; private List<ActionInfo> functions; private static Label errorLabel; private static class ActionInfo { private final String name; private final Category category; public ActionInfo(MoeAbstractAction action) { name = action.getName(); category = action.getCategory(); } } public void categoryMenuChanged() { Category selected = categoryMenu.getSelectionModel().getSelectedItem(); functionList.getItems().setAll(functions.stream().filter(a -> a.category == selected).map(a -> a.name).collect(Collectors.toList())); clearKeyList(); clearHelpText(); addKeyButton.setDisable(true); delKeyButton.setDisable(true); } public KeyBindingsPanel(FXPlatformSupplier<Window> parent) { this.parent = parent; actions = MoeActions.getActions(null); functions = Utility.mapList(actions.getAllActions(), ActionInfo::new); ColumnConstraints c = new ColumnConstraints(); c.setPercentWidth(50.0); getColumnConstraints().setAll(c, c); JavaFXUtil.addStyleClass(this, "prefmgr-key-panel"); BorderPane funcPanel = new BorderPane(); functionList = new ListView<>(); functionList.setEditable(false); funcPanel.setCenter(functionList); Label label = new Label(categoriesLabel + " "); categoryMenu = new ComboBox<>(); HBox categoryHBox = new HBox(label, categoryMenu); categoryHBox.setAlignment(Pos.BASELINE_CENTER); BorderPane.setAlignment(categoryHBox, Pos.BASELINE_CENTER); funcPanel.setTop(categoryHBox); BorderPane controlPanel = new BorderPane(); BorderPane keyPanel = new BorderPane(); Label kLabel = new Label(keyLabel); JavaFXUtil.addStyleClass(kLabel, "key-header-label"); keyPanel.setTop(kLabel); keyList = new ListView<>(); keyList.setCellFactory(lv -> new TextFieldListCell<>(new StringConverter<KeyCodeCombination>() { @Override public String toString(KeyCodeCombination object) { return object.getDisplayText(); } @Override public KeyCodeCombination fromString(String string) { return null; } })); keyList.setEditable(false); keyPanel.setCenter(keyList); HBox keyButtonPanel = new HBox(); keyButtonPanel.setAlignment(Pos.BASELINE_CENTER); JavaFXUtil.addStyleClass(keyButtonPanel, "key-bindings-buttons"); addKeyButton = new Button(addKeyLabel); keyButtonPanel.getChildren().add(addKeyButton); delKeyButton = new Button(delKeyLabel); keyButtonPanel.getChildren().add(delKeyButton); defaultsButton = new Button(defaultsLabel); controlPanel.setTop(defaultsButton); BorderPane.setAlignment(defaultsButton, Pos.BASELINE_RIGHT); keyPanel.setBottom(keyButtonPanel); controlPanel.setCenter(keyPanel); helpLabel=new Text(); TextFlow textFlow = new TextFlow(helpLabel); textFlow.setMinHeight(80); controlPanel.setBottom(textFlow); JavaFXUtil.addStyleClass(funcPanel, "key-bindings-column"); JavaFXUtil.addStyleClass(controlPanel, "key-bindings-column"); add(funcPanel, 0, 0); add(controlPanel, 1, 0); updateDisplay(); } @OnThread(Tag.FXPlatform) public void beginEditing(Project project) { } @OnThread(Tag.FXPlatform) public void commitEditing(Project project) { handleClose(); } @OnThread(Tag.FXPlatform) public void revertEditing(Project project) { }
public void updateDisplay() { JavaFXUtil.addChangeListenerPlatform(categoryMenu.getSelectionModel().selectedIndexProperty(), i -> categoryMenuChanged()); JavaFXUtil.addChangeListenerPlatform(functionList.getSelectionModel().selectedIndexProperty(), i -> handleFuncListSelect()); JavaFXUtil.addChangeListenerPlatform(keyList.getSelectionModel().selectedIndexProperty(), i -> handleKeyListSelect()); defaultsButton.setOnAction(e -> handleDefaults()); addKeyButton.setOnAction(e -> handleAddKey()); delKeyButton.setOnAction(e -> handleDelKey()); openHelpFile(); categoryMenu.getItems().setAll(Category.values()); categoryMenu.getSelectionModel().selectFirst(); }
| Handle click on Defaults button. | private void handleDefaults() { int answer = DialogManager.askQuestionFX(parent.get(), "default-keys"); if (answer == 0) { actions.setDefaultKeyBindings(); handleFuncListSelect(); } }
| Handle click in functions list. | private void handleFuncListSelect() { int index = functionList.getSelectionModel().getSelectedIndex(); if (index == -1) return; String currentAction = functionList.getSelectionModel().getSelectedItem(); updateKeyList(currentAction); String helpText = getHelpText(currentAction); helpLabel.setText(helpText); }
| Handle click in key bindings list. | private void handleKeyListSelect() { delKeyButton.setDisable(false); }
| Handle click on Close button. | private void handleClose() { if (!actions.save()) DialogManager.showErrorFX(parent.get(), "cannot-save-keys"); }
| Handle click on Add Key button. | private void handleAddKey() { Optional<KeyCodeCombination> newKey = new KeyCaptureDialog().showAndWait(); if (newKey.equals(Optional.of(ButtonType.CANCEL))) { return; } if (newKey.isPresent()) { String action = functionList.getSelectionModel().getSelectedItem(); if (action != null) { MoeActions.addKeyCombinationForActionToAllEditors(newKey.get(), action); updateKeyList(action); } } }
| Handle click on Delete Key button. | private void handleDelKey() { int index = keyList.getSelectionModel().getSelectedIndex(); if (index == -1) return; actions.removeKeyStrokeBinding(keyList.getSelectionModel().getSelectedItem()); updateKeyList(functionList.getSelectionModel().getSelectedItem()); }
| Display key bindings in the key list | private void updateKeyList(String action) { List<KeyCodeCombination> currentKeys = actions.getKeyStrokesForAction(action); if (currentKeys == null) clearKeyList(); else { keyList.getItems().setAll(currentKeys); delKeyButton.setDisable(true); } addKeyButton.setDisable(false); } private void clearKeyList() { keyList.getItems().clear(); } private void clearHelpText() { helpLabel.setText(null); } private void openHelpFile() { help = Config.getMoeHelp(); } private String getHelpText(String function) { if (help == null) return null; String helpText=help.getProperty(function); if (helpText!=null && helpText.length()>0) { helpText=helpText.replaceAll("\n", ""); helpText=helpText.trim(); } return helpText; } @OnThread(Tag.FXPlatform) private static class KeyCaptureDialog extends Dialog<KeyCodeCombination> { public KeyCaptureDialog() { TextField textField = new TextField(); errorLabel = JavaFXUtil.withStyleClass(new Label(), "dialog-error-label"); errorLabel.setText(""); textField.addEventFilter(javafx.scene.input.KeyEvent.KEY_PRESSED, (javafx.scene.input.KeyEvent e) -> { if (e.getCode() != KeyCode.ESCAPE && e.getCode() != KeyCode.SHIFT && e.getCode() != KeyCode.CONTROL && e.getCode() != KeyCode.ALT && e.getCode() != KeyCode.ALT_GRAPH && e.getCode() != KeyCode.META && e.getCode() != KeyCode.COMMAND) { if ( e.getCode().isLetterKey()) { if (!(e.isShiftDown() || e.isControlDown() || e.isAltDown() || e.isMetaDown())) { errorLabel.setText("Single Character is not allowed"); RotateTransition animation = null; animation = new RotateTransition(Duration.millis(70), errorLabel); animation.setByAngle(5); animation.setAutoReverse(true); animation.setCycleCount(4); animation.play(); return; } } JavaFXUtil.runAfterCurrent(() -> { setResult(new KeyCodeCombination(e.getCode(), mod(e.isShiftDown()), mod(e.isControlDown()), mod(e.isAltDown()), mod(e.isMetaDown()), ModifierValue.ANY)); hide(); }); e.consume(); } }); VBox mainPanel=new VBox(new Label("Press a key, or Escape to cancel"), textField); getDialogPane().setContent(mainPanel); setOnShown(e -> textField.requestFocus()); Config.addDialogStylesheets(getDialogPane()); getDialogPane().getButtonTypes().setAll(ButtonType.CANCEL); mainPanel.getChildren().add(errorLabel); } private static ModifierValue mod(boolean down) { return down ? ModifierValue.DOWN : ModifierValue.UP; } } }
top, use, map, class KeyBindingsPanel

top, use, map, class KeyBindingsPanel . ActionInfo

.   ActionInfo
.   categoryMenuChanged
.   KeyBindingsPanel
.   toString
.   fromString
.   beginEditing
.   commitEditing
.   revertEditing
.   updateDisplay
.   handleDefaults
.   handleFuncListSelect
.   handleKeyListSelect
.   handleClose
.   handleAddKey
.   handleDelKey
.   updateKeyList
.   clearKeyList
.   clearHelpText
.   openHelpFile
.   getHelpText
.   KeyCaptureDialog
.   mod




446 neLoCode + 9 LoComm