diff --git a/pom.xml b/pom.xml index d01b886..ded2f8a 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 de.srsoftware web4rail - 1.3.35 + 1.3.36 Web4Rail jar Java Model Railway Control diff --git a/resources/css/style.css b/resources/css/style.css index 0c4cebe..62fc459 100644 --- a/resources/css/style.css +++ b/resources/css/style.css @@ -406,4 +406,20 @@ svg.Block text{ .plan-file{ color: green; +} + +.Switch rect{ + fill:none; +} + +.Switch.off rect.enabled, +.Switch.on rect.disabled{ + display: none; +} + +.Switch.off rect.disabled{ + fill: red; +} +.Switch.on rect.enabled{ + fill: forestgreen; } \ No newline at end of file diff --git a/resources/svg/Switch.svg b/resources/svg/Switch.svg new file mode 100644 index 0000000..f125e6c --- /dev/null +++ b/resources/svg/Switch.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/resources/translations/Application.de.translation b/resources/translations/Application.de.translation index 5497ae2..a3ef8fd 100644 --- a/resources/translations/Application.de.translation +++ b/resources/translations/Application.de.translation @@ -1,6 +1,9 @@ abort : abbrechen Accessory : Zubehör +Action : Aktion Actions : Aktionen +Actions (On) : Aktionen (Ein) +Actions (Off) : Aktionen (Aus) Actions and contacts : Aktionen und Kontakte Action type : Aktions-Typ Actions will only fire, if all conditions are fullfilled. : Aktionen werden nur ausgeführt, wenn alle Bedingungen erfüllt sind. @@ -164,6 +167,8 @@ Falls aktiviert, wird die Strecke anhand von Zug- und Kachel-Länge hinter dem Z internal contacts : interne Kontakte inverted : invertiert Inverts the direction {} is heading to. : Kehrt die Richtung, in welche {} fährt, um. +{} is off : {} ist Aus +{} is on : {} ist Ein {} is oriented {} : {} ist {} gerichtet known cars : bekannte Waggons known locomotives : bekannte Lokomotiven @@ -276,6 +281,7 @@ Select from plan : Auf Plan auswählen Select object : Objekt auswählen Select relay : Relais auswählen Select state : Status auswählen +Select switch : Schalter auswählen Select train : Zug auswählen Select turnout : Weiche wählen SendCommand : Kommando senden @@ -330,6 +336,7 @@ STRAIGHT : gerade Swap order : Reihenfolge umkehren Swap order of trains : Reihenfolge der Züge tauschen SwitchFunction : Funktion schalten +SwitchIsOn : Schalter is an Switch power off : Strom ausschalten Switch power on : Strom anschalten SYSTEM : Betriebssystem diff --git a/src/main/java/de/srsoftware/web4rail/Plan.java b/src/main/java/de/srsoftware/web4rail/Plan.java index c78363c..3b3f6f5 100644 --- a/src/main/java/de/srsoftware/web4rail/Plan.java +++ b/src/main/java/de/srsoftware/web4rail/Plan.java @@ -71,6 +71,7 @@ import de.srsoftware.web4rail.tiles.SignalS; import de.srsoftware.web4rail.tiles.SignalW; import de.srsoftware.web4rail.tiles.StraightH; import de.srsoftware.web4rail.tiles.StraightV; +import de.srsoftware.web4rail.tiles.Switch; import de.srsoftware.web4rail.tiles.TextDisplay; import de.srsoftware.web4rail.tiles.Tile; import de.srsoftware.web4rail.tiles.TileWithShadow; @@ -938,6 +939,7 @@ public class Plan extends BaseClass{ new DecouplerV().tag(null).addTo(tiles); new Relay().setLabel(true,"RL").tag(null).addTo(tiles); new Contact().tag(null).addTo(tiles); + new Switch().tag(null).addTo(tiles); new TextDisplay().text("tx").tag(null).addTo(tiles); new Eraser().tag(null).addTo(tiles); return tiles.addTo(tileMenu); diff --git a/src/main/java/de/srsoftware/web4rail/conditions/Condition.java b/src/main/java/de/srsoftware/web4rail/conditions/Condition.java index 56c303d..88e7e8b 100644 --- a/src/main/java/de/srsoftware/web4rail/conditions/Condition.java +++ b/src/main/java/de/srsoftware/web4rail/conditions/Condition.java @@ -123,6 +123,7 @@ public abstract class Condition extends BaseClass { OrCondition.class, PushPullTrain.class, RouteEndBlock.class, + SwitchIsOn.class, TrainHasTag.class, TrainIsShunting.class, TrainLength.class, diff --git a/src/main/java/de/srsoftware/web4rail/conditions/SwitchIsOn.java b/src/main/java/de/srsoftware/web4rail/conditions/SwitchIsOn.java new file mode 100644 index 0000000..69c8253 --- /dev/null +++ b/src/main/java/de/srsoftware/web4rail/conditions/SwitchIsOn.java @@ -0,0 +1,58 @@ +package de.srsoftware.web4rail.conditions; + +import java.util.HashMap; +import java.util.List; + +import org.json.JSONObject; + +import de.srsoftware.web4rail.BaseClass; +import de.srsoftware.web4rail.tags.Fieldset; +import de.srsoftware.web4rail.tags.Window; +import de.srsoftware.web4rail.tiles.Switch; + +public class SwitchIsOn extends Condition { + + private Switch swtch = null; + private static final String SWITCH = "switch"; + + + + @Override + public boolean fulfilledBy(Context context) { + if (isSet(swtch)) return swtch.isOn() != inverted; + return false; + } + + @Override + public JSONObject json() { + JSONObject json = super.json(); + if (isSet(swtch)) json.put(SWITCH, swtch.id().toString()); + return json; + } + + public Condition load(JSONObject json) { + super.load(json); + if (json.has(SWITCH)) swtch = BaseClass.get(new Id(json.getString(SWITCH))); + return this; + } + + @Override + protected Window properties(List
preForm, FormInput formInputs, List
postForm) { + formInputs.add(t("Select switch"),Switch.selector(swtch)); + + return super.properties(preForm, formInputs, postForm); + } + + @Override + public String toString() { + if (isNull(SWITCH)) return "["+t("Click here to select switch!")+"]"; + return t(inverted ? "{} is off" : "{} is on",swtch) ; + } + + @Override + protected Object update(HashMap params) { + String switchId = params.get(Switch.class.getSimpleName()); + if (isSet(switchId)) swtch = BaseClass.get(new Id(switchId)); + return super.update(params); + } +} diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Switch.java b/src/main/java/de/srsoftware/web4rail/tiles/Switch.java new file mode 100644 index 0000000..1100a8b --- /dev/null +++ b/src/main/java/de/srsoftware/web4rail/tiles/Switch.java @@ -0,0 +1,194 @@ +package de.srsoftware.web4rail.tiles; + +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map.Entry; +import java.util.TreeMap; + +import org.json.JSONArray; +import org.json.JSONObject; + +import de.srsoftware.tools.Tag; +import de.srsoftware.web4rail.Application; +import de.srsoftware.web4rail.BaseClass; +import de.srsoftware.web4rail.actions.Action; +import de.srsoftware.web4rail.actions.ActionList; +import de.srsoftware.web4rail.tags.Fieldset; +import de.srsoftware.web4rail.tags.Select; +import de.srsoftware.web4rail.tags.Window; + +public class Switch extends Tile{ + + private boolean state = false; + private ActionList actionsOn,actionsOff; + private static final String ON = "ON"; + private static final String OFF = "OFF"; + + public Switch() { + actionsOn = new ActionList(this); + actionsOff = new ActionList(this); + } + + @Override + protected HashSet classes() { + HashSet classes = super.classes(); + classes.add(state?"on":"off"); + return classes; + } + + + @Override + public Object click() throws IOException { + state = !state; + Application.threadPool.execute(new Runnable() { + + @Override + public void run() { + Context context = new Context(Switch.this); + if (state) { + actionsOn.fire(context); + } else actionsOff.fire(context); + } + }); + stream(); + return super.click(); + } + + @Override + public JSONObject json() { + JSONObject json = super.json(); + if (!actionsOn.isEmpty()) json.put(ON, actionsOn.json()); + if (!actionsOff.isEmpty()) json.put(OFF, actionsOff.json()); + json.put(STATE, state); + return json; + } + + @Override + public Tile load(JSONObject json) { + if (json.has(ON)) { + Object dummy = json.get(ON); + if (dummy instanceof JSONArray) { + JSONArray jarr = (JSONArray) dummy; + for (Object o : jarr) { + if (o instanceof JSONObject) { + JSONObject jo = (JSONObject) o; + String type = jo.getString("type"); + Action action = Action.create(type, actionsOn); + if (isSet(action)) { + action.load(jo); + actionsOn.add(action); + } + } + } + } + if (dummy instanceof JSONObject) { + actionsOn.load((JSONObject) dummy); + } + } + if (json.has(OFF)) { + Object dummy = json.get(OFF); + if (dummy instanceof JSONArray) { + JSONArray jarr = (JSONArray) dummy; + for (Object o : jarr) { + if (o instanceof JSONObject) { + JSONObject jo = (JSONObject) o; + String type = jo.getString("type"); + Action action = Action.create(type, actionsOff); + if (isSet(action)) { + action.load(jo); + actionsOff.add(action); + } + } + } + } + if (dummy instanceof JSONObject) { + actionsOff.load((JSONObject) dummy); + } + } + if (json.has(STATE)) state =json.getBoolean(STATE); + return super.load(json); + } + + @Override + public Tile position(int x, int y) { + super.position(x, y); + return this; + } + + public static Object process(HashMap params) { + String action = params.get(ACTION); + Id id = Id.from(params); + if (action == null) return t("Missing ACTION on call to {}.process()",Switch.class.getSimpleName()); + Switch swtch = isSet(id) ? BaseClass.get(id) : null; + switch (action) { + case ACTION_DROP: + if (isNull(id)) return t("Missing ID on call to {}.process()",Switch.class.getSimpleName()); + if (isNull(swtch)) return t("No contact with id {} found!",id); + swtch.remove(); + return t("Removed {}.",id); + case ACTION_PROPS: + return swtch.properties(); + case ACTION_UPDATE: + return plan.update(params); + } + return t("Unknown action: {}",action); + } + + @Override + protected Window properties(List
preForm, FormInput formInputs, List
postForm) { + Fieldset fieldset = new Fieldset(t("Actions (On)")); + fieldset.id("actionsOn"); + actionsOn.list().addTo(fieldset); + postForm.add(fieldset); + fieldset = new Fieldset(t("Actions (Off)")); + fieldset.id("actionsOff"); + actionsOff.list().addTo(fieldset); + postForm.add(fieldset); + return super.properties(preForm, formInputs, postForm); + } + + @Override + public void removeChild(BaseClass child) { + if (child == actionsOn) actionsOn = null; + if (child == actionsOff) actionsOff = null; + super.removeChild(child); + } + + public static Select selector(Switch preselect) { + TreeMap sortedSet = new TreeMap(); // Map from Name to Contact + for (Switch contact : BaseClass.listElements(Switch.class)) sortedSet.put(contact.toString(), contact); + Select select = new Select("Switch"); + for (Entry entry : sortedSet.entrySet()) { + Switch contact = entry.getValue(); + Tag option = select.addOption(contact.id(),contact); + if (contact == preselect) option.attr("selected", "selected"); + } + return select; + } + + public boolean isOn() { + return state; + } + + public void stream() { + try { + Tag tag = tag(null); + if (state) tag.clazz(tag.get("class")+" active"); + plan.stream("place "+tag); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public String title() { + return t("Switch @ ({}, {})",x,y); + } + + @Override + public String toString() { + return t("Switch")+"("+x+","+y+")"; + } +}