mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-29 07:50:29 -04:00
Merge remote-tracking branch 'remotes/origin/groupEdit'
Conflicts: src/main/java/de/neemann/digital/gui/components/EditorFactory.java
This commit is contained in:
commit
be49ce68e6
@ -3,6 +3,8 @@ Release Notes
|
||||
HEAD, planned as v0.15
|
||||
- Added an EEPROM which behaves like a memory that can be written and whose content
|
||||
is non-volatile.
|
||||
- Replaced shortcut 'B' with a more general attribute editing dialog (select
|
||||
and left click).
|
||||
|
||||
v0.14, released on 31. Aug 2017
|
||||
- Added visualization of KV maps (thanks to roy77)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@ public class Key<VALUE> {
|
||||
private final String key;
|
||||
private final VALUE def;
|
||||
private final String langKey;
|
||||
private boolean groupEditAllowed = false;
|
||||
|
||||
/**
|
||||
* Creates a new Key
|
||||
@ -84,6 +85,18 @@ public class Key<VALUE> {
|
||||
return langKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if group edit is allowed
|
||||
*/
|
||||
public boolean isGroupEditAllowed() {
|
||||
return groupEditAllowed;
|
||||
}
|
||||
|
||||
Key<VALUE> setGroupEditAllowed(boolean groupEditAllowed) {
|
||||
this.groupEditAllowed = groupEditAllowed;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A integer attribute.
|
||||
* Stores additional combo box values
|
||||
@ -146,6 +159,7 @@ public class Key<VALUE> {
|
||||
setMin(1);
|
||||
super.setMax(64);
|
||||
setComboBoxValues(VALUES);
|
||||
setGroupEditAllowed(true);
|
||||
}
|
||||
|
||||
KeyBits setMax(int bits) {
|
||||
@ -202,6 +216,7 @@ public class Key<VALUE> {
|
||||
names = new String[values.length];
|
||||
for (int i = 0; i < values.length; i++)
|
||||
names[i] = Lang.get(getLangKey(values[i]));
|
||||
setGroupEditAllowed(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,10 +48,11 @@ public final class Keys {
|
||||
/**
|
||||
* The size of a LED
|
||||
*/
|
||||
public static final Key.KeyInteger SIZE
|
||||
public static final Key<Integer> SIZE
|
||||
= new Key.KeyInteger("Size", 1)
|
||||
.setComboBoxValues(new Integer[]{1, 2, 3, 4, 5})
|
||||
.setMin(1);
|
||||
.setMin(1)
|
||||
.setGroupEditAllowed(true);
|
||||
|
||||
/**
|
||||
* The value of constants
|
||||
@ -75,7 +76,7 @@ public final class Keys {
|
||||
* Color of LEDs
|
||||
*/
|
||||
public static final Key<java.awt.Color> COLOR
|
||||
= new Key<>("Color", java.awt.Color.RED);
|
||||
= new Key<>("Color", java.awt.Color.RED).setGroupEditAllowed(true);
|
||||
|
||||
/**
|
||||
* Background Color of nested circuits
|
||||
@ -119,19 +120,19 @@ public final class Keys {
|
||||
* indicates a diode as blown fuse or as programmed
|
||||
*/
|
||||
public static final Key<Boolean> BLOWN
|
||||
= new Key<>("Blown", false);
|
||||
= new Key<>("Blown", false).setGroupEditAllowed(true);
|
||||
|
||||
/**
|
||||
* indicates a switch as closed or not
|
||||
*/
|
||||
public static final Key<Boolean> CLOSED
|
||||
= new Key<>("Closed", false);
|
||||
= new Key<>("Closed", false).setGroupEditAllowed(true);
|
||||
|
||||
/**
|
||||
* signed flag for comparator element
|
||||
*/
|
||||
public static final Key<Boolean> SIGNED
|
||||
= new Key<>("Signed", false);
|
||||
= new Key<>("Signed", false).setGroupEditAllowed(true);
|
||||
|
||||
/**
|
||||
* the data key for memory
|
||||
@ -183,7 +184,7 @@ public final class Keys {
|
||||
* flag to make a value a probe
|
||||
*/
|
||||
public static final Key<Boolean> VALUE_IS_PROBE
|
||||
= new Key<>("valueIsProbe", false);
|
||||
= new Key<>("valueIsProbe", false).setGroupEditAllowed(true);
|
||||
|
||||
/**
|
||||
* flag to set a ROM as program memory
|
||||
@ -331,7 +332,7 @@ public final class Keys {
|
||||
* Used to enable the storage of the last state in the Seven Seg display.
|
||||
*/
|
||||
public static final Key<Boolean> LED_PERSISTENCE
|
||||
= new Key<>("ledPersistence", false);
|
||||
= new Key<>("ledPersistence", false).setGroupEditAllowed(true);
|
||||
|
||||
/**
|
||||
* Fitter for the atf1502
|
||||
@ -339,12 +340,6 @@ public final class Keys {
|
||||
public static final Key<File> SETTINGS_ATF1502_FITTER
|
||||
= new Key.KeyFile("atf1502Fitter", new File("c:/Wincupl/WinCupl/Fitters")).setDirectoryOnly(true);
|
||||
|
||||
/**
|
||||
* A pin number, empty means no pin assigned
|
||||
*/
|
||||
public static final Key<String> PIN
|
||||
= new Key<>("pin", "");
|
||||
|
||||
/**
|
||||
* row bits in led matrix
|
||||
*/
|
||||
@ -414,7 +409,7 @@ public final class Keys {
|
||||
* true if component is active low
|
||||
*/
|
||||
public static final Key<Boolean> ACTIVE_LOW
|
||||
= new Key<>("activeLow", false);
|
||||
= new Key<>("activeLow", false).setGroupEditAllowed(true);
|
||||
|
||||
/**
|
||||
* Fitter for the atf1502
|
||||
|
@ -13,6 +13,7 @@ import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Dialog used to edit Attributes.
|
||||
@ -32,6 +33,8 @@ public class AttributeDialog extends JDialog {
|
||||
private final ElementAttributes originalAttributes;
|
||||
private final ElementAttributes modifiedAttributes;
|
||||
private final JPanel buttonPanel;
|
||||
private final ConstrainsBuilder constrains;
|
||||
private HashMap<Key, JCheckBox> checkBoxes;
|
||||
private JComponent topMostTextComponent;
|
||||
private VisualElement visualElement;
|
||||
private boolean okPressed = false;
|
||||
@ -44,7 +47,7 @@ public class AttributeDialog extends JDialog {
|
||||
* @param elementAttributes the data stored
|
||||
*/
|
||||
public AttributeDialog(Component parent, java.util.List<Key> list, ElementAttributes elementAttributes) {
|
||||
this(parent, null, list, elementAttributes);
|
||||
this(parent, null, list, elementAttributes, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -56,6 +59,19 @@ public class AttributeDialog extends JDialog {
|
||||
* @param elementAttributes the data stored
|
||||
*/
|
||||
public AttributeDialog(Component parent, Point pos, java.util.List<Key> list, ElementAttributes elementAttributes) {
|
||||
this(parent, pos, list, elementAttributes, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param parent the parent
|
||||
* @param pos the position to pop up the dialog
|
||||
* @param list the list of keys which are to edit
|
||||
* @param elementAttributes the data stored
|
||||
* @param addCheckBoxes add checkboxes behind the attributes
|
||||
*/
|
||||
public AttributeDialog(Component parent, Point pos, java.util.List<Key> list, ElementAttributes elementAttributes, boolean addCheckBoxes) {
|
||||
super(SwingUtilities.getWindowAncestor(parent), Lang.get("attr_dialogTitle"), ModalityType.APPLICATION_MODAL);
|
||||
this.parent = parent;
|
||||
this.pos = pos;
|
||||
@ -63,17 +79,27 @@ public class AttributeDialog extends JDialog {
|
||||
this.modifiedAttributes = new ElementAttributes(elementAttributes);
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
|
||||
panel = new JPanel(new DialogLayout());
|
||||
panel = new JPanel(new GridBagLayout());
|
||||
|
||||
getContentPane().add(new JScrollPane(panel));
|
||||
|
||||
editors = new ArrayList<>();
|
||||
|
||||
topMostTextComponent = null;
|
||||
constrains = new ConstrainsBuilder().inset(3).fill();
|
||||
for (Key key : list) {
|
||||
Editor e = EditorFactory.INSTANCE.create(key, modifiedAttributes.get(key));
|
||||
editors.add(new EditorHolder(e, key));
|
||||
e.addToPanel(panel, key, modifiedAttributes, this);
|
||||
e.addToPanel(panel, key, modifiedAttributes, this, constrains);
|
||||
if (addCheckBoxes) {
|
||||
if (checkBoxes == null)
|
||||
checkBoxes = new HashMap<>();
|
||||
JCheckBox checkBox = new JCheckBox();
|
||||
checkBox.setToolTipText(Lang.get("msg_modifyThisAttribute"));
|
||||
checkBoxes.put(key, checkBox);
|
||||
panel.add(checkBox, constrains.x(2));
|
||||
}
|
||||
constrains.nextRow();
|
||||
|
||||
if (topMostTextComponent == null && e instanceof EditorFactory.StringEditor)
|
||||
topMostTextComponent = ((EditorFactory.StringEditor) e).getTextComponent();
|
||||
@ -119,6 +145,13 @@ public class AttributeDialog extends JDialog {
|
||||
dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the keys check boxes
|
||||
*/
|
||||
public HashMap<Key, JCheckBox> getCheckBoxes() {
|
||||
return checkBoxes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a button to this dialog
|
||||
*
|
||||
@ -127,13 +160,14 @@ public class AttributeDialog extends JDialog {
|
||||
* @return this for chained calls
|
||||
*/
|
||||
public AttributeDialog addButton(String label, ToolTipAction action) {
|
||||
panel.add(new JLabel(label), DialogLayout.LABEL);
|
||||
panel.add(action.createJButton(), DialogLayout.INPUT);
|
||||
panel.add(new JLabel(label), constrains);
|
||||
panel.add(action.createJButton(), constrains.x(1));
|
||||
constrains.nextRow();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a button to the bottom of this dialog
|
||||
* Adds a button to the botton of this dialog
|
||||
*
|
||||
* @param action the action
|
||||
* @return this for chained calls
|
||||
@ -181,6 +215,14 @@ public class AttributeDialog extends JDialog {
|
||||
return parent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true if ok is pressed
|
||||
*/
|
||||
public boolean isOkPressed() {
|
||||
return okPressed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the containing Main instance or null
|
||||
*/
|
||||
|
@ -7,6 +7,7 @@ import de.neemann.digital.core.element.*;
|
||||
import de.neemann.digital.core.io.In;
|
||||
import de.neemann.digital.core.io.InValue;
|
||||
import de.neemann.digital.draw.elements.*;
|
||||
import de.neemann.digital.draw.graphics.Vector;
|
||||
import de.neemann.digital.draw.shapes.InputShape;
|
||||
import de.neemann.digital.gui.components.modification.*;
|
||||
import de.neemann.digital.draw.graphics.*;
|
||||
@ -33,9 +34,7 @@ import java.awt.geom.Point2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
|
||||
@ -45,6 +44,7 @@ import static java.awt.event.InputEvent.CTRL_DOWN_MASK;
|
||||
/**
|
||||
* Component which shows the circuit.
|
||||
* ToDo: refactoring of repaint logic. Its to complex now.
|
||||
* ToDo: class is to large, move the MouseController classes to their own package
|
||||
*
|
||||
* @author hneemann
|
||||
*/
|
||||
@ -187,8 +187,6 @@ public class CircuitComponent extends JComponent implements Circuit.ChangedListe
|
||||
new PlusMinusAction(1).setAccelerator("PLUS").enableAcceleratorIn(this);
|
||||
new PlusMinusAction(-1).setAccelerator("MINUS").enableAcceleratorIn(this);
|
||||
|
||||
new BitSetAction().setAccelerator("B").enableAcceleratorIn(this);
|
||||
|
||||
new ToolTipAction(Lang.get("menu_programDiode")) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) { // is allowed also if locked!
|
||||
@ -978,6 +976,59 @@ public class CircuitComponent extends JComponent implements Circuit.ChangedListe
|
||||
return library;
|
||||
}
|
||||
|
||||
private void editGroup(Vector min, Vector max) {
|
||||
if (!isLocked())
|
||||
try {
|
||||
ArrayList<Key> keyList = new ArrayList<>();
|
||||
ArrayList<VisualElement> elementList = new ArrayList<>();
|
||||
HashMap<Key, Boolean> useKeyMap = new HashMap<>();
|
||||
ElementAttributes attr = new ElementAttributes();
|
||||
for (VisualElement ve : circuit.getElements())
|
||||
if (ve.matches(min, max)) {
|
||||
elementList.add(ve);
|
||||
for (Key k : library.getElementType(ve.getElementName()).getAttributeList()) {
|
||||
if (k.isGroupEditAllowed()) {
|
||||
if (keyList.contains(k)) {
|
||||
if (!ve.getElementAttributes().get(k).equals(attr.get(k))) {
|
||||
useKeyMap.put(k, false);
|
||||
}
|
||||
} else {
|
||||
keyList.add(k);
|
||||
attr.set(k, ve.getElementAttributes().get(k));
|
||||
useKeyMap.put(k, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (keyList.size() > 0) {
|
||||
AttributeDialog ad = new AttributeDialog(this, null, keyList, attr, true);
|
||||
for (Map.Entry<Key, Boolean> u : useKeyMap.entrySet())
|
||||
ad.getCheckBoxes().get(u.getKey()).setSelected(u.getValue());
|
||||
ElementAttributes mod = ad.showDialog();
|
||||
if (ad.isOkPressed()) {
|
||||
if (mod == null) mod = attr;
|
||||
|
||||
Modifications.Builder modBuilder = new Modifications.Builder(Lang.get("mod_groupEdit"));
|
||||
for (Key key : keyList)
|
||||
if (ad.getCheckBoxes().get(key).isSelected()) {
|
||||
Object newVal = mod.get(key);
|
||||
for (VisualElement ve : elementList) {
|
||||
if (library.getElementType(ve.getElementName()).getAttributeList().contains(key)) {
|
||||
if (!ve.getElementAttributes().get(key).equals(newVal))
|
||||
modBuilder.add(new ModifyAttribute<>(ve, key, newVal));
|
||||
}
|
||||
}
|
||||
}
|
||||
modify(modBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ElementNotFoundException e) {
|
||||
// Do nothing if an element is not in library
|
||||
}
|
||||
}
|
||||
|
||||
private final class PlusMinusAction extends ToolTipAction {
|
||||
private final int delta;
|
||||
|
||||
@ -1005,38 +1056,6 @@ public class CircuitComponent extends JComponent implements Circuit.ChangedListe
|
||||
}
|
||||
}
|
||||
|
||||
private final class BitSetAction extends ToolTipAction {
|
||||
|
||||
private BitSetAction() {
|
||||
super("setBits");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (!isLocked()) {
|
||||
if (activeMouseController instanceof MouseControllerSelect) {
|
||||
MouseControllerSelect mouseControllerSelect = (MouseControllerSelect) activeMouseController;
|
||||
String num = JOptionPane.showInputDialog(CircuitComponent.this, Lang.get("key_Bits"), "1");
|
||||
if (num != null) {
|
||||
try {
|
||||
int bits = Integer.decode(num);
|
||||
Vector c1 = mouseControllerSelect.corner1;
|
||||
Vector c2 = mouseControllerSelect.corner2;
|
||||
ModifySetBits modifySetBits = new ModifySetBits(c1, c2, bits);
|
||||
if (modifySetBits.isSomethingToDo(circuit, library))
|
||||
modify(modifySetBits);
|
||||
removeHighLighted();
|
||||
mouseNormal.activate();
|
||||
} catch (NumberFormatException ex) {
|
||||
new ErrorMessage(Lang.get("msg_stringIsNotANumber_N", num)).show(CircuitComponent.this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class MouseDispatcher extends MouseAdapter implements MouseMotionListener {
|
||||
private Vector pos;
|
||||
private boolean isMoved;
|
||||
@ -1610,8 +1629,14 @@ public class CircuitComponent extends JComponent implements Circuit.ChangedListe
|
||||
|
||||
@Override
|
||||
void clicked(MouseEvent e) {
|
||||
mouseNormal.activate();
|
||||
removeHighLighted();
|
||||
if (e.getButton() == MouseEvent.BUTTON1) {
|
||||
mouseNormal.activate();
|
||||
removeHighLighted();
|
||||
} else if (e.getButton() == MouseEvent.BUTTON3) {
|
||||
editGroup(Vector.min(corner1, corner2), Vector.max(corner1, corner2));
|
||||
mouseNormal.activate();
|
||||
removeHighLighted();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,142 @@
|
||||
package de.neemann.digital.gui.components;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* More simple to use GridBagConstrains
|
||||
*/
|
||||
public class ConstrainsBuilder extends GridBagConstraints {
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* Position is set to (0,0)
|
||||
*/
|
||||
public ConstrainsBuilder() {
|
||||
gridx = 0;
|
||||
gridy = 0;
|
||||
}
|
||||
|
||||
private ConstrainsBuilder(ConstrainsBuilder original) {
|
||||
gridx = original.gridx;
|
||||
gridy = original.gridy;
|
||||
gridwidth = original.gridwidth;
|
||||
gridheight = original.gridheight;
|
||||
weightx = original.weightx;
|
||||
weighty = original.weighty;
|
||||
ipadx = original.ipadx;
|
||||
ipady = original.ipady;
|
||||
fill = original.fill;
|
||||
insets = original.insets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the position
|
||||
*
|
||||
* @param x x position
|
||||
* @param y y position
|
||||
* @return the new created ConstrainsBuilder instance
|
||||
*/
|
||||
public ConstrainsBuilder pos(int x, int y) {
|
||||
ConstrainsBuilder c = new ConstrainsBuilder(this);
|
||||
c.gridx = x;
|
||||
c.gridy = y;
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the position
|
||||
*
|
||||
* @param x x position
|
||||
* @return the new created ConstrainsBuilder instance
|
||||
*/
|
||||
public ConstrainsBuilder x(int x) {
|
||||
ConstrainsBuilder c = new ConstrainsBuilder(this);
|
||||
c.gridx = x;
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the width
|
||||
*
|
||||
* @param x width
|
||||
* @return the new created ConstrainsBuilder instance
|
||||
*/
|
||||
public ConstrainsBuilder width(int x) {
|
||||
ConstrainsBuilder c = new ConstrainsBuilder(this);
|
||||
c.gridwidth = x;
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a dynamic height
|
||||
*
|
||||
* @return the new created ConstrainsBuilder instance
|
||||
*/
|
||||
public ConstrainsBuilder dynamicHeight() {
|
||||
ConstrainsBuilder c = new ConstrainsBuilder(this);
|
||||
c.weighty = 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a dynamic width
|
||||
*
|
||||
* @return the new created ConstrainsBuilder instance
|
||||
*/
|
||||
public ConstrainsBuilder dynamicWidth() {
|
||||
ConstrainsBuilder c = new ConstrainsBuilder(this);
|
||||
c.weightx = 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the padding
|
||||
*
|
||||
* @param x x padding
|
||||
* @param y y padding
|
||||
* @return the new created ConstrainsBuilder instance
|
||||
*/
|
||||
public ConstrainsBuilder pad(int x, int y) {
|
||||
ConstrainsBuilder c = new ConstrainsBuilder(this);
|
||||
c.ipadx = x;
|
||||
c.ipady = y;
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fill attribute to BOTH
|
||||
*
|
||||
* @return the new created ConstrainsBuilder instance
|
||||
*/
|
||||
public ConstrainsBuilder fill() {
|
||||
ConstrainsBuilder c = new ConstrainsBuilder(this);
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets insets to a border of width b
|
||||
*
|
||||
* @param b border width
|
||||
* @return the new created ConstrainsBuilder instance
|
||||
*/
|
||||
public ConstrainsBuilder inset(int b) {
|
||||
ConstrainsBuilder c = new ConstrainsBuilder(this);
|
||||
c.insets = new Insets(b, b, b, b);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the row.
|
||||
* Does not create a new instance!
|
||||
*
|
||||
* @return this for chained calls
|
||||
*/
|
||||
public ConstrainsBuilder nextRow() {
|
||||
gridx = 0;
|
||||
gridy++;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
@ -1,279 +0,0 @@
|
||||
package de.neemann.digital.gui.components;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Layout manager used in teh GUI dialog
|
||||
*
|
||||
* @author hneemann
|
||||
*/
|
||||
public class DialogLayout implements LayoutManager {
|
||||
/**
|
||||
* Used to indicate the element as a label
|
||||
*/
|
||||
public static final String LABEL = "label";
|
||||
/**
|
||||
* Used to indicate the element as a label
|
||||
*/
|
||||
public static final String INPUT = "input";
|
||||
/**
|
||||
* Used to indicate that the element should use the space for label and input (e.g. CheckBoxes)
|
||||
*/
|
||||
public static final String BOTH = "both";
|
||||
/**
|
||||
* Use label and input column, but indent field
|
||||
*/
|
||||
public static final String BOTHINDENT = "indent";
|
||||
/**
|
||||
* Use label and input column, height is adjustable
|
||||
*/
|
||||
public static final String BOTHDYNAMIC = "bothDyn";
|
||||
private static final int BOTHOFFSET = 20;
|
||||
private static final int SPACEX = 5;
|
||||
private static final int SPACEY = 5;
|
||||
private ArrayList<Line> lines;
|
||||
private int label;
|
||||
private boolean initialized = false;
|
||||
private int dynCount;
|
||||
|
||||
/**
|
||||
* @return true if the are fields with
|
||||
*/
|
||||
public boolean isDynamic() {
|
||||
initialize();
|
||||
return dynCount > 0;
|
||||
}
|
||||
|
||||
private static class Line {
|
||||
private boolean both;
|
||||
private Component label;
|
||||
private Component input;
|
||||
private boolean indent;
|
||||
private boolean dynamic;
|
||||
|
||||
Line(Component both, boolean indent) {
|
||||
this.label = both;
|
||||
this.both = true;
|
||||
this.indent = indent;
|
||||
}
|
||||
|
||||
Line(Component component, String s) {
|
||||
both = false;
|
||||
if (LABEL.equals(s)) label = component;
|
||||
else if (INPUT.equals(s)) input = component;
|
||||
else throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
public Component getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public Component getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public void setLabel(Component component) {
|
||||
label = component;
|
||||
}
|
||||
|
||||
public boolean isLabelFree() {
|
||||
return !both && label == null;
|
||||
}
|
||||
|
||||
public boolean isInputFree() {
|
||||
return !both && input == null;
|
||||
}
|
||||
|
||||
public void setInput(Component input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public boolean isBoth() {
|
||||
return both;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
if (both) return label.getPreferredSize().height;
|
||||
else {
|
||||
int height = 0;
|
||||
if (label != null) {
|
||||
int h = label.getPreferredSize().height;
|
||||
if (h > height) height = h;
|
||||
}
|
||||
if (input != null) {
|
||||
int h = input.getPreferredSize().height;
|
||||
if (h > height) height = h;
|
||||
}
|
||||
return height;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isIndent() {
|
||||
return indent;
|
||||
}
|
||||
|
||||
public void setDynamic(boolean dynamic) {
|
||||
this.dynamic = dynamic;
|
||||
}
|
||||
|
||||
public boolean isDynamic() {
|
||||
return dynamic;
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
if (both) {
|
||||
if (label instanceof Container)
|
||||
initContainer((Container) label);
|
||||
}
|
||||
}
|
||||
|
||||
private void initContainer(Container container) {
|
||||
for (int i = 0; i < container.getComponentCount(); i++) {
|
||||
Component c = container.getComponent(i);
|
||||
if (c instanceof Container /*&& !(((Container)c).getLayout() instanceof DialogLayout)*/)
|
||||
initContainer((Container) c);
|
||||
}
|
||||
|
||||
|
||||
LayoutManager lm = container.getLayout();
|
||||
if (lm instanceof DialogLayout) {
|
||||
DialogLayout dl = (DialogLayout) lm;
|
||||
if (dl.isDynamic()) setDynamic(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Layout for the edit dialog
|
||||
*/
|
||||
public DialogLayout() {
|
||||
lines = new ArrayList<Line>();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addLayoutComponent(String s, Component component) {
|
||||
if (BOTH.equals(s)) {
|
||||
lines.add(new Line(component, false));
|
||||
} else if (BOTHDYNAMIC.equals(s)) {
|
||||
Line l = new Line(component, false);
|
||||
lines.add(l);
|
||||
l.setDynamic(true);
|
||||
} else if (BOTHINDENT.equals(s)) {
|
||||
lines.add(new Line(component, true));
|
||||
} else if (LABEL.equals(s)) {
|
||||
if (lines.size() > 0 && lines.get(lines.size() - 1).isLabelFree())
|
||||
lines.get(lines.size() - 1).setLabel(component);
|
||||
else
|
||||
lines.add(new Line(component, LABEL));
|
||||
} else if (INPUT.equals(s)) {
|
||||
addInput(component);
|
||||
} else
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
private Line addInput(Component component) {
|
||||
Line l;
|
||||
if (lines.size() > 0 && lines.get(lines.size() - 1).isInputFree()) {
|
||||
l = lines.get(lines.size() - 1);
|
||||
l.setInput(component);
|
||||
} else {
|
||||
l = new Line(component, INPUT);
|
||||
lines.add(l);
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeLayoutComponent(Component component) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension preferredLayoutSize(Container container) {
|
||||
return minimumLayoutSize(container);
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
if (!initialized) {
|
||||
dynCount = 0;
|
||||
for (Line l : lines) {
|
||||
l.initialize();
|
||||
if (l.isDynamic()) dynCount++;
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension minimumLayoutSize(Container container) {
|
||||
initialize();
|
||||
|
||||
int both = 0;
|
||||
label = 0;
|
||||
int input = 0;
|
||||
int height = 0;
|
||||
for (Line l : lines) {
|
||||
if (l.isBoth()) {
|
||||
int w = l.getLabel().getPreferredSize().width;
|
||||
if (l.isIndent()) w += BOTHOFFSET;
|
||||
if (w > both) both = w;
|
||||
} else {
|
||||
if (l.getLabel() != null) {
|
||||
int w = l.getLabel().getPreferredSize().width;
|
||||
if (w > label) label = w;
|
||||
}
|
||||
if (l.getInput() != null) {
|
||||
int w = l.getInput().getPreferredSize().width;
|
||||
if (w > input) input = w;
|
||||
}
|
||||
}
|
||||
height += l.getHeight();
|
||||
}
|
||||
Insets in = container.getInsets();
|
||||
return new Dimension(Math.max(both + SPACEX * 2, label + input + SPACEX * 3) + in.left + in.right, height + in.top + in.bottom + (lines.size() + 1) * SPACEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layoutContainer(Container container) {
|
||||
Dimension minSize = minimumLayoutSize(container);
|
||||
Insets in = container.getInsets();
|
||||
|
||||
int dynAddendum = 0;
|
||||
if (dynCount > 0) dynAddendum = (container.getSize().height - minSize.height) / dynCount;
|
||||
|
||||
|
||||
int width = container.getSize().width;
|
||||
|
||||
int top = in.top + SPACEY;
|
||||
for (Line l : lines) {
|
||||
int height = l.getHeight();
|
||||
if (l.isDynamic()) height += dynAddendum;
|
||||
if (l.isBoth()) {
|
||||
Component c = l.getLabel();
|
||||
if (l.isIndent()) {
|
||||
c.setLocation(in.left + BOTHOFFSET + SPACEX, top);
|
||||
c.setSize(width - BOTHOFFSET - SPACEX * 2 - in.left - in.right, height);
|
||||
} else {
|
||||
c.setLocation(in.left + SPACEX, top);
|
||||
c.setSize(width - SPACEX * 2 - in.left - in.right, height);
|
||||
}
|
||||
} else {
|
||||
Component labelComp = l.getLabel();
|
||||
if (labelComp != null) {
|
||||
labelComp.setLocation(in.left + SPACEX, top);
|
||||
labelComp.setSize(label, height);
|
||||
}
|
||||
Component inputComp = l.getInput();
|
||||
if (inputComp != null) {
|
||||
inputComp.setLocation(label + in.left + SPACEX * 2, top);
|
||||
inputComp.setSize(width - label - SPACEX * 3 - in.left - in.right, height);
|
||||
}
|
||||
}
|
||||
|
||||
top += height + SPACEY;
|
||||
}
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ public interface Editor<T> {
|
||||
* @param key the key which is to edit
|
||||
* @param elementAttributes the attributes
|
||||
* @param dialog the containing dialog
|
||||
* @param constrains the constrains used to place the components in the panel
|
||||
*/
|
||||
void addToPanel(JPanel panel, Key key, ElementAttributes elementAttributes, AttributeDialog dialog);
|
||||
void addToPanel(JPanel panel, Key key, ElementAttributes elementAttributes, AttributeDialog dialog, ConstrainsBuilder constrains);
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ public final class EditorFactory {
|
||||
private boolean labelAtTop = false;
|
||||
|
||||
@Override
|
||||
public void addToPanel(JPanel panel, Key key, ElementAttributes elementAttributes, AttributeDialog attributeDialog) {
|
||||
public void addToPanel(JPanel panel, Key key, ElementAttributes elementAttributes, AttributeDialog attributeDialog, ConstrainsBuilder constrains) {
|
||||
this.attributeDialog = attributeDialog;
|
||||
JLabel label = new JLabel(key.getName() + ": ");
|
||||
final String description = new LineBreaker().toHTML().breakLines(key.getDescription());
|
||||
@ -105,11 +105,12 @@ public final class EditorFactory {
|
||||
JComponent component = getComponent(elementAttributes);
|
||||
component.setToolTipText(description);
|
||||
if (labelAtTop) {
|
||||
panel.add(label, DialogLayout.BOTH);
|
||||
panel.add(component, DialogLayout.BOTHDYNAMIC);
|
||||
panel.add(label, constrains.width(2));
|
||||
constrains.nextRow();
|
||||
panel.add(component, constrains.width(2).dynamicHeight());
|
||||
} else {
|
||||
panel.add(label, DialogLayout.LABEL);
|
||||
panel.add(component, DialogLayout.INPUT);
|
||||
panel.add(label, constrains);
|
||||
panel.add(component, constrains.x(1).dynamicWidth());
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,8 +256,8 @@ public final class EditorFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToPanel(JPanel panel, Key key, ElementAttributes elementAttributes, AttributeDialog attributeDialog) {
|
||||
panel.add(bool, DialogLayout.BOTH);
|
||||
public void addToPanel(JPanel panel, Key key, ElementAttributes elementAttributes, AttributeDialog attributeDialog, ConstrainsBuilder constrains) {
|
||||
panel.add(bool, constrains.width(2));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,11 +89,13 @@ public final class SingleValueDialog extends JDialog implements ModelStateObserv
|
||||
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);
|
||||
JPanel panel = new JPanel(new GridBagLayout());
|
||||
ConstrainsBuilder constr = new ConstrainsBuilder().inset(3).fill();
|
||||
panel.add(formatComboBox, constr);
|
||||
panel.add(textField, constr.dynamicWidth().x(1));
|
||||
constr.nextRow();
|
||||
panel.add(new JLabel(Lang.get("attr_dialogBinary")), constr);
|
||||
panel.add(createCheckBoxPanel(value.getBits(), editValue), constr.dynamicWidth().x(1));
|
||||
getContentPane().add(panel);
|
||||
|
||||
textField.getDocument().addDocumentListener(new MyDocumentListener(() -> setStringToDialog(textField.getText())));
|
||||
|
@ -756,6 +756,7 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
|
||||
<string name="mod_circuitAttrModified">Schaltungsattribute verändert.</string>
|
||||
<string name="mod_modifiedMeasurementOrdering">Reihenfolge der Messwerte verändert.</string>
|
||||
<string name="mod_set_N_BitsToSelection">In selektierten Elementen die Zahl der Daten-Bits auf {0} gesetzt.</string>
|
||||
<string name="mod_groupEdit">In selektierten Elementen Attribute geändert.</string>
|
||||
|
||||
<string name="lib_Logic">Logisch</string>
|
||||
<string name="lib_arithmetic">Arithmetik</string>
|
||||
@ -1014,7 +1015,7 @@ eine <a href="https://github.com/hneemann/Digital/issues/new?labels=enha
|
||||
<string name="msg_modelHasErrors">Es kann nur eine fehlerfreie Schaltung exportiert werden!</string>
|
||||
<string name="msg_noKVMapAvailable">Keine KV-Tafel verfügbar!</string>
|
||||
<string name="msg_dataNotUpdatedAnymore">Daten werden nicht mehr aktualisiert!</string>
|
||||
<string name="msg_stringIsNotANumber_N">Der String {0} ist keine Zahl!</string>
|
||||
<string name="msg_modifyThisAttribute">Diesen Wert verändern.</string>
|
||||
|
||||
<string name="ok">Ok</string>
|
||||
<string name="rot_0">0°</string>
|
||||
|
@ -740,6 +740,7 @@ The names of the variables may not be unique.</string>
|
||||
<string name="mod_circuitAttrModified">Modified circuit attributes.</string>
|
||||
<string name="mod_modifiedMeasurementOrdering">Ordered measurements.</string>
|
||||
<string name="mod_set_N_BitsToSelection">Sets the number of data bits to {0} in selected components.</string>
|
||||
<string name="mod_groupEdit">Modified attributes of selected components.</string>
|
||||
|
||||
<string name="lib_Logic">Logic</string>
|
||||
<string name="lib_arithmetic">Arithmetic</string>
|
||||
@ -920,7 +921,6 @@ The names of the variables may not be unique.</string>
|
||||
<string name="menu_pdfDocumentation">Documentation</string>
|
||||
<string name="menu_openPdfDocumentation">Open {0}</string>
|
||||
<string name="msg_errorOpeningDocumentation">Error opening a PDF file!</string>
|
||||
<string name="msg_stringIsNotANumber_N">The string {0} is not a number!</string>
|
||||
|
||||
<string name="message"><h1>Digital</h1>A simple simulator for digital circuits.
|
||||
Written by H. Neemann in 2016, 2017.
|
||||
@ -996,6 +996,7 @@ an <a href="https://github.com/hneemann/Digital/issues/new?labels=enhanc
|
||||
<string name="msg_modelHasErrors">You can only export a circuit without errors!</string>
|
||||
<string name="msg_noKVMapAvailable">No KV map available!</string>
|
||||
<string name="msg_dataNotUpdatedAnymore">Data will not be updated anymore!</string>
|
||||
<string name="msg_modifyThisAttribute">Modify this Value</string>
|
||||
|
||||
<string name="ok">Ok</string>
|
||||
<string name="rot_0">0°</string>
|
||||
|
@ -388,7 +388,6 @@
|
||||
<shortcut key="STRG-S">Speichern der Schaltung.</shortcut>
|
||||
<shortcut key="STRG-Z">Letzte Änderung zurücknehmen.</shortcut>
|
||||
<shortcut key="STRG-Y">Zurückgenommene Änderung erneut anwenden.</shortcut>
|
||||
<shortcut key="B">Anzahl der Datenbits in allen selektierten Elementen setzen.</shortcut>
|
||||
<shortcut key="P">Programmieren einer Diode oder eines FG-FET.</shortcut>
|
||||
<shortcut key="D">Beim Ziehen einer rechteckigen Leitung in den Diagonalmodus wechseln.</shortcut>
|
||||
<shortcut key="F">Beim Ziehen einer rechteckigen Leitung die Orientierung wechseln.</shortcut>
|
||||
|
@ -326,7 +326,6 @@
|
||||
<shortcut key="CTRL-S">Save the circuit.</shortcut>
|
||||
<shortcut key="CTRL-Z">Undo last modification.</shortcut>
|
||||
<shortcut key="CTRL-Y">Redo the last undone modification.</shortcut>
|
||||
<shortcut key="B">Set the number of data bits in all selected components.</shortcut>
|
||||
<shortcut key="P">Programs a diode or a FG-FET.</shortcut>
|
||||
<shortcut key="D">While drawing a wire switches to the diagonal mode.</shortcut>
|
||||
<shortcut key="F">While drawing a line flips the orientation.</shortcut>
|
||||
|
@ -60,7 +60,9 @@
|
||||
|
||||
<!-- Checks for Size Violations. -->
|
||||
<!-- See http://checkstyle.sf.net/config_sizes.html -->
|
||||
<module name="FileLength"/>
|
||||
<module name="FileLength">
|
||||
<property name="max" value="2500"/>
|
||||
</module>
|
||||
|
||||
<!-- Checks for whitespace -->
|
||||
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user