@@ -17,6 +17,7 @@ import com.google.gwt.json.client.JSONArray; | |||
import com.google.gwt.json.client.JSONObject; | |||
import com.google.gwt.json.client.JSONString; | |||
import com.vaadin.terminal.gwt.client.ApplicationConnection; | |||
import com.vaadin.terminal.gwt.client.Connector; | |||
import com.vaadin.terminal.gwt.client.ConnectorMap; | |||
import com.vaadin.terminal.gwt.client.ServerConnector; | |||
@@ -63,6 +64,8 @@ public class JsonDecoder { | |||
val = decodeArray((JSONArray) value, idMapper, connection); | |||
} else if (JsonEncoder.VTYPE_MAP.equals(variableType)) { | |||
val = decodeMap((JSONObject) value, idMapper, connection); | |||
} else if (JsonEncoder.VTYPE_MAP_CONNECTOR.equals(variableType)) { | |||
val = decodeConnectorMap((JSONObject) value, idMapper, connection); | |||
} else if (JsonEncoder.VTYPE_LIST.equals(variableType)) { | |||
val = decodeList((JSONArray) value, idMapper, connection); | |||
} else if (JsonEncoder.VTYPE_SET.equals(variableType)) { | |||
@@ -114,6 +117,21 @@ public class JsonDecoder { | |||
return map; | |||
} | |||
private static Map<Connector, Object> decodeConnectorMap( | |||
JSONObject jsonMap, ConnectorMap idMapper, | |||
ApplicationConnection connection) { | |||
HashMap<Connector, Object> map = new HashMap<Connector, Object>(); | |||
Iterator<String> it = jsonMap.keySet().iterator(); | |||
while (it.hasNext()) { | |||
String connectorId = it.next(); | |||
Connector connector = idMapper.getConnector(connectorId); | |||
map.put(connector, | |||
decodeValue((JSONArray) jsonMap.get(connectorId), idMapper, | |||
connection)); | |||
} | |||
return map; | |||
} | |||
private static String[] decodeStringArray(JSONArray jsonArray) { | |||
int size = jsonArray.size(); | |||
List<String> tokens = new ArrayList<String>(size); |
@@ -42,6 +42,10 @@ public class JsonEncoder { | |||
public static final String VTYPE_ARRAY = "a"; | |||
public static final String VTYPE_STRINGARRAY = "S"; | |||
public static final String VTYPE_MAP = "m"; | |||
// Hack to support Map<Connector,?>. Should be replaced by generic support | |||
// for any object as key (#8602) | |||
@Deprecated | |||
public static final String VTYPE_MAP_CONNECTOR = "M"; | |||
public static final String VTYPE_LIST = "L"; | |||
public static final String VTYPE_SET = "q"; | |||
public static final String VTYPE_NULL = "n"; | |||
@@ -77,14 +81,26 @@ public class JsonEncoder { | |||
} else if (value instanceof Object[]) { | |||
return encodeObjectArray((Object[]) value, connectorMap, connection); | |||
} else if (value instanceof Map) { | |||
Map<String, Object> map = (Map<String, Object>) value; | |||
Map<Object, Object> map = (Map<Object, Object>) value; | |||
JSONObject jsonMap = new JSONObject(); | |||
for (String mapKey : map.keySet()) { | |||
// TODO handle object graph loops? | |||
String type = VTYPE_MAP; | |||
for (Object mapKey : map.keySet()) { | |||
Object mapValue = map.get(mapKey); | |||
jsonMap.put(mapKey, encode(mapValue, connectorMap, connection)); | |||
if (mapKey instanceof Connector) { | |||
mapKey = ((Connector) mapKey).getConnectorId(); | |||
type = VTYPE_MAP_CONNECTOR; | |||
} | |||
if (!(mapKey instanceof String)) { | |||
throw new RuntimeException( | |||
"Only Map<String,?> and Map<Connector,?> is currently supported." | |||
+ " Failed map used " | |||
+ mapKey.getClass().getName() + " as keys"); | |||
} | |||
jsonMap.put((String) mapKey, | |||
encode(mapValue, connectorMap, connection)); | |||
} | |||
return combineTypeAndValue(VTYPE_MAP, jsonMap); | |||
return combineTypeAndValue(type, jsonMap); | |||
} else if (value instanceof Connector) { | |||
Connector connector = (Connector) value; | |||
return combineTypeAndValue(VTYPE_CONNECTOR, new JSONString( |
@@ -12,6 +12,7 @@ import com.google.gwt.user.client.Element; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.vaadin.terminal.gwt.client.BrowserInfo; | |||
import com.vaadin.terminal.gwt.client.ComponentConnector; | |||
import com.vaadin.terminal.gwt.client.Connector; | |||
import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent; | |||
import com.vaadin.terminal.gwt.client.Util; | |||
import com.vaadin.terminal.gwt.client.VCaption; | |||
@@ -25,13 +26,13 @@ import com.vaadin.ui.CssLayout; | |||
public class CssLayoutConnector extends AbstractLayoutConnector { | |||
public static class CssLayoutState extends AbstractLayoutState { | |||
private Map<String, String> childCss = new HashMap<String, String>(); | |||
private Map<Connector, String> childCss = new HashMap<Connector, String>(); | |||
public Map<String, String> getChildCss() { | |||
public Map<Connector, String> getChildCss() { | |||
return childCss; | |||
} | |||
public void setChildCss(Map<String, String> childCss) { | |||
public void setChildCss(Map<Connector, String> childCss) { | |||
this.childCss = childCss; | |||
} | |||
@@ -79,10 +80,10 @@ public class CssLayoutConnector extends AbstractLayoutConnector { | |||
new VMarginInfo(getState().getMarginsBitmask())); | |||
for (ComponentConnector child : getChildren()) { | |||
if (!getState().getChildCss().containsKey(child.getConnectorId())) { | |||
if (!getState().getChildCss().containsKey(child)) { | |||
continue; | |||
} | |||
String css = getState().getChildCss().get(child.getConnectorId()); | |||
String css = getState().getChildCss().get(child); | |||
Style style = child.getWidget().getElement().getStyle(); | |||
// should we remove styles also? How can we know what we have added | |||
// as it is added directly to the child component? |
@@ -90,6 +90,8 @@ public class JsonCodec implements Serializable { | |||
val = decodeList((JSONArray) value, application); | |||
} else if (JsonEncoder.VTYPE_SET.equals(variableType)) { | |||
val = decodeSet((JSONArray) value, application); | |||
} else if (JsonEncoder.VTYPE_MAP_CONNECTOR.equals(variableType)) { | |||
val = decodeConnectorMap((JSONObject) value, application); | |||
} else if (JsonEncoder.VTYPE_MAP.equals(variableType)) { | |||
val = decodeMap((JSONObject) value, application); | |||
} else if (JsonEncoder.VTYPE_STRINGARRAY.equals(variableType)) { | |||
@@ -135,6 +137,19 @@ public class JsonCodec implements Serializable { | |||
return map; | |||
} | |||
private static Object decodeConnectorMap(JSONObject jsonMap, | |||
Application application) throws JSONException { | |||
HashMap<Connector, Object> map = new HashMap<Connector, Object>(); | |||
Iterator<String> it = jsonMap.keys(); | |||
while (it.hasNext()) { | |||
String connectorId = it.next(); | |||
Connector connector = application.getConnector(connectorId); | |||
map.put(connector, | |||
decode(jsonMap.getJSONArray(connectorId), application)); | |||
} | |||
return map; | |||
} | |||
private static String[] decodeStringArray(JSONArray jsonArray) | |||
throws JSONException { | |||
int length = jsonArray.length(); | |||
@@ -227,7 +242,14 @@ public class JsonCodec implements Serializable { | |||
} else if (value instanceof Map) { | |||
Map<Object, Object> map = (Map<Object, Object>) value; | |||
JSONObject jsonMap = encodeMapContents(map, application); | |||
return combineTypeAndValue(JsonEncoder.VTYPE_MAP, jsonMap); | |||
// Hack to support Connector as map key. Should be fixed by # | |||
if (!map.isEmpty() | |||
&& map.keySet().iterator().next() instanceof Connector) { | |||
return combineTypeAndValue(JsonEncoder.VTYPE_MAP_CONNECTOR, | |||
jsonMap); | |||
} else { | |||
return combineTypeAndValue(JsonEncoder.VTYPE_MAP, jsonMap); | |||
} | |||
} else if (value instanceof Connector) { | |||
Connector connector = (Connector) value; | |||
return combineTypeAndValue(JsonEncoder.VTYPE_CONNECTOR, | |||
@@ -328,12 +350,16 @@ public class JsonCodec implements Serializable { | |||
Application application) throws JSONException { | |||
JSONObject jsonMap = new JSONObject(); | |||
for (Object mapKey : map.keySet()) { | |||
Object mapValue = map.get(mapKey); | |||
if (mapKey instanceof ClientConnector) { | |||
mapKey = ((ClientConnector) mapKey).getConnectorId(); | |||
} | |||
if (!(mapKey instanceof String)) { | |||
throw new JSONException( | |||
"Only maps with String keys are currently supported (#8602)"); | |||
"Only maps with String/Connector keys are currently supported (#8602)"); | |||
} | |||
Object mapValue = map.get(mapKey); | |||
jsonMap.put((String) mapKey, encode(mapValue, application)); | |||
} | |||
return jsonMap; |
@@ -11,7 +11,6 @@ import com.vaadin.event.LayoutEvents.LayoutClickListener; | |||
import com.vaadin.event.LayoutEvents.LayoutClickNotifier; | |||
import com.vaadin.terminal.gwt.client.Connector; | |||
import com.vaadin.terminal.gwt.client.MouseEventDetails; | |||
import com.vaadin.terminal.gwt.client.ui.CssLayoutConnector; | |||
import com.vaadin.terminal.gwt.client.ui.CssLayoutConnector.CssLayoutServerRPC; | |||
import com.vaadin.terminal.gwt.client.ui.CssLayoutConnector.CssLayoutState; | |||
import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler; | |||
@@ -189,8 +188,7 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier { | |||
for (Component child : this) { | |||
String componentCssString = getCss(child); | |||
if (componentCssString != null) { | |||
getState().getChildCss().put(child.getConnectorId(), | |||
componentCssString); | |||
getState().getChildCss().put(child, componentCssString); | |||
} | |||
} |