private String height = "";
private String width = "";
- // TODO more javadoc
-
+ /**
+ * Returns the component height as set by the server.
+ *
+ * Can be relative (containing the percent sign) or absolute, or empty
+ * string for undefined height.
+ *
+ * @return component height as defined by the server, not null
+ */
public String getHeight() {
if (height == null) {
return "";
return height;
}
+ /**
+ * Sets the height of the component in the server format.
+ *
+ * Can be relative (containing the percent sign) or absolute, or null or
+ * empty string for undefined height.
+ *
+ * @param height
+ * component height
+ */
public void setHeight(String height) {
this.height = height;
}
+ /**
+ * Returns true if the component height is undefined, false if defined
+ * (absolute or relative).
+ *
+ * @return true if component height is undefined
+ */
public boolean isUndefinedHeight() {
return "".equals(getHeight());
}
+ /**
+ * Returns the component width as set by the server.
+ *
+ * Can be relative (containing the percent sign) or absolute, or empty
+ * string for undefined height.
+ *
+ * @return component width as defined by the server, not null
+ */
public String getWidth() {
if (width == null) {
return "";
return width;
}
+ /**
+ * Sets the width of the component in the server format.
+ *
+ * Can be relative (containing the percent sign) or absolute, or null or
+ * empty string for undefined width.
+ *
+ * @param width
+ * component width
+ */
public void setWidth(String width) {
this.width = width;
}
+ /**
+ * Returns true if the component width is undefined, false if defined
+ * (absolute or relative).
+ *
+ * @return true if component width is undefined
+ */
public boolean isUndefinedWidth() {
return "".equals(getWidth());
}
- // TODO constants for the state attributes for now
- public static final String STATE_STYLE = "style";
- public static final String STATE_READONLY = "readonly";
- public static final String STATE_IMMEDIATE = "immediate";
- public static final String STATE_DISABLED = "disabled";
- public static final String STATE_CAPTION = "caption";
- public static final String STATE_DESCRIPTION = "description";
+ // TODO more fields to move here: style, readonly, immediate, disabled,
+ // caption and description
}
// object, class name as type
VaadinSerializer serializer = serializerMap
.getSerializer(variableType);
+ // TODO handle case with no serializer found
Object object = serializer
.deserialize((JSONObject) value, idMapper);
return object;
+/*\r
+@VaadinApache2LicenseForJavaFiles@\r
+ */\r
+\r
package com.vaadin.terminal.gwt.client.communication;\r
\r
+import com.vaadin.terminal.gwt.widgetsetutils.SerializerMapGenerator;\r
+\r
+/**\r
+ * Provide a mapping from a type (communicated between the server and the\r
+ * client) and a {@link VaadinSerializer} instance.\r
+ * \r
+ * An implementation of this class is created at GWT compilation time by\r
+ * {@link SerializerMapGenerator}, so this interface can be instantiated with\r
+ * GWT.create().\r
+ * \r
+ * @since 7.0\r
+ */\r
public interface SerializerMap {\r
\r
+ /**\r
+ * Returns a serializer instance for a given type.\r
+ * \r
+ * @param type\r
+ * type communicated on between the server and the client\r
+ * (currently fully qualified class name)\r
+ * @return serializer instance, not null\r
+ * @throws RuntimeException\r
+ * if no serializer is found\r
+ */\r
+ // TODO better error handling in javadoc and in generator\r
public VaadinSerializer getSerializer(String type);\r
\r
}\r
import java.io.Serializable;
-import com.google.gwt.core.client.GWT;
import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidget;
/**
* necessary (changed or missing on the client side) parts are re-sent to the
* client, but the client will have access to the whole state.
*
- * TODO the rest of the javadoc corresponds to the design that is not yet
- * implemented
- *
* A shared state class should be a bean with getters and setters for each
* field, and should only contain simple data types, or arrays or maps of
* supported data types.
*
- * On the client side, SharedState instances must be created using
- * {@link GWT#create(Class)} to let a generator create custom deserialization
- * support for them. For most widgets,
- * {@link VAbstractPaintableWidget#createSharedState()} method should be
- * overridden to create a shared state instance of the correct type using
- * {@link GWT#create(Class)}.
+ * On the client side, for most widgets,
+ * {@link VAbstractPaintableWidget#createState()} and
+ * {@link VAbstractPaintableWidget#getState()} methods should be overridden to
+ * create and use a shared state instance of the correct type.
*
* Subclasses of a paintable using shared state should also provide a subclass
* of the shared state class of the parent class to extend the state - a single
+/*\r
+@VaadinApache2LicenseForJavaFiles@\r
+ */\r
+\r
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
+/**\r
+ * Serializer that can deserialize custom objects received from the server.\r
+ * \r
+ * Each serializer can handle objects of a single type - see\r
+ * {@link SerializerMap}.\r
+ * \r
+ * @since 7.0\r
+ */\r
public interface VaadinSerializer {\r
\r
+ /**\r
+ * Creates and deserializes an object received from the server.\r
+ * \r
+ * @param jsonValue\r
+ * JSON map from property name to property value\r
+ * @param idMapper\r
+ * mapper from paintable id to paintable, used to decode\r
+ * references to paintables\r
+ * @return deserialized object\r
+ */\r
// TODO Object -> something\r
Object deserialize(JSONObject jsonValue, VPaintableMap idMapper);\r
\r
this.id = id;
}
+ /**
+ * Returns the shared state object for a paintable widget.
+ *
+ * A new state instance is created using {@link #createState()} if none has
+ * been set by the server.
+ *
+ * If overriding this method to return a more specific type, also
+ * {@link #createState()} must be overridden.
+ *
+ * @return current shared state (not null)
+ */
public ComponentState getState() {
if (state == null) {
state = createState();
return state;
}
+ /**
+ * Creates a new instance of a shared state object for the widget. Normally,
+ * the state instance is created by the server and sent to the client before
+ * being used - this method is used if no shared state has been sent by the
+ * server.
+ *
+ * When overriding {@link #getState()}, also {@link #createState()} should
+ * be overridden to match it.
+ *
+ * @return newly created component shared state instance
+ */
protected ComponentState createState() {
return GWT.create(ComponentState.class);
}
return styleBuf.toString();
}
+ /**
+ * Sets the shared state for the paintable widget.
+ *
+ * @param new shared state (must be compatible with the return value of
+ * {@link #getState()} - {@link ComponentState} if
+ * {@link #getState()} is not overridden
+ */
public final void setState(SharedState state) {
this.state = (ComponentState) state;
}
import com.google.gwt.user.client.DOM;
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.EventHelper;
import com.vaadin.terminal.gwt.client.UIDL;
public VButtonState getState() {
return (VButtonState) super.getState();
}
+
+ @Override
+ protected ComponentState createState() {
+ return GWT.create(VButtonState.class);
+ }
}
+/*\r
+@VaadinApache2LicenseForJavaFiles@\r
+ */\r
+\r
package com.vaadin.terminal.gwt.client.ui;\r
\r
import com.vaadin.terminal.gwt.client.ComponentState;\r
+import com.vaadin.ui.Button;\r
\r
+/**\r
+ * Shared state for Button and NativeButton.\r
+ * \r
+ * @see ComponentState\r
+ * \r
+ * @since 7.0\r
+ */\r
public class VButtonState extends ComponentState {\r
private boolean disableOnClick = false;\r
private int clickShortcutKeyCode = 0;\r
\r
+ /**\r
+ * Checks whether the button should be disabled on the client side on next\r
+ * click.\r
+ * \r
+ * @return true if the button should be disabled on click\r
+ */\r
public boolean isDisableOnClick() {\r
return disableOnClick;\r
}\r
\r
+ /**\r
+ * Sets whether the button should be disabled on the client side on next\r
+ * click.\r
+ * \r
+ * @param disableOnClick\r
+ * true if the button should be disabled on click\r
+ */\r
public void setDisableOnClick(boolean disableOnClick) {\r
this.disableOnClick = disableOnClick;\r
}\r
\r
+ /**\r
+ * Returns the key code for activating the button via a keyboard shortcut.\r
+ * \r
+ * See {@link Button#setClickShortcut(int, int...)} for more information.\r
+ * \r
+ * @return key code or 0 for none\r
+ */\r
public int getClickShortcutKeyCode() {\r
return clickShortcutKeyCode;\r
}\r
\r
+ /**\r
+ * Sets the key code for activating the button via a keyboard shortcut.\r
+ * \r
+ * See {@link Button#setClickShortcut(int, int...)} for more information.\r
+ * \r
+ * @param clickShortcutKeyCode\r
+ * key code or 0 for none\r
+ */\r
public void setClickShortcutKeyCode(int clickShortcutKeyCode) {\r
this.clickShortcutKeyCode = clickShortcutKeyCode;\r
}\r
if (state != null && !cached) {
boolean widthDefined = !state.isUndefinedWidth();
boolean heightDefined = !state.isUndefinedHeight();
- if (heightDefined && state.getHeight().contains("%")) {
- relHeight = true;
- } else {
- relHeight = false;
- }
+
+ relHeight = state.getHeight().contains("%");
+ relWidth = state.getWidth().contains("%");
if (widthDefined) {
- widthCanAffectHeight = relWidth = state.getWidth()
- .contains("%");
- if (heightDefined) {
- widthCanAffectHeight = false;
- }
+ widthCanAffectHeight = (relWidth && !heightDefined);
} else {
widthCanAffectHeight = !heightDefined;
- relWidth = false;
}
}
}
import com.google.gwt.user.client.DOM;
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.EventHelper;
import com.vaadin.terminal.gwt.client.UIDL;
public VButtonState getState() {
return (VButtonState) super.getState();
}
+
+ @Override
+ protected ComponentState createState() {
+ return GWT.create(VButtonState.class);
+ }
}
\ No newline at end of file
+/*\r
+@VaadinApache2LicenseForJavaFiles@\r
+ */\r
+\r
package com.vaadin.terminal.gwt.widgetsetutils;\r
\r
import java.io.PrintWriter;\r
import com.vaadin.terminal.gwt.client.communication.JsonDecoder;\r
import com.vaadin.terminal.gwt.client.communication.VaadinSerializer;\r
\r
+/**\r
+ * GWT generator for creating serializer classes for custom classes sent from\r
+ * server to client.\r
+ * \r
+ * Only fields with a correspondingly named setter are deserialized.\r
+ * \r
+ * @since 7.0\r
+ */\r
public class SerializerGenerator extends Generator {\r
\r
private String packageName;\r
}\r
\r
/**\r
- * Generate source code for WidgetMapImpl\r
+ * Generate source code for a VaadinSerializer implementation.\r
* \r
* @param logger\r
* Logger object\r
* @param context\r
* Generator context\r
- * @param typeName\r
+ * @param beanTypeName\r
+ * bean type for which the serializer is to be generated\r
+ * @param beanSerializerTypeName\r
+ * name of the serializer class to generate\r
*/\r
private void generateClass(TreeLogger logger, GeneratorContext context,\r
String beanTypeName, String beanSerializerTypeName) {\r
// JSONArray jsonHeight = (JSONArray) jsonValue.get("height");\r
sourceWriter.println("JSONArray " + jsonFieldName\r
+ " = (JSONArray) jsonValue.get(\"" + fieldName + "\");");\r
+\r
// state.setHeight((String)\r
// JsonDecoder.convertValue(jsonFieldValue,idMapper));\r
\r
+/*\r
+@VaadinApache2LicenseForJavaFiles@\r
+ */\r
+\r
package com.vaadin.terminal.gwt.widgetsetutils;\r
\r
import java.io.PrintWriter;\r
import com.vaadin.terminal.gwt.client.communication.SharedState;\r
import com.vaadin.terminal.gwt.client.communication.VaadinSerializer;\r
\r
+/**\r
+ * GWT generator that creates a {@link SerializerMap} implementation (mapper\r
+ * from type string to serializer instance) and serializer classes for all\r
+ * subclasses of {@link SharedState}.\r
+ * \r
+ * @since 7.0\r
+ */\r
public class SerializerMapGenerator extends Generator {\r
\r
private String packageName;\r
JClassType classType = typeOracle.getType(typeName);\r
packageName = classType.getPackage().getName();\r
className = classType.getSimpleSourceName() + "Impl";\r
- // Generate class source code\r
+ // Generate class source code for SerializerMapImpl\r
generateClass(logger, context);\r
\r
+ // Generate serializer classes for each subclass of SharedState\r
JClassType serializerType = typeOracle.findType(SharedState.class\r
.getName());\r
JClassType[] serializerSubtypes = serializerType.getSubtypes();\r
+ " getSerializer(String type) {");\r
sourceWriter.indent();\r
\r
+ // TODO cache serializer instances in a map\r
for (JClassType type : serializerSubtypes) {\r
sourceWriter.println("if (type.equals(\""\r
+ type.getQualifiedSourceName() + "\")) {");\r
// 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>();
if (getHeight() >= 0
&& (getHeightUnits() != Unit.PERCENTAGE || ComponentSizeValidator
// if (getDescription() != null && getDescription().length() > 0) {
// state.put(ComponentState.STATE_DESCRIPTION, getDescription());
// }
- //
- // sharedState.setState(state);
return sharedState;
}