VPaintable paintable = paintableMap
.getPaintable(paintableId);
if (null != paintable) {
- // TODO handle as a ValueMap or similar object and
- // native JavaScript processing?
- JavaScriptObject value = states
- .getJavaScriptObject(paintableId);
- // TODO implement with shared state subclasses
- SharedState state = GWT.create(SharedState.class);
- Map<String, Object> stateMap = (Map<String, Object>) JsonDecoder
- .convertValue(new JSONArray(value),
- getPaintableMap());
- state.setState(stateMap);
- paintable.updateState(state);
+
+ JSONArray stateDataAndType = new JSONArray(
+ states.getJavaScriptObject(paintableId));
+
+ Object state = JsonDecoder.deserialize(
+ stateDataAndType, paintableMap);
+
+ paintable.setState((SharedState) state);
}
} catch (final Throwable e) {
VConsole.error(e);
SharedState state = paintable.getState();
String w = "";
String h = "";
- if (null != state) {
+ if (null != state || !(state instanceof ComponentState)) {
+ ComponentState componentState = (ComponentState) state;
// TODO move logging to VUIDLBrowser and VDebugConsole
- VConsole.log("Paintable state for "
- + getPaintableMap().getPid(paintable) + ": "
- + String.valueOf(state.getState()));
- if (state.getState().containsKey(ComponentState.STATE_WIDTH)) {
- w = String.valueOf(state.getState().get(
- ComponentState.STATE_WIDTH));
- }
- if (state.getState().containsKey(ComponentState.STATE_HEIGHT)) {
- h = String.valueOf(state.getState().get(
- ComponentState.STATE_HEIGHT));
- }
+ // VConsole.log("Paintable state for "
+ // + getPaintableMap().getPid(paintable) + ": "
+ // + String.valueOf(state.getState()));
+ h = componentState.getHeight();
+ w = componentState.getWidth();
} else {
// TODO move logging to VUIDLBrowser and VDebugConsole
VConsole.log("No state for paintable "
* @since 7.0
*/
public class ComponentState extends SharedState {
+ private String height = "";
+ private String width = "";
+
// TODO more javadoc
+ public String getHeight() {
+ if (height == null) {
+ return "";
+ }
+ return height;
+ }
+
+ public void setHeight(String height) {
+ this.height = height;
+ }
+
+ public boolean isUndefinedHeight() {
+ return "".equals(getHeight());
+ }
+
+ public String getWidth() {
+ if (width == null) {
+ return "";
+ }
+ return width;
+ }
+
+ public void setWidth(String width) {
+ this.width = width;
+ }
+
+ public boolean isUndefinedWidth() {
+ return "".equals(getWidth());
+ }
+
// TODO constants for the state attributes for now
- public static final String STATE_HEIGHT = "height";
- public static final String STATE_WIDTH = "width";
public static final String STATE_STYLE = "style";
public static final String STATE_READONLY = "readonly";
public static final String STATE_IMMEDIATE = "immediate";
--- /dev/null
+package com.vaadin.terminal.gwt.client;\r
+\r
+import com.google.gwt.core.client.GWT;\r
+import com.google.gwt.json.client.JSONArray;\r
+import com.google.gwt.json.client.JSONObject;\r
+import com.vaadin.terminal.gwt.client.communication.JsonDecoder;\r
+import com.vaadin.terminal.gwt.client.communication.VaadinSerializer;\r
+\r
+//TODO This should be autogenerated\r
+public class ComponentState_Serializer implements VaadinSerializer {\r
+\r
+ public ComponentState deserialize(JSONObject jsonValue,\r
+ VPaintableMap idMapper) {\r
+ ComponentState state = GWT.create(ComponentState.class);\r
+\r
+ // For (Field f : fields) {\r
+ // state.setState((Map<String, Object>)\r
+ // JsonDecoder.convertMap(jsonValue,\r
+ // idMapper));\r
+ JSONArray jsonHeight = (JSONArray) jsonValue.get("height");\r
+ state.setHeight((String) JsonDecoder.convertValue(jsonHeight, idMapper));\r
+\r
+ JSONArray jsonWidth = (JSONArray) jsonValue.get("width");\r
+ state.setWidth((String) JsonDecoder.convertValue(jsonWidth, idMapper));\r
+\r
+ return state;\r
+ }\r
+}\r
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize;
import com.vaadin.terminal.gwt.client.communication.MethodInvocation;
-import com.vaadin.terminal.gwt.client.communication.SharedState;
public class Util {
* @param state
* @return
*/
- public static FloatSize parseRelativeSize(SharedState state) {
- if (null == state) {
+ public static FloatSize parseRelativeSize(ComponentState state) {
+ if (state.isUndefinedHeight() && state.isUndefinedWidth()) {
return null;
}
- boolean hasAttribute = false;
- String w = "";
- String h = "";
- Map<String, Object> stateMap = state.getState();
- if (stateMap.containsKey("width")) {
- hasAttribute = true;
- w = String.valueOf(stateMap.get("width"));
- }
- if (stateMap.containsKey("height")) {
- hasAttribute = true;
- h = String.valueOf(stateMap.get("height"));
- }
-
- if (!hasAttribute) {
- return null;
- }
-
- float relativeWidth = Util.parseRelativeSize(w);
- float relativeHeight = Util.parseRelativeSize(h);
+ float relativeWidth = Util.parseRelativeSize(state.getWidth());
+ float relativeHeight = Util.parseRelativeSize(state.getHeight());
FloatSize relativeSize = new FloatSize(relativeWidth, relativeHeight);
return relativeSize;
public void updateFromUIDL(UIDL uidl, ApplicationConnection client);
/**
- * Sets the shared state for the paintable.
+ * Gets the current shared state of the paintable.
*
- * @param state
+ * @return state
*/
- public void updateState(SharedState state);
+ public SharedState getState();
/**
- * Gets the current shared state of the paintable.
+ * Sets a new state for the paintable.
+ *
+ * @param state
+ * The new state
*
- * @return state
*/
- public SharedState getState();
+ public void setState(SharedState state);
/**
* Returns the id for this VPaintable. This must always be what has been set
*/
public interface VPaintableWidget extends VPaintable {
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.terminal.gwt.client.VPaintable#getState()
+ */
+ public ComponentState getState();
+
/**
* TODO: Rename to getWidget
*/
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import com.google.gwt.core.client.GWT;
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.ComponentState_Serializer;
import com.vaadin.terminal.gwt.client.VPaintable;
import com.vaadin.terminal.gwt.client.VPaintableMap;
} else if (JsonEncoder.VTYPE_PAINTABLE.equals(variableType)) {
// TODO handle properly
val = idMapper.getPaintable(String.valueOf(value));
- } else if (JsonEncoder.VTYPE_SHAREDSTATE.equals(variableType)) {
- val = convertMap((JSONObject) value, idMapper);
- // TODO convert to a SharedState instance
+ } else {
+ // object, class name as type
+ VaadinSerializer serializer = getSerializer(variableType);
+ Object object = serializer
+ .deserialize((JSONObject) value, idMapper);
+ return object;
}
return val;
}
- private static Object convertMap(JSONObject jsonMap, VPaintableMap idMapper) {
+ public static Map<String, Object> convertMap(JSONObject jsonMap,
+ VPaintableMap idMapper) {
HashMap<String, Object> map = new HashMap<String, Object>();
Iterator<String> it = jsonMap.keySet().iterator();
while (it.hasNext()) {
return tokens.toArray(new String[tokens.size()]);
}
- private static Object convertArray(JSONArray jsonArray,
+ private static Object[] convertArray(JSONArray jsonArray,
VPaintableMap idMapper) {
List<Object> tokens = new ArrayList<Object>();
for (int i = 0; i < jsonArray.size(); ++i) {
return tokens.toArray(new Object[tokens.size()]);
}
+ public static Object deserialize(JSONArray jsonArray, VPaintableMap idMapper) {
+ // jsonArray always contains two items
+ // 1. type (String)
+ // 2. data (Serialized)
+ String type = ((JSONString) jsonArray.get(0)).stringValue();
+ VaadinSerializer serializer = getSerializer(type);
+ Object object = serializer.deserialize((JSONObject) jsonArray.get(1),
+ idMapper);
+ return object;
+ }
+
+ private static VaadinSerializer getSerializer(String type) {
+ // TODO This should be in a separate class and constructed by a
+ // generator
+ return GWT.create(ComponentState_Serializer.class);
+ }
}
package com.vaadin.terminal.gwt.client.communication;
import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
import com.google.gwt.core.client.GWT;
import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidget;
* @since 7.0
*/
public class SharedState implements Serializable {
- private Map<String, Object> state = new HashMap<String, Object>();
-
- // TODO temporary until reflection based serialization is implemented
- public Map<String, Object> getState() {
- return state;
- }
-
- // TODO temporary until generator based deserialization is implemented
- public void setState(Map<String, Object> stateMap) {
- state = stateMap;
- }
}
--- /dev/null
+package com.vaadin.terminal.gwt.client.communication;\r
+\r
+import com.google.gwt.json.client.JSONObject;\r
+import com.vaadin.terminal.gwt.client.VPaintableMap;\r
+\r
+public interface VaadinSerializer {\r
+\r
+ // TODO Object -> something\r
+ Object deserialize(JSONObject jsonValue, VPaintableMap idMapper);\r
+\r
+}\r
*/
package com.vaadin.terminal.gwt.client.ui;
+import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.Focusable;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.ComponentState;
import com.vaadin.terminal.gwt.client.TooltipInfo;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.VPaintableMap;
private boolean visible = true;
// shared state from the server to the client
- private SharedState state;
+ private ComponentState state;
/**
* Default constructor
this.id = id;
}
- public void updateState(SharedState state) {
- this.state = state;
- }
+ public ComponentState getState() {
+ if (state == null) {
+ state = createState();
+ }
- public SharedState getState() {
return state;
}
+ protected ComponentState createState() {
+ return GWT.create(ComponentState.class);
+ }
+
public VPaintableWidgetContainer getParent() {
// FIXME: Hierarchy should be set by framework instead of looked up here
VPaintableMap paintableMap = VPaintableMap.get(getConnection());
return styleBuf.toString();
}
+ public final void setState(SharedState state) {
+ this.state = (ComponentState) state;
+ }
}
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui;\r
+\r
+import com.vaadin.terminal.gwt.client.ComponentState;\r
+\r
+public class VButtonState extends ComponentState {\r
+ private boolean disableOnClick = false;\r
+\r
+ public boolean isDisableOnClick() {\r
+ return disableOnClick;\r
+ }\r
+\r
+ public void setDisableOnClick(boolean disableOnClick) {\r
+ this.disableOnClick = disableOnClick;\r
+ }\r
+\r
+}\r
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui;\r
+\r
+import com.google.gwt.core.client.GWT;\r
+import com.google.gwt.json.client.JSONArray;\r
+import com.google.gwt.json.client.JSONObject;\r
+import com.vaadin.terminal.gwt.client.VPaintableMap;\r
+import com.vaadin.terminal.gwt.client.communication.JsonDecoder;\r
+import com.vaadin.terminal.gwt.client.communication.VaadinSerializer;\r
+\r
+//TODO This should be autogenerated\r
+public class VButtonState_Serializer implements VaadinSerializer {\r
+\r
+ public VButtonState deserialize(JSONObject jsonValue, VPaintableMap idMapper) {\r
+ VButtonState state = GWT.create(VButtonState.class);\r
+\r
+ JSONArray jsonHeight = (JSONArray) jsonValue.get("height");\r
+ state.setHeight((String) JsonDecoder.convertValue(jsonHeight, idMapper));\r
+\r
+ JSONArray jsonWidth = (JSONArray) jsonValue.get("width");\r
+ state.setWidth((String) JsonDecoder.convertValue(jsonWidth, idMapper));\r
+\r
+ JSONArray jsonDisableOnClick = (JSONArray) jsonValue\r
+ .get("disableOnClick");\r
+ state.setDisableOnClick((Boolean) JsonDecoder.convertValue(\r
+ jsonDisableOnClick, idMapper));\r
+\r
+ return state;\r
+ }\r
+}\r
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.ComponentState;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.VConsole;
import com.vaadin.terminal.gwt.client.VTooltip;
// Set attributes
Style style = el.getStyle();
- String w = "";
- String h = "";
- if (null != getState()) {
- if (getState().getState().containsKey(
- ComponentState.STATE_WIDTH)) {
- w = String.valueOf(getState().getState().get(
- ComponentState.STATE_WIDTH));
- }
- if (getState().getState().containsKey(
- ComponentState.STATE_HEIGHT)) {
- h = String.valueOf(getState().getState().get(
- ComponentState.STATE_HEIGHT));
- }
- }
- style.setProperty("width", w);
- style.setProperty("height", h);
+ style.setProperty("width", getState().getWidth());
+ style.setProperty("height", getState().getHeight());
DOM.setElementProperty(el, "src", getWidgetForPaintable()
.getSrc(uidl, client));
}
};
-}
+
+}
\ No newline at end of file
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.ComponentState;
import com.vaadin.terminal.gwt.client.Container;
import com.vaadin.terminal.gwt.client.RenderSpace;
import com.vaadin.terminal.gwt.client.StyleConstants;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VPaintableMap;
import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.communication.SharedState;
import com.vaadin.terminal.gwt.client.ui.layout.CellBasedLayout;
import com.vaadin.terminal.gwt.client.ui.layout.ChildComponentContainer;
}
}
- protected void updateRelSizeStatus(SharedState state, boolean cached) {
+ protected void updateRelSizeStatus(ComponentState state, boolean cached) {
if (state != null && !cached) {
- boolean widthDefined = state.getState().containsKey("width");
- boolean heightDefined = state.getState().containsKey("height");
- if (heightDefined
- && String.valueOf(state.getState().get("height"))
- .contains("%")) {
+ boolean widthDefined = !state.isUndefinedWidth();
+ boolean heightDefined = !state.isUndefinedHeight();
+ if (heightDefined && state.getHeight().contains("%")) {
relHeight = true;
} else {
relHeight = false;
}
if (widthDefined) {
- widthCanAffectHeight = relWidth = String.valueOf(
- state.getState().get("width")).contains("%");
+ widthCanAffectHeight = relWidth = state.getWidth()
+ .contains("%");
if (heightDefined) {
widthCanAffectHeight = false;
}
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.ComponentState;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.ui.VMenuBar.CustomMenuItem;
UIDL options = uidl.getChildUIDL(0);
- if (null != getState()
- && getState().getState()
- .containsKey(ComponentState.STATE_WIDTH)) {
+ if (null != getState() && !getState().isUndefinedWidth()) {
UIDL moreItemUIDL = options.getChildUIDL(0);
StringBuffer itemHTML = new StringBuffer();
*/
package com.vaadin.terminal.gwt.client.ui;
-import java.util.Map;
-
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.DomEvent.Type;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.user.client.ui.Frame;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.ComponentState;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VPaintableWidget;
getWidgetForPaintable().layout = lo;
}
- if (null != getState()) {
- Map<String, Object> state = getState().getState();
- getWidgetForPaintable().dynamicWidth = !state
- .containsKey(ComponentState.STATE_WIDTH);
- getWidgetForPaintable().dynamicHeight = !state
- .containsKey(ComponentState.STATE_HEIGHT);
- } else {
- getWidgetForPaintable().dynamicWidth = true;
- getWidgetForPaintable().dynamicHeight = true;
- }
+ getWidgetForPaintable().dynamicWidth = getState().isUndefinedWidth();
+ getWidgetForPaintable().dynamicHeight = getState().isUndefinedHeight();
getWidgetForPaintable().layoutRelativeWidth = uidl
.hasAttribute("layoutRelativeWidth");
package com.vaadin.terminal.gwt.client.ui.layout;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.ComponentState;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidgetContainer;
import com.vaadin.terminal.gwt.client.ui.VMarginInfo;
}
private void handleDynamicDimensions() {
- String w = "";
- String h = "";
- if (null != getState()) {
- if (getState().getState().containsKey(ComponentState.STATE_WIDTH)) {
- w = String.valueOf(getState().getState().get(
- ComponentState.STATE_WIDTH));
- }
- if (getState().getState().containsKey(ComponentState.STATE_HEIGHT)) {
- h = String.valueOf(getState().getState().get(
- ComponentState.STATE_HEIGHT));
- }
- }
-
- if (w.equals("")) {
- getWidgetForPaintable().dynamicWidth = true;
- } else {
- getWidgetForPaintable().dynamicWidth = false;
- }
-
- if (h.equals("")) {
- getWidgetForPaintable().dynamicHeight = true;
- } else {
- getWidgetForPaintable().dynamicHeight = false;
- }
-
+ getWidgetForPaintable().dynamicWidth = getState().isUndefinedWidth();
+ getWidgetForPaintable().dynamicHeight = getState().isUndefinedHeight();
}
void updateMarginAndSpacingInfo(UIDL uidl) {
package com.vaadin.terminal.gwt.server;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
import java.io.Serializable;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
return combineTypeAndValue(JsonEncoder.VTYPE_UNDEFINED,
JSONObject.NULL);
} else if (value instanceof SharedState) {
- // TODO implement by encoding the bean
- Map<String, Object> map = ((SharedState) value).getState();
- return combineTypeAndValue(JsonEncoder.VTYPE_SHAREDSTATE,
- encodeMapContents(map, idMapper));
+ return combineTypeAndValue(value.getClass().getName(),
+ encodeObject(value, idMapper));
} else if (value instanceof String[]) {
String[] array = (String[]) value;
JSONArray jsonArray = new JSONArray();
}
}
+ private static Object encodeObject(Object value, PaintableIdMapper idMapper)
+ throws JSONException {
+ JSONObject jsonMap = new JSONObject();
+
+ try {
+ for (PropertyDescriptor pd : Introspector.getBeanInfo(
+ value.getClass()).getPropertyDescriptors()) {
+ String fieldName = pd.getName();
+ if (pd.getReadMethod() == null || pd.getWriteMethod() == null) {
+ continue;
+ }
+ Method getterMethod = pd.getReadMethod();
+ Object fieldValue = getterMethod.invoke(value, null);
+ jsonMap.put(fieldName, encode(fieldValue, idMapper));
+ }
+ } catch (Exception e) {
+ // TODO: Should exceptions be handled in a different way?
+ throw new JSONException(e);
+ }
+ return jsonMap;
+ }
+
private static JSONArray encodeArrayContents(Object[] array,
PaintableIdMapper idMapper) throws JSONException {
JSONArray jsonArray = new JSONArray();
// TODO for now, this superclass always recreates the state from
// scratch, whereas subclasses should only modify it
- Map<String, Object> state = new HashMap<String, Object>();
+ // Map<String, Object> state = new HashMap<String, Object>();
if (getHeight() >= 0
&& (getHeightUnits() != Unit.PERCENTAGE || ComponentSizeValidator
.parentCanDefineHeight(this))) {
- state.put(ComponentState.STATE_HEIGHT, "" + getCSSHeight());
+ sharedState.setHeight("" + getCSSHeight());
}
if (getWidth() >= 0
&& (getWidthUnits() != Unit.PERCENTAGE || ComponentSizeValidator
.parentCanDefineWidth(this))) {
- state.put(ComponentState.STATE_WIDTH, "" + getCSSWidth());
+ sharedState.setWidth("" + getCSSWidth());
}
// if (getCaption() != null) {
// if (getDescription() != null && getDescription().length() > 0) {
// state.put(ComponentState.STATE_DESCRIPTION, getDescription());
// }
-
- sharedState.setState(state);
+ //
+ // sharedState.setState(state);
return sharedState;
}
import com.vaadin.event.ShortcutListener;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
+import com.vaadin.terminal.gwt.client.ComponentState;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
import com.vaadin.terminal.gwt.client.ui.VButton;
import com.vaadin.terminal.gwt.client.ui.VButton.ButtonClientToServerRpc;
import com.vaadin.terminal.gwt.client.ui.VButtonPaintable;
+import com.vaadin.terminal.gwt.client.ui.VButtonState;
import com.vaadin.terminal.gwt.server.RpcTarget;
import com.vaadin.tools.ReflectTools;
import com.vaadin.ui.ClientWidget.LoadStyle;
FieldEvents.BlurNotifier, FieldEvents.FocusNotifier, Focusable,
Action.ShortcutNotifier, RpcTarget {
- /* Private members */
-
- boolean disableOnClick = false;
-
/**
* Creates a new push button.
*/
* @return true if the button is disabled when clicked, false otherwise
*/
public boolean isDisableOnClick() {
- return disableOnClick;
+ return getState().isDisableOnClick();
}
/**
* true to disable button when it is clicked, false otherwise
*/
public void setDisableOnClick(boolean disableOnClick) {
- this.disableOnClick = disableOnClick;
+ getState().setDisableOnClick(disableOnClick);
requestRepaint();
}
// Overridden only to make public
super.focus();
}
+
+ @Override
+ protected ComponentState createState() {
+ return new VButtonState();
+ }
+
+ @Override
+ public VButtonState getState() {
+ return (VButtonState) super.getState();
+ }
}