001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.mappaint.mapcss; 003 004import java.util.Arrays; 005 006import org.openstreetmap.josm.gui.mappaint.Cascade; 007import org.openstreetmap.josm.gui.mappaint.Environment; 008import org.openstreetmap.josm.gui.mappaint.Keyword; 009import org.openstreetmap.josm.gui.mappaint.MapPaintStyles; 010import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference; 011import org.openstreetmap.josm.gui.mappaint.StyleKeys; 012 013@FunctionalInterface 014public interface Instruction extends StyleKeys { 015 016 void execute(Environment env); 017 018 class RelativeFloat { 019 public final float val; 020 021 public RelativeFloat(float val) { 022 this.val = val; 023 } 024 025 @Override 026 public String toString() { 027 return "RelativeFloat{" + "val=" + val + '}'; 028 } 029 } 030 031 class AssignmentInstruction implements Instruction { 032 public final String key; 033 public final Object val; 034 public final boolean isSetInstruction; 035 036 public AssignmentInstruction(String key, Object val, boolean isSetInstruction) { 037 this.key = key; 038 this.isSetInstruction = isSetInstruction; 039 if (val instanceof LiteralExpression) { 040 Object litValue = ((LiteralExpression) val).evaluate(null); 041 if (litValue instanceof Keyword && "none".equals(((Keyword) litValue).val)) { 042 this.val = null; 043 } else if (TEXT.equals(key)) { 044 /* Special case for declaration 'text: ...' 045 * 046 * - Treat the value 'auto' as keyword. 047 * - Treat any other literal value 'litval' as as reference to tag with key 'litval' 048 * 049 * - Accept function expressions as is. This allows for 050 * tag(a_tag_name) value of a tag 051 * eval("a static text") a static text 052 * parent_tag(a_tag_name) value of a tag of a parent relation 053 */ 054 if (litValue.equals(Keyword.AUTO)) { 055 this.val = Keyword.AUTO; 056 } else { 057 String s = Cascade.convertTo(litValue, String.class); 058 if (s != null) { 059 this.val = new MapPaintStyles.TagKeyReference(s); 060 } else { 061 this.val = litValue; 062 } 063 } 064 } else { 065 this.val = litValue; 066 } 067 } else { 068 this.val = val; 069 } 070 } 071 072 @Override 073 public void execute(Environment env) { 074 Object value; 075 if (val instanceof Expression) { 076 value = ((Expression) val).evaluate(env); 077 } else { 078 value = val; 079 } 080 if (ICON_IMAGE.equals(key) || FILL_IMAGE.equals(key) || REPEAT_IMAGE.equals(key)) { 081 if (value instanceof String) { 082 value = new IconReference((String) value, env.source); 083 } 084 } 085 env.mc.getOrCreateCascade(env.layer).putOrClear(key, value); 086 } 087 088 @Override 089 public String toString() { 090 return key + ": " + (val instanceof float[] ? Arrays.toString((float[]) val) : 091 (val instanceof String ? ("String<"+val+'>') : val)) + ';'; 092 } 093 } 094}