diff --git a/resources/css/style.css b/resources/css/style.css
index 54ec151..f6e8cfd 100644
--- a/resources/css/style.css
+++ b/resources/css/style.css
@@ -39,8 +39,10 @@ svg text{
float: left;
border: 1px solid black;
height: 30px;
+ min-width: 30px;
background: white;
padding: 3px;
+ text-align: center;
}
.menu .list{
@@ -62,6 +64,8 @@ svg text{
position: relative;
border: 1px solid black;
height: 30px;
+ min-width: 30px;
+ text-align: center;
float: left;
}
diff --git a/resources/js/plan.js b/resources/js/plan.js
index 2a2fed5..0f3806f 100644
--- a/resources/js/plan.js
+++ b/resources/js/plan.js
@@ -1,6 +1,8 @@
const ADD = 'add';
+const MOVE = 'move';
const SQUARE = 30;
const BODY = 'body';
+const DIV = 'DIV';
const SVG = 'svg';
const PLAN = 'plan';
const POST = 'POST';
@@ -27,19 +29,20 @@ function addTile(x,y){
addMessage(resp);
}
});
-
}
function bodyClick(ev){
- //console.log('bodyClick:',ev);
+ console.log('bodyClick:',ev);
switch (mode){
case undefined:
case null:
return clickTile(ev.clientX,ev.clientY);
case ADD:
return addTile(ev.clientX,ev.clientY);
+ case MOVE:
+ return moveTile(ev.clientX,ev.clientY);
}
- console.log(ev.clientX,ev.clientY);
+ console.log('unknown action "'+mode+'" @ ('+ev.clientX+','+ev.clientY+')');
}
function clickTile(x,y){
@@ -83,11 +86,46 @@ function enableAdding(ev){
return false; // otherwise body.click would also be triggered
}
+function enableMove(ev){
+ console.log('enableMove:',ev);
+ if (selected != null) $(selected).css('border','');
+ selected = ev.target;
+ while (selected != null && selected.nodeName != DIV) selected = selected.parentNode;
+ if (selected == null){
+ mode = null;
+ } else {
+ $(selected).css('border','2px solid red');
+ $('.menu .move .list').css('display','inherit');
+ mode = MOVE;
+ }
+ return false; // otherwise body.click would also be triggered
+}
+
+function moveTile(x,y){
+ console.log("moveTile:",selected.id,x,y);
+ x = Math.floor(x/SQUARE);
+ y = Math.floor(y/SQUARE);
+ $.ajax({
+ url : PLAN,
+ method: POST,
+ data : {action:mode,direction:selected.id,x:x,y:y},
+ success: function(resp){
+ $(resp).each(function(){
+ if (this.id != undefined){
+ $('#'+this.id).remove();
+ $(BODY).append($(this));
+ }
+ });
+ $('#tile-'+x+'-'+y).remove();
+ }
+ });
+}
+
function savePlan(ev){
$.ajax({
url : PLAN,
method : POST,
- data : {action:'save',name:'default'}, // todo: ask for name
+ data : {action:'save',name:'default'}, // TODO: ask for name
success: function(resp){ addMessage(resp);}
});
return false;
@@ -97,6 +135,7 @@ window.onload = function () {
var isDragging = false;
$('.menu > div').click(closeMenu);
$('.menu .addtile .list svg').click(enableAdding);
+ $('.menu .move .list div').click(enableMove);
$(BODY).click(bodyClick);
$('#save').click(savePlan);
}
diff --git a/resources/svg/TurnoutEN.svg b/resources/svg/TurnoutEN.svg
new file mode 100644
index 0000000..74eb417
--- /dev/null
+++ b/resources/svg/TurnoutEN.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/resources/svg/TurnoutES.svg b/resources/svg/TurnoutES.svg
new file mode 100644
index 0000000..347786e
--- /dev/null
+++ b/resources/svg/TurnoutES.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/resources/svg/TurnoutWN.svg b/resources/svg/TurnoutWN.svg
new file mode 100644
index 0000000..8bf393c
--- /dev/null
+++ b/resources/svg/TurnoutWN.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/src/main/java/de/srsoftware/web4rail/Application.java b/src/main/java/de/srsoftware/web4rail/Application.java
index 609ac82..f14248d 100644
--- a/src/main/java/de/srsoftware/web4rail/Application.java
+++ b/src/main/java/de/srsoftware/web4rail/Application.java
@@ -92,7 +92,7 @@ public class Application {
html = ((Page)response).html().toString().getBytes(UTF8);
client.getResponseHeaders().add("content-type", "text/html");
} else {
- html = response.toString().getBytes(UTF8);
+ html = (response == null ? "" : response.toString()).getBytes(UTF8);
client.getResponseHeaders().add("content-type", "text/plain");
}
diff --git a/src/main/java/de/srsoftware/web4rail/Plan.java b/src/main/java/de/srsoftware/web4rail/Plan.java
index 3b0b91e..c70736a 100644
--- a/src/main/java/de/srsoftware/web4rail/Plan.java
+++ b/src/main/java/de/srsoftware/web4rail/Plan.java
@@ -9,6 +9,7 @@ import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map.Entry;
+import java.util.Vector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,8 +26,11 @@ import de.srsoftware.web4rail.tiles.Eraser;
import de.srsoftware.web4rail.tiles.StraightH;
import de.srsoftware.web4rail.tiles.StraightV;
import de.srsoftware.web4rail.tiles.Tile;
+import de.srsoftware.web4rail.tiles.TurnoutEN;
+import de.srsoftware.web4rail.tiles.TurnoutES;
import de.srsoftware.web4rail.tiles.TurnoutSE;
import de.srsoftware.web4rail.tiles.TurnoutSW;
+import de.srsoftware.web4rail.tiles.TurnoutWN;
import de.srsoftware.web4rail.tiles.TurnoutWS;
public class Plan {
@@ -39,13 +43,15 @@ public class Plan {
private static final String Y = "y";
private static final String NAME = "name";
private static final String ACTION_PROPS = "openProps";
+ private static final String ACTION_MOVE = "move";
+ private static final String DIRECTION = "direction";
+ private static final String EAST = "east";
+ private static final String WEST = "west";
private HashMap> tiles = new HashMap>();
private Tag actionMenu() throws IOException {
-
- Tag tileMenu = new Tag("div").clazz("actions").content(t("Actions"));
-
+ Tag tileMenu = new Tag("div").clazz("actions").content(t("Actions"));
StringBuffer tiles = new StringBuffer();
tiles.append(new Tag("div").id("save").content(t("Save plan")));
return new Tag("div").clazz("list").content(tiles.toString()).addTo(tileMenu);
@@ -99,13 +105,20 @@ public class Plan {
private Tag menu() throws IOException {
Tag menu = new Tag("div").clazz("menu");
-
- tileMenu().addTo(menu);
actionMenu().addTo(menu);
-
+ moveMenu().addTo(menu);
+ tileMenu().addTo(menu);
return menu;
}
+ private Tag moveMenu() {
+ Tag tileMenu = new Tag("div").clazz("move").title(t("Move tiles")).content(t("↹"));
+ StringBuffer tiles = new StringBuffer();
+ tiles.append(new Tag("div").id("west").title(t("Move west")).content("🢀"));
+ tiles.append(new Tag("div").id("east").title(t("Move east")).content("🢂"));
+ return new Tag("div").clazz("list").content(tiles.toString()).addTo(tileMenu);
+ }
+
public Object process(HashMap params) {
try {
String action = params.get(ACTION);
@@ -115,10 +128,12 @@ public class Plan {
case ACTION_ADD:
Tile tile = addTile(params.get(TILE),params.get(X),params.get(Y));
return t("Added {}",tile.getClass().getSimpleName());
- case ACTION_SAVE:
- return saveTo(params.get(NAME));
+ case ACTION_MOVE:
+ return moveTile(params.get(DIRECTION),params.get(X),params.get(Y));
case ACTION_PROPS:
return Tile.propMenu();
+ case ACTION_SAVE:
+ return saveTo(params.get(NAME));
default:
LOG.warn("Unknown action: {}",action);
}
@@ -128,6 +143,40 @@ public class Plan {
}
}
+ private String moveTile(String direction, String x, String y) throws NumberFormatException, IOException {
+ return moveTile(direction,Integer.parseInt(x),Integer.parseInt(y));
+ }
+
+ private String moveTile(String direction, int x, int y) throws IOException {
+ LOG.debug("moveTile({},{},{})",direction,x,y);
+ Vector moved = null;
+ switch (direction) {
+ case EAST:
+ moved = moveHorizontal(x,y,+1);
+ break;
+ case WEST:
+ moved = moveHorizontal(x,y,-1);
+ break;
+ }
+ if (!moved.isEmpty()) {
+ set(x,y,null);
+ StringBuilder sb = new StringBuilder();
+ for (Tile tile : moved) sb.append(tile.html()+"\n");
+ return sb.toString();
+ }
+ return null;
+ }
+
+ private Vector moveHorizontal(int x, int y,int step) {
+ LOG.debug("moveEast({},{})",x,y);
+ Tile tile = this.get(x, y);
+ if (tile == null) return new Vector();
+ Vector result = moveHorizontal(x+step,y,step);
+ set(x+step, y, tile);
+ result.add(tile);
+ return result;
+ }
+
private String saveTo(String name) throws IOException {
if (name == null || name.isEmpty()) throw new NullPointerException("Name must not be empty!");
File file = new File(name+".plan");
@@ -152,7 +201,7 @@ public class Plan {
tiles.put(x, column);
}
old = column.remove(y);
- if (!(tile instanceof Eraser)) column.put(y,tile.position(x, y));
+ if (tile != null && !(tile instanceof Eraser)) column.put(y,tile.position(x, y));
return old;
}
@@ -161,7 +210,7 @@ public class Plan {
}
private Tag tileMenu() throws IOException {
- Tag tileMenu = new Tag("div").clazz("addtile").content(t("Add tile"));
+ Tag tileMenu = new Tag("div").clazz("addtile").title(t("Add tile")).content("◫");
StringBuffer tiles = new StringBuffer();
tiles.append(new StraightH().html());
@@ -173,7 +222,10 @@ public class Plan {
tiles.append(new EndE().html());
tiles.append(new EndW().html());
tiles.append(new TurnoutSE().html());
+ tiles.append(new TurnoutEN().html());
+ tiles.append(new TurnoutES().html());
tiles.append(new TurnoutWS().html());
+ tiles.append(new TurnoutWN().html());
tiles.append(new TurnoutSW().html());
tiles.append(new Eraser().html());
return new Tag("div").clazz("list").content(tiles.toString()).addTo(tileMenu);