implemented renaming of plan and opening of other plans
This commit is contained in:
4
pom.xml
4
pom.xml
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>de.srsoftware</groupId>
|
||||
<artifactId>web4rail</artifactId>
|
||||
<version>1.3.6</version>
|
||||
<version>1.3.7</version>
|
||||
<name>Web4Rail</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>Java Model Railway Control</description>
|
||||
@@ -38,7 +38,7 @@
|
||||
<dependency>
|
||||
<groupId>de.srsoftware</groupId>
|
||||
<artifactId>tools</artifactId>
|
||||
<version>1.1.9</version>
|
||||
<version>1.1.11</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -393,4 +393,12 @@ svg.Block text{
|
||||
|
||||
#aspect-form td{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.directory{
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.plan-file{
|
||||
color: green;
|
||||
}
|
||||
@@ -157,9 +157,7 @@ function moveTile(x,y){
|
||||
}
|
||||
|
||||
function place(data){
|
||||
var tag = $(data);
|
||||
$('#'+tag.attr('id')).remove();
|
||||
$('#scroll').append(tag);
|
||||
$('#'+$(data).attr('id')).replaceWith(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -227,8 +225,6 @@ function runAction(ev){
|
||||
window.open("https://api.qrserver.com/v1/create-qr-code/?data="+window.location.href,'_blank');
|
||||
} else if (clicked.id == 'fullscreen'){
|
||||
toggleFullscreen();
|
||||
} else if (clicked.id == 'save'){
|
||||
alert('save');
|
||||
} else return request({action:ev.target.id,realm:realm}); // TODO: ask for name
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ Analyze may overwrite these routes! : Durch die Analyse können diese Fahrstraß
|
||||
Analyzing plan... : Plan wird analysiert...
|
||||
and : und
|
||||
AndCondition : Und-Bedingung
|
||||
Application will load "{}" on next launch and will now quit! : Anwendung wird beim nächsten Start „{}“ laden und wird jetzt beendet.
|
||||
Apply : Übernehmen
|
||||
Aspect : Signalbild
|
||||
Aspects : Signalbilder
|
||||
@@ -109,6 +110,7 @@ Edit json : JSON bearbeiten
|
||||
Effect : Effekt
|
||||
Emergency : Notfall
|
||||
enable {} : {} aktivieren
|
||||
Enter new name for plan : Neuen Namen für den Plan eingeben
|
||||
export : exportieren
|
||||
Faster (10 {}) : 10 {} schneller
|
||||
Final speed after breaking, before halting : Endgeschwindigkeit nach Bremsvorgang, vor dem Anhalten
|
||||
@@ -179,6 +181,8 @@ On : An
|
||||
One of : eine von
|
||||
One way : Richtung
|
||||
Online Documentation : Online-Dokumentation
|
||||
open other plan : anderen Plan öffnen
|
||||
Open plan... : Plan öffnen...
|
||||
Operating System : Betriebssystem
|
||||
or : oder
|
||||
OrCondition : Oder-Bedingung
|
||||
@@ -200,6 +204,8 @@ Relay : Relais
|
||||
Relay/Signal/Turnout : Relais/Signal/Weiche
|
||||
Remove tag "{}" from train : Markierung "{}" von Zug entfernen
|
||||
Removed {} : {} gelöscht
|
||||
rename : umbenennen
|
||||
Rename plan : Plan umbenennen
|
||||
Report Issue : Problem melden
|
||||
reverse : wenden
|
||||
Reversed {}. : {} umgedreht.
|
||||
@@ -209,6 +215,7 @@ Route properties : Routen-Eigenschaften
|
||||
Routes : Fahrstraßen
|
||||
Routes using this tile : Fahrstraßen, die diesen Abschnitt verwenden
|
||||
Route will only be available, if all conditions are fulfilled. : Route ist nur verfügbar, wenn alle Bedingungen erfüllt sind.
|
||||
Save "{}" : „{}“ speichern
|
||||
Save : speichern
|
||||
SavePlan : Plan speichern
|
||||
Select block : Block auswählen
|
||||
|
||||
@@ -3,7 +3,6 @@ package de.srsoftware.web4rail;
|
||||
import java.awt.Desktop;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
@@ -13,8 +12,8 @@ import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@@ -43,6 +42,8 @@ public class Application extends BaseClass{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Application.class);
|
||||
private static final String START_TRAINS = "--start-trains";
|
||||
public static final ExecutorService threadPool = Executors.newCachedThreadPool();
|
||||
private static final String FILENAME = "filename";
|
||||
private static Configuration config;
|
||||
|
||||
/**
|
||||
* entry point for the application:<br/>
|
||||
@@ -57,10 +58,11 @@ public class Application extends BaseClass{
|
||||
* @throws NoSuchMethodException
|
||||
* @throws SecurityException
|
||||
*/
|
||||
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
|
||||
Configuration config = new Configuration(Configuration.dir("Web4Rail")+"/app.config");
|
||||
public static void main(String[] args) throws IOException {
|
||||
config = new Configuration(Configuration.dir("Web4Rail")+"/app.config");
|
||||
LOG.debug("config: {}",config);
|
||||
InetSocketAddress addr = new InetSocketAddress(config.getOrAdd(PORT, 8080));
|
||||
String planName = config.getOrAdd(Plan.NAME, Plan.DEFAULT_NAME);
|
||||
HttpServer server = HttpServer.create(addr, 0);
|
||||
server.createContext("/plan", client -> sendPlan(client));
|
||||
server.createContext("/css" , client -> sendFile(client));
|
||||
@@ -69,10 +71,17 @@ public class Application extends BaseClass{
|
||||
server.setExecutor(threadPool);
|
||||
server.start();
|
||||
try {
|
||||
Plan.load(Plan.DEFAULT_NAME);
|
||||
} catch (FileNotFoundException|NoSuchFileException e) {
|
||||
Plan.load(planName);
|
||||
} catch (IOException e) {
|
||||
plan = new Plan();
|
||||
}
|
||||
plan.setAppConfig(config);
|
||||
try {
|
||||
Desktop.getDesktop().browse(URI.create("http://"+InetAddress.getLocalHost().getHostName()+":"+config.getInt(PORT)+"/plan"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
for (String arg : args) {
|
||||
switch (arg) {
|
||||
case START_TRAINS:
|
||||
@@ -80,9 +89,8 @@ public class Application extends BaseClass{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Desktop.getDesktop().browse(URI.create("http://"+InetAddress.getLocalHost().getHostName()+":"+config.getInt(PORT)+"/plan"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* handles request from clients by delegating them to respective classes
|
||||
* @param params
|
||||
@@ -99,10 +107,12 @@ public class Application extends BaseClass{
|
||||
private static Object handle(HashMap<String, String> params) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
|
||||
LOG.debug("Application.handle({})",params);
|
||||
String realm = params.get(REALM);
|
||||
if (realm == null) throw new NullPointerException(REALM+" should not be null!");
|
||||
if (isNull(realm)) throw new NullPointerException(REALM+" should not be null!");
|
||||
|
||||
String action = params.get(ACTION);
|
||||
if (action == null) throw new NullPointerException(ACTION+" should not be null!");
|
||||
if (isNull(action)) throw new NullPointerException(ACTION+" should not be null!");
|
||||
|
||||
if (action.equals(ACTION_OPEN)) return open(params);
|
||||
|
||||
switch (realm) {
|
||||
case REALM_ACTIONS:
|
||||
@@ -168,6 +178,49 @@ public class Application extends BaseClass{
|
||||
return Files.probeContentType(file.toPath());
|
||||
}
|
||||
|
||||
private static Object open(HashMap<String, String> params) {
|
||||
Window win = new Window("open-plan", t("Open plan..."));
|
||||
String filename = params.get(FILENAME);
|
||||
if (isNull(filename)) {
|
||||
filename = ".";
|
||||
} else if (filename.startsWith("."+File.separator)) {
|
||||
filename = filename.substring(2);
|
||||
}
|
||||
File file = new File(filename);
|
||||
if (file.isDirectory()) {
|
||||
Tag ul = null;
|
||||
File[] children = file.listFiles();
|
||||
for (File child : children) {
|
||||
if (child.isDirectory()) {
|
||||
if (isNull(ul)) ul = new Tag("ul").addTo(win);
|
||||
Plan.link("li", child.getName(), Map.of(REALM,REALM_APP,ACTION,ACTION_OPEN,FILENAME,filename+File.separator+child.getName())).clazz("directory").addTo(ul);
|
||||
}
|
||||
}
|
||||
for (File child : children) {
|
||||
if (!child.isDirectory() && child.getName().endsWith(".plan")) {
|
||||
if (isNull(ul)) ul = new Tag("ul").addTo(win);
|
||||
Plan.link("li", child.getName(), Map.of(REALM,REALM_APP,ACTION,ACTION_OPEN,FILENAME,filename+File.separator+child.getName())).clazz("plan-file").addTo(ul);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (file.getName().endsWith(".plan")) {
|
||||
String name = file.getPath();
|
||||
config.put(NAME,name.substring(0,name.length()-5));
|
||||
try {
|
||||
config.save();
|
||||
plan.controlUnit().set(false);
|
||||
plan.stream(t("Application will load \"{}\" on next launch and will now quit!",file));
|
||||
plan.controlUnit().end();
|
||||
System.exit(0);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return win;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sends a response generated from the application to a given client
|
||||
* @param client
|
||||
|
||||
@@ -497,6 +497,12 @@ public abstract class BaseClass implements Constants{
|
||||
}
|
||||
|
||||
protected void removeChild(BaseClass child) {}
|
||||
|
||||
public static void resetRegistry() {
|
||||
registry = new HashMap<BaseClass.Id, BaseClass>();
|
||||
customFieldNames = new HashMap<Class<? extends BaseClass>, Set<String>>();
|
||||
}
|
||||
|
||||
|
||||
protected static String t(String txt, Object...fills) {
|
||||
if (isSet(fills)) for (int i=0; i<fills.length; i++) {
|
||||
|
||||
@@ -21,6 +21,7 @@ public interface Constants {
|
||||
public static final String ACTION_EMERGENCY = "emergency";
|
||||
public static final String ACTION_FASTER10 = "faster10";
|
||||
public static final String ACTION_MOVE = "move";
|
||||
public static final String ACTION_OPEN = "open";
|
||||
public static final String ACTION_POWER = "power";
|
||||
public static final String ACTION_PROPS = "props";
|
||||
public static final String ACTION_QUIT = "quit";
|
||||
@@ -38,6 +39,7 @@ public interface Constants {
|
||||
|
||||
public static final String REALM = "realm";
|
||||
public static final String REALM_ACTIONS = "actions";
|
||||
public static final String REALM_APP = "application";
|
||||
public static final String REALM_CAR = "car";
|
||||
public static final String REALM_CONDITION = "condition";
|
||||
public static final String REALM_CONTACT = "contact";
|
||||
@@ -56,6 +58,7 @@ public interface Constants {
|
||||
public static final String DISABLED = "disabled";
|
||||
public static final String GITHUB_URL = "https://github.com/srsoftware-de/Web4Rail";
|
||||
public static final String ID = "id";
|
||||
public static final String NAME = "name";
|
||||
public static final String NBSP = " ";
|
||||
public static final String NOTES = "notes";
|
||||
public static final String PARENT = "parent";
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import de.keawe.localconfig.Configuration;
|
||||
import de.srsoftware.tools.Tag;
|
||||
import de.srsoftware.web4rail.moving.Car;
|
||||
import de.srsoftware.web4rail.moving.Train;
|
||||
@@ -142,15 +143,20 @@ public class Plan extends BaseClass{
|
||||
private static final String CONFIRM = "confirm";
|
||||
private static final String FINAL_SPEED = "final_speed";
|
||||
private static final String FREE_BEHIND_TRAIN = "free_behind_train";
|
||||
private static final String RENAME = "rename";
|
||||
private String name = DEFAULT_NAME;
|
||||
|
||||
private ControlUnit controlUnit = new ControlUnit(this); // the control unit, to which the plan is connected
|
||||
private Contact learningContact;
|
||||
private Configuration appConfig;
|
||||
|
||||
/**
|
||||
* creates a new plan, starts to send heart beats
|
||||
*/
|
||||
public Plan() {
|
||||
public Plan() {
|
||||
BaseClass.resetRegistry();
|
||||
Application.threadPool.execute(new Heartbeat());
|
||||
name = DEFAULT_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,8 +200,10 @@ public class Plan extends BaseClass{
|
||||
return signal.properties();
|
||||
}
|
||||
return null;
|
||||
case RENAME:
|
||||
return rename(params);
|
||||
case ACTION_SAVE:
|
||||
return saveTo(DEFAULT_NAME);
|
||||
return save();
|
||||
case ACTION_TIMES:
|
||||
return updateTimes(params);
|
||||
case ACTION_UPDATE:
|
||||
@@ -489,15 +497,16 @@ public class Plan extends BaseClass{
|
||||
* @throws NoSuchMethodException
|
||||
* @throws SecurityException
|
||||
*/
|
||||
public static void load(String filename) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
|
||||
public static void load(String name) throws IOException {
|
||||
plan = new Plan();
|
||||
plan.name = name;
|
||||
try {
|
||||
Car.loadAll(filename+".cars",plan);
|
||||
Car.loadAll(name+".cars",plan);
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Was not able to load cars!",e);
|
||||
}
|
||||
|
||||
String content = new String(Files.readAllBytes(new File(filename+".plan").toPath()),UTF8);
|
||||
String content = new String(Files.readAllBytes(new File(name+".plan").toPath()),UTF8);
|
||||
JSONObject json = new JSONObject(content);
|
||||
if (json.has(TILE)) json.getJSONArray(TILE).forEach(object -> Tile.load(object, plan));
|
||||
if (json.has(LENGTH_UNIT)) lengthUnit = json.getString(LENGTH_UNIT);
|
||||
@@ -506,17 +515,17 @@ public class Plan extends BaseClass{
|
||||
if (json.has(FREE_BEHIND_TRAIN)) Route.freeBehindTrain = json.getBoolean(FREE_BEHIND_TRAIN);
|
||||
|
||||
try {
|
||||
Train.loadAll(filename+".trains",plan);
|
||||
Train.loadAll(name+".trains",plan);
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Was not able to load trains!",e);
|
||||
}
|
||||
try {
|
||||
Route.loadAll(filename+".routes",plan);
|
||||
Route.loadAll(name+".routes",plan);
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Was not able to load routes!",e);
|
||||
}
|
||||
try {
|
||||
plan.controlUnit.load(filename+".cu");
|
||||
plan.controlUnit.load(name+".cu");
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Was not able to load control unit settings!",e);
|
||||
}
|
||||
@@ -642,11 +651,13 @@ public class Plan extends BaseClass{
|
||||
private Tag planMenu() throws IOException {
|
||||
Tag actionMenu = new Tag("div").clazz("actions").content(t("Plan"));
|
||||
Tag actions = new Tag("div").clazz("list").content("");
|
||||
new Div(ACTION_SAVE).clazz(REALM_PLAN).content(t("Save")).addTo(actions);
|
||||
saveButton().addTo(actions);
|
||||
new Div(ACTION_ANALYZE).clazz(REALM_PLAN).content(t("Analyze")).addTo(actions);
|
||||
new Div(ACTION_QR).clazz(REALM_PLAN).content(t("QR-Code")).addTo(actions);
|
||||
new Div(FULLSCREEN).clazz(REALM_PLAN).content(t("Fullscreen")).addTo(actions);
|
||||
new Div(ACTION_PROPS).clazz(REALM_PLAN).content(t("Properties")).addTo(actions);
|
||||
new Div(RENAME).clazz(REALM_PLAN).content(t("rename")).addTo(actions);
|
||||
new Div(ACTION_OPEN).clazz(REALM_APP).content(t("open other plan")).addTo(actions);
|
||||
return actions.addTo(actionMenu);
|
||||
}
|
||||
|
||||
@@ -727,8 +738,7 @@ public class Plan extends BaseClass{
|
||||
if (device.address() % 4 == 1) table.children().lastElement().clazz("group");
|
||||
|
||||
}
|
||||
table.clazz("turnouts").addTo(fieldset);
|
||||
return fieldset;
|
||||
return table.clazz("turnouts").addTo(fieldset);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -736,6 +746,35 @@ public class Plan extends BaseClass{
|
||||
if (child instanceof Tile) drop((Tile) child);
|
||||
super.removeChild(child);
|
||||
}
|
||||
|
||||
private Object rename(HashMap<String, String> params) {
|
||||
String newName = params.get(NAME);
|
||||
Window win = new Window("rename-plan", t("Rename plan"));
|
||||
if (isSet(newName)) {
|
||||
newName = newName.trim();
|
||||
if (!newName.isEmpty() && !newName.equals(name)) {
|
||||
String old = name;
|
||||
name = newName;
|
||||
try {
|
||||
String saved = save();
|
||||
appConfig.put(NAME, name);
|
||||
appConfig.save();
|
||||
stream("place "+saveButton());
|
||||
return saved;
|
||||
} catch (IOException e) {
|
||||
new Tag("div").content(t("Was not able to save plan as \"{}\".",newName));
|
||||
name = old;
|
||||
}
|
||||
}
|
||||
}
|
||||
Form form = new Form("rename-form");
|
||||
new Input(REALM, REALM_PLAN).hideIn(form);
|
||||
new Input(ACTION, RENAME).hideIn(form);
|
||||
new Input(NAME,name).addTo(new Label(t("Enter new name for plan")+":"+NBSP)).addTo(form);
|
||||
new Button(t("Save"), form).addTo(form);
|
||||
return form.addTo(win);
|
||||
}
|
||||
|
||||
|
||||
private Tag routeProperties() {
|
||||
Fieldset fieldset = new Fieldset(t("Routes"));
|
||||
@@ -754,12 +793,7 @@ public class Plan extends BaseClass{
|
||||
actions);
|
||||
if (route.isDisabled()) row.clazz("disabled");
|
||||
}
|
||||
table.clazz("turnouts").addTo(fieldset);
|
||||
return fieldset;
|
||||
}
|
||||
|
||||
public void save() throws IOException {
|
||||
plan.stream(plan.saveTo("default"));
|
||||
return table.clazz("turnouts").addTo(fieldset);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -768,8 +802,8 @@ public class Plan extends BaseClass{
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
private String saveTo(String name) throws IOException {
|
||||
if (name == null || name.isEmpty()) throw new NullPointerException("Name must not be empty!");
|
||||
public String save() throws IOException {
|
||||
if (isNull(name) || name.isEmpty()) throw new NullPointerException("Name must not be empty!");
|
||||
Car.saveAll(name+".cars");
|
||||
|
||||
Tile.saveAll(name+".plan");
|
||||
@@ -783,6 +817,10 @@ public class Plan extends BaseClass{
|
||||
|
||||
return t("Plan saved as \"{}\".",name);
|
||||
}
|
||||
|
||||
private Tag saveButton() {
|
||||
return new Div(ACTION_SAVE).clazz(REALM_PLAN).content(t("Save \"{}\"",name));
|
||||
}
|
||||
|
||||
public void sensor(int addr, boolean active) {
|
||||
Contact contact = Contact.get(addr);
|
||||
@@ -800,6 +838,11 @@ public class Plan extends BaseClass{
|
||||
if (isSet(contact)) contact.activate(active);
|
||||
}
|
||||
|
||||
public void setAppConfig(Configuration config) {
|
||||
appConfig = config;
|
||||
}
|
||||
|
||||
|
||||
private Object simplifyRouteName(HashMap<String, String> params) {
|
||||
String routeId = params.get(ROUTE);
|
||||
if (isSet(routeId)) {
|
||||
@@ -926,8 +969,7 @@ public class Plan extends BaseClass{
|
||||
if (params.containsKey(FINAL_SPEED)) Route.endSpeed = Integer.parseInt(params.get(FINAL_SPEED));
|
||||
Route.freeBehindTrain = "on".equalsIgnoreCase(params.get(FREE_BEHIND_TRAIN));
|
||||
|
||||
return t("Plan updated.");
|
||||
|
||||
return t("Plan updated.");
|
||||
}
|
||||
|
||||
private Object updateTimes(HashMap<String, String> params) throws IOException {
|
||||
|
||||
@@ -13,7 +13,7 @@ public class SavePlan extends Action{
|
||||
@Override
|
||||
public boolean fire(Context context) {
|
||||
try {
|
||||
plan.save();
|
||||
plan.stream(plan.save());
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ import de.srsoftware.web4rail.tags.Table;
|
||||
public class Car extends BaseClass implements Comparable<Car>{
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(Car.class);
|
||||
|
||||
public static final String NAME = "name";
|
||||
public static boolean FORWARD = true;
|
||||
public static boolean REVERSE = false;
|
||||
private static final String LENGTH = "length";
|
||||
|
||||
Reference in New Issue
Block a user