refactored tiles data structure in plan
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -4,7 +4,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>de.srsoftware</groupId>
|
<groupId>de.srsoftware</groupId>
|
||||||
<artifactId>web4rail</artifactId>
|
<artifactId>web4rail</artifactId>
|
||||||
<version>0.3.5</version>
|
<version>0.3.6</version>
|
||||||
<name>Web4Rail</name>
|
<name>Web4Rail</name>
|
||||||
<description>Java Model Railway Control</description>
|
<description>Java Model Railway Control</description>
|
||||||
<url>https://github.com/StephanRichter/Web4Rail</url>
|
<url>https://github.com/StephanRichter/Web4Rail</url>
|
||||||
|
|||||||
@@ -24,8 +24,9 @@ function addTile(x,y){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function clickTile(x,y){
|
function clickTile(x,y){
|
||||||
console.log("clickTile:",x,y);
|
var id = x+"-"+y;
|
||||||
if ($('#tile-'+x+'-'+y).length > 0) request({action:'click',x:x,y:y});
|
console.log("clickTile:",id);
|
||||||
|
if ($('#'+id).length > 0) request({action:'click',id:id});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,8 +85,9 @@ function heartbeat(data){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function moveTile(x,y){
|
function moveTile(x,y){
|
||||||
console.log("moveTile:",selected.id,x,y);
|
var id = x+"-"+y;
|
||||||
return request({action:mode,direction:selected.id,x:x,y:y});
|
console.log("moveTile:",selected.id,id);
|
||||||
|
return request({action:mode,direction:selected.id,id:id});
|
||||||
}
|
}
|
||||||
|
|
||||||
function openRoute(id){
|
function openRoute(id){
|
||||||
@@ -153,6 +155,7 @@ function train(id,mode){
|
|||||||
|
|
||||||
function stream(ev){
|
function stream(ev){
|
||||||
var data = ev.data;
|
var data = ev.data;
|
||||||
|
console.log("received: ",data);
|
||||||
if (data.startsWith("heartbeat")) return heartbeat(data);
|
if (data.startsWith("heartbeat")) return heartbeat(data);
|
||||||
if (data.startsWith("place ")) return place(data.substring(6));
|
if (data.startsWith("place ")) return place(data.substring(6));
|
||||||
if (data.startsWith("remove")) return remove(data.substring(7));
|
if (data.startsWith("remove")) return remove(data.substring(7));
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class Plan {
|
|||||||
private static final HashMap<OutputStreamWriter,Integer> clients = new HashMap<OutputStreamWriter, Integer>();
|
private static final HashMap<OutputStreamWriter,Integer> clients = new HashMap<OutputStreamWriter, Integer>();
|
||||||
private static final String ACTION_TRAIN = "train";
|
private static final String ACTION_TRAIN = "train";
|
||||||
|
|
||||||
public HashMap<Integer,HashMap<Integer,Tile>> tiles = new HashMap<Integer,HashMap<Integer,Tile>>();
|
public HashMap<String,Tile> tiles = new HashMap<String,Tile>();
|
||||||
private HashSet<Block> blocks = new HashSet<Block>();
|
private HashSet<Block> blocks = new HashSet<Block>();
|
||||||
private HashMap<String, Route> routes = new HashMap<String, Route>();
|
private HashMap<String, Route> routes = new HashMap<String, Route>();
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ public class Plan {
|
|||||||
clazz = tc.getName().replace(".Tile", "."+clazz);
|
clazz = tc.getName().replace(".Tile", "."+clazz);
|
||||||
Tile tile = (Tile) tc.getClassLoader().loadClass(clazz).getDeclaredConstructor().newInstance();
|
Tile tile = (Tile) tc.getClassLoader().loadClass(clazz).getDeclaredConstructor().newInstance();
|
||||||
if (tile instanceof Eraser) {
|
if (tile instanceof Eraser) {
|
||||||
Tile erased = get(x,y,true);
|
Tile erased = get(Tile.id(x,y),true);
|
||||||
remove(erased);
|
remove(erased);
|
||||||
return erased == null ? null : t("Removed {}.",erased);
|
return erased == null ? null : t("Removed {}.",erased);
|
||||||
}
|
}
|
||||||
@@ -154,9 +154,7 @@ public class Plan {
|
|||||||
for (Connector con : block.startPoints()) routes.addAll(follow(new Route().start(block,con.from.inverse()),con));
|
for (Connector con : block.startPoints()) routes.addAll(follow(new Route().start(block,con.from.inverse()),con));
|
||||||
}
|
}
|
||||||
this.routes.clear();
|
this.routes.clear();
|
||||||
for (HashMap<Integer, Tile> column: tiles.values()) {
|
for (Tile tile : tiles.values()) tile.routes().clear();
|
||||||
for (Tile tile : column.values()) tile.routes().clear();
|
|
||||||
}
|
|
||||||
for (Route route : routes) {
|
for (Route route : routes) {
|
||||||
route.complete();
|
route.complete();
|
||||||
registerRoute(route);
|
registerRoute(route);
|
||||||
@@ -174,7 +172,7 @@ public class Plan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Collection<Route> follow(Route route, Connector connector) {
|
private Collection<Route> follow(Route route, Connector connector) {
|
||||||
Tile tile = get(connector.x,connector.y,false);
|
Tile tile = get(Tile.id(connector.x,connector.y),false);
|
||||||
Vector<Route> results = new Vector<>();
|
Vector<Route> results = new Vector<>();
|
||||||
if (tile == null) return results;
|
if (tile == null) return results;
|
||||||
Tile addedTile = route.add(tile,connector.from);
|
Tile addedTile = route.add(tile,connector.from);
|
||||||
@@ -183,7 +181,7 @@ public class Plan {
|
|||||||
LOG.debug("Found {}, coming from {}.",addedTile,connector.from);
|
LOG.debug("Found {}, coming from {}.",addedTile,connector.from);
|
||||||
for (Connector con : cons.keySet()) { // falls direkt nach dem Block noch ein Kontakt kommt: diesen mit zu Route hinzufügen
|
for (Connector con : cons.keySet()) { // falls direkt nach dem Block noch ein Kontakt kommt: diesen mit zu Route hinzufügen
|
||||||
LOG.debug("This is connected to {}",con);
|
LOG.debug("This is connected to {}",con);
|
||||||
Tile nextTile = get(con.x,con.y,false);
|
Tile nextTile = get(Tile.id(con.x,con.y),false);
|
||||||
if (nextTile instanceof Contact) {
|
if (nextTile instanceof Contact) {
|
||||||
LOG.debug("{} is followed by {}",addedTile,nextTile);
|
LOG.debug("{} is followed by {}",addedTile,nextTile);
|
||||||
route.add(nextTile, con.from);
|
route.add(nextTile, con.from);
|
||||||
@@ -208,13 +206,8 @@ public class Plan {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tile get(String x, String y,boolean resolveShadows) {
|
public Tile get(String tileId,boolean resolveShadows) {
|
||||||
return get(Integer.parseInt(x),Integer.parseInt(y),resolveShadows);
|
Tile tile = tiles.get(tileId);
|
||||||
}
|
|
||||||
|
|
||||||
public Tile get(int x, int y,boolean resolveShadows) {
|
|
||||||
HashMap<Integer, Tile> column = tiles.get(x);
|
|
||||||
Tile tile = (column == null) ? null : column.get(y);
|
|
||||||
if (resolveShadows && tile instanceof Shadow) tile = ((Shadow)tile).overlay();
|
if (resolveShadows && tile instanceof Shadow) tile = ((Shadow)tile).overlay();
|
||||||
return tile;
|
return tile;
|
||||||
}
|
}
|
||||||
@@ -229,14 +222,9 @@ public class Plan {
|
|||||||
|
|
||||||
public Page html() throws IOException {
|
public Page html() throws IOException {
|
||||||
Page page = new Page().append("<div id=\"plan\">");
|
Page page = new Page().append("<div id=\"plan\">");
|
||||||
for (Entry<Integer, HashMap<Integer, Tile>> column : tiles.entrySet()) {
|
for (Tile tile: tiles.values()) {
|
||||||
int x = column.getKey();
|
if (tile == null) continue;
|
||||||
for (Entry<Integer, Tile> row : column.getValue().entrySet()) {
|
page.append("\t\t"+tile.tag(null)+"\n");
|
||||||
int y = row.getKey();
|
|
||||||
Tile tile = row.getValue().position(x, y);
|
|
||||||
if (tile == null) continue;
|
|
||||||
page.append("\t\t"+tile.tag(null)+"\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return page
|
return page
|
||||||
.append(menu())
|
.append(menu())
|
||||||
@@ -281,54 +269,54 @@ public class Plan {
|
|||||||
return new Tag("div").clazz("list").content(tiles.toString()).addTo(tileMenu);
|
return new Tag("div").clazz("list").content(tiles.toString()).addTo(tileMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String moveTile(String direction, String x, String y) throws NumberFormatException, IOException {
|
private String moveTile(String direction, String tileId) throws NumberFormatException, IOException {
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case "south":
|
case "south":
|
||||||
return moveTile(Direction.SOUTH,Integer.parseInt(x),Integer.parseInt(y));
|
return moveTile(get(tileId,false),Direction.SOUTH);
|
||||||
case "north":
|
case "north":
|
||||||
return moveTile(Direction.NORTH,Integer.parseInt(x),Integer.parseInt(y));
|
return moveTile(get(tileId,false),Direction.NORTH);
|
||||||
case "east":
|
case "east":
|
||||||
return moveTile(Direction.EAST,Integer.parseInt(x),Integer.parseInt(y));
|
return moveTile(get(tileId,false),Direction.EAST);
|
||||||
case "west":
|
case "west":
|
||||||
return moveTile(Direction.WEST,Integer.parseInt(x),Integer.parseInt(y));
|
return moveTile(get(tileId,false),Direction.WEST);
|
||||||
}
|
}
|
||||||
throw new InvalidParameterException(t("\"{}\" is not a known direction!"));
|
throw new InvalidParameterException(t("\"{}\" is not a known direction!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String moveTile(Direction direction, int x, int y) throws IOException {
|
private String moveTile(Tile tile, Direction direction) throws IOException {
|
||||||
//LOG.debug("moveTile({},{},{})",direction,x,y);
|
|
||||||
boolean moved = false;
|
boolean moved = false;
|
||||||
switch (direction) {
|
if (tile != null) {
|
||||||
case EAST:
|
LOG.debug("moveTile({},{},{})",direction,tile.x,tile.y);
|
||||||
moved = moveTile(x,y,+1,0);
|
switch (direction) {
|
||||||
break;
|
case EAST:
|
||||||
case WEST:
|
moved = moveTile(tile,+1,0);
|
||||||
moved = moveTile(x,y,-1,0);
|
break;
|
||||||
break;
|
case WEST:
|
||||||
case NORTH:
|
moved = moveTile(tile,-1,0);
|
||||||
moved = moveTile(x,y,0,-1);
|
break;
|
||||||
break;
|
case NORTH:
|
||||||
case SOUTH:
|
moved = moveTile(tile,0,-1);
|
||||||
moved = moveTile(x,y,0,+1);
|
break;
|
||||||
break;
|
case SOUTH:
|
||||||
|
moved = moveTile(tile,0,+1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return t(moved ? "Tile(s) moved.":"No tile(s) moved.");
|
return t(moved ? "Tile(s) moved.":"No tile(s) moved.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean moveTile(int x, int y,int xstep,int ystep) throws IOException {
|
private boolean moveTile(Tile tile,int xstep,int ystep) throws IOException {
|
||||||
LOG.error("moveTile({}+ {},{}+ {})",x,xstep,y,ystep);
|
LOG.error("moveTile({} +{}/+{})",tile,xstep,ystep);
|
||||||
Stack<Tile> stack = new Stack<Tile>();
|
Stack<Tile> stack = new Stack<Tile>();
|
||||||
Tile tile = get(x,y,false);
|
|
||||||
while (tile != null) {
|
while (tile != null) {
|
||||||
LOG.debug("scheduling tile for movement: {} @ {},{}",tile,x,y);
|
LOG.debug("scheduling tile for movement: {}",tile);
|
||||||
stack.add(tile);
|
stack.add(tile);
|
||||||
x+=xstep;
|
tile = get(Tile.id(tile.x+xstep, tile.y+ystep),false);
|
||||||
y+=ystep;
|
|
||||||
tile = get(x,y,false);
|
|
||||||
}
|
}
|
||||||
while (!stack.isEmpty()) {
|
while (!stack.isEmpty()) {
|
||||||
tile = stack.pop();
|
tile = stack.pop();
|
||||||
if (!(tile instanceof Shadow)) {
|
if (!(tile instanceof Shadow)) {
|
||||||
|
LOG.debug("altering position of {}",tile);
|
||||||
remove(tile);
|
remove(tile);
|
||||||
set(tile.x+xstep,tile.y+ystep,tile);
|
set(tile.x+xstep,tile.y+ystep,tile);
|
||||||
}
|
}
|
||||||
@@ -349,11 +337,11 @@ public class Plan {
|
|||||||
case ACTION_ADD:
|
case ACTION_ADD:
|
||||||
return addTile(params.get(TILE),params.get(X),params.get(Y),null);
|
return addTile(params.get(TILE),params.get(X),params.get(Y),null);
|
||||||
case ACTION_CLICK:
|
case ACTION_CLICK:
|
||||||
return click(get(params.get(X),params.get(Y),true));
|
return click(get(params.get(Tile.ID),true));
|
||||||
case ACTION_ANALYZE:
|
case ACTION_ANALYZE:
|
||||||
return analyze();
|
return analyze();
|
||||||
case ACTION_MOVE:
|
case ACTION_MOVE:
|
||||||
return moveTile(params.get(DIRECTION),params.get(X),params.get(Y));
|
return moveTile(params.get(DIRECTION),params.get(Tile.ID));
|
||||||
case ACTION_ROUTE:
|
case ACTION_ROUTE:
|
||||||
return routeProperties(params.get(ID));
|
return routeProperties(params.get(ID));
|
||||||
case ACTION_SAVE:
|
case ACTION_SAVE:
|
||||||
@@ -395,12 +383,11 @@ public class Plan {
|
|||||||
if (tile instanceof Block) blocks.remove(tile);
|
if (tile instanceof Block) blocks.remove(tile);
|
||||||
for (int i=1; i<tile.len(); i++) remove_intern(tile.x+i, tile.y); // remove shadow tiles
|
for (int i=1; i<tile.len(); i++) remove_intern(tile.x+i, tile.y); // remove shadow tiles
|
||||||
for (int i=1; i<tile.height(); i++) remove_intern(tile.x, tile.y+i); // remove shadow tiles
|
for (int i=1; i<tile.height(); i++) remove_intern(tile.x, tile.y+i); // remove shadow tiles
|
||||||
if (tile != null) stream("remove tile-"+tile.x+"-"+tile.y);
|
if (tile != null) stream("remove "+tile.id());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void remove_intern(int x, int y) {
|
private void remove_intern(int x, int y) {
|
||||||
HashMap<Integer, Tile> column = tiles.get(x);
|
LOG.debug("removed {} from tile list",tiles.remove(Tile.id(x, y)));
|
||||||
if (column != null) column.remove(y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String saveTo(String name) throws IOException {
|
private String saveTo(String name) throws IOException {
|
||||||
@@ -422,13 +409,8 @@ public class Plan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void set_intern(int x, int y, Tile tile) {
|
private void set_intern(int x, int y, Tile tile) {
|
||||||
HashMap<Integer, Tile> column = tiles.get(x);
|
|
||||||
if (column == null) {
|
|
||||||
column = new HashMap<Integer, Tile>();
|
|
||||||
tiles.put(x,column);
|
|
||||||
}
|
|
||||||
tile.position(x, y).plan(this);
|
tile.position(x, y).plan(this);
|
||||||
column.put(y,tile);
|
tiles.put(tile.id(),tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void stream(String data) {
|
public synchronized void stream(String data) {
|
||||||
@@ -510,7 +492,7 @@ public class Plan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void update(int x,int y, HashMap<String, String> params) throws IOException {
|
private void update(int x,int y, HashMap<String, String> params) throws IOException {
|
||||||
Tile tile = get(x,y,true);
|
Tile tile = get(Tile.id(x, y),true);
|
||||||
if (tile != null) set(x,y,tile.update(params));
|
if (tile != null) set(x,y,tile.update(params));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package de.srsoftware.web4rail;
|
package de.srsoftware.web4rail;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.FileReader;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -35,7 +37,6 @@ import de.srsoftware.web4rail.tiles.Turnout.State;
|
|||||||
public class Route {
|
public class Route {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Route.class);
|
private static final Logger LOG = LoggerFactory.getLogger(Route.class);
|
||||||
static final String NAME = "name";
|
static final String NAME = "name";
|
||||||
private static final HashMap<String,String> names = new HashMap<String, String>();
|
|
||||||
static final String PATH = "path";
|
static final String PATH = "path";
|
||||||
static final String SIGNALS = "signals";
|
static final String SIGNALS = "signals";
|
||||||
static final String TURNOUTS = "turnouts";
|
static final String TURNOUTS = "turnouts";
|
||||||
@@ -45,6 +46,7 @@ public class Route {
|
|||||||
private HashMap<Turnout,Turnout.State> turnouts;
|
private HashMap<Turnout,Turnout.State> turnouts;
|
||||||
private HashMap<Object,Vector<Action>> triggers = new HashMap<Object, Vector<Action>>();
|
private HashMap<Object,Vector<Action>> triggers = new HashMap<Object, Vector<Action>>();
|
||||||
private String id;
|
private String id;
|
||||||
|
private String name;
|
||||||
public Train train;
|
public Train train;
|
||||||
private Block startBlock = null,endBlock;
|
private Block startBlock = null,endBlock;
|
||||||
public Direction startDirection;
|
public Direction startDirection;
|
||||||
@@ -190,14 +192,29 @@ public class Route {
|
|||||||
}
|
}
|
||||||
props.put(TURNOUTS, turnouts);
|
props.put(TURNOUTS, turnouts);
|
||||||
|
|
||||||
if (names.containsKey(id())) props.put(NAME, names.get(id));
|
if (name != null) props.put(NAME, name);
|
||||||
|
|
||||||
return props.toString();
|
return props.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadAll(String string, Plan plan) {
|
private Route load(JSONObject json,Plan plan) {
|
||||||
// TODO Auto-generated method stub
|
JSONArray pathIds = json.getJSONArray(PATH);
|
||||||
|
for (Object tileId : pathIds) {
|
||||||
|
plan.get((String) tileId,false);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void loadAll(String filename, Plan plan) throws IOException {
|
||||||
|
BufferedReader file = new BufferedReader(new FileReader(filename));
|
||||||
|
String line = file.readLine();
|
||||||
|
while (line != null) {
|
||||||
|
JSONObject json = new JSONObject(line);
|
||||||
|
new Route().load(json,plan);
|
||||||
|
|
||||||
|
line = file.readLine();
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Route lock(Train train) throws IOException {
|
public Route lock(Train train) throws IOException {
|
||||||
@@ -216,14 +233,11 @@ public class Route {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String name() {
|
public String name() {
|
||||||
String name = names.get(id());
|
|
||||||
return name == null ? id() : name;
|
return name == null ? id() : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void name(String name) {
|
public void name(String name) {
|
||||||
if (name.isEmpty()) {
|
this.name = name;
|
||||||
names.remove(id());
|
|
||||||
} else names.put(id(),name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector<Tile> path() {
|
public Vector<Tile> path() {
|
||||||
|
|||||||
@@ -96,7 +96,11 @@ public abstract class Tile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String id() {
|
public String id() {
|
||||||
return x+":"+y;
|
return Tile.id(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String id(int x, int y) {
|
||||||
|
return x+"-"+y;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void inflate(String clazz, JSONObject json, Plan plan) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException, IOException {
|
private static void inflate(String clazz, JSONObject json, Plan plan) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException, IOException {
|
||||||
@@ -237,14 +241,11 @@ public abstract class Tile {
|
|||||||
return routes;
|
return routes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void saveAll(HashMap<Integer, HashMap<Integer, Tile>> tiles ,String filename) throws IOException {
|
public static void saveAll(HashMap<String, Tile> tiles ,String filename) throws IOException {
|
||||||
BufferedWriter file = new BufferedWriter(new FileWriter(filename));
|
BufferedWriter file = new BufferedWriter(new FileWriter(filename));
|
||||||
for (Entry<Integer, HashMap<Integer, Tile>> column : tiles.entrySet()) {
|
for (Tile tile : tiles.values()) {
|
||||||
for (Entry<Integer, Tile> row : column.getValue().entrySet()) {
|
if (tile == null || tile instanceof Shadow) continue;
|
||||||
Tile tile = row.getValue();
|
file.append(tile.json()+"\n");
|
||||||
if (tile == null || tile instanceof Shadow) continue;
|
|
||||||
file.append(tile.json()+"\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
@@ -261,7 +262,7 @@ public abstract class Tile {
|
|||||||
replacements.put("%height%",height);
|
replacements.put("%height%",height);
|
||||||
String style = "";
|
String style = "";
|
||||||
Tag svg = new Tag("svg")
|
Tag svg = new Tag("svg")
|
||||||
.id((x!=-1 && y!=-1)?("tile-"+x+"-"+y):(getClass().getSimpleName()))
|
.id((x!=-1 && y!=-1)?(id()):(getClass().getSimpleName()))
|
||||||
.clazz(classes())
|
.clazz(classes())
|
||||||
.size(100,100)
|
.size(100,100)
|
||||||
.attr("name", getClass().getSimpleName())
|
.attr("name", getClass().getSimpleName())
|
||||||
|
|||||||
Reference in New Issue
Block a user