mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-28 23:45:17 -04:00
Improved the SingleValueDialog to enter multi bit values
This commit is contained in:
parent
5a27cf916f
commit
7fc84db1f1
@ -5,54 +5,204 @@ import de.neemann.digital.gui.sync.Sync;
|
|||||||
import de.neemann.digital.lang.Lang;
|
import de.neemann.digital.lang.Lang;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.DocumentEvent;
|
||||||
|
import javax.swing.event.DocumentListener;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog to edit a single value.
|
* Dialog to edit a single value.
|
||||||
* Used to enter a multi bit input value
|
* Used to enter a multi bit input value.
|
||||||
*
|
*
|
||||||
* @author hneemann
|
* @author hneemann
|
||||||
|
* @author Rüdiger Heintz
|
||||||
*/
|
*/
|
||||||
public final class SingleValueDialog extends JDialog {
|
public final class SingleValueDialog extends JDialog {
|
||||||
|
|
||||||
private String returnText;
|
private enum InMode {
|
||||||
|
HEX(Lang.get("attr_dialogHex")),
|
||||||
|
DECIMAL(Lang.get("attr_dialogDecimal")),
|
||||||
|
OCTAL(Lang.get("attr_dialogOctal")),
|
||||||
|
ASCII(Lang.get("attr_dialogAscii")),
|
||||||
|
HIGHZ(Lang.get("attr_dialogHighz"));
|
||||||
|
|
||||||
/**
|
private String langText;
|
||||||
* Creates a new instance
|
|
||||||
*
|
InMode(String langKey) {
|
||||||
* @param pos the position to show the dialog
|
this.langText = langKey;
|
||||||
* @param text the text to edit
|
}
|
||||||
*/
|
|
||||||
private SingleValueDialog(Point pos, String text) {
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return langText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InMode[] values(boolean supportsHighZ) {
|
||||||
|
if (supportsHighZ) {
|
||||||
|
return values();
|
||||||
|
} else {
|
||||||
|
return Arrays.copyOf(values(), values().length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final JTextField textField;
|
||||||
|
private final boolean supportsHighZ;
|
||||||
|
private final JComboBox<InMode> formatComboBox;
|
||||||
|
private JCheckBox[] checkBoxes;
|
||||||
|
private boolean programmaticModifyingFormat = false;
|
||||||
|
private long editValue;
|
||||||
|
private boolean ok = false;
|
||||||
|
|
||||||
|
private SingleValueDialog(Point pos, ObservableValue value) {
|
||||||
super((Frame) null, Lang.get("attr_dialogTitle"), true);
|
super((Frame) null, Lang.get("attr_dialogTitle"), true);
|
||||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||||
|
|
||||||
JTextField textField = new JTextField(30);
|
editValue = value.getValue();
|
||||||
textField.setText(text);
|
supportsHighZ = value.supportsHighZ();
|
||||||
getContentPane().add(textField);
|
|
||||||
|
|
||||||
textField.addActionListener(new ActionListener() {
|
textField = new JTextField(10);
|
||||||
|
textField.setHorizontalAlignment(JTextField.RIGHT);
|
||||||
|
formatComboBox = new JComboBox<>(InMode.values(supportsHighZ));
|
||||||
|
formatComboBox.addActionListener(actionEvent -> {
|
||||||
|
if (!programmaticModifyingFormat)
|
||||||
|
setLongToDialog(editValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
JPanel panel = new JPanel(new DialogLayout());
|
||||||
|
panel.add(formatComboBox, DialogLayout.LABEL);
|
||||||
|
panel.add(textField, DialogLayout.INPUT);
|
||||||
|
panel.add(new JLabel(Lang.get("attr_dialogBinary")), DialogLayout.LABEL);
|
||||||
|
panel.add(createCheckBoxPanel(value.getBits(), editValue), DialogLayout.INPUT);
|
||||||
|
getContentPane().add(panel);
|
||||||
|
|
||||||
|
textField.getDocument().addDocumentListener(new MyDocumentListener(() -> setStringToDialog(textField.getText())));
|
||||||
|
|
||||||
|
if (value.isHighZ())
|
||||||
|
formatComboBox.setSelectedItem(InMode.HIGHZ);
|
||||||
|
else
|
||||||
|
setLongToDialog(editValue);
|
||||||
|
|
||||||
|
JButton okButton = new JButton(new AbstractAction(Lang.get("ok")) {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
returnText = textField.getText();
|
ok = true;
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
|
||||||
|
buttonPanel.add(okButton);
|
||||||
|
getContentPane().add(buttonPanel, BorderLayout.EAST);
|
||||||
|
|
||||||
|
getRootPane().setDefaultButton(okButton);
|
||||||
|
getRootPane().registerKeyboardAction(actionEvent -> dispose(),
|
||||||
|
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
|
||||||
|
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||||
|
|
||||||
pack();
|
pack();
|
||||||
setLocation(pos.x, pos.y);
|
setLocation(pos.x, pos.y);
|
||||||
|
textField.requestFocus();
|
||||||
|
textField.select(0, Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private JPanel createCheckBoxPanel(int bits, long value) {
|
||||||
* edits the given value
|
JPanel p = new JPanel();
|
||||||
*
|
p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
|
||||||
* @return result or null if dialog closed without something entered
|
checkBoxes = new JCheckBox[bits];
|
||||||
*/
|
for (int i = bits - 1; i >= 0; i--) {
|
||||||
private String showDialog() {
|
final int bit = i;
|
||||||
|
checkBoxes[bit] = new JCheckBox("", (value & (1L << bit)) != 0);
|
||||||
|
checkBoxes[bit].setBorder(null);
|
||||||
|
checkBoxes[bit].addActionListener(actionEvent -> setBit(bit, checkBoxes[bit].isSelected()));
|
||||||
|
p.add(checkBoxes[bit]);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBit(int bitNum, boolean set) {
|
||||||
|
if (set)
|
||||||
|
editValue |= 1L << bitNum;
|
||||||
|
else
|
||||||
|
editValue &= ~(1L << bitNum);
|
||||||
|
|
||||||
|
if (getSelectedFormat().equals(InMode.HIGHZ))
|
||||||
|
setSelectedFormat(InMode.HEX);
|
||||||
|
|
||||||
|
setLongToDialog(editValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setLongToDialog(long editValue) {
|
||||||
|
switch (getSelectedFormat()) {
|
||||||
|
case ASCII:
|
||||||
|
char val = (char) (editValue);
|
||||||
|
textField.setText("\'" + val + "\'");
|
||||||
|
textField.setCaretPosition(1);
|
||||||
|
break;
|
||||||
|
case DECIMAL:
|
||||||
|
textField.setText(Long.toString(editValue));
|
||||||
|
break;
|
||||||
|
case HEX:
|
||||||
|
textField.setText("0x" + Long.toHexString(editValue));
|
||||||
|
break;
|
||||||
|
case OCTAL:
|
||||||
|
textField.setText("0" + Long.toOctalString(editValue));
|
||||||
|
break;
|
||||||
|
case HIGHZ:
|
||||||
|
textField.setText("?");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
textField.requestFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private InMode getSelectedFormat() {
|
||||||
|
return (InMode) formatComboBox.getSelectedItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setSelectedFormat(InMode format) {
|
||||||
|
if (!getSelectedFormat().equals(format)) {
|
||||||
|
programmaticModifyingFormat = true;
|
||||||
|
formatComboBox.setSelectedItem(format);
|
||||||
|
programmaticModifyingFormat = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setStringToDialog(String text) {
|
||||||
|
text = text.trim();
|
||||||
|
if (text.length() > 0) {
|
||||||
|
if (text.contains("?") && supportsHighZ) {
|
||||||
|
setSelectedFormat(InMode.HIGHZ);
|
||||||
|
editValue = 0;
|
||||||
|
} else if (text.charAt(0) == '\'') {
|
||||||
|
setSelectedFormat(InMode.ASCII);
|
||||||
|
if (text.length() > 1) {
|
||||||
|
editValue = text.charAt(1);
|
||||||
|
} else {
|
||||||
|
editValue = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (text.startsWith("0x"))
|
||||||
|
setSelectedFormat(InMode.HEX);
|
||||||
|
else if (text.startsWith("0"))
|
||||||
|
setSelectedFormat(InMode.OCTAL);
|
||||||
|
else
|
||||||
|
setSelectedFormat(InMode.DECIMAL);
|
||||||
|
try {
|
||||||
|
editValue = Long.decode(text);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// do nothing on error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < checkBoxes.length; i++)
|
||||||
|
checkBoxes[i].setSelected((editValue & (1L << i)) != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean showDialog() {
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
return returnText;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,23 +212,37 @@ public final class SingleValueDialog extends JDialog {
|
|||||||
* @param value the value to edit
|
* @param value the value to edit
|
||||||
*/
|
*/
|
||||||
public static void editValue(Point pos, ObservableValue value, Sync modelSync) {
|
public static void editValue(Point pos, ObservableValue value, Sync modelSync) {
|
||||||
String ret = new SingleValueDialog(pos, value.getValueString()).showDialog();
|
SingleValueDialog svd = new SingleValueDialog(pos, value);
|
||||||
if (ret != null) {
|
if (svd.showDialog()) {
|
||||||
ret = ret.trim();
|
if (svd.getSelectedFormat().equals(InMode.HIGHZ)) {
|
||||||
if (ret.equals("?") && value.supportsHighZ()) {
|
modelSync.access(() -> value.setHighZ(true));
|
||||||
modelSync.access(() -> {
|
|
||||||
value.setHighZ(true);
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
try {
|
modelSync.access(() -> value.set(svd.editValue, false));
|
||||||
long l = Long.decode(ret);
|
}
|
||||||
modelSync.access(() -> {
|
}
|
||||||
value.set(l, false);
|
}
|
||||||
});
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
private static final class MyDocumentListener implements DocumentListener {
|
||||||
|
private final Runnable runnable;
|
||||||
|
|
||||||
|
private MyDocumentListener(Runnable runnable) {
|
||||||
|
this.runnable = runnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insertUpdate(DocumentEvent documentEvent) {
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeUpdate(DocumentEvent documentEvent) {
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changedUpdate(DocumentEvent documentEvent) {
|
||||||
|
runnable.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,12 @@
|
|||||||
<string name="attr_openCircuit_tt">Öffnet die Schaltung in einem neuen Fenster.</string>
|
<string name="attr_openCircuit_tt">Öffnet die Schaltung in einem neuen Fenster.</string>
|
||||||
<string name="attr_help">Hilfe</string>
|
<string name="attr_help">Hilfe</string>
|
||||||
<string name="attr_help_tt">Zeigt eine Beschreibung dieses Elements.</string>
|
<string name="attr_help_tt">Zeigt eine Beschreibung dieses Elements.</string>
|
||||||
|
<string name="attr_dialogHex">Hex</string>
|
||||||
|
<string name="attr_dialogDecimal">Dezimal</string>
|
||||||
|
<string name="attr_dialogAscii">Ascii</string>
|
||||||
|
<string name="attr_dialogHighz">HighZ</string>
|
||||||
|
<string name="attr_dialogOctal">Oktal</string>
|
||||||
|
<string name="attr_dialogBinary">Binär</string>
|
||||||
<string name="btn_discard">Verwerfen</string>
|
<string name="btn_discard">Verwerfen</string>
|
||||||
<string name="btn_edit">Bearbeiten</string>
|
<string name="btn_edit">Bearbeiten</string>
|
||||||
<string name="btn_editFurther">Weiter bearbeiten</string>
|
<string name="btn_editFurther">Weiter bearbeiten</string>
|
||||||
|
@ -13,6 +13,12 @@
|
|||||||
<string name="attr_openCircuit_tt">Opens the circuit in a new window.</string>
|
<string name="attr_openCircuit_tt">Opens the circuit in a new window.</string>
|
||||||
<string name="attr_help">Help</string>
|
<string name="attr_help">Help</string>
|
||||||
<string name="attr_help_tt">Shows a short description of this element.</string>
|
<string name="attr_help_tt">Shows a short description of this element.</string>
|
||||||
|
<string name="attr_dialogHex">Hex</string>
|
||||||
|
<string name="attr_dialogDecimal">Decimal</string>
|
||||||
|
<string name="attr_dialogAscii">Ascii</string>
|
||||||
|
<string name="attr_dialogHighz">HighZ</string>
|
||||||
|
<string name="attr_dialogOctal">Octal</string>
|
||||||
|
<string name="attr_dialogBinary">Binary</string>
|
||||||
<string name="btn_discard">Discard Changes</string>
|
<string name="btn_discard">Discard Changes</string>
|
||||||
<string name="btn_edit">Edit</string>
|
<string name="btn_edit">Edit</string>
|
||||||
<string name="btn_editFurther">Continue editing</string>
|
<string name="btn_editFurther">Continue editing</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user