Added a tabbed pane to the attributes dialog to make it more beginner friendly.

This commit is contained in:
hneemann 2018-05-19 12:49:56 +02:00
parent 28db768c8e
commit ebc596e3f6
43 changed files with 129 additions and 39 deletions

View File

@ -1,6 +1,7 @@
Release Notes Release Notes
HEAD, planned as v0.19 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. - Added support for asynchronous sequential circuits such as the Muller-pipeline.
Take a look at the new asynchronous examples for illustration. Take a look at the new asynchronous examples for illustration.
- All examples are translated to english. - All examples are translated to english.

View File

@ -26,6 +26,7 @@ public class Key<VALUE> {
// Both are only used within a custom implemented component. // Both are only used within a custom implemented component.
private String name; private String name;
private String description; private String description;
private boolean isSecondary;
/** /**
* Creates a new Key * Creates a new Key
@ -183,6 +184,23 @@ public class Key<VALUE> {
return this; 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<VALUE> setSecondary() {
isSecondary = true;
return this;
}
/** /**
* A integer attribute. * A integer attribute.
* Stores additional combo box values * Stores additional combo box values

View File

@ -140,7 +140,8 @@ public final class Keys {
= new Key.KeyInteger("Size", 1) = new Key.KeyInteger("Size", 1)
.setComboBoxValues(new Integer[]{0, 1, 2, 3, 4, 5}) .setComboBoxValues(new Integer[]{0, 1, 2, 3, 4, 5})
.setMin(0) .setMin(0)
.allowGroupEdit(); .allowGroupEdit()
.setSecondary();
/** /**
* The value of constants * The value of constants
@ -152,19 +153,19 @@ public final class Keys {
* The default value of elements * The default value of elements
*/ */
public static final Key<Integer> DEFAULT public static final Key<Integer> DEFAULT
= new Key<>("Default", 0).allowGroupEdit(); = new Key<>("Default", 0).allowGroupEdit().setSecondary();
/** /**
* The default value of inputs * The default value of inputs
*/ */
public static final Key<InValue> INPUT_DEFAULT public static final Key<InValue> INPUT_DEFAULT
= new Key<>("InDefault", new InValue(0)).allowGroupEdit(); = new Key<>("InDefault", new InValue(0)).allowGroupEdit().setSecondary();
/** /**
* The default value of the dip switch * The default value of the dip switch
*/ */
public static final Key<Boolean> DIP_DEFAULT public static final Key<Boolean> DIP_DEFAULT
= new Key<>("dipDefault", false); = new Key<>("dipDefault", false).allowGroupEdit().setSecondary();
/** /**
@ -188,11 +189,12 @@ public final class Keys {
/** /**
* The splitter spreading * The splitter spreading
*/ */
public static final Key.KeyInteger SPLITTER_SPREADING public static final Key<Integer> SPLITTER_SPREADING
= new Key.KeyInteger("splitterSpreading", 1) = new Key.KeyInteger("splitterSpreading", 1)
.setComboBoxValues(new Integer[]{1, 2, 3, 4}) .setComboBoxValues(new Integer[]{1, 2, 3, 4})
.setMin(1) .setMin(1)
.setMax(10); .setMax(10)
.setSecondary();
/** /**
@ -262,7 +264,7 @@ public final class Keys {
* the rotation of the elements * the rotation of the elements
*/ */
public static final Key<Rotation> ROTATE public static final Key<Rotation> 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 * 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 * flag to make a value a probe
*/ */
public static final Key<Boolean> VALUE_IS_PROBE public static final Key<Boolean> VALUE_IS_PROBE
= new Key<>("valueIsProbe", false).allowGroupEdit(); = new Key<>("valueIsProbe", false).allowGroupEdit().setSecondary();
/** /**
* flag to set a ROM as program memory * flag to set a ROM as program memory
*/ */
public static final Key<Boolean> IS_PROGRAM_MEMORY public static final Key<Boolean> IS_PROGRAM_MEMORY
= new Key<>("isProgramMemory", false); = new Key<>("isProgramMemory", false).setSecondary();
/** /**
* flag to enable the ROMs auto load function * flag to enable the ROMs auto load function
*/ */
public static final Key<Boolean> AUTO_RELOAD_ROM public static final Key<Boolean> AUTO_RELOAD_ROM
= new Key<>("autoReload", false); = new Key<>("autoReload", false).setSecondary();
/** /**
* flag to show the data table window * flag to show the data table window
*/ */
public static final Key<Boolean> SHOW_DATA_TABLE public static final Key<Boolean> SHOW_DATA_TABLE
= new Key<>("showDataTable", false); = new Key<>("showDataTable", false).setSecondary();
/** /**
* flag to show the data graph window * flag to show the data graph window
*/ */
public static final Key<Boolean> SHOW_DATA_GRAPH public static final Key<Boolean> SHOW_DATA_GRAPH
= new Key<>("showDataGraph", false); = new Key<>("showDataGraph", false).setSecondary();
/** /**
* flag to show the data graph window in single gate mode * flag to show the data graph window in single gate mode
*/ */
public static final Key<Boolean> SHOW_DATA_GRAPH_MICRO public static final Key<Boolean> 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 * 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 * flag to enable high z mode at an input
*/ */
public static final Key<Boolean> IS_HIGH_Z public static final Key<Boolean> IS_HIGH_Z
= new Key<>("isHighZ", false).allowGroupEdit(); = new Key<>("isHighZ", false).allowGroupEdit().setSecondary();
/** /**
* the description of an element * the description of an element
@ -405,8 +407,8 @@ public final class Keys {
/** /**
* output format for numbers * output format for numbers
*/ */
public static final Key.KeyEnum<IntFormat> INT_FORMAT public static final Key<IntFormat> INT_FORMAT
= new Key.KeyEnum<>("intFormat", IntFormat.def, IntFormat.values()); = new Key.KeyEnum<>("intFormat", IntFormat.def, IntFormat.values()).setSecondary();
/** /**
* width of the terminal * width of the terminal
@ -462,13 +464,13 @@ public final class Keys {
* Fitter for the atf15xx * Fitter for the atf15xx
*/ */
public static final Key<File> SETTINGS_ATF1502_FITTER public static final Key<File> 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 * Flash software for the atf15xx
*/ */
public static final Key<File> SETTINGS_ATMISP public static final Key<File> 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 * row bits in led matrix
@ -492,20 +494,21 @@ public final class Keys {
* the pin number * the pin number
*/ */
public static final Key<String> PINNUMBER = public static final Key<String> PINNUMBER =
new Key<>("pinNumber", ""); new Key<>("pinNumber", "").setSecondary();
/** /**
* true if shape is a dil shape * true if shape is a dil shape
*/ */
public static final Key<Boolean> IS_DIL public static final Key<Boolean> IS_DIL
= new Key<>("isDIL", false); = new Key<>("isDIL", false).setSecondary();
/** /**
* the pin count * the pin count
*/ */
public static final Key<Integer> PINCOUNT = public static final Key<Integer> PINCOUNT =
new Key.KeyInteger("pinCount", 0) new Key.KeyInteger("pinCount", 0)
.setMin(0) .setMin(0)
.setDependsOn(IS_DIL); .setDependsOn(IS_DIL)
.setSecondary();
/** /**
@ -558,19 +561,19 @@ public final class Keys {
* Fitter for the atf1502 * Fitter for the atf1502
*/ */
public static final Key<File> SETTINGS_LIBRARY_PATH public static final Key<File> 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 * A jar containing custom java components
*/ */
public static final Key<File> SETTINGS_JAR_PATH public static final Key<File> SETTINGS_JAR_PATH
= new Key.KeyFile("jarPath", new File("")); = new Key.KeyFile("jarPath", new File("")).setSecondary();
/** /**
* The manager which contains all the roms data * The manager which contains all the roms data
*/ */
public static final Key<ROMManger> ROMMANAGER public static final Key<ROMManger> ROMMANAGER
= new Key<>("romContent", ROMManger.EMPTY); = new Key<>("romContent", ROMManger.EMPTY).setSecondary();
/** /**
@ -597,8 +600,8 @@ public final class Keys {
/** /**
* Path to ghdl * Path to ghdl
*/ */
public static final Key.KeyFile SETTINGS_GHDL_PATH public static final Key<File> SETTINGS_GHDL_PATH
= new Key.KeyFile("ghdlPath", new File("ghdl")); = new Key.KeyFile("ghdlPath", new File("ghdl")).setSecondary();
/** /**
* Avoid component tooltips in the main panel * Avoid component tooltips in the main panel
@ -616,6 +619,6 @@ public final class Keys {
* Shape used to represent a visual element * Shape used to represent a visual element
*/ */
public static final Key<CustomShapeDescription> CUSTOM_SHAPE public static final Key<CustomShapeDescription> CUSTOM_SHAPE
= new Key<>("customShape", CustomShapeDescription.EMPTY); = new Key<>("customShape", CustomShapeDescription.EMPTY).setSecondary();
} }

View File

@ -40,8 +40,8 @@ public class Multiplexer extends FanIn {
} }
.addAttribute(Keys.ROTATE) .addAttribute(Keys.ROTATE)
.addAttribute(Keys.BITS) .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 * Creates a new instance

View File

@ -20,6 +20,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
/** /**
* Dialog used to edit Attributes. * Dialog used to edit Attributes.
@ -85,16 +86,31 @@ public class AttributeDialog extends JDialog {
panel = new JPanel(new GridBagLayout()); panel = new JPanel(new GridBagLayout());
getContentPane().add(new JScrollPane(panel));
editors = new ArrayList<>(); editors = new ArrayList<>();
topMostTextComponent = null; topMostTextComponent = null;
constraints = new ConstraintsBuilder().inset(3).fill(); 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) { for (Key key : list) {
Editor e = EditorFactory.INSTANCE.create(key, modifiedAttributes.get(key)); Editor e = EditorFactory.INSTANCE.create(key, modifiedAttributes.get(key));
editors.add(new EditorHolder(e, key)); editors.add(new EditorHolder(e, key));
if (key.isSecondary() && enableTwoTabs) {
e.addToPanel(secondaryPanel, key, modifiedAttributes, this, secondaryConstraints);
isSecondary = true;
} else
e.addToPanel(panel, key, modifiedAttributes, this, constraints); e.addToPanel(panel, key, modifiedAttributes, this, constraints);
if (addCheckBoxes) { if (addCheckBoxes) {
if (checkBoxes == null) if (checkBoxes == null)
checkBoxes = new HashMap<>(); checkBoxes = new HashMap<>();
@ -105,6 +121,10 @@ public class AttributeDialog extends JDialog {
panel.add(checkBox, constraints.x(2)); panel.add(checkBox, constraints.x(2));
checkBox.addChangeListener(event -> e.setEnabled(checkBox.isSelected())); checkBox.addChangeListener(event -> e.setEnabled(checkBox.isSelected()));
} }
if (key.isSecondary() && enableTwoTabs)
secondaryConstraints.nextRow();
else
constraints.nextRow(); constraints.nextRow();
if (topMostTextComponent == null && e instanceof EditorFactory.StringEditor) if (topMostTextComponent == null && e instanceof EditorFactory.StringEditor)
@ -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")) { JButton okButton = new JButton(new AbstractAction(Lang.get("ok")) {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
@ -151,6 +180,25 @@ public class AttributeDialog extends JDialog {
JComponent.WHEN_IN_FOCUSED_WINDOW); 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<Key> 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 * Closes the dialog and stores modified values
* *

View File

@ -34,7 +34,7 @@ public class CustomShapeEditor extends EditorFactory.LabelEditor<CustomShapeDesc
@Override @Override
public JComponent getComponent(ElementAttributes attr) { public JComponent getComponent(ElementAttributes attr) {
JPanel panel = new JPanel(new FlowLayout()); JPanel panel = new JPanel(new GridLayout(1, 2));
panel.add(new ToolTipAction(Lang.get("btn_clearData")) { panel.add(new ToolTipAction(Lang.get("btn_clearData")) {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {

View File

@ -465,7 +465,7 @@ public final class EditorFactory {
@Override @Override
public JComponent getComponent(ElementAttributes attr) { public JComponent getComponent(ElementAttributes attr) {
JPanel panel = new JPanel(new FlowLayout()); JPanel panel = new JPanel(new GridLayout(1, 2));
panel.add(new ToolTipAction(Lang.get("btn_edit")) { panel.add(new ToolTipAction(Lang.get("btn_edit")) {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {

View File

@ -231,6 +231,10 @@ public class ElementHelpDialog extends JDialog {
if (et.getAttributeList().size() > 0) { if (et.getAttributeList().size() > 0) {
w.append("<h4>").append(Lang.get("elem_Help_attributes")).append(":</h4>\n<dl>\n"); w.append("<h4>").append(Lang.get("elem_Help_attributes")).append(":</h4>\n<dl>\n");
for (Key k : et.getAttributeList()) for (Key k : et.getAttributeList())
if (!k.isSecondary())
writeEntry(w, k.getName(), k.getDescription());
for (Key k : et.getAttributeList())
if (k.isSecondary())
writeEntry(w, k.getName(), k.getDescription()); writeEntry(w, k.getName(), k.getDescription());
w.append("</dl>\n"); w.append("</dl>\n");
} }

View File

@ -18,6 +18,8 @@
<string name="attr_dialogHighz">HighZ</string> <string name="attr_dialogHighz">HighZ</string>
<string name="attr_dialogOctal">Oktal</string> <string name="attr_dialogOctal">Oktal</string>
<string name="attr_dialogBinary">Binär</string> <string name="attr_dialogBinary">Binär</string>
<string name="attr_primary">Standard</string>
<string name="attr_secondary">Erweitert</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>

View File

@ -18,6 +18,8 @@
<string name="attr_dialogHighz">HighZ</string> <string name="attr_dialogHighz">HighZ</string>
<string name="attr_dialogOctal">Octal</string> <string name="attr_dialogOctal">Octal</string>
<string name="attr_dialogBinary">Binary</string> <string name="attr_dialogBinary">Binary</string>
<string name="attr_primary">Basic</string>
<string name="attr_secondary">Advanced</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>

View File

@ -116,10 +116,19 @@ public class DocuTest extends TestCase {
if (etd.getAttributeList().size() > 0) { if (etd.getAttributeList().size() > 0) {
w.append(" <attributes name=\"").append(Lang.get("elem_Help_attributes")).append("\">\n"); w.append(" <attributes name=\"").append(Lang.get("elem_Help_attributes")).append("\">\n");
for (Key k : etd.getAttributeList()) { for (Key k : etd.getAttributeList()) {
if (!k.isSecondary()) {
w.append(" <attr name=\"").append(escapeHTML(k.getName())).append("\">"); w.append(" <attr name=\"").append(escapeHTML(k.getName())).append("\">");
w.append(escapeHTML(k.getDescription())); w.append(escapeHTML(k.getDescription()));
w.append("</attr>\n"); w.append("</attr>\n");
} }
}
for (Key k : etd.getAttributeList()) {
if (k.isSecondary()) {
w.append(" <attr name=\"").append(escapeHTML(k.getName())).append("\">");
w.append(escapeHTML(k.getDescription()));
w.append("</attr>\n");
}
}
w.append(" </attributes>\n"); w.append(" </attributes>\n");
} }

View File

@ -44,6 +44,7 @@ public class ScreenShots {
public static void main(String[] args) { public static void main(String[] args) {
Settings.getInstance().getAttributes().set(Keys.SETTINGS_DEFAULT_TREESELECT, false); Settings.getInstance().getAttributes().set(Keys.SETTINGS_DEFAULT_TREESELECT, false);
Settings.getInstance().getAttributes().set(Keys.SETTINGS_GRID, true);
// mainScreenShot(); // mainScreenShot();
// firstSteps(); // firstSteps();
// hierarchicalDesign(); // hierarchicalDesign();

View File

@ -766,6 +766,8 @@ public class TestInGUI extends TestCase {
.press("RIGHT", 2) .press("RIGHT", 2)
.press("DOWN", 1) .press("DOWN", 1)
.press("ENTER", 1) .press("ENTER", 1)
.press("control TAB", 4)
.press("RIGHT", 1)
.add(new GuiTester.SetFocusTo<>(AttributeDialog.class, .add(new GuiTester.SetFocusTo<>(AttributeDialog.class,
b -> b instanceof JButton && Lang.get("btn_edit").equals(((JButton) b).getText()))) b -> b instanceof JButton && Lang.get("btn_edit").equals(((JButton) b).getText())))
.press("SPACE") .press("SPACE")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB