diff --git a/distribution/ReleaseNotes.txt b/distribution/ReleaseNotes.txt index 1c65fbe2a..8670ae7be 100644 --- a/distribution/ReleaseNotes.txt +++ b/distribution/ReleaseNotes.txt @@ -1,6 +1,7 @@ Release Notes HEAD, planned as v0.19 +- Added a tabbed pane to the attributes dialog to make it more beginner friendly. - Added support for asynchronous sequential circuits such as the Muller-pipeline. Take a look at the new asynchronous examples for illustration. - All examples are translated to english. diff --git a/src/main/java/de/neemann/digital/core/element/Key.java b/src/main/java/de/neemann/digital/core/element/Key.java index 94041b784..1bd03a72b 100644 --- a/src/main/java/de/neemann/digital/core/element/Key.java +++ b/src/main/java/de/neemann/digital/core/element/Key.java @@ -26,6 +26,7 @@ public class Key { // Both are only used within a custom implemented component. private String name; private String description; + private boolean isSecondary; /** * Creates a new Key @@ -183,6 +184,23 @@ public class Key { return this; } + /** + * @return true is this is a secondary attribute + */ + public boolean isSecondary() { + return isSecondary; + } + + /** + * Makes this attribute to be a secondary attribute + * + * @return this for chained calls + */ + public Key setSecondary() { + isSecondary = true; + return this; + } + /** * A integer attribute. * Stores additional combo box values diff --git a/src/main/java/de/neemann/digital/core/element/Keys.java b/src/main/java/de/neemann/digital/core/element/Keys.java index 81a61552e..6759c1d78 100644 --- a/src/main/java/de/neemann/digital/core/element/Keys.java +++ b/src/main/java/de/neemann/digital/core/element/Keys.java @@ -140,7 +140,8 @@ public final class Keys { = new Key.KeyInteger("Size", 1) .setComboBoxValues(new Integer[]{0, 1, 2, 3, 4, 5}) .setMin(0) - .allowGroupEdit(); + .allowGroupEdit() + .setSecondary(); /** * The value of constants @@ -152,19 +153,19 @@ public final class Keys { * The default value of elements */ public static final Key DEFAULT - = new Key<>("Default", 0).allowGroupEdit(); + = new Key<>("Default", 0).allowGroupEdit().setSecondary(); /** * The default value of inputs */ public static final Key INPUT_DEFAULT - = new Key<>("InDefault", new InValue(0)).allowGroupEdit(); + = new Key<>("InDefault", new InValue(0)).allowGroupEdit().setSecondary(); /** * The default value of the dip switch */ public static final Key DIP_DEFAULT - = new Key<>("dipDefault", false); + = new Key<>("dipDefault", false).allowGroupEdit().setSecondary(); /** @@ -188,11 +189,12 @@ public final class Keys { /** * The splitter spreading */ - public static final Key.KeyInteger SPLITTER_SPREADING + public static final Key SPLITTER_SPREADING = new Key.KeyInteger("splitterSpreading", 1) .setComboBoxValues(new Integer[]{1, 2, 3, 4}) .setMin(1) - .setMax(10); + .setMax(10) + .setSecondary(); /** @@ -262,7 +264,7 @@ public final class Keys { * the rotation of the elements */ public static final Key ROTATE - = new Key<>("rotation", new Rotation(0)).allowGroupEdit(); + = new Key<>("rotation", new Rotation(0)).allowGroupEdit().setSecondary(); /** * the width of an element if it is included as nested element @@ -296,37 +298,37 @@ public final class Keys { * flag to make a value a probe */ public static final Key VALUE_IS_PROBE - = new Key<>("valueIsProbe", false).allowGroupEdit(); + = new Key<>("valueIsProbe", false).allowGroupEdit().setSecondary(); /** * flag to set a ROM as program memory */ public static final Key IS_PROGRAM_MEMORY - = new Key<>("isProgramMemory", false); + = new Key<>("isProgramMemory", false).setSecondary(); /** * flag to enable the ROMs auto load function */ public static final Key AUTO_RELOAD_ROM - = new Key<>("autoReload", false); + = new Key<>("autoReload", false).setSecondary(); /** * flag to show the data table window */ public static final Key SHOW_DATA_TABLE - = new Key<>("showDataTable", false); + = new Key<>("showDataTable", false).setSecondary(); /** * flag to show the data graph window */ public static final Key SHOW_DATA_GRAPH - = new Key<>("showDataGraph", false); + = new Key<>("showDataGraph", false).setSecondary(); /** * flag to show the data graph window in single gate mode */ public static final Key SHOW_DATA_GRAPH_MICRO - = new Key<>("showDataGraphMicro", false); + = new Key<>("showDataGraphMicro", false).setSecondary(); /** * flag to enable the single gate mode in the embedded data view @@ -345,7 +347,7 @@ public final class Keys { * flag to enable high z mode at an input */ public static final Key IS_HIGH_Z - = new Key<>("isHighZ", false).allowGroupEdit(); + = new Key<>("isHighZ", false).allowGroupEdit().setSecondary(); /** * the description of an element @@ -405,8 +407,8 @@ public final class Keys { /** * output format for numbers */ - public static final Key.KeyEnum INT_FORMAT - = new Key.KeyEnum<>("intFormat", IntFormat.def, IntFormat.values()); + public static final Key INT_FORMAT + = new Key.KeyEnum<>("intFormat", IntFormat.def, IntFormat.values()).setSecondary(); /** * width of the terminal @@ -462,13 +464,13 @@ public final class Keys { * Fitter for the atf15xx */ public static final Key SETTINGS_ATF1502_FITTER - = new Key.KeyFile("atf1502Fitter", new File("c:/Wincupl/WinCupl/Fitters")).setDirectoryOnly(true); + = new Key.KeyFile("atf1502Fitter", new File("c:/Wincupl/WinCupl/Fitters")).setDirectoryOnly(true).setSecondary(); /** * Flash software for the atf15xx */ public static final Key SETTINGS_ATMISP - = new Key.KeyFile("ATMISP", new File("c:/ATMISP7/ATMISP.exe")); + = new Key.KeyFile("ATMISP", new File("c:/ATMISP7/ATMISP.exe")).setSecondary(); /** * row bits in led matrix @@ -492,20 +494,21 @@ public final class Keys { * the pin number */ public static final Key PINNUMBER = - new Key<>("pinNumber", ""); + new Key<>("pinNumber", "").setSecondary(); /** * true if shape is a dil shape */ public static final Key IS_DIL - = new Key<>("isDIL", false); + = new Key<>("isDIL", false).setSecondary(); /** * the pin count */ public static final Key PINCOUNT = new Key.KeyInteger("pinCount", 0) .setMin(0) - .setDependsOn(IS_DIL); + .setDependsOn(IS_DIL) + .setSecondary(); /** @@ -558,19 +561,19 @@ public final class Keys { * Fitter for the atf1502 */ public static final Key SETTINGS_LIBRARY_PATH - = new Key.KeyFile("libraryPath", ElementLibrary.getLibPath()).setDirectoryOnly(true); + = new Key.KeyFile("libraryPath", ElementLibrary.getLibPath()).setDirectoryOnly(true).setSecondary(); /** * A jar containing custom java components */ public static final Key SETTINGS_JAR_PATH - = new Key.KeyFile("jarPath", new File("")); + = new Key.KeyFile("jarPath", new File("")).setSecondary(); /** * The manager which contains all the roms data */ public static final Key ROMMANAGER - = new Key<>("romContent", ROMManger.EMPTY); + = new Key<>("romContent", ROMManger.EMPTY).setSecondary(); /** @@ -597,8 +600,8 @@ public final class Keys { /** * Path to ghdl */ - public static final Key.KeyFile SETTINGS_GHDL_PATH - = new Key.KeyFile("ghdlPath", new File("ghdl")); + public static final Key SETTINGS_GHDL_PATH + = new Key.KeyFile("ghdlPath", new File("ghdl")).setSecondary(); /** * Avoid component tooltips in the main panel @@ -616,6 +619,6 @@ public final class Keys { * Shape used to represent a visual element */ public static final Key CUSTOM_SHAPE - = new Key<>("customShape", CustomShapeDescription.EMPTY); + = new Key<>("customShape", CustomShapeDescription.EMPTY).setSecondary(); } diff --git a/src/main/java/de/neemann/digital/core/wiring/Multiplexer.java b/src/main/java/de/neemann/digital/core/wiring/Multiplexer.java index e5b4aff7a..40db0e02e 100644 --- a/src/main/java/de/neemann/digital/core/wiring/Multiplexer.java +++ b/src/main/java/de/neemann/digital/core/wiring/Multiplexer.java @@ -40,8 +40,8 @@ public class Multiplexer extends FanIn { } .addAttribute(Keys.ROTATE) .addAttribute(Keys.BITS) - .addAttribute(Keys.FLIP_SEL_POSITON) - .addAttribute(Keys.SELECTOR_BITS); + .addAttribute(Keys.SELECTOR_BITS) + .addAttribute(Keys.FLIP_SEL_POSITON); /** * Creates a new instance diff --git a/src/main/java/de/neemann/digital/gui/components/AttributeDialog.java b/src/main/java/de/neemann/digital/gui/components/AttributeDialog.java index b41964787..b67a89564 100644 --- a/src/main/java/de/neemann/digital/gui/components/AttributeDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/AttributeDialog.java @@ -20,6 +20,7 @@ import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; /** * Dialog used to edit Attributes. @@ -85,16 +86,31 @@ public class AttributeDialog extends JDialog { panel = new JPanel(new GridBagLayout()); - getContentPane().add(new JScrollPane(panel)); - editors = new ArrayList<>(); topMostTextComponent = null; constraints = new ConstraintsBuilder().inset(3).fill(); + + JPanel secondaryPanel = null; + ConstraintsBuilder secondaryConstraints = null; + + boolean enableTwoTabs = !addCheckBoxes && enableTwoTabs(list); + + if (enableTwoTabs) { + secondaryPanel = new JPanel(new GridBagLayout()); + secondaryConstraints = new ConstraintsBuilder().inset(3).fill(); + } + + boolean isSecondary = false; 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, constraints); + if (key.isSecondary() && enableTwoTabs) { + e.addToPanel(secondaryPanel, key, modifiedAttributes, this, secondaryConstraints); + isSecondary = true; + } else + e.addToPanel(panel, key, modifiedAttributes, this, constraints); + if (addCheckBoxes) { if (checkBoxes == null) checkBoxes = new HashMap<>(); @@ -105,7 +121,11 @@ public class AttributeDialog extends JDialog { panel.add(checkBox, constraints.x(2)); checkBox.addChangeListener(event -> e.setEnabled(checkBox.isSelected())); } - constraints.nextRow(); + + if (key.isSecondary() && enableTwoTabs) + secondaryConstraints.nextRow(); + else + constraints.nextRow(); if (topMostTextComponent == null && e instanceof EditorFactory.StringEditor) topMostTextComponent = ((EditorFactory.StringEditor) e).getTextComponent(); @@ -121,6 +141,15 @@ public class AttributeDialog extends JDialog { } + if (isSecondary) { + JTabbedPane tp = new JTabbedPane(JTabbedPane.TOP); + tp.addTab(Lang.get("attr_primary"), new JScrollPane(panel)); + tp.addTab(Lang.get("attr_secondary"), new JScrollPane(secondaryPanel)); + getContentPane().add(tp); + } else + getContentPane().add(new JScrollPane(panel)); + + JButton okButton = new JButton(new AbstractAction(Lang.get("ok")) { @Override public void actionPerformed(ActionEvent e) { @@ -151,6 +180,25 @@ public class AttributeDialog extends JDialog { JComponent.WHEN_IN_FOCUSED_WINDOW); } + /** + * Returns true if two tabs are to be used. + * + * @param list the list a keys + * @return true if two tabs are to be used. + */ + public boolean enableTwoTabs(List list) { + int secCount = 0; + int primCount = 0; + for (Key k : list) { + if (k.isSecondary()) + secCount++; + else + primCount++; + } + + return (primCount > 1) && (secCount > 1); + } + /** * Closes the dialog and stores modified values * diff --git a/src/main/java/de/neemann/digital/gui/components/CustomShapeEditor.java b/src/main/java/de/neemann/digital/gui/components/CustomShapeEditor.java index 434455485..5866d863e 100644 --- a/src/main/java/de/neemann/digital/gui/components/CustomShapeEditor.java +++ b/src/main/java/de/neemann/digital/gui/components/CustomShapeEditor.java @@ -34,7 +34,7 @@ public class CustomShapeEditor extends EditorFactory.LabelEditor 0) { w.append("

").append(Lang.get("elem_Help_attributes")).append(":

\n
\n"); for (Key k : et.getAttributeList()) - writeEntry(w, k.getName(), k.getDescription()); + if (!k.isSecondary()) + writeEntry(w, k.getName(), k.getDescription()); + for (Key k : et.getAttributeList()) + if (k.isSecondary()) + writeEntry(w, k.getName(), k.getDescription()); w.append("
\n"); } } diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 1f6fa1fb7..9ba721ea6 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -18,6 +18,8 @@ HighZ Oktal Binär + Standard + Erweitert Verwerfen Bearbeiten Weiter bearbeiten diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 91c810065..8863d83e6 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -18,6 +18,8 @@ HighZ Octal Binary + Basic + Advanced Discard Changes Edit Continue editing diff --git a/src/test/java/de/neemann/digital/docu/DocuTest.java b/src/test/java/de/neemann/digital/docu/DocuTest.java index a7adb82b3..5caee1dc3 100644 --- a/src/test/java/de/neemann/digital/docu/DocuTest.java +++ b/src/test/java/de/neemann/digital/docu/DocuTest.java @@ -116,9 +116,18 @@ public class DocuTest extends TestCase { if (etd.getAttributeList().size() > 0) { w.append(" \n"); for (Key k : etd.getAttributeList()) { - w.append(" "); - w.append(escapeHTML(k.getDescription())); - w.append("\n"); + if (!k.isSecondary()) { + w.append(" "); + w.append(escapeHTML(k.getDescription())); + w.append("\n"); + } + } + for (Key k : etd.getAttributeList()) { + if (k.isSecondary()) { + w.append(" "); + w.append(escapeHTML(k.getDescription())); + w.append("\n"); + } } w.append(" \n"); } diff --git a/src/test/java/de/neemann/digital/docu/ScreenShots.java b/src/test/java/de/neemann/digital/docu/ScreenShots.java index d7e5e858b..d6ebe7617 100644 --- a/src/test/java/de/neemann/digital/docu/ScreenShots.java +++ b/src/test/java/de/neemann/digital/docu/ScreenShots.java @@ -44,6 +44,7 @@ public class ScreenShots { public static void main(String[] args) { Settings.getInstance().getAttributes().set(Keys.SETTINGS_DEFAULT_TREESELECT, false); + Settings.getInstance().getAttributes().set(Keys.SETTINGS_GRID, true); // mainScreenShot(); // firstSteps(); // hierarchicalDesign(); diff --git a/src/test/java/de/neemann/digital/integration/TestInGUI.java b/src/test/java/de/neemann/digital/integration/TestInGUI.java index 248827b64..3eb706306 100644 --- a/src/test/java/de/neemann/digital/integration/TestInGUI.java +++ b/src/test/java/de/neemann/digital/integration/TestInGUI.java @@ -766,6 +766,8 @@ public class TestInGUI extends TestCase { .press("RIGHT", 2) .press("DOWN", 1) .press("ENTER", 1) + .press("control TAB", 4) + .press("RIGHT", 1) .add(new GuiTester.SetFocusTo<>(AttributeDialog.class, b -> b instanceof JButton && Lang.get("btn_edit").equals(((JButton) b).getText()))) .press("SPACE") diff --git a/src/test/resources/docu/images/de/scr00.png b/src/test/resources/docu/images/de/scr00.png index 3c00c58ed..edf5ab1b7 100644 Binary files a/src/test/resources/docu/images/de/scr00.png and b/src/test/resources/docu/images/de/scr00.png differ diff --git a/src/test/resources/docu/images/de/scr01.png b/src/test/resources/docu/images/de/scr01.png index f2c5ca58e..a728b71fb 100644 Binary files a/src/test/resources/docu/images/de/scr01.png and b/src/test/resources/docu/images/de/scr01.png differ diff --git a/src/test/resources/docu/images/de/scr02.png b/src/test/resources/docu/images/de/scr02.png index 774143c01..8eded8ce3 100644 Binary files a/src/test/resources/docu/images/de/scr02.png and b/src/test/resources/docu/images/de/scr02.png differ diff --git a/src/test/resources/docu/images/de/scr03.png b/src/test/resources/docu/images/de/scr03.png index 2e8240d12..9ea948104 100644 Binary files a/src/test/resources/docu/images/de/scr03.png and b/src/test/resources/docu/images/de/scr03.png differ diff --git a/src/test/resources/docu/images/de/scr04.png b/src/test/resources/docu/images/de/scr04.png index 7c4c7ae6a..d86726e78 100644 Binary files a/src/test/resources/docu/images/de/scr04.png and b/src/test/resources/docu/images/de/scr04.png differ diff --git a/src/test/resources/docu/images/de/scr05.png b/src/test/resources/docu/images/de/scr05.png index cec9c5acb..bf2aec47f 100644 Binary files a/src/test/resources/docu/images/de/scr05.png and b/src/test/resources/docu/images/de/scr05.png differ diff --git a/src/test/resources/docu/images/de/scr06.png b/src/test/resources/docu/images/de/scr06.png index 75162027f..7cd2c2f35 100644 Binary files a/src/test/resources/docu/images/de/scr06.png and b/src/test/resources/docu/images/de/scr06.png differ diff --git a/src/test/resources/docu/images/de/scr07.png b/src/test/resources/docu/images/de/scr07.png index 7c74c31f9..be94ce2e3 100644 Binary files a/src/test/resources/docu/images/de/scr07.png and b/src/test/resources/docu/images/de/scr07.png differ diff --git a/src/test/resources/docu/images/de/scr08.png b/src/test/resources/docu/images/de/scr08.png index ac7923d4f..5146aa6f6 100644 Binary files a/src/test/resources/docu/images/de/scr08.png and b/src/test/resources/docu/images/de/scr08.png differ diff --git a/src/test/resources/docu/images/de/scr09.png b/src/test/resources/docu/images/de/scr09.png index c9a632b67..eb64103fa 100644 Binary files a/src/test/resources/docu/images/de/scr09.png and b/src/test/resources/docu/images/de/scr09.png differ diff --git a/src/test/resources/docu/images/de/scr10.png b/src/test/resources/docu/images/de/scr10.png index 7410f1b2e..2130d164d 100644 Binary files a/src/test/resources/docu/images/de/scr10.png and b/src/test/resources/docu/images/de/scr10.png differ diff --git a/src/test/resources/docu/images/de/scr11.png b/src/test/resources/docu/images/de/scr11.png index 3d9edce03..b947b1040 100644 Binary files a/src/test/resources/docu/images/de/scr11.png and b/src/test/resources/docu/images/de/scr11.png differ diff --git a/src/test/resources/docu/images/de/scr12.png b/src/test/resources/docu/images/de/scr12.png index 28b30f78a..805d16e30 100644 Binary files a/src/test/resources/docu/images/de/scr12.png and b/src/test/resources/docu/images/de/scr12.png differ diff --git a/src/test/resources/docu/images/de/scr13.png b/src/test/resources/docu/images/de/scr13.png index 7088908d3..c80341f3e 100644 Binary files a/src/test/resources/docu/images/de/scr13.png and b/src/test/resources/docu/images/de/scr13.png differ diff --git a/src/test/resources/docu/images/de/scr14.png b/src/test/resources/docu/images/de/scr14.png index 70fd8bc1f..3a33bffaf 100644 Binary files a/src/test/resources/docu/images/de/scr14.png and b/src/test/resources/docu/images/de/scr14.png differ diff --git a/src/test/resources/docu/images/en/scr00.png b/src/test/resources/docu/images/en/scr00.png index 228a29fec..f035b8b39 100644 Binary files a/src/test/resources/docu/images/en/scr00.png and b/src/test/resources/docu/images/en/scr00.png differ diff --git a/src/test/resources/docu/images/en/scr01.png b/src/test/resources/docu/images/en/scr01.png index b42a3727e..4f53a8ed2 100644 Binary files a/src/test/resources/docu/images/en/scr01.png and b/src/test/resources/docu/images/en/scr01.png differ diff --git a/src/test/resources/docu/images/en/scr02.png b/src/test/resources/docu/images/en/scr02.png index 6b6c1d78a..d3fd66a61 100644 Binary files a/src/test/resources/docu/images/en/scr02.png and b/src/test/resources/docu/images/en/scr02.png differ diff --git a/src/test/resources/docu/images/en/scr03.png b/src/test/resources/docu/images/en/scr03.png index 1176f962a..a2758937b 100644 Binary files a/src/test/resources/docu/images/en/scr03.png and b/src/test/resources/docu/images/en/scr03.png differ diff --git a/src/test/resources/docu/images/en/scr04.png b/src/test/resources/docu/images/en/scr04.png index 4c78b6228..38852db88 100644 Binary files a/src/test/resources/docu/images/en/scr04.png and b/src/test/resources/docu/images/en/scr04.png differ diff --git a/src/test/resources/docu/images/en/scr05.png b/src/test/resources/docu/images/en/scr05.png index 08f566bfb..a5874f35a 100644 Binary files a/src/test/resources/docu/images/en/scr05.png and b/src/test/resources/docu/images/en/scr05.png differ diff --git a/src/test/resources/docu/images/en/scr06.png b/src/test/resources/docu/images/en/scr06.png index b6cd704eb..e9f25d59f 100644 Binary files a/src/test/resources/docu/images/en/scr06.png and b/src/test/resources/docu/images/en/scr06.png differ diff --git a/src/test/resources/docu/images/en/scr07.png b/src/test/resources/docu/images/en/scr07.png index 6531486da..1e95adee6 100644 Binary files a/src/test/resources/docu/images/en/scr07.png and b/src/test/resources/docu/images/en/scr07.png differ diff --git a/src/test/resources/docu/images/en/scr08.png b/src/test/resources/docu/images/en/scr08.png index b06f4f1d1..7f9d47b7b 100644 Binary files a/src/test/resources/docu/images/en/scr08.png and b/src/test/resources/docu/images/en/scr08.png differ diff --git a/src/test/resources/docu/images/en/scr09.png b/src/test/resources/docu/images/en/scr09.png index 5819d3db8..83bc65cb0 100644 Binary files a/src/test/resources/docu/images/en/scr09.png and b/src/test/resources/docu/images/en/scr09.png differ diff --git a/src/test/resources/docu/images/en/scr10.png b/src/test/resources/docu/images/en/scr10.png index 091508791..b3ee90b38 100644 Binary files a/src/test/resources/docu/images/en/scr10.png and b/src/test/resources/docu/images/en/scr10.png differ diff --git a/src/test/resources/docu/images/en/scr11.png b/src/test/resources/docu/images/en/scr11.png index e69bccb28..b6541eea7 100644 Binary files a/src/test/resources/docu/images/en/scr11.png and b/src/test/resources/docu/images/en/scr11.png differ diff --git a/src/test/resources/docu/images/en/scr12.png b/src/test/resources/docu/images/en/scr12.png index 00d702af8..599ad0a1e 100644 Binary files a/src/test/resources/docu/images/en/scr12.png and b/src/test/resources/docu/images/en/scr12.png differ diff --git a/src/test/resources/docu/images/en/scr13.png b/src/test/resources/docu/images/en/scr13.png index 728d5533d..9edf386c1 100644 Binary files a/src/test/resources/docu/images/en/scr13.png and b/src/test/resources/docu/images/en/scr13.png differ diff --git a/src/test/resources/docu/images/en/scr14.png b/src/test/resources/docu/images/en/scr14.png index e4af82cc6..b31b9f218 100644 Binary files a/src/test/resources/docu/images/en/scr14.png and b/src/test/resources/docu/images/en/scr14.png differ