Skip to content

Commit

Permalink
Add right click menu to JTextFields
Browse files Browse the repository at this point in the history
  • Loading branch information
bwRavencl committed Feb 19, 2025
1 parent f39ca21 commit 56801b8
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 4 deletions.
115 changes: 115 additions & 0 deletions src/main/java/de/bwravencl/controllerbuddy/gui/GuiUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,28 @@
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.Serial;
import java.util.List;
import java.util.Optional;
import java.util.prefs.Preferences;
import java.util.stream.Collectors;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.text.Document;
import javax.swing.undo.UndoManager;

@SuppressWarnings({ "exports", "missing-explicit-ctor" })
public final class GuiUtils {
Expand All @@ -66,6 +74,113 @@ static JComboBox<Mode> addModePanel(final Container container, final List<Mode>
return modeComboBox;
}

public static JTextField createTextFieldWithMenu(final String text, final int columns) {
return createTextFieldWithMenu(null, text, columns);
}

public static JTextField createTextFieldWithMenu(final Document doc, final String text, final int columns) {
final var textField = new JTextField(doc, text, columns);

final var undoManager = new UndoManager();
textField.getDocument().addUndoableEditListener(undoManager);

final var undoAction = new AbstractAction(Main.strings.getString("UNDO_ACTION_NAME")) {

@Serial
private static final long serialVersionUID = 283480113359047860L;

@Override
public void actionPerformed(final ActionEvent e) {
if (!undoManager.canUndo()) {
return;
}

undoManager.undo();
setEnabled(undoManager.canUndo());

}
};

final var cutAction = new AbstractAction(Main.strings.getString("CUT_ACTION_NAME")) {

@Serial
private static final long serialVersionUID = 166873451012920651L;

@Override
public void actionPerformed(final ActionEvent e) {
textField.cut();
}
};

final var copyAction = new AbstractAction(Main.strings.getString("COPY_ACTION_NAME")) {

@Serial
private static final long serialVersionUID = 4845008543826860777L;

@Override
public void actionPerformed(final ActionEvent e) {
textField.copy();
}
};

final var pasteAction = new AbstractAction(Main.strings.getString("PASTE_ACTION_NAME")) {

@Serial
private static final long serialVersionUID = -669017641654371170L;

@Override
public void actionPerformed(final ActionEvent e) {
textField.paste();
}
};

final var selectAllAction = new AbstractAction(Main.strings.getString("SELECT_ALL_ACTION_NAME")) {

@Serial
private static final long serialVersionUID = -6215392890571518146L;

@Override
public void actionPerformed(final ActionEvent e) {
textField.selectAll();
}
};

cutAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control X"));
copyAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control C"));
pasteAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control V"));
selectAllAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control A"));

final var popup = new JPopupMenu() {

@Serial
private static final long serialVersionUID = -7112090718851303887L;

@Override
public void show(final Component invoker, final int x, final int y) {
undoAction.setEnabled(undoManager.canUndo());

final var selectedText = textField.getSelectedText();
final var canCopyOrCut = selectedText != null && !selectedText.isEmpty();
copyAction.setEnabled(canCopyOrCut);
cutAction.setEnabled(canCopyOrCut);

super.show(invoker, x, y);
}
};

popup.add(undoAction);
popup.addSeparator();
popup.add(cutAction);
popup.add(copyAction);
popup.add(pasteAction);
popup.addSeparator();
popup.add(selectAllAction);

textField.setComponentPopupMenu(popup);

return textField;
}

static Rectangle getAndStoreTotalDisplayBounds(final Main main) {
final var totalDisplayBounds = new Rectangle();

Expand Down
5 changes: 3 additions & 2 deletions src/main/java/de/bwravencl/controllerbuddy/gui/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -3414,7 +3414,7 @@ void updateModesPanel(final boolean newModeAdded) {
modePanel.add(Box.createGlue(), new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1d, 1d,
GridBagConstraints.CENTER, GridBagConstraints.NONE, LIST_ITEM_INNER_INSETS, 0, 0));

final var descriptionTextField = new JTextField(mode.getDescription(), 35);
final var descriptionTextField = GuiUtils.createTextFieldWithMenu(mode.getDescription(), 35);
modePanel.add(descriptionTextField, new GridBagConstraints(2, 0, 1, 1, 1d, 1d, GridBagConstraints.CENTER,
GridBagConstraints.NONE, LIST_ITEM_INNER_INSETS, 0, 0));
if (newModeAdded && i == numModes - 1) {
Expand Down Expand Up @@ -4489,7 +4489,8 @@ private ConnectionSettingsPanel(final boolean withHost) {
hostPanel.add(hostLabel);

final var host = getHost();
hostTextField = new JTextField(new LimitedLengthPlainDocument(64), host, TEXT_FIELD_COLUMNS);
hostTextField = GuiUtils.createTextFieldWithMenu(new LimitedLengthPlainDocument(64), host,
TEXT_FIELD_COLUMNS);
hostTextField.setCaretPosition(0);
hostPanel.add(hostTextField);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package de.bwravencl.controllerbuddy.input.action.gui;

import de.bwravencl.controllerbuddy.gui.EditActionsDialog;
import de.bwravencl.controllerbuddy.gui.GuiUtils;
import de.bwravencl.controllerbuddy.input.action.IAction;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
Expand Down Expand Up @@ -44,8 +45,7 @@ public StringEditorBuilder(final EditActionsDialog editActionsDialog, final IAct

@Override
public void buildEditor(final JPanel parentPanel) {
final var textField = new JTextField(17);
textField.setText((String) initialValue);
final var textField = GuiUtils.createTextFieldWithMenu((String) initialValue, 17);
textField.setCaretPosition(0);

final var textFieldPropertySetter = new TextFieldPropertySetter(textField, action, setterMethod);
Expand Down
6 changes: 6 additions & 0 deletions src/main/resources/strings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ CHANGE_VJOY_DIRECTORY_ACTION_DESCRIPTION = Change the vJoy directory
EXPORT_ACTION_NAME = Export
EXPORT_ACTION_DESCRIPTION = Export a Profile visualization

UNDO_ACTION_NAME = Undo
CUT_ACTION_NAME = Cut
COPY_ACTION_NAME = Copy
PASTE_ACTION_NAME = Paste
SELECT_ALL_ACTION_NAME = Select all

SHOW_TRAY_ENTRY_LABEL = Show

STATUS_CONNECTED_TO_VJOY_DEVICE = Connected to vJoy device {0,number,integer}
Expand Down
6 changes: 6 additions & 0 deletions src/main/resources/strings_de_DE.properties
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,12 @@ CHANGE_VJOY_DIRECTORY_ACTION_DESCRIPTION = Das vJoy Verzeichnis ändern
EXPORT_ACTION_NAME = Export
EXPORT_ACTION_DESCRIPTION = Profil-Visualisierung exportieren

UNDO_ACTION_NAME = Rückgängig
CUT_ACTION_NAME = Ausschneiden
COPY_ACTION_NAME = Kopieren
PASTE_ACTION_NAME = Einfügen
SELECT_ALL_ACTION_NAME = Alles auswählen

SHOW_TRAY_ENTRY_LABEL = Anzeigen

STATUS_CONNECTED_TO_VJOY_DEVICE = Verbunden mit vJoy Gerät {0,number,integer}
Expand Down

0 comments on commit 56801b8

Please sign in to comment.