first implementation of different color schemes, see #421, see #481

This commit is contained in:
hneemann 2020-06-22 18:24:20 +02:00
parent 6c8bc65d7c
commit dadc335178
11 changed files with 225 additions and 30 deletions

View File

@ -23,6 +23,7 @@ public class Key<VALUE> {
private CheckEnabled checkEnabled;
private boolean isSecondary;
private boolean requiresRestart = false;
private boolean requiresRepaint = false;
private String panelId;
// Both values are always null in digital.
@ -235,6 +236,23 @@ public class Key<VALUE> {
return requiresRestart;
}
/**
* Called if this setting needs a repaint.
*
* @return this for chained calls
*/
public Key<VALUE> setRequiresRepaint() {
requiresRepaint = true;
return this;
}
/**
* @return true if changing this value needs a repaint
*/
public boolean getRequiresRepaint() {
return requiresRepaint;
}
/**
* Moves this key to the panel with the given id
*

View File

@ -466,7 +466,7 @@ public final class Keys {
* enables the grid
*/
public static final Key<Boolean> SETTINGS_GRID
= new Key<>("grid", true);
= new Key<>("grid", true).setRequiresRepaint();
/**
* enables the wire bits view

View File

@ -0,0 +1,153 @@
/*
* Copyright (c) 2020 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.draw.graphics;
import de.neemann.digital.core.element.Key;
import de.neemann.digital.gui.Settings;
import java.awt.*;
/**
* Color map.
* Used to define the different color schemes.
*/
public final class ColorMap {
private static final ColorMap DEFAULT_MAP = new ColorMap()
.set(ColorKey.BACKGROUND, Color.WHITE)
.set(ColorKey.MAIN, Color.BLACK)
.set(ColorKey.WIRE, Color.BLUE.darker())
.set(ColorKey.WIRE_LOW, new Color(0, 142, 0))
.set(ColorKey.WIRE_HIGH, new Color(102, 255, 102))
.set(ColorKey.WIRE_OUT, Color.RED.darker())
.set(ColorKey.WIRE_VALUE, new Color(50, 162, 50))
.set(ColorKey.WIRE_Z, Color.GRAY)
.set(ColorKey.PINS, Color.GRAY)
.set(ColorKey.HIGHLIGHT, Color.CYAN)
.set(ColorKey.GRID, new Color(210, 210, 210))
.set(ColorKey.PASSED, Color.GREEN)
.set(ColorKey.ERROR, Color.RED);
private static final ColorMap DARK_MAP = new ColorMap()
.set(ColorKey.BACKGROUND, Color.BLACK)
.set(ColorKey.MAIN, Color.GRAY)
.set(ColorKey.WIRE, Color.BLUE.darker())
.set(ColorKey.WIRE_LOW, new Color(0, 142, 0))
.set(ColorKey.WIRE_HIGH, new Color(102, 255, 102))
.set(ColorKey.WIRE_OUT, Color.RED.darker())
.set(ColorKey.WIRE_VALUE, new Color(50, 162, 50))
.set(ColorKey.WIRE_Z, Color.GRAY)
.set(ColorKey.PINS, Color.GRAY)
.set(ColorKey.HIGHLIGHT, Color.CYAN)
.set(ColorKey.GRID, new Color(50, 50, 50))
.set(ColorKey.PASSED, Color.GREEN)
.set(ColorKey.ERROR, Color.RED);
private static final ColorMap COLOR_BLIND_MAP = new ColorMap()
.set(ColorKey.BACKGROUND, Color.WHITE)
.set(ColorKey.MAIN, Color.BLACK)
.set(ColorKey.WIRE, Color.BLUE.darker())
.set(ColorKey.WIRE_LOW, new Color(32, 59, 232))
.set(ColorKey.WIRE_HIGH, new Color(244, 235, 66))
.set(ColorKey.WIRE_OUT, Color.RED.darker())
.set(ColorKey.WIRE_VALUE, new Color(50, 162, 50))
.set(ColorKey.WIRE_Z, new Color(1, 188, 157))
.set(ColorKey.PINS, Color.GRAY)
.set(ColorKey.HIGHLIGHT, Color.CYAN)
.set(ColorKey.GRID, new Color(210, 210, 210))
.set(ColorKey.PASSED, Color.GREEN)
.set(ColorKey.ERROR, Color.RED);
private enum ColorSchemes {
DEFAULT(DEFAULT_MAP), DARK(DARK_MAP), COLOR_BLIND(COLOR_BLIND_MAP);
private final ColorMap map;
ColorSchemes(ColorMap map) {
this.map = map;
}
private ColorMap getMap() {
return map;
}
}
/**
* The key used to select the color map
*/
public static final Key<ColorSchemes> COLOR_SCHEME =
new Key.KeyEnum<>("colorScheme", ColorSchemes.DEFAULT, ColorSchemes.values())
.setRequiresRepaint();
private static ColorMap instance = null;
/**
* @return the selected color map
*/
public static ColorMap getInstance() {
if (instance == null) {
Settings.getInstance().getAttributes().addListener(ColorMap::updateInstance);
updateInstance();
}
return instance;
}
private static void updateInstance() {
instance = Settings.getInstance().get(COLOR_SCHEME).getMap();
}
/**
* The identifiers for the different colors
*/
public enum ColorKey {BACKGROUND, MAIN, WIRE, WIRE_HIGH, WIRE_LOW, WIRE_VALUE, WIRE_OUT, WIRE_Z, ERROR, PASSED, PINS, GRID, HIGHLIGHT}
private final Color[] colors;
private ColorMap() {
colors = new Color[ColorKey.HIGHLIGHT.ordinal() + 1];
}
private ColorMap set(ColorKey key, Color color) {
colors[key.ordinal()] = color;
return this;
}
/**
* Returns the selected color
*
* @param key te color key
* @return the color
*/
public Color getColor(ColorKey key) {
Color color = colors[key.ordinal()];
if (color == null)
return colors[ColorKey.MAIN.ordinal()];
return color;
}
/**
* Provides a color
*/
public interface ColorProvider {
/**
* @return the color
*/
Color getColor();
}
static final class ColorByKey implements ColorProvider {
private final ColorKey key;
ColorByKey(ColorKey key) {
this.key = key;
}
@Override
public Color getColor() {
return getInstance().getColor(key);
}
}
}

View File

@ -37,11 +37,11 @@ public final class Style {
/**
* used to draw the failed state lines in the measurement graph
*/
public static final Style FAILED = new Builder(NORMAL).setColor(Color.RED).build();
public static final Style FAILED = new Builder(NORMAL).setColor(ColorMap.ColorKey.ERROR).build();
/**
* used to draw the passed state lines in the measurement graph
*/
public static final Style PASS = new Builder(NORMAL).setColor(Color.GREEN).build();
public static final Style PASS = new Builder(NORMAL).setColor(ColorMap.ColorKey.PASSED).build();
/**
* Used for text which is integral part of the shape.
* Text which uses this style is always included in sizing!
@ -66,25 +66,25 @@ public final class Style {
public static final Style WIRE = new Builder()
.setThickness(WIRETHICK)
.setFilled(true)
.setColor(Color.BLUE.darker())
.setColor(ColorMap.ColorKey.WIRE)
.setEndCap(BasicStroke.CAP_ROUND)
.build();
/**
* Used for low wires in running mode
*/
public static final Style WIRE_LOW = new Builder(WIRE).setColor(new Color(0, 142, 0)).build();
public static final Style WIRE_LOW = new Builder(WIRE).setColor(ColorMap.ColorKey.WIRE_LOW).build();
/**
* Used for high wires in running mode
*/
public static final Style WIRE_HIGH = new Builder(WIRE).setColor(new Color(102, 255, 102)).build();
public static final Style WIRE_HIGH = new Builder(WIRE).setColor(ColorMap.ColorKey.WIRE_HIGH).build();
/**
* Used for wires in high Z state
*/
public static final Style WIRE_HIGHZ = new Builder(WIRE).setColor(Color.GRAY).build();
public static final Style WIRE_HIGHZ = new Builder(WIRE).setColor(ColorMap.ColorKey.WIRE_Z).build();
/**
* used to draw the output dots
*/
public static final Style WIRE_OUT = new Builder(WIRE).setColor(Color.RED.darker()).build();
public static final Style WIRE_OUT = new Builder(WIRE).setColor(ColorMap.ColorKey.WIRE_OUT).build();
/**
* used to draw the bus wires
@ -107,7 +107,7 @@ public final class Style {
*/
public static final Style SHAPE_PIN = new Builder()
.setThickness(LINETHIN)
.setColor(Color.GRAY)
.setColor(ColorMap.ColorKey.PINS)
.setFontSize(18)
.build();
/**
@ -118,19 +118,19 @@ public final class Style {
* Used to draw the pin description text
*/
public static final Style WIRE_VALUE = new Builder(SHAPE_SPLITTER)
.setColor(new Color(50, 162, 50))
.setColor(ColorMap.ColorKey.WIRE_VALUE)
.build();
/**
* Used to draw the wire bit number
*/
public static final Style WIRE_BITS = new Builder(SHAPE_SPLITTER)
.setColor(WIRE.color)
.setColor(ColorMap.ColorKey.WIRE)
.build();
/**
* highlight color used for the circles to mark an element
*/
public static final Style HIGHLIGHT = new Builder(NORMAL)
.setColor(Color.CYAN)
.setColor(ColorMap.ColorKey.HIGHLIGHT)
.setEndCap(BasicStroke.CAP_ROUND)
.build();
@ -138,13 +138,13 @@ public final class Style {
* error color used for the circles to mark an element
*/
public static final Style ERROR = new Builder(NORMAL)
.setColor(Color.RED)
.setColor(ColorMap.ColorKey.ERROR)
.setEndCap(BasicStroke.CAP_ROUND)
.build();
private final int thickness;
private final boolean filled;
private final Color color;
private final ColorMap.ColorProvider color;
private final int fontSize;
private final float[] dash;
private final BasicStroke stroke;
@ -188,7 +188,7 @@ public final class Style {
* @return the color
*/
public Color getColor() {
return color;
return color.getColor();
}
/**
@ -309,7 +309,7 @@ public final class Style {
private static final class Builder {
private int thickness = LINETHICK;
private boolean filled = false;
private Color color = Color.BLACK;
private ColorMap.ColorProvider color = new ColorMap.ColorByKey(ColorMap.ColorKey.MAIN);
private int fontSize = 24;
private float[] dash = null;
private boolean mattersForSize = false;
@ -339,8 +339,13 @@ public final class Style {
return this;
}
private Builder setColor(ColorMap.ColorKey key) {
this.color = new ColorMap.ColorByKey(key);
return this;
}
private Builder setColor(Color color) {
this.color = color;
this.color = () -> color;
return this;
}

View File

@ -8,9 +8,6 @@ package de.neemann.digital.draw.shapes;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.draw.graphics.*;
import de.neemann.digital.draw.graphics.Polygon;
import java.awt.*;
/**
* The shape to show a seven seg display.
@ -46,7 +43,7 @@ public abstract class SevenShape implements Shape {
*/
public SevenShape(ElementAttributes attr) {
onStyle = Style.NORMAL.deriveFillStyle(attr.get(Keys.COLOR));
offStyle = Style.NORMAL.deriveFillStyle(new Color(230, 230, 230));
offStyle = Style.NORMAL.deriveFillStyle(ColorMap.getInstance().getColor(ColorMap.ColorKey.GRID));
size = attr.get(Keys.SEVEN_SEG_SIZE);
}

View File

@ -14,9 +14,6 @@ import de.neemann.digital.draw.elements.IOState;
import de.neemann.digital.draw.elements.Pin;
import de.neemann.digital.draw.elements.Pins;
import de.neemann.digital.draw.graphics.*;
import de.neemann.digital.draw.graphics.Polygon;
import java.awt.*;
import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
@ -67,7 +64,7 @@ public class SixteenShape implements Shape {
public SixteenShape(ElementAttributes attr, PinDescriptions inputs, PinDescriptions outputs) {
pins = inputs;
onStyle = Style.NORMAL.deriveFillStyle(attr.get(Keys.COLOR));
offStyle = Style.NORMAL.deriveFillStyle(new Color(230, 230, 230));
offStyle = Style.NORMAL.deriveFillStyle(ColorMap.getInstance().getColor(ColorMap.ColorKey.GRID));
size = attr.get(Keys.SEVEN_SEG_SIZE);
}

View File

@ -745,7 +745,7 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS
Lang.setLanguage(modified.get(Keys.SETTINGS_LANGUAGE));
JOptionPane.showMessageDialog(Main.this, Lang.get("msg_restartNeeded"));
}
if (!Settings.getInstance().getAttributes().equalsKey(Keys.SETTINGS_GRID, modified))
if (Settings.getInstance().requiresRepaint(modified))
circuitComponent.graphicHasChanged();
Settings.getInstance().getAttributes().getValuesFrom(modified);

View File

@ -8,6 +8,7 @@ package de.neemann.digital.gui;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.Key;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.draw.graphics.ColorMap;
import java.util.ArrayList;
import java.util.Collections;
@ -42,6 +43,7 @@ public final class Settings extends SettingsBase {
intList.add(Keys.SETTINGS_IEEE_SHAPES);
intList.add(Keys.SETTINGS_LANGUAGE);
intList.add(Keys.SETTINGS_EXPRESSION_FORMAT);
intList.add(ColorMap.COLOR_SCHEME);
intList.add(Keys.SETTINGS_DEFAULT_TREESELECT);
intList.add(Keys.SETTINGS_GRID);
intList.add(Keys.SETTINGS_SHOW_WIRE_BITS);
@ -76,4 +78,18 @@ public final class Settings extends SettingsBase {
return false;
}
/**
* Returns true if the given modification requires a repaint.
*
* @param modified the modified settings
* @return true if the modification requires a repaint
*/
public boolean requiresRepaint(ElementAttributes modified) {
for (Key<?> key : getKeys())
if (key.getRequiresRepaint() && !getAttributes().equalsKey(key, modified))
return true;
return false;
}
}

View File

@ -43,6 +43,7 @@ import java.io.IOException;
import java.util.List;
import java.util.*;
import static de.neemann.digital.draw.graphics.ColorMap.*;
import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
import static de.neemann.digital.draw.shapes.GenericShape.SIZE2;
@ -92,8 +93,6 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
private static final int DRAG_DISTANCE = (int) (SIZE2 * Screen.getInstance().getScaling());
private static final Color GRID_COLOR = new Color(210, 210, 210);
private final Main parent;
private final ElementLibrary library;
private final HashSet<Drawable> highLighted;
@ -859,7 +858,7 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
Graphics2D gr2 = buffer.createGraphics();
enableAntiAlias(gr2);
gr2.setColor(Color.WHITE);
gr2.setColor(getInstance().getColor(ColorKey.BACKGROUND));
gr2.fillRect(0, 0, getWidth(), getHeight());
if (scaleX > 0.3 && Settings.getInstance().get(Keys.SETTINGS_GRID))
@ -917,7 +916,7 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
if (delta > max) delta = max;
double sub = delta / 2.0;
gr2.setColor(GRID_COLOR);
gr2.setColor(getInstance().getColor(ColorKey.GRID));
for (int x = 0; x <= cx; x++) {
double xx = p1.getX() + (p2.getX() - p1.getX()) * x / cx - sub;
for (int y = 0; y <= cy; y++) {

View File

@ -1506,6 +1506,11 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
<string name="key_layoutShapeDelta_tt">Wird vom Layout-Shape verwendet. Legt den Abstand zum vorherigen Pin fest.
</string>
<string name="key_colorScheme">Farbschema</string>
<string name="key_colorScheme_DEFAULT">Normal</string>
<string name="key_colorScheme_DARK">Dunkel</string>
<string name="key_colorScheme_COLOR_BLIND">Rot-Grün-Sehschwäche</string>
<string name="mod_insertWire">Leitung eingefügt.</string>
<string name="mod_insertCopied">Aus Zwischenablage eingefügt.</string>
<string name="mod_setKey_N0_in_element_N1">Wert ''{0}'' in Element ''{1}'' verändert.</string>

View File

@ -1470,6 +1470,11 @@
<string name="key_layoutShapeDelta_tt">Used by the layout shape type. Sets the distance to the previous pin.
</string>
<string name="key_colorScheme">Color-Scheme</string>
<string name="key_colorScheme_DEFAULT">Normal</string>
<string name="key_colorScheme_DARK">Dark</string>
<string name="key_colorScheme_COLOR_BLIND">red/green colorblind</string>
<string name="mod_insertWire">Inserted wire.</string>
<string name="mod_insertCopied">Insert from clipboard.</string>
<string name="mod_setKey_N0_in_element_N1">Value ''{0}'' in component ''{1}'' modified.</string>