--- /dev/null
+package com.vaadin.terminal;
+
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.logging.Logger;
+
+import com.vaadin.Application;
+import com.vaadin.terminal.gwt.client.communication.ClientRpc;
+import com.vaadin.terminal.gwt.client.communication.ServerRpc;
+import com.vaadin.terminal.gwt.client.communication.SharedState;
+import com.vaadin.terminal.gwt.server.ClientConnector;
+import com.vaadin.terminal.gwt.server.ClientMethodInvocation;
+import com.vaadin.terminal.gwt.server.RpcManager;
+import com.vaadin.terminal.gwt.server.RpcTarget;
+import com.vaadin.terminal.gwt.server.ServerRpcManager;
+import com.vaadin.ui.HasComponents;
+import com.vaadin.ui.Root;
+
+/**
+ *
+ */
+public abstract class AbstractClientConnector implements ClientConnector {
+ /**
+ * A map from client to server RPC interface class to the RPC call manager
+ * that handles incoming RPC calls for that interface.
+ */
+ private Map<Class<?>, RpcManager> rpcManagerMap = new HashMap<Class<?>, RpcManager>();
+
+ /**
+ * A map from server to client RPC interface class to the RPC proxy that
+ * sends ourgoing RPC calls for that interface.
+ */
+ private Map<Class<?>, ClientRpc> rpcProxyMap = new HashMap<Class<?>, ClientRpc>();
+
+ /**
+ * Shared state object to be communicated from the server to the client when
+ * modified.
+ */
+ private SharedState sharedState;
+
+ /**
+ * Pending RPC method invocations to be sent.
+ */
+ private ArrayList<ClientMethodInvocation> pendingInvocations = new ArrayList<ClientMethodInvocation>();
+
+ private String connectorId;
+
+ private ArrayList<Extension> extensions = new ArrayList<Extension>();
+
+ private ClientConnector parent;
+
+ /* Documentation copied from interface */
+ public void requestRepaint() {
+ Root root = getRoot();
+ if (root != null) {
+ root.getDirtyConnectorTracker().markDirty(this);
+ }
+ }
+
+ /**
+ * Registers an RPC interface implementation for this component.
+ *
+ * A component can listen to multiple RPC interfaces, and subclasses can
+ * register additional implementations.
+ *
+ * @since 7.0
+ *
+ * @param implementation
+ * RPC interface implementation
+ * @param rpcInterfaceType
+ * RPC interface class for which the implementation should be
+ * registered
+ */
+ protected <T> void registerRpc(T implementation, Class<T> rpcInterfaceType) {
+ rpcManagerMap.put(rpcInterfaceType, new ServerRpcManager<T>(
+ implementation, rpcInterfaceType));
+ }
+
+ /**
+ * Registers an RPC interface implementation for this component.
+ *
+ * A component can listen to multiple RPC interfaces, and subclasses can
+ * register additional implementations.
+ *
+ * @since 7.0
+ *
+ * @param implementation
+ * RPC interface implementation. Also used to deduce the type.
+ */
+ protected <T extends ServerRpc> void registerRpc(T implementation) {
+ Class<?> cls = implementation.getClass();
+ Class<?>[] interfaces = cls.getInterfaces();
+ while (interfaces.length == 0) {
+ // Search upwards until an interface is found. It must be found as T
+ // extends ServerRpc
+ cls = cls.getSuperclass();
+ interfaces = cls.getInterfaces();
+ }
+ if (interfaces.length != 1
+ || !(ServerRpc.class.isAssignableFrom(interfaces[0]))) {
+ throw new RuntimeException(
+ "Use registerRpc(T implementation, Class<T> rpcInterfaceType) if the Rpc implementation implements more than one interface");
+ }
+ Class<T> type = (Class<T>) interfaces[0];
+ registerRpc(implementation, type);
+ }
+
+ public SharedState getState() {
+ if (null == sharedState) {
+ sharedState = createState();
+ }
+ return sharedState;
+ }
+
+ /**
+ * Creates the shared state bean to be used in server to client
+ * communication.
+ * <p>
+ * By default a state object of the defined return type of
+ * {@link #getState()} is created. Subclasses can override this method and
+ * return a new instance of the correct state class but this should rarely
+ * be necessary.
+ * </p>
+ * <p>
+ * No configuration of the values of the state should be performed in
+ * {@link #createState()}.
+ *
+ * @since 7.0
+ *
+ * @return new shared state object
+ */
+ protected SharedState createState() {
+ try {
+ return getStateType().newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Error creating state of type " + getStateType().getName()
+ + " for " + getClass().getName(), e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.terminal.gwt.server.ClientConnector#getStateType()
+ */
+ public Class<? extends SharedState> getStateType() {
+ try {
+ Method m = getClass().getMethod("getState", (Class[]) null);
+ Class<?> type = m.getReturnType();
+ return type.asSubclass(SharedState.class);
+ } catch (Exception e) {
+ throw new RuntimeException("Error finding state type for "
+ + getClass().getName(), e);
+ }
+ }
+
+ /**
+ * Returns an RPC proxy for a given server to client RPC interface for this
+ * component.
+ *
+ * TODO more javadoc, subclasses, ...
+ *
+ * @param rpcInterface
+ * RPC interface type
+ *
+ * @since 7.0
+ */
+ public <T extends ClientRpc> T getRpcProxy(final Class<T> rpcInterface) {
+ // create, initialize and return a dynamic proxy for RPC
+ try {
+ if (!rpcProxyMap.containsKey(rpcInterface)) {
+ Class<?> proxyClass = Proxy.getProxyClass(
+ rpcInterface.getClassLoader(), rpcInterface);
+ Constructor<?> constructor = proxyClass
+ .getConstructor(InvocationHandler.class);
+ T rpcProxy = rpcInterface.cast(constructor
+ .newInstance(new RpcInvoicationHandler(rpcInterface)));
+ // cache the proxy
+ rpcProxyMap.put(rpcInterface, rpcProxy);
+ }
+ return (T) rpcProxyMap.get(rpcInterface);
+ } catch (Exception e) {
+ // TODO exception handling?
+ throw new RuntimeException(e);
+ }
+ }
+
+ private class RpcInvoicationHandler implements InvocationHandler,
+ Serializable {
+
+ private String rpcInterfaceName;
+
+ public RpcInvoicationHandler(Class<?> rpcInterface) {
+ rpcInterfaceName = rpcInterface.getName().replaceAll("\\$", ".");
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+ addMethodInvocationToQueue(rpcInterfaceName, method, args);
+ // TODO no need to do full repaint if only RPC calls
+ requestRepaint();
+ return null;
+ }
+
+ }
+
+ /**
+ * For internal use: adds a method invocation to the pending RPC call queue.
+ *
+ * @param interfaceName
+ * RPC interface name
+ * @param method
+ * RPC method
+ * @param parameters
+ * RPC all parameters
+ *
+ * @since 7.0
+ */
+ protected void addMethodInvocationToQueue(String interfaceName,
+ Method method, Object[] parameters) {
+ // add to queue
+ pendingInvocations.add(new ClientMethodInvocation(this, interfaceName,
+ method, parameters));
+ }
+
+ /**
+ * @see RpcTarget#getRpcManager(Class)
+ *
+ * @param rpcInterface
+ * RPC interface for which a call was made
+ * @return RPC Manager handling calls for the interface
+ *
+ * @since 7.0
+ */
+ public RpcManager getRpcManager(Class<?> rpcInterface) {
+ return rpcManagerMap.get(rpcInterface);
+ }
+
+ public List<ClientMethodInvocation> retrievePendingRpcCalls() {
+ if (pendingInvocations.isEmpty()) {
+ return Collections.emptyList();
+ } else {
+ List<ClientMethodInvocation> result = pendingInvocations;
+ pendingInvocations = new ArrayList<ClientMethodInvocation>();
+ return Collections.unmodifiableList(result);
+ }
+ }
+
+ public String getConnectorId() {
+ if (connectorId == null) {
+ if (getApplication() == null) {
+ throw new RuntimeException(
+ "Component must be attached to an application when getConnectorId() is called for the first time");
+ }
+ connectorId = getApplication().createConnectorId(this);
+ }
+ return connectorId;
+ }
+
+ /**
+ * Finds the Application to which this connector belongs. If the connector
+ * has not been attached, <code>null</code> is returned.
+ *
+ * @return The connector's application, or <code>null</code> if not attached
+ */
+ protected Application getApplication() {
+ Root root = getRoot();
+ if (root == null) {
+ return null;
+ } else {
+ return root.getApplication();
+ }
+ }
+
+ /**
+ * Finds a Root ancestor of this connector. <code>null</code> is returned if
+ * no Root ancestor is found (typically because the connector is not
+ * attached to a proper hierarchy).
+ *
+ * @return the Root ancestor of this connector, or <code>null</code> if none
+ * is found.
+ */
+ protected Root getRoot() {
+ ClientConnector connector = this;
+ while (connector != null) {
+ if (connector instanceof Root) {
+ return (Root) connector;
+ }
+ connector = connector.getParent();
+ }
+ return null;
+ }
+
+ private static Logger getLogger() {
+ return Logger.getLogger(AbstractClientConnector.class.getName());
+ }
+
+ public void requestRepaintAll() {
+ requestRepaint();
+
+ for (ClientConnector connector : getAllChildrenIteratable(this)) {
+ connector.requestRepaintAll();
+ }
+ }
+
+ private static final class CombinedIterator<T> implements Iterator<T>,
+ Serializable {
+
+ private final Collection<Iterator<? extends T>> iterators = new ArrayList<Iterator<? extends T>>();
+
+ public void addIterator(Iterator<? extends T> iterator) {
+ iterators.add(iterator);
+ }
+
+ public boolean hasNext() {
+ for (Iterator<? extends T> i : iterators) {
+ if (i.hasNext()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public T next() {
+ for (Iterator<? extends T> i : iterators) {
+ if (i.hasNext()) {
+ return i.next();
+ }
+ }
+ throw new NoSuchElementException();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public static Iterable<ClientConnector> getAllChildrenIteratable(
+ final ClientConnector connector) {
+ return new Iterable<ClientConnector>() {
+ public Iterator<ClientConnector> iterator() {
+ CombinedIterator<ClientConnector> iterator = new CombinedIterator<ClientConnector>();
+ iterator.addIterator(connector.getExtensionIterator());
+
+ if (connector instanceof HasComponents) {
+ HasComponents hasComponents = (HasComponents) connector;
+ iterator.addIterator(hasComponents.iterator());
+ }
+
+ return iterator;
+ }
+ };
+ }
+
+ public Iterator<Extension> getExtensionIterator() {
+ return Collections.unmodifiableList(extensions).iterator();
+ }
+
+ protected void addExtension(Extension extension) {
+ addExtensionAtIndex(extension, extensions.size());
+ }
+
+ protected void addExtensionAtIndex(Extension extension, int index) {
+ ClientConnector previousParent = extension.getParent();
+ if (previousParent == this) {
+ int oldIndex = extensions.indexOf(extension);
+ if (oldIndex < index) {
+ index--;
+ }
+ extensions.remove(oldIndex);
+ extensions.add(index, extension);
+ } else {
+ if (previousParent != null) {
+ previousParent.removeExtension(extension);
+ }
+ extensions.add(index, extension);
+ extension.setParent(this);
+ }
+ requestRepaint();
+ }
+
+ public void removeExtension(Extension extension) {
+ extension.setParent(null);
+ extensions.remove(extension);
+ requestRepaint();
+ }
+
+ public void setParent(ClientConnector parent) {
+
+ // If the parent is not changed, don't do anything
+ if (parent == this.parent) {
+ return;
+ }
+
+ if (parent != null && this.parent != null) {
+ throw new IllegalStateException(getClass().getName()
+ + " already has a parent.");
+ }
+
+ // Send detach event if the component have been connected to a window
+ if (getApplication() != null) {
+ detach();
+ }
+
+ // Connect to new parent
+ this.parent = parent;
+
+ // Send attach event if connected to an application
+ if (getApplication() != null) {
+ attach();
+ }
+ }
+
+ public ClientConnector getParent() {
+ return parent;
+ }
+
+ public void attach() {
+ requestRepaint();
+
+ for (ClientConnector connector : getAllChildrenIteratable(this)) {
+ connector.attach();
+ }
+ }
+
+ public void detach() {
+ for (ClientConnector connector : getAllChildrenIteratable(this)) {
+ connector.detach();
+ }
+ }
+
+ public boolean isConnectorEnabled() {
+ if (getParent() == null) {
+ // No parent -> the component cannot receive updates from the client
+ return false;
+ } else {
+ return getParent().isConnectorEnabled();
+ }
+ }
+}
--- /dev/null
+package com.vaadin.terminal;
+
+import com.vaadin.terminal.gwt.server.ClientConnector;
+
+public abstract class AbstractExtension extends AbstractClientConnector implements
+ Extension {
+
+ protected Class<? extends ClientConnector> getAcceptedParentType() {
+ return ClientConnector.class;
+ }
+
+ @Override
+ public void setParent(ClientConnector parent) {
+ Class<? extends ClientConnector> acceptedParentType = getAcceptedParentType();
+ if (parent == null || acceptedParentType.isInstance(parent)) {
+ super.setParent(parent);
+ } else {
+ throw new IllegalArgumentException(getClass().getName()
+ + " can only be attached to parents of type "
+ + acceptedParentType.getName() + " but attach to "
+ + parent.getClass().getName() + " was attempted.");
+ }
+ }
+
+}
--- /dev/null
+package com.vaadin.terminal;
+
+import com.vaadin.terminal.gwt.server.ClientConnector;
+
+public interface Extension extends ClientConnector {
+
+}
import com.vaadin.terminal.StreamVariable.StreamingStartEvent;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.server.ClientConnector;
+import com.vaadin.ui.Component;
/**
* This interface defines the methods for painting XML to the UIDL stream.
/**
* Result of starting to paint a Paintable (
- * {@link PaintTarget#startPaintable(ClientConnector, String)}).
+ * {@link PaintTarget#startPaintable(Component, String)}).
*
* @since 7.0
*/
* changes.
*/
CACHED
- };
+ }
/**
* Prints element start tag of a paintable section. Starts a paintable
* </p>
* <p>
* Each paintable being painted should be closed by a matching
- * {@link #endPaintable(ClientConnector)} regardless of the
- * {@link PaintStatus} returned.
+ * {@link #endPaintable(Component)} regardless of the {@link PaintStatus}
+ * returned.
* </p>
*
* @param paintable
* @see #startTag(String)
* @since 7.0 (previously using startTag(Paintable, String))
*/
- public PaintStatus startPaintable(ClientConnector paintable, String tag)
+ public PaintStatus startPaintable(Component paintable, String tag)
throws PaintException;
/**
* Prints paintable element end tag.
*
- * Calls to {@link #startPaintable(ClientConnector, String)}should be
- * matched by {@link #endPaintable(ClientConnector)}. If the parent tag is
- * closed before every child tag is closed a PaintException is raised.
+ * Calls to {@link #startPaintable(Component, String)}should be matched by
+ * {@link #endPaintable(Component)}. If the parent tag is closed before
+ * every child tag is closed a PaintException is raised.
*
* @param paintable
* the paintable to close.
* if the paint operation failed.
* @since 7.0 (previously using engTag(String))
*/
- public void endPaintable(ClientConnector paintable) throws PaintException;
+ public void endPaintable(Component paintable) throws PaintException;
/**
* Prints element start tag.
* the Paintable to be referenced on client side
* @throws PaintException
*/
- public void addAttribute(String name, ClientConnector value)
+ public void addAttribute(String name, Component value)
throws PaintException;
/**
* @throws PaintException
* if the paint oparation fails
*/
- public void addVariable(VariableOwner owner, String name,
- ClientConnector value) throws PaintException;
+ public void addVariable(VariableOwner owner, String name, Component value)
+ throws PaintException;
/**
* Adds a upload stream type variable.
private HashMap<Integer, String> unknownComponents;
- private Class<? extends ComponentConnector>[] classes = new Class[1024];
+ private Class<? extends ServerConnector>[] classes = new Class[1024];
private boolean browserDetailsSent = false;
private boolean widgetsetVersionSent = false;
return useDebugIdInDom;
}
- public Class<? extends ComponentConnector> getWidgetClassByEncodedTag(
+ public Class<? extends ServerConnector> getConnectorClassByEncodedTag(
int tag) {
try {
return classes[tag];
public void run() {
pending = false;
if (!isBusy()) {
- Class<? extends ComponentConnector> nextType = getNextType();
+ Class<? extends ServerConnector> nextType = getNextType();
if (nextType == null) {
// ensured that all widgets are loaded
deferredWidgetLoader = null;
}
}
- private Class<? extends ComponentConnector> getNextType() {
- Class<? extends ComponentConnector>[] deferredLoadedWidgets = widgetSet
- .getDeferredLoadedWidgets();
- if (deferredLoadedWidgets.length <= nextWidgetIndex) {
+ private Class<? extends ServerConnector> getNextType() {
+ Class<? extends ServerConnector>[] deferredLoadedConnectors = widgetSet
+ .getDeferredLoadedConnectors();
+ if (deferredLoadedConnectors.length <= nextWidgetIndex) {
return null;
} else {
- return deferredLoadedWidgets[nextWidgetIndex++];
+ return deferredLoadedConnectors[nextWidgetIndex++];
}
}
List<ServerConnector> currentConnectors = new ArrayList<ServerConnector>(
connectorMap.getConnectors());
for (ServerConnector c : currentConnectors) {
- if (c instanceof ComponentConnector) {
- ComponentConnector cc = (ComponentConnector) c;
- if (cc.getParent() != null) {
- if (!cc.getParent().getChildren().contains(cc)) {
- VConsole.error("ERROR: Connector is connected to a parent but the parent does not contain the connector");
- }
- } else if ((cc instanceof RootConnector && cc == getRootConnector())) {
- // RootConnector for this connection, leave as-is
- } else if (cc instanceof WindowConnector
- && getRootConnector().hasSubWindow(
- (WindowConnector) cc)) {
- // Sub window attached to this RootConnector, leave
- // as-is
- } else {
- // The connector has been detached from the
- // hierarchy, unregister it and any possible
- // children. The RootConnector should never be
- // unregistered even though it has no parent.
- connectorMap.unregisterConnector(cc);
- unregistered++;
+ if (c.getParent() != null) {
+ if (!c.getParent().getChildren().contains(c)) {
+ VConsole.error("ERROR: Connector is connected to a parent but the parent does not contain the connector");
}
+ } else if ((c instanceof RootConnector && c == getRootConnector())) {
+ // RootConnector for this connection, leave as-is
+ } else if (c instanceof WindowConnector
+ && getRootConnector().hasSubWindow(
+ (WindowConnector) c)) {
+ // Sub window attached to this RootConnector, leave
+ // as-is
+ } else {
+ // The connector has been detached from the
+ // hierarchy, unregister it and any possible
+ // children. The RootConnector should never be
+ // unregistered even though it has no parent.
+ connectorMap.unregisterConnector(c);
+ unregistered++;
}
}
continue;
}
- Class<? extends ComponentConnector> connectorClass = configuration
- .getWidgetClassByEncodedTag(connectorType);
+ Class<? extends ServerConnector> connectorClass = configuration
+ .getConnectorClassByEncodedTag(connectorType);
// Connector does not exist so we must create it
if (connectorClass != RootConnector.class) {
for (int i = 0; i < hierarchyKeys.length(); i++) {
try {
String connectorId = hierarchyKeys.get(i);
- ServerConnector connector = connectorMap
+ ServerConnector parentConnector = connectorMap
.getConnector(connectorId);
- if (!(connector instanceof ComponentContainerConnector)) {
- VConsole.error("Retrieved a hierarchy update for a connector ("
- + connectorId
- + ") that is not a ComponentContainerConnector");
- continue;
- }
- ComponentContainerConnector ccc = (ComponentContainerConnector) connector;
-
JsArrayString childConnectorIds = hierarchies
.getJSStringArray(connectorId);
int childConnectorSize = childConnectorIds.length();
List<ServerConnector> newChildren = new ArrayList<ServerConnector>();
+ List<ComponentConnector> newComponents = new ArrayList<ComponentConnector>();
for (int connectorIndex = 0; connectorIndex < childConnectorSize; connectorIndex++) {
String childConnectorId = childConnectorIds
.get(connectorIndex);
- ComponentConnector childConnector = (ComponentConnector) connectorMap
+ ServerConnector childConnector = connectorMap
.getConnector(childConnectorId);
if (childConnector == null) {
VConsole.error("Hierarchy claims that "
+ childConnectorId + " is a child for "
+ connectorId + " ("
- + connector.getClass().getName()
+ + parentConnector.getClass().getName()
+ ") but no connector with id "
+ childConnectorId
+ " has been registered");
continue;
}
newChildren.add(childConnector);
- if (childConnector.getParent() != ccc) {
+ if (childConnector instanceof ComponentConnector) {
+ newComponents
+ .add((ComponentConnector) childConnector);
+ }
+ if (childConnector.getParent() != parentConnector) {
// Avoid extra calls to setParent
- childConnector.setParent(ccc);
+ childConnector.setParent(parentConnector);
}
}
// TODO This check should be done on the server side in
// the future so the hierarchy update is only sent when
// something actually has changed
- List<ComponentConnector> oldChildren = ccc
+ List<ServerConnector> oldChildren = parentConnector
.getChildren();
boolean actuallyChanged = !Util.collectionsEquals(
oldChildren, newChildren);
continue;
}
- // Fire change event if the hierarchy has changed
- ConnectorHierarchyChangeEvent event = GWT
- .create(ConnectorHierarchyChangeEvent.class);
- event.setOldChildren(oldChildren);
- event.setConnector(ccc);
- ccc.setChildren((List) newChildren);
- events.add(event);
+ if (parentConnector instanceof ComponentContainerConnector) {
+ ComponentContainerConnector ccc = (ComponentContainerConnector) parentConnector;
+ List<ComponentConnector> oldComponents = ccc
+ .getChildComponents();
+ if (!Util.collectionsEquals(oldComponents,
+ newComponents)) {
+ // Fire change event if the hierarchy has
+ // changed
+ ConnectorHierarchyChangeEvent event = GWT
+ .create(ConnectorHierarchyChangeEvent.class);
+ event.setOldChildren(oldComponents);
+ event.setConnector(parentConnector);
+ ccc.setChildComponents(newComponents);
+ events.add(event);
+ }
+ } else if (!newComponents.isEmpty()) {
+ VConsole.error("Hierachy claims "
+ + Util.getConnectorString(parentConnector)
+ + " has component children even though it isn't a ComponentContainerConnector");
+ }
+
+ parentConnector.setChildren(newChildren);
// Remove parent for children that are no longer
// attached to this (avoid updating children if they
// have already been assigned to a new parent)
- for (ComponentConnector oldChild : oldChildren) {
- if (oldChild.getParent() != ccc) {
+ for (ServerConnector oldChild : oldChildren) {
+ if (oldChild.getParent() != parentConnector) {
continue;
}
@Deprecated
public ComponentConnector getPaintable(UIDL uidl) {
- return getConnector(uidl.getId(), Integer.parseInt(uidl.getTag()));
+ // Non-component connectors shouldn't be painted from legacy connectors
+ return (ComponentConnector) getConnector(uidl.getId(),
+ Integer.parseInt(uidl.getTag()));
}
/**
* @return Either an existing ComponentConnector or a new ComponentConnector
* of the given type
*/
- public ComponentConnector getConnector(String connectorId, int connectorType) {
+ public ServerConnector getConnector(String connectorId, int connectorType) {
if (!connectorMap.hasConnector(connectorId)) {
return createAndRegisterConnector(connectorId, connectorType);
}
- return (ComponentConnector) connectorMap.getConnector(connectorId);
+ return connectorMap.getConnector(connectorId);
}
/**
- * Creates a new ComponentConnector with the given type and id.
+ * Creates a new ServerConnector with the given type and id.
*
- * Creates and registers a new ComponentConnector of the given type. Should
+ * Creates and registers a new ServerConnector of the given type. Should
* never be called with the connector id of an existing connector.
*
* @param connectorId
* @param connectorType
* Type of the connector, as passed from the server side
*
- * @return A new ComponentConnector of the given type
+ * @return A new ServerConnector of the given type
*/
- private ComponentConnector createAndRegisterConnector(String connectorId,
+ private ServerConnector createAndRegisterConnector(String connectorId,
int connectorType) {
// Create and register a new connector with the given type
- ComponentConnector p = widgetSet.createWidget(connectorType,
- configuration);
+ ServerConnector p = widgetSet
+ .createWidget(connectorType, configuration);
connectorMap.registerConnector(connectorId, p);
p.doInit(connectorId, this);
*/
public boolean isRelativeHeight();
- /**
- * Returns the parent of this connector. Can be null for only the root
- * connector.
- *
- * @return The parent of this connector, as set by
- * {@link #setParent(ComponentContainerConnector)}.
- */
- public ComponentContainerConnector getParent();
-
- /**
- * Sets the parent for this connector. This method should only be called by
- * the framework to ensure that the connector hierarchy on the client side
- * and the server side are in sync.
- * <p>
- * Note that calling this method does not fire a
- * {@link ConnectorHierarchyChangeEvent}. The event is fired only when the
- * whole hierarchy has been updated.
- *
- * @param parent
- * The new parent of the connector
- */
- public void setParent(ComponentContainerConnector parent);
-
/**
* Checks if the connector is read only.
*
* An interface used by client-side connectors whose widget is a component
* container (implements {@link HasWidgets}).
*/
-public interface ComponentContainerConnector extends ComponentConnector {
+public interface ComponentContainerConnector extends ServerConnector {
/**
* Update child components caption, description and error message.
* @return A collection of children for this connector. An empty collection
* if there are no children. Never returns null.
*/
- public List<ComponentConnector> getChildren();
+ public List<ComponentConnector> getChildComponents();
/**
* Sets the children for this connector. This method should only be called
* side and the server side are in sync.
* <p>
* Note that calling this method does not call
- * {@link #connectorHierarchyChanged(ConnectorHierarchyChangeEvent)}. The
- * event method is called only when the hierarchy has been updated for all
- * connectors.
+ * {@link ConnectorHierarchyChangeHandler#onConnectorHierarchyChange(ConnectorHierarchyChangeEvent)}
+ * . The event method is called only when the hierarchy has been updated for
+ * all connectors.
*
* @param children
* The new child connectors
*/
- public void setChildren(List<ComponentConnector> children);
+ public void setChildComponents(List<ComponentConnector> children);
/**
* Adds a handler that is called whenever the child hierarchy of this
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.communication.SharedState;
import com.vaadin.terminal.gwt.client.ui.SubPartAware;
import com.vaadin.terminal.gwt.client.ui.gridlayout.VGridLayout;
import com.vaadin.terminal.gwt.client.ui.orderedlayout.VMeasuringOrderedLayout;
} else if (w == null) {
String id = part;
// Must be old static pid (PID_S*)
- ComponentConnector connector = (ComponentConnector) ConnectorMap
- .get(client).getConnector(id);
+ ServerConnector connector = ConnectorMap.get(client)
+ .getConnector(id);
if (connector == null) {
// Lookup by debugId
// TODO Optimize this
id.substring(5));
}
- if (connector != null) {
- w = connector.getWidget();
+ if (connector instanceof ComponentConnector) {
+ w = ((SimplePanel) connector).getWidget();
} else {
// Not found
return null;
return w;
}
- private ComponentConnector findConnectorById(ComponentConnector root,
- String id) {
- if (root instanceof ComponentConnector
- && id.equals(root.getState().getDebugId())) {
+ private ServerConnector findConnectorById(ServerConnector root, String id) {
+ SharedState state = root.getState();
+ if (state instanceof ComponentState
+ && id.equals(((ComponentState) state).getDebugId())) {
return root;
}
- if (root instanceof ComponentContainerConnector) {
- ComponentContainerConnector ccc = (ComponentContainerConnector) root;
- for (ComponentConnector child : ccc.getChildren()) {
- ComponentConnector found = findConnectorById(child, id);
- if (found != null) {
- return found;
- }
+ for (ServerConnector child : root.getChildren()) {
+ ServerConnector found = findConnectorById(child, id);
+ if (found != null) {
+ return found;
}
}
private String width = "";
private boolean readOnly = false;
private boolean immediate = false;
- private boolean enabled = true;
private String description = "";
// Note: for the caption, there is a difference between null and an empty
// string!
return styles != null && !styles.isEmpty();
}
- /**
- * Returns true if the component is enabled.
- *
- * @see com.vaadin.ui.Component#isEnabled()
- *
- * @return true if the component is enabled
- */
- public boolean isEnabled() {
- return enabled;
- }
-
- /**
- * Enables or disables the component.
- *
- * @see com.vaadin.ui.Component#setEnabled(boolean)
- *
- * @param enabled
- * new mode for the component
- */
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- }
-
/**
* Gets the description of the component (typically shown as tooltip).
*
*/
public String getConnectorId();
+ /**
+ * Gets the parent connector of this connector, or <code>null</code> if the
+ * connector is not attached to any parent.
+ *
+ * @return the parent connector, or <code>null</code> if there is no parent.
+ */
+ public Connector getParent();
+
}
idToConnector.remove(connectorId);
connector.onUnregister();
- if (connector instanceof ComponentContainerConnector) {
- for (ComponentConnector child : ((ComponentContainerConnector) connector)
- .getChildren()) {
- if (child.getParent() == connector) {
- // Only unregister children that are actually connected to
- // this parent. For instance when moving connectors from one
- // layout to another and removing the first layout it will
- // still contain references to its old children, which are
- // now attached to another connector.
- unregisterConnector(child);
- }
+ for (ServerConnector child : connector.getChildren()) {
+ if (child.getParent() == connector) {
+ /*
+ * Only unregister children that are actually connected to this
+ * parent. For instance when moving connectors from one layout
+ * to another and removing the first layout it will still
+ * contain references to its old children, which are now
+ * attached to another connector.
+ */
+ unregisterConnector(child);
}
}
}
for (ComponentConnector componentConnector : pendingOverflowFixes) {
// Delay the overflow fix if the involved connectors might still
// change
- if (!currentDependencyTree
- .noMoreChangesExpected(componentConnector)
- || !currentDependencyTree
- .noMoreChangesExpected(componentConnector
- .getParent())) {
+ boolean connectorChangesExpected = !currentDependencyTree
+ .noMoreChangesExpected(componentConnector);
+ boolean parentChangesExcpected = componentConnector.getParent() instanceof ComponentConnector
+ && !currentDependencyTree
+ .noMoreChangesExpected((ComponentConnector) componentConnector
+ .getParent());
+ if (connectorChangesExpected || parentChangesExcpected) {
delayedOverflowFixes.add(componentConnector);
continue;
}
package com.vaadin.terminal.gwt.client;
import java.util.Collection;
+import java.util.List;
import com.google.gwt.event.shared.GwtEvent;
import com.google.web.bindery.event.shared.HandlerRegistration;
*/
public void onUnregister();
+ /**
+ * Returns the parent of this connector. Can be null for only the root
+ * connector.
+ *
+ * @return The parent of this connector, as set by
+ * {@link #setParent(ServerConnector)}.
+ */
+ public ServerConnector getParent();
+
+ /**
+ * Sets the parent for this connector. This method should only be called by
+ * the framework to ensure that the connector hierarchy on the client side
+ * and the server side are in sync.
+ * <p>
+ * Note that calling this method does not fire a
+ * {@link ConnectorHierarchyChangeEvent}. The event is fired only when the
+ * whole hierarchy has been updated.
+ *
+ * @param parent
+ * The new parent of the connector
+ */
+ public void setParent(ServerConnector parent);
+
+ public void updateEnabledState(boolean enabledState);
+
+ public void setChildren(List<ServerConnector> children);
+
+ public List<ServerConnector> getChildren();
}
return idx;
}
- private static void printPaintablesInvocations(
+ private static void printConnectorInvocations(
ArrayList<MethodInvocation> invocations, String id,
ApplicationConnection c) {
- ComponentConnector paintable = (ComponentConnector) ConnectorMap.get(c)
- .getConnector(id);
- if (paintable != null) {
- VConsole.log("\t" + id + " (" + paintable.getClass() + ") :");
+ ServerConnector connector = ConnectorMap.get(c).getConnector(id);
+ if (connector != null) {
+ VConsole.log("\t" + id + " (" + connector.getClass() + ") :");
for (MethodInvocation invocation : invocations) {
Object[] parameters = invocation.getParameters();
String formattedParams = null;
+ ")");
}
} else {
- VConsole.log("\t" + id + ": Warning: no corresponding paintable!");
+ VConsole.log("\t" + id + ": Warning: no corresponding connector!");
}
}
if (curId == null) {
curId = id;
} else if (!curId.equals(id)) {
- printPaintablesInvocations(invocations, curId, c);
+ printConnectorInvocations(invocations, curId, c);
invocations.clear();
curId = id;
}
invocations.add(loggedBurst.get(i));
}
if (!invocations.isEmpty()) {
- printPaintablesInvocations(invocations, curId, c);
+ printConnectorInvocations(invocations, curId, c);
}
} catch (Exception e) {
VConsole.error(e);
Set<ComponentConnector> zeroHeightComponents,
ApplicationConnection ac) {
for (final ComponentConnector paintable : zeroHeightComponents) {
- final Widget layout = paintable.getParent().getWidget();
+ final ServerConnector parent = paintable.getParent();
VerticalPanel errorDetails = new VerticalPanel();
errorDetails.add(new Label("" + Util.getSimpleName(paintable)
- + " inside " + Util.getSimpleName(layout)));
- final CheckBox emphasisInUi = new CheckBox(
- "Emphasize components parent in UI (the actual component is not visible)");
- emphasisInUi.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent event) {
- if (paintable != null) {
+ + " inside " + Util.getSimpleName(parent)));
+ if (parent instanceof ComponentConnector) {
+ ComponentConnector parentComponent = (ComponentConnector) parent;
+ final Widget layout = parentComponent.getWidget();
+
+ final CheckBox emphasisInUi = new CheckBox(
+ "Emphasize components parent in UI (the actual component is not visible)");
+ emphasisInUi.addClickHandler(new ClickHandler() {
+ public void onClick(ClickEvent event) {
Element element2 = layout.getElement();
Widget.setStyleName(element2, "invalidlayout",
- emphasisInUi.getValue());
+ emphasisInUi.getValue().booleanValue());
}
- }
- });
- errorDetails.add(emphasisInUi);
+ });
+
+ errorDetails.add(emphasisInUi);
+ }
panel.add(errorDetails);
}
}
log("================");
log("Connector hierarchy for Root: " + root.getState().getCaption()
+ " (" + root.getConnectorId() + ")");
- Set<ComponentConnector> connectorsInHierarchy = new HashSet<ComponentConnector>();
+ Set<ServerConnector> connectorsInHierarchy = new HashSet<ServerConnector>();
SimpleTree rootHierachy = dumpConnectorHierarchy(root, "",
connectorsInHierarchy);
if (panel.isAttached()) {
Collection<? extends ServerConnector> registeredConnectors = connectorMap
.getConnectors();
log("Sub windows:");
- Set<ComponentConnector> subWindowHierarchyConnectors = new HashSet<ComponentConnector>();
+ Set<ServerConnector> subWindowHierarchyConnectors = new HashSet<ServerConnector>();
for (WindowConnector wc : root.getSubWindows()) {
SimpleTree windowHierachy = dumpConnectorHierarchy(wc, "",
subWindowHierarchyConnectors);
}
- private SimpleTree dumpConnectorHierarchy(
- final ComponentConnector connector, String indent,
- Set<ComponentConnector> connectors) {
+ private SimpleTree dumpConnectorHierarchy(final ServerConnector connector,
+ String indent, Set<ServerConnector> connectors) {
SimpleTree simpleTree = new SimpleTree(getConnectorString(connector)) {
@Override
protected void select(ClickEvent event) {
super.select(event);
- VUIDLBrowser.highlight(connector);
+ if (connector instanceof ComponentConnector) {
+ VUIDLBrowser.highlight((ComponentConnector) connector);
+ }
}
};
simpleTree.addDomHandler(new MouseOutHandler() {
consoleLog(msg);
System.out.println(msg);
- if (connector instanceof ComponentContainerConnector) {
- for (ComponentConnector c : ((ComponentContainerConnector) connector)
- .getChildren()) {
- simpleTree.add(dumpConnectorHierarchy(c, indent + " ",
- connectors));
- }
+ for (ServerConnector c : connector.getChildren()) {
+ simpleTree.add(dumpConnectorHierarchy(c, indent + " ", connectors));
}
return simpleTree;
}
private String getNodeName(UIDL uidl, ApplicationConfiguration conf,
int tag) {
- Class<? extends ComponentConnector> widgetClassByDecodedTag = conf
- .getWidgetClassByEncodedTag(tag);
+ Class<? extends ServerConnector> widgetClassByDecodedTag = conf
+ .getConnectorClassByEncodedTag(tag);
if (widgetClassByDecodedTag == UnknownComponentConnector.class) {
return conf.getUnknownServerClassNameByTag(tag)
+ "(NO CLIENT IMPLEMENTATION FOUND)";
* A helper class used by WidgetMap implementation. Used by the generated code.
*/
interface WidgetInstantiator {
- public ComponentConnector get();
+ public ServerConnector get();
}
*/
abstract class WidgetMap {
- protected static HashMap<Class, WidgetInstantiator> instmap = new HashMap<Class, WidgetInstantiator>();
+ protected static HashMap<Class<? extends ServerConnector>, WidgetInstantiator> instmap = new HashMap<Class<? extends ServerConnector>, WidgetInstantiator>();
/**
* Create a new instance of a connector based on its type.
* {@link ComponentConnector} class to instantiate
* @return new instance of the connector
*/
- public ComponentConnector instantiate(
- Class<? extends ComponentConnector> classType) {
+ public ServerConnector instantiate(
+ Class<? extends ServerConnector> classType) {
return instmap.get(classType).get();
}
* fully qualified name of the server side component class
* @return component connector class to use
*/
- public abstract Class<? extends ComponentConnector> getConnectorClassForServerSideClassName(
+ public abstract Class<? extends ServerConnector> getConnectorClassForServerSideClassName(
String fullyqualifiedName);
/**
* @return component connector class to load after the initial widgetset
* loading
*/
- public abstract Class<? extends ComponentConnector>[] getDeferredLoadedWidgets();
+ public abstract Class<? extends ServerConnector>[] getDeferredLoadedConnectors();
/**
* Make sure the code for a (deferred or lazy) component connector type has
* component connector class
*/
public abstract void ensureInstantiator(
- Class<? extends ComponentConnector> classType);
+ Class<? extends ServerConnector> classType);
}
private WidgetMap widgetMap = GWT.create(WidgetMap.class);
/**
- * Create an uninitialized component that best matches given UIDL. The
- * component must be a {@link Widget} that implements
- * {@link ComponentConnector}.
+ * Create an uninitialized connector that best matches given UIDL. The
+ * connector must be a {@link Widget} that implements
+ * {@link ServerConnector}.
*
* @param tag
- * component type tag for the component to create
+ * connector type tag for the connector to create
* @param client
* the application connection that whishes to instantiate widget
*
- * @return New uninitialized and unregistered component that can paint given
+ * @return New uninitialized and unregistered connector that can paint given
* UIDL.
*/
- public ComponentConnector createWidget(int tag,
- ApplicationConfiguration conf) {
+ public ServerConnector createWidget(int tag, ApplicationConfiguration conf) {
/*
* Yes, this (including the generated code in WidgetMap) may look very
* odd code, but due the nature of GWT, we cannot do this any cleaner.
* has no "native" counterpart on client side.
*/
- Class<? extends ComponentConnector> classType = resolveInheritedWidgetType(
+ Class<? extends ServerConnector> classType = resolveInheritedWidgetType(
conf, tag);
if (classType == null || classType == UnknownComponentConnector.class) {
}
}
- private Class<? extends ComponentConnector> resolveInheritedWidgetType(
+ private Class<? extends ServerConnector> resolveInheritedWidgetType(
ApplicationConfiguration conf, int tag) {
- Class<? extends ComponentConnector> classType = null;
+ Class<? extends ServerConnector> classType = null;
Integer t = tag;
do {
classType = resolveWidgetType(t, conf);
return classType;
}
- protected Class<? extends ComponentConnector> resolveWidgetType(int tag,
+ protected Class<? extends ServerConnector> resolveWidgetType(int tag,
ApplicationConfiguration conf) {
- Class<? extends ComponentConnector> widgetClass = conf
- .getWidgetClassByEncodedTag(tag);
+ Class<? extends ServerConnector> widgetClass = conf
+ .getConnectorClassByEncodedTag(tag);
return widgetClass;
}
* @param applicationConfiguration
* @return
*/
- public Class<? extends ComponentConnector> getConnectorClassByTag(int tag,
+ public Class<? extends ServerConnector> getConnectorClassByTag(int tag,
ApplicationConfiguration conf) {
- Class<? extends ComponentConnector> connectorClass = null;
+ Class<? extends ServerConnector> connectorClass = null;
Integer t = tag;
do {
String serverSideClassName = conf.getServerSideClassNameForTag(t);
return connectorClass;
}
- public Class<? extends ComponentConnector>[] getDeferredLoadedWidgets() {
- return widgetMap.getDeferredLoadedWidgets();
+ public Class<? extends ServerConnector>[] getDeferredLoadedConnectors() {
+ return widgetMap.getDeferredLoadedConnectors();
}
- public void loadImplementation(Class<? extends ComponentConnector> nextType) {
+ public void loadImplementation(Class<? extends ServerConnector> nextType) {
widgetMap.ensureInstantiator(nextType);
}
* @since 7.0
*/
public class SharedState implements Serializable {
+
+ private boolean enabled = true;
+
+ /**
+ * Returns true if the component is enabled.
+ *
+ * @see com.vaadin.ui.Component#isEnabled()
+ *
+ * @return true if the component is enabled
+ */
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ /**
+ * Enables or disables the component.
+ *
+ * @see com.vaadin.ui.Component#setEnabled(boolean)
+ *
+ * @param enabled
+ * new mode for the component
+ */
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
}
import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.ComponentContainerConnector;
import com.vaadin.terminal.gwt.client.ComponentState;
+import com.vaadin.terminal.gwt.client.Connector;
import com.vaadin.terminal.gwt.client.ConnectorMap;
import com.vaadin.terminal.gwt.client.LayoutManager;
+import com.vaadin.terminal.gwt.client.ServerConnector;
import com.vaadin.terminal.gwt.client.TooltipInfo;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
public abstract class AbstractComponentConnector extends AbstractConnector
implements ComponentConnector {
- private ComponentContainerConnector parent;
-
private Widget widget;
private String lastKnownWidth = "";
@Override
public void onStateChanged(StateChangeEvent stateChangeEvent) {
- super.onStateChanged(stateChangeEvent);
-
ConnectorMap paintableMap = ConnectorMap.get(getConnection());
if (getState().getDebugId() != null) {
/*
* Disabled state may affect (override) tabindex so the order must be
- * first setting tabindex, then enabled state.
+ * first setting tabindex, then enabled state (through super
+ * implementation).
*/
if (getState() instanceof TabIndexState
&& getWidget() instanceof Focusable) {
.getTabIndex());
}
- setWidgetEnabled(isEnabled());
+ super.onStateChanged(stateChangeEvent);
// Style names
String styleName = getStyleNames(getWidget().getStylePrimaryName());
// Set captions
if (delegateCaptionHandling()) {
- ComponentContainerConnector parent = getParent();
- if (parent != null) {
- parent.updateCaption(this);
- } else if (!(this instanceof RootConnector)) {
+ ServerConnector parent = getParent();
+ if (parent instanceof ComponentContainerConnector) {
+ ((ComponentContainerConnector) parent).updateCaption(this);
+ } else if (parent == null && !(this instanceof RootConnector)) {
VConsole.error("Parent of connector "
+ Util.getConnectorString(this)
+ " is null. This is typically an indication of a broken component hierarchy");
// Parent should be updated if either dimension changed between relative
// and non-relative
if (newWidth.endsWith("%") != lastKnownWidth.endsWith("%")) {
- ComponentContainerConnector parent = getParent();
+ Connector parent = getParent();
if (parent instanceof ManagedLayout) {
getLayoutManager().setNeedsHorizontalLayout(
(ManagedLayout) parent);
}
if (newHeight.endsWith("%") != lastKnownHeight.endsWith("%")) {
- ComponentContainerConnector parent = getParent();
+ Connector parent = getParent();
if (parent instanceof ManagedLayout) {
getLayoutManager().setNeedsVerticalLayout(
(ManagedLayout) parent);
return getState().getWidth().length() == 0;
}
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.terminal.gwt.client.Connector#isEnabled()
- */
- public boolean isEnabled() {
- if (!getState().isEnabled()) {
- return false;
- }
-
- if (getParent() == null) {
- return true;
- } else {
- return getParent().isEnabled();
- }
- }
-
/*
* (non-Javadoc)
*
return LayoutManager.get(getConnection());
}
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.terminal.gwt.client.Connector#getParent()
- */
- public ComponentContainerConnector getParent() {
- return parent;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.terminal.gwt.client.Connector#setParent(com.vaadin.terminal
- * .gwt.client.ComponentContainerConnector)
- */
- public void setParent(ComponentContainerConnector parent) {
- this.parent = parent;
- }
-
/**
* Checks if there is a registered server side listener for the given event
* identifier.
return (reg != null && reg.contains(eventIdentifier));
}
+ @Override
+ public void updateEnabledState(boolean enabledState) {
+ super.updateEnabledState(enabledState);
+
+ setWidgetEnabled(isEnabled());
+ }
+
@Override
public void onUnregister() {
super.onUnregister();
*/
package com.vaadin.terminal.gwt.client.ui;
-import java.util.LinkedList;
+import java.util.Collections;
import java.util.List;
import com.google.gwt.event.shared.HandlerRegistration;
AbstractComponentConnector implements ComponentContainerConnector,
ConnectorHierarchyChangeHandler {
- List<ComponentConnector> children;
+ List<ComponentConnector> childComponents;
private final boolean debugLogging = false;
- /**
- * Temporary storage for last enabled state to be able to see if it has
- * changed. Can be removed once we are able to listen specifically for
- * enabled changes in the state. Widget.isEnabled() cannot be used as all
- * Widgets do not implement HasEnabled
- */
- private boolean lastWidgetEnabledState = true;
-
/**
* Default constructor
*/
* @see
* com.vaadin.terminal.gwt.client.ComponentContainerConnector#getChildren()
*/
- public List<ComponentConnector> getChildren() {
- if (children == null) {
- return new LinkedList<ComponentConnector>();
+ public List<ComponentConnector> getChildComponents() {
+ if (childComponents == null) {
+ return Collections.emptyList();
}
- return children;
+ return childComponents;
}
/*
* com.vaadin.terminal.gwt.client.ComponentContainerConnector#setChildren
* (java.util.Collection)
*/
- public void setChildren(List<ComponentConnector> children) {
- this.children = children;
+ public void setChildComponents(List<ComponentConnector> childComponents) {
+ this.childComponents = childComponents;
}
/*
VConsole.log(oldChildren);
String newChildren = "* New children: ";
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
newChildren += Util.getConnectorString(child) + " ";
}
VConsole.log(newChildren);
return ensureHandlerManager().addHandler(
ConnectorHierarchyChangeEvent.TYPE, handler);
}
-
- @Override
- public void setWidgetEnabled(boolean widgetEnabled) {
- if (lastWidgetEnabledState == widgetEnabled) {
- return;
- }
- lastWidgetEnabledState = widgetEnabled;
-
- super.setWidgetEnabled(widgetEnabled);
- for (ComponentConnector c : getChildren()) {
- // Update children as they might be affected by the enabled state of
- // their parent
- c.setWidgetEnabled(c.isEnabled());
- }
- }
}
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import com.google.gwt.event.shared.GwtEvent;
private final boolean debugLogging = false;
private SharedState state;
+ private ServerConnector parent;
+
+ /**
+ * Temporary storage for last enabled state to be able to see if it has
+ * changed. Can be removed once we are able to listen specifically for
+ * enabled changes in the state. Widget.isEnabled() cannot be used as all
+ * Widgets do not implement HasEnabled
+ */
+ private boolean lastEnabledState = true;
+ private List<ServerConnector> children;
/*
* (non-Javadoc)
return (Collection<T>) rpcImplementations.get(rpcInterfaceId);
}
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.terminal.gwt.client.Connector#isConnectorEnabled()
- */
- public boolean isConnectorEnabled() {
- // Client side can always receive message from the server
- return true;
- }
-
public void fireEvent(GwtEvent<?> event) {
if (handlerManager != null) {
handlerManager.fireEvent(event);
+ Util.getConnectorString(stateChangeEvent.getConnector())
+ " received by " + Util.getConnectorString(this));
}
+
+ updateEnabledState(isEnabled());
}
/*
return ConnectorStateFactory.createState(getClass());
}
+ public ServerConnector getParent() {
+ return parent;
+ }
+
+ public void setParent(ServerConnector parent) {
+ this.parent = parent;
+ }
+
+ public List<ServerConnector> getChildren() {
+ if (children == null) {
+ return Collections.emptyList();
+ }
+ return children;
+ }
+
+ public void setChildren(List<ServerConnector> children) {
+ this.children = children;
+ }
+
+ public boolean isEnabled() {
+ if (!getState().isEnabled()) {
+ return false;
+ }
+
+ if (getParent() == null) {
+ return true;
+ } else {
+ return getParent().isEnabled();
+ }
+ }
+
+ public void updateEnabledState(boolean enabledState) {
+ if (lastEnabledState == enabledState) {
+ return;
+ }
+ lastEnabledState = enabledState;
+
+ for (ServerConnector c : getChildren()) {
+ // Update children as they might be affected by the enabled state of
+ // their parent
+ c.updateEnabledState(c.isEnabled());
+ }
+ }
}
// TODO Margin handling
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
getWrapper(child).setPosition(
getState().getConnectorPosition(child));
}
public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
super.onConnectorHierarchyChange(event);
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
getWrapper(child);
}
public void layoutVertically() {
VAbsoluteLayout layout = getWidget();
- for (ComponentConnector paintable : getChildren()) {
+ for (ComponentConnector paintable : getChildComponents()) {
Widget widget = paintable.getWidget();
AbsoluteWrapper wrapper = (AbsoluteWrapper) widget.getParent();
Style wrapperStyle = wrapper.getElement().getStyle();
public void layoutHorizontally() {
VAbsoluteLayout layout = getWidget();
- for (ComponentConnector paintable : getChildren()) {
+ for (ComponentConnector paintable : getChildComponents()) {
AbsoluteWrapper wrapper = getWrapper(paintable);
Style wrapperStyle = wrapper.getElement().getStyle();
getWidget().setMarginStyles(
new VMarginInfo(getState().getMarginsBitmask()));
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
if (!getState().getChildCss().containsKey(child)) {
continue;
}
int index = 0;
FlowPane cssLayoutWidgetContainer = getWidget().panel;
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
VCaption childCaption = childToCaption.get(child);
if (childCaption != null) {
cssLayoutWidgetContainer.addOrMove(childCaption, index++);
super.onConnectorHierarchyChange(event);
ComponentConnector newChild = null;
- if (getChildren().size() == 1) {
- newChild = getChildren().get(0);
+ if (getChildComponents().size() == 1) {
+ newChild = getChildComponents().get(0);
}
VCustomComponent customComponent = getWidget();
updateHtmlTemplate();
// For all contained widgets
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
String location = getState().getChildLocations().get(child);
try {
getWidget().setWidget(child.getWidget(), location);
int childId = 0;
- formLayoutTable.setRowCount(getChildren().size());
+ formLayoutTable.setRowCount(getChildComponents().size());
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
Widget childWidget = child.getWidget();
Caption caption = formLayoutTable.getCaption(childWidget);
layout.spacingMeasureElement);
// Unregister caption size dependencies
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
Cell cell = layout.widgetToCell.get(child.getWidget());
cell.slot.setCaption(null);
}
if (needCaptionUpdate) {
needCaptionUpdate = false;
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
updateCaption(child);
}
}
--- /dev/null
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui.helloworldfeature;
+
+import com.vaadin.terminal.gwt.client.communication.ClientRpc;
+
+public interface GreetAgainRpc extends ClientRpc {
+
+ public void greetAgain();
+
+}
--- /dev/null
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui.helloworldfeature;
+
+import com.google.gwt.user.client.Window;
+import com.vaadin.terminal.gwt.client.ServerConnector;
+import com.vaadin.terminal.gwt.client.Util;
+import com.vaadin.terminal.gwt.client.VConsole;
+import com.vaadin.terminal.gwt.client.communication.RpcProxy;
+import com.vaadin.terminal.gwt.client.ui.AbstractConnector;
+import com.vaadin.terminal.gwt.client.ui.Connect;
+import com.vaadin.ui.HelloWorldExtension;
+
+@Connect(HelloWorldExtension.class)
+public class HelloWorldExtensionConnector extends AbstractConnector {
+ HelloWorldRpc rpc = RpcProxy.create(HelloWorldRpc.class, this);
+
+ @Override
+ public HelloWorldState getState() {
+ return (HelloWorldState) super.getState();
+ }
+
+ @Override
+ protected void init() {
+ registerRpc(GreetAgainRpc.class, new GreetAgainRpc() {
+ public void greetAgain() {
+ greet();
+ }
+ });
+ }
+
+ @Override
+ public void setParent(ServerConnector parent) {
+ super.setParent(parent);
+ greet();
+ }
+
+ private void greet() {
+ String msg = getState().getGreeting() + " from "
+ + Util.getConnectorString(this) + " attached to "
+ + Util.getConnectorString(getParent());
+ VConsole.log(msg);
+
+ String response = Window.prompt(msg, "");
+ rpc.onMessageSent(response);
+ }
+}
--- /dev/null
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui.helloworldfeature;
+
+import com.vaadin.terminal.gwt.client.communication.ServerRpc;
+
+public interface HelloWorldRpc extends ServerRpc {
+ public void onMessageSent(String message);
+}
--- /dev/null
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui.helloworldfeature;
+
+import com.vaadin.terminal.gwt.client.communication.SharedState;
+
+public class HelloWorldState extends SharedState {
+ private String greeting = "Hello world";
+
+ public String getGreeting() {
+ return greeting;
+ }
+
+ public void setGreeting(String greeting) {
+ this.greeting = greeting;
+ }
+}
import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.ComponentContainerConnector;
import com.vaadin.terminal.gwt.client.ComponentState;
+import com.vaadin.terminal.gwt.client.ServerConnector;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VConsole;
import com.vaadin.terminal.gwt.client.ui.ManagedLayout;
needsSize.add(connector);
}
if (!isRelativeInDirection(connector, direction)) {
- ComponentConnector parent = connector.getParent();
- if (parent != null) {
- needsSize.add(parent);
+ ServerConnector parent = connector.getParent();
+ if (parent instanceof ComponentConnector) {
+ needsSize.add((ComponentConnector) parent);
}
}
if (connector instanceof ComponentContainerConnector) {
ComponentContainerConnector container = (ComponentContainerConnector) connector;
- for (ComponentConnector child : container.getChildren()) {
+ for (ComponentConnector child : container.getChildComponents()) {
if (isRelativeInDirection(child, direction)) {
resized.add(child);
}
private LayoutDependency findPotentiallyChangedScrollbar() {
ComponentConnector currentConnector = connector;
while (true) {
- ComponentContainerConnector parent = currentConnector
- .getParent();
- if (parent == null) {
+ ServerConnector parent = currentConnector.getParent();
+ if (!(parent instanceof ComponentConnector)) {
return null;
}
if (parent instanceof MayScrollChildren) {
return getDependency(currentConnector,
getOppositeDirection());
}
- currentConnector = parent;
+ currentConnector = (ComponentConnector) parent;
}
}
public ComponentConnector getScrollingBoundary(ComponentConnector connector) {
LayoutDependency dependency = getDependency(connector, HORIZONTAL);
if (!dependency.scrollingParentCached) {
- ComponentContainerConnector parent = dependency.connector
- .getParent();
+ ServerConnector parent = dependency.connector.getParent();
if (parent instanceof MayScrollChildren) {
dependency.scrollingBoundary = connector;
- } else if (parent != null) {
- dependency.scrollingBoundary = getScrollingBoundary(parent);
+ } else if (parent instanceof ComponentConnector) {
+ dependency.scrollingBoundary = getScrollingBoundary((ComponentConnector) parent);
} else {
// No scrolling parent
}
lm.unregisterDependency(this, layout.spacingMeasureElement);
// Unregister child caption listeners
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
VLayoutSlot slot = layout.getSlotForChild(child.getWidget());
slot.setCaption(null);
}
VMeasuringOrderedLayout layout = getWidget();
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
VLayoutSlot slot = layout.getSlotForChild(child.getWidget());
AlignmentInfo alignment = new AlignmentInfo(getState()
int currentIndex = 0;
VMeasuringOrderedLayout layout = getWidget();
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
Widget childWidget = child.getWidget();
VLayoutSlot slot = layout.getSlotForChild(childWidget);
super.onConnectorHierarchyChange(event);
// We always have 1 child, unless the child is hidden
Widget newChildWidget = null;
- if (getChildren().size() == 1) {
- ComponentConnector newChild = getChildren().get(0);
+ if (getChildComponents().size() == 1) {
+ ComponentConnector newChild = getChildComponents().get(0);
newChildWidget = newChild.getWidget();
}
*/
@Deprecated
public boolean hasSubWindow(WindowConnector wc) {
- return getChildren().contains(wc);
+ return getChildComponents().contains(wc);
}
/**
*/
public List<WindowConnector> getSubWindows() {
ArrayList<WindowConnector> windows = new ArrayList<WindowConnector>();
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
if (child instanceof WindowConnector) {
windows.add((WindowConnector) child);
}
onChildSizeChange();
}
- for (ComponentConnector c : getChildren()) {
+ for (ComponentConnector c : getChildComponents()) {
if (c instanceof WindowConnector) {
WindowConnector wc = (WindowConnector) c;
wc.setWindowOrderAndPosition();
splitPanel.setSplitPosition(splitPanel.position);
splitPanel.updateSizes();
// Report relative sizes in other direction for quicker propagation
- List<ComponentConnector> children = getChildren();
+ List<ComponentConnector> children = getChildComponents();
for (ComponentConnector child : children) {
reportOtherDimension(child);
}
import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.DirectionalManagedLayout;
import com.vaadin.terminal.gwt.client.Paintable;
+import com.vaadin.terminal.gwt.client.ServerConnector;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector;
Scheduler.get().scheduleFinally(new ScheduledCommand() {
public void execute() {
getLayoutManager().setNeedsMeasure(TableConnector.this);
- getLayoutManager().setNeedsMeasure(
- TableConnector.this.getParent());
+ ServerConnector parent = getParent();
+ if (parent instanceof ComponentConnector) {
+ getLayoutManager().setNeedsMeasure(
+ (ComponentConnector) parent);
+ }
getLayoutManager().setNeedsVerticalLayout(
TableConnector.this);
getLayoutManager().layoutNow();
// We always have 1 child, unless the child is hidden
Widget newChildWidget = null;
ComponentConnector newChild = null;
- if (getChildren().size() == 1) {
- newChild = getChildren().get(0);
+ if (getChildComponents().size() == 1) {
+ newChild = getChildComponents().get(0);
newChildWidget = newChild.getWidget();
}
private static final Logger logger = Logger
.getLogger(AbstractApplicationPortlet.class.getName());
- public static class WrappedHttpAndPortletRequest extends
+ private static class WrappedHttpAndPortletRequest extends
WrappedPortletRequest {
public WrappedHttpAndPortletRequest(PortletRequest request,
}
}
- public static class WrappedGateinRequest extends
+ private static class WrappedGateinRequest extends
WrappedHttpAndPortletRequest {
public WrappedGateinRequest(PortletRequest request,
DeploymentConfiguration deploymentConfiguration) {
}
}
- public static class WrappedLiferayRequest extends
+ private static class WrappedLiferayRequest extends
WrappedHttpAndPortletRequest {
public WrappedLiferayRequest(PortletRequest request,
}
- public static class AbstractApplicationPortletWrapper implements Callback {
+ private static class AbstractApplicationPortletWrapper implements Callback {
private final AbstractApplicationPortlet portlet;
AbstractApplicationPortletWrapper portletWrapper = new AbstractApplicationPortletWrapper(
this);
- WrappedPortletRequest wrappedRequest = createWrappedRequest(request);
+ WrappedPortletRequest wrappedRequest;
+
+ String portalInfo = request.getPortalContext().getPortalInfo()
+ .toLowerCase();
+ if (portalInfo.contains("liferay")) {
+ wrappedRequest = new WrappedLiferayRequest(request,
+ getDeploymentConfiguration());
+ } else if (portalInfo.contains("gatein")) {
+ wrappedRequest = new WrappedGateinRequest(request,
+ getDeploymentConfiguration());
+ } else {
+ wrappedRequest = new WrappedPortletRequest(request,
+ getDeploymentConfiguration());
+ }
WrappedPortletResponse wrappedResponse = new WrappedPortletResponse(
response, getDeploymentConfiguration());
}
}
- /**
- * Wraps the request in a (possibly portal specific) wrapped portlet
- * request.
- *
- * @param request
- * The original PortletRequest
- * @return A wrapped version of the PorletRequest
- */
- protected WrappedPortletRequest createWrappedRequest(PortletRequest request) {
- String portalInfo = request.getPortalContext().getPortalInfo()
- .toLowerCase();
- if (portalInfo.contains("liferay")) {
- return new WrappedLiferayRequest(request,
- getDeploymentConfiguration());
- } else if (portalInfo.contains("gatein")) {
- return new WrappedGateinRequest(request,
- getDeploymentConfiguration());
- } else {
- return new WrappedPortletRequest(request,
- getDeploymentConfiguration());
- }
-
- }
-
private DeploymentConfiguration getDeploymentConfiguration() {
return deploymentConfiguration;
}
import com.vaadin.external.json.JSONArray;
import com.vaadin.external.json.JSONException;
import com.vaadin.external.json.JSONObject;
+import com.vaadin.terminal.AbstractClientConnector;
import com.vaadin.terminal.CombinedRequest;
import com.vaadin.terminal.LegacyPaint;
import com.vaadin.terminal.PaintException;
import com.vaadin.ui.Component;
import com.vaadin.ui.DirtyConnectorTracker;
import com.vaadin.ui.HasComponents;
-import com.vaadin.ui.Panel;
import com.vaadin.ui.Root;
import com.vaadin.ui.Window;
logger.log(Level.FINE, "* Creating response to client");
if (repaintAll) {
getClientCache(root).clear();
- rootConnectorTracker.markAllComponentsDirty();
+ rootConnectorTracker.markAllConnectorsDirty();
// Reset sent locales
locales = null;
}
dirtyVisibleConnectors
- .addAll(getDirtyVisibleComponents(rootConnectorTracker));
+ .addAll(getDirtyVisibleConnectors(rootConnectorTracker));
logger.log(Level.FINE, "Found " + dirtyVisibleConnectors.size()
+ " dirty connectors to paint");
((Component) connector).updateState();
}
}
- rootConnectorTracker.markAllComponentsClean();
+ rootConnectorTracker.markAllConnectorsClean();
outWriter.print("\"changes\":[");
outWriter.print("\"hierarchy\":");
JSONObject hierarchyInfo = new JSONObject();
- for (Connector connector : dirtyVisibleConnectors) {
- if (connector instanceof HasComponents) {
- HasComponents parent = (HasComponents) connector;
- String parentConnectorId = parent.getConnectorId();
- JSONArray children = new JSONArray();
-
- for (Component child : getChildComponents(parent)) {
- if (isVisible(child)) {
- children.put(child.getConnectorId());
- }
- }
- try {
- hierarchyInfo.put(parentConnectorId, children);
- } catch (JSONException e) {
- throw new PaintException(
- "Failed to send hierarchy information about "
- + parentConnectorId + " to the client: "
- + e.getMessage(), e);
+ for (ClientConnector connector : dirtyVisibleConnectors) {
+ String connectorId = connector.getConnectorId();
+ JSONArray children = new JSONArray();
+
+ for (ClientConnector child : AbstractClientConnector
+ .getAllChildrenIteratable(connector)) {
+ if (isVisible(child)) {
+ children.put(child.getConnectorId());
}
}
+ try {
+ hierarchyInfo.put(connectorId, children);
+ } catch (JSONException e) {
+ throw new PaintException(
+ "Failed to send hierarchy information about "
+ + connectorId + " to the client: "
+ + e.getMessage(), e);
+ }
}
outWriter.append(hierarchyInfo.toString());
outWriter.print(", "); // close hierarchy
return cache;
}
+ /**
+ * Checks if the connector is visible in context. For Components,
+ * {@link #isVisible(Component)} is used. For other types of connectors, the
+ * contextual visibility of its first Component ancestor is used. If no
+ * Component ancestor is found, the connector is not visible.
+ *
+ * @param connector
+ * The connector to check
+ * @return <code>true</code> if the connector is visible to the client,
+ * <code>false</code> otherwise
+ */
+ static boolean isVisible(ClientConnector connector) {
+ if (connector instanceof Component) {
+ return isVisible((Component) connector);
+ } else {
+ ClientConnector parent = connector.getParent();
+ if (parent == null) {
+ return false;
+ } else {
+ return isVisible(parent);
+ }
+ }
+ }
+
/**
* Checks if the component is visible in context, i.e. returns false if the
* child is hidden, the parent is hidden or the parent says the child should
}
- public static Iterable<Component> getChildComponents(HasComponents cc) {
- // TODO This must be moved to Root/Panel
- if (cc instanceof Root) {
- Root root = (Root) cc;
- List<Component> children = new ArrayList<Component>();
- if (root.getContent() != null) {
- children.add(root.getContent());
- }
- for (Window w : root.getWindows()) {
- children.add(w);
- }
- return children;
- } else if (cc instanceof Panel) {
- // This is so wrong.. (#2924)
- if (((Panel) cc).getContent() == null) {
- return Collections.emptyList();
- } else {
- return Collections.singleton((Component) ((Panel) cc)
- .getContent());
- }
- }
- return cc;
- }
-
/**
* Collects all pending RPC calls from listed {@link ClientConnector}s and
* clears their RPC queues.
* root window for which dirty components is to be fetched
* @return
*/
- private ArrayList<Component> getDirtyVisibleComponents(
+ private ArrayList<ClientConnector> getDirtyVisibleConnectors(
DirtyConnectorTracker dirtyConnectorTracker) {
- ArrayList<Component> dirtyComponents = new ArrayList<Component>();
- for (Component c : dirtyConnectorTracker.getDirtyComponents()) {
+ ArrayList<ClientConnector> dirtyConnectors = new ArrayList<ClientConnector>();
+ for (ClientConnector c : dirtyConnectorTracker.getDirtyConnectors()) {
if (isVisible(c)) {
- dirtyComponents.add(c);
+ dirtyConnectors.add(c);
}
}
- return dirtyComponents;
+ return dirtyConnectors;
}
/**
*/
package com.vaadin.terminal.gwt.server;
+import java.util.Iterator;
import java.util.List;
+import com.vaadin.terminal.AbstractClientConnector;
+import com.vaadin.terminal.Extension;
import com.vaadin.terminal.gwt.client.Connector;
import com.vaadin.terminal.gwt.client.communication.SharedState;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.ComponentContainer;
+import com.vaadin.ui.Root;
/**
* Interface implemented by all connectors that are capable of communicating
*/
public Class<? extends SharedState> getStateType();
+ public ClientConnector getParent();
+
+ /**
+ * Requests that the connector should be repainted as soon as possible.
+ */
+ public void requestRepaint();
+
+ /**
+ * Causes a repaint of this connector, and all connectors below it.
+ *
+ * This should only be used in special cases, e.g when the state of a
+ * descendant depends on the state of a ancestor.
+ */
+ public void requestRepaintAll();
+
+ /**
+ * Sets the parent connector of the connector.
+ *
+ * <p>
+ * This method automatically calls {@link #attach()} if the parent becomes
+ * attached to the application, regardless of whether it was attached
+ * previously. Conversely, if the parent is {@code null} and the connector
+ * is attached to the application, {@link #detach()} is called for the
+ * connector.
+ * </p>
+ * <p>
+ * This method is rarely called directly. One of the
+ * {@link ComponentContainer#addComponent(Component)} or
+ * {@link AbstractClientConnector#addFeature(Feature)} methods is normally
+ * used for adding connectors to a container and it will call this method
+ * implicitly.
+ * </p>
+ *
+ * <p>
+ * It is not possible to change the parent without first setting the parent
+ * to {@code null}.
+ * </p>
+ *
+ * @param parent
+ * the parent connector
+ * @throws IllegalStateException
+ * if a parent is given even though the connector already has a
+ * parent
+ */
+ public void setParent(ClientConnector parent);
+
+ /**
+ * Notifies the connector that it is connected to an application.
+ *
+ * <p>
+ * The caller of this method is {@link #setParent(ClientConnector)} if the
+ * parent is itself already attached to the application. If not, the parent
+ * will call the {@link #attach()} for all its children when it is attached
+ * to the application. This method is always called before the connector is
+ * painted for the first time.
+ * </p>
+ *
+ * <p>
+ * The attachment logic is implemented in {@link AbstractClientConnector}.
+ * </p>
+ *
+ * @see #getApplication()
+ */
+ public void attach();
+
+ /**
+ * Notifies the component that it is detached from the application.
+ *
+ * <p>
+ * The {@link #getApplication()} and {@link #getRoot()} methods might return
+ * <code>null</code> after this method is called.
+ * </p>
+ *
+ * <p>
+ * This method must call {@link Root#componentDetached(Component)} to let
+ * the Root know that a new Component has been attached.
+ * </p>
+ * *
+ * <p>
+ * The caller of this method is {@link #setParent(Component)} if the parent
+ * is in the application. When the parent is detached from the application
+ * it is its response to call {@link #detach()} for all the children and to
+ * detach itself from the terminal.
+ * </p>
+ */
+ public void detach();
+
+ public Iterator<Extension> getExtensionIterator();
+
+ public void removeExtension(Extension feature);
}
package com.vaadin.terminal.gwt.server;
import java.io.PrintWriter;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import com.vaadin.event.dd.TargetDetails;
import com.vaadin.event.dd.TargetDetailsImpl;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
+import com.vaadin.terminal.Extension;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.VariableOwner;
import com.vaadin.terminal.gwt.client.communication.SharedState;
public Class<? extends SharedState> getStateType() {
return SharedState.class;
}
+
+ public void requestRepaint() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public ClientConnector getParent() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void requestRepaintAll() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setParent(ClientConnector parent) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void attach() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void detach() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public Iterator<Extension> getExtensionIterator() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void removeExtension(Extension feature) {
+ // TODO Auto-generated method stub
+
+ }
}
import com.vaadin.terminal.VariableOwner;
import com.vaadin.terminal.gwt.client.Connector;
import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Component;
import com.vaadin.ui.CustomLayout;
/**
}
- public void addAttribute(String name, ClientConnector value)
+ public void addAttribute(String name, Component value)
throws PaintException {
final String id = value.getConnectorId();
addAttribute(name, id);
}
public void addVariable(VariableOwner owner, String name,
- ClientConnector value) throws PaintException {
+ Component value) throws PaintException {
tag.addVariable(new StringVariable(owner, name, value.getConnectorId()));
}
* @see com.vaadin.terminal.PaintTarget#startPaintable(com.vaadin.terminal
* .Paintable, java.lang.String)
*/
- public PaintStatus startPaintable(ClientConnector connector, String tagName)
+ public PaintStatus startPaintable(Component connector, String tagName)
throws PaintException {
boolean topLevelPaintable = openPaintables.isEmpty();
return PaintStatus.PAINTING;
}
- public void endPaintable(ClientConnector paintable) throws PaintException {
+ public void endPaintable(Component paintable) throws PaintException {
logger.fine("endPaintable for " + paintable.getClass().getName() + "@"
+ Integer.toHexString(paintable.hashCode()));
import java.util.HashSet;
import com.vaadin.terminal.gwt.client.ComponentConnector;
+import com.vaadin.terminal.gwt.client.ServerConnector;
import com.vaadin.terminal.gwt.client.ui.Connect;
import com.vaadin.terminal.gwt.client.ui.Connect.LoadStyle;
private Collection<Class<? extends ComponentConnector>> deferredPaintables = new HashSet<Class<? extends ComponentConnector>>();
@Override
- protected LoadStyle getLoadStyle(
- Class<? extends ComponentConnector> connector) {
+ protected LoadStyle getLoadStyle(Class<? extends ServerConnector> connector) {
if (eagerPaintables == null) {
init();
}
*/
package com.vaadin.terminal.gwt.widgetsetutils;
-import com.vaadin.terminal.gwt.client.ComponentConnector;
+import com.vaadin.terminal.gwt.client.ServerConnector;
import com.vaadin.terminal.gwt.client.ui.Connect.LoadStyle;
/**
public class EagerWidgetMapGenerator extends WidgetMapGenerator {
@Override
- protected LoadStyle getLoadStyle(
- Class<? extends ComponentConnector> connector) {
+ protected LoadStyle getLoadStyle(Class<? extends ServerConnector> connector) {
return LoadStyle.EAGER;
}
}
*/
package com.vaadin.terminal.gwt.widgetsetutils;
-import com.vaadin.terminal.gwt.client.ComponentConnector;
+import com.vaadin.terminal.gwt.client.ServerConnector;
import com.vaadin.terminal.gwt.client.ui.Connect.LoadStyle;
/**
*/
public class LazyWidgetMapGenerator extends WidgetMapGenerator {
@Override
- protected LoadStyle getLoadStyle(
- Class<? extends ComponentConnector> connector) {
+ protected LoadStyle getLoadStyle(Class<? extends ServerConnector> connector) {
return LoadStyle.LAZY;
}
// Generate serializer classes for each subclass of SharedState
JClassType serializerType = typeOracle.findType(SharedState.class
.getName());
+ types.add(serializerType);
JClassType[] serializerSubtypes = serializerType.getSubtypes();
for (JClassType type : serializerSubtypes) {
types.add(type);
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
-import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.Connector;
+import com.vaadin.terminal.gwt.client.ServerConnector;
import com.vaadin.terminal.gwt.client.ui.Connect;
import com.vaadin.terminal.gwt.client.ui.Connect.LoadStyle;
import com.vaadin.terminal.gwt.client.ui.UnknownComponentConnector;
*/
public class WidgetMapGenerator extends Generator {
- private static String componentConnectorClassName = ComponentConnector.class
+ private static String serverConnectorClassName = ServerConnector.class
.getName();
private String packageName;
return;
}
logger.log(Type.INFO,
- "Detecting Vaadin components in classpath to generate WidgetMapImpl.java ...");
+ "Detecting Vaadin connectors in classpath to generate WidgetMapImpl.java ...");
Date date = new Date();
// init composer, set class properties, create source writer
SourceWriter sourceWriter = composer.createSourceWriter(context,
printWriter);
- Collection<Class<? extends ComponentConnector>> connectors = getUsedConnectors(context
+ Collection<Class<? extends ServerConnector>> connectors = getUsedConnectors(context
.getTypeOracle());
validateConnectors(logger, connectors);
}
private void validateConnectors(TreeLogger logger,
- Collection<Class<? extends ComponentConnector>> connectors) {
+ Collection<Class<? extends ServerConnector>> connectors) {
- Iterator<Class<? extends ComponentConnector>> iter = connectors
- .iterator();
+ Iterator<Class<? extends ServerConnector>> iter = connectors.iterator();
while (iter.hasNext()) {
- Class<? extends ComponentConnector> connectorClass = iter.next();
+ Class<? extends ServerConnector> connectorClass = iter.next();
Connect annotation = connectorClass.getAnnotation(Connect.class);
if (!ClientConnector.class.isAssignableFrom(annotation.value())) {
logger.log(
}
private void logConnectors(TreeLogger logger, GeneratorContext context,
- Collection<Class<? extends ComponentConnector>> connectors) {
+ Collection<Class<? extends ServerConnector>> connectors) {
logger.log(Type.INFO,
"Widget set will contain implementations for following component connectors: ");
TreeSet<String> classNames = new TreeSet<String>();
HashMap<String, String> loadStyle = new HashMap<String, String>();
- for (Class<? extends ComponentConnector> connectorClass : connectors) {
+ for (Class<? extends ServerConnector> connectorClass : connectors) {
String className = connectorClass.getCanonicalName();
classNames.add(className);
if (getLoadStyle(connectorClass) == LoadStyle.DEFERRED) {
* widgetset
*/
@SuppressWarnings("unchecked")
- private Collection<Class<? extends ComponentConnector>> getUsedConnectors(
+ private Collection<Class<? extends ServerConnector>> getUsedConnectors(
TypeOracle typeOracle) {
JClassType connectorType = typeOracle.findType(Connector.class
.getName());
- Collection<Class<? extends ComponentConnector>> connectors = new HashSet<Class<? extends ComponentConnector>>();
+ Collection<Class<? extends ServerConnector>> connectors = new HashSet<Class<? extends ServerConnector>>();
for (JClassType jClassType : connectorType.getSubtypes()) {
Connect annotation = jClassType.getAnnotation(Connect.class);
if (annotation != null) {
try {
- Class<? extends ComponentConnector> clazz = (Class<? extends ComponentConnector>) Class
+ Class<? extends ServerConnector> clazz = (Class<? extends ServerConnector>) Class
.forName(jClassType.getQualifiedSourceName());
connectors.add(clazz);
} catch (ClassNotFoundException e) {
* @return true iff the widget for given component should be lazy loaded by
* the client side engine
*/
- protected LoadStyle getLoadStyle(
- Class<? extends ComponentConnector> connector) {
+ protected LoadStyle getLoadStyle(Class<? extends ServerConnector> connector) {
Connect annotation = connector.getAnnotation(Connect.class);
return annotation.loadStyle();
}
private void generateInstantiatorMethod(
SourceWriter sourceWriter,
- Collection<Class<? extends ComponentConnector>> connectorsHavingComponentAnnotation) {
+ Collection<Class<? extends ServerConnector>> connectorsHavingComponentAnnotation) {
Collection<Class<?>> deferredWidgets = new LinkedList<Class<?>>();
// lookup with index than with the hashmap
sourceWriter.println("public void ensureInstantiator(Class<? extends "
- + componentConnectorClassName + "> classType) {");
+ + serverConnectorClassName + "> classType) {");
sourceWriter.println("if(!instmap.containsKey(classType)){");
boolean first = true;
- ArrayList<Class<? extends ComponentConnector>> lazyLoadedWidgets = new ArrayList<Class<? extends ComponentConnector>>();
+ ArrayList<Class<? extends ServerConnector>> lazyLoadedConnectors = new ArrayList<Class<? extends ServerConnector>>();
- HashSet<Class<? extends com.vaadin.terminal.gwt.client.ComponentConnector>> connectorsWithInstantiator = new HashSet<Class<? extends com.vaadin.terminal.gwt.client.ComponentConnector>>();
+ HashSet<Class<? extends ServerConnector>> connectorsWithInstantiator = new HashSet<Class<? extends ServerConnector>>();
- for (Class<? extends ComponentConnector> class1 : connectorsHavingComponentAnnotation) {
- Class<? extends ComponentConnector> clientClass = class1;
+ for (Class<? extends ServerConnector> class1 : connectorsHavingComponentAnnotation) {
+ Class<? extends ServerConnector> clientClass = class1;
if (connectorsWithInstantiator.contains(clientClass)) {
continue;
}
+ ".class) {");
String instantiator = "new WidgetInstantiator() {\n public "
- + componentConnectorClassName
+ + serverConnectorClassName
+ " get() {\n return GWT.create(" + clientClass.getName()
+ ".class );\n}\n}\n";
+ clientClass.getName()
+ ".class,"
+ instantiator + ");}});\n");
- lazyLoadedWidgets.add(class1);
+ lazyLoadedConnectors.add(class1);
if (loadStyle == LoadStyle.DEFERRED) {
deferredWidgets.add(class1);
sourceWriter.println("}");
sourceWriter.println("public Class<? extends "
- + componentConnectorClassName
- + ">[] getDeferredLoadedWidgets() {");
+ + serverConnectorClassName
+ + ">[] getDeferredLoadedConnectors() {");
sourceWriter.println("return new Class[] {");
first = true;
// TODO an index of last ensured widget in array
- sourceWriter.println("public " + componentConnectorClassName
- + " instantiate(Class<? extends " + componentConnectorClassName
+ sourceWriter.println("public " + serverConnectorClassName
+ + " instantiate(Class<? extends " + serverConnectorClassName
+ "> classType) {");
sourceWriter.indent();
- sourceWriter.println(componentConnectorClassName
+ sourceWriter.println(serverConnectorClassName
+ " p = super.instantiate(classType); if(p!= null) return p;");
sourceWriter.println("return instmap.get(classType).get();");
*/
private void generateImplementationDetector(
SourceWriter sourceWriter,
- Collection<Class<? extends ComponentConnector>> paintablesHavingWidgetAnnotation) {
+ Collection<Class<? extends ServerConnector>> paintablesHavingWidgetAnnotation) {
sourceWriter
.println("public Class<? extends "
- + componentConnectorClassName
+ + serverConnectorClassName
+ "> "
+ "getConnectorClassForServerSideClassName(String fullyQualifiedName) {");
sourceWriter.indent();
sourceWriter
.println("fullyQualifiedName = fullyQualifiedName.intern();");
- for (Class<? extends ComponentConnector> connectorClass : paintablesHavingWidgetAnnotation) {
+ for (Class<? extends ServerConnector> connectorClass : paintablesHavingWidgetAnnotation) {
Class<? extends ClientConnector> clientConnectorClass = getClientConnectorClass(connectorClass);
sourceWriter.print("if ( fullyQualifiedName == \"");
sourceWriter.print(clientConnectorClass.getName());
}
private static Class<? extends ClientConnector> getClientConnectorClass(
- Class<? extends ComponentConnector> connectorClass) {
+ Class<? extends ServerConnector> connectorClass) {
Connect annotation = connectorClass.getAnnotation(Connect.class);
return (Class<? extends ClientConnector>) annotation.value();
}
// connectorId unless the component is attached to the application so
// the String->String map cannot be populated in internal* either.
Map<String, String> connectorToPosition = new HashMap<String, String>();
- for (Component c : this) {
+ for (Iterator<Component> ci = getComponentIterator(); ci.hasNext();) {
+ Component c = ci.next();
connectorToPosition.put(c.getConnectorId(), getPosition(c)
.getCSSString());
}
package com.vaadin.ui;
import java.io.Serializable;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
-import java.util.Map;
-import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.vaadin.event.EventRouter;
import com.vaadin.event.MethodEventSource;
import com.vaadin.event.ShortcutListener;
+import com.vaadin.terminal.AbstractClientConnector;
import com.vaadin.terminal.ErrorMessage;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.Terminal;
import com.vaadin.terminal.gwt.client.ComponentState;
-import com.vaadin.terminal.gwt.client.communication.ClientRpc;
-import com.vaadin.terminal.gwt.client.communication.ServerRpc;
-import com.vaadin.terminal.gwt.server.ClientMethodInvocation;
+import com.vaadin.terminal.gwt.server.ClientConnector;
import com.vaadin.terminal.gwt.server.ComponentSizeValidator;
import com.vaadin.terminal.gwt.server.ResourceReference;
-import com.vaadin.terminal.gwt.server.RpcManager;
-import com.vaadin.terminal.gwt.server.RpcTarget;
-import com.vaadin.terminal.gwt.server.ServerRpcManager;
import com.vaadin.tools.ReflectTools;
/**
* @since 3.0
*/
@SuppressWarnings("serial")
-public abstract class AbstractComponent implements Component, MethodEventSource {
+public abstract class AbstractComponent extends AbstractClientConnector
+ implements Component, MethodEventSource {
/* Private members */
*/
private Object applicationData;
- /**
- * The container this component resides in.
- */
- private HasComponents parent = null;
-
/**
* The EventRouter used for the event model.
*/
*/
private boolean delayedFocus;
- /**
- * List of repaint request listeners or null if not listened at all.
- */
- private LinkedList<RepaintRequestListener> repaintRequestListeners = null;
-
/* Sizeable fields */
private float width = SIZE_UNDEFINED;
*/
private ActionManager actionManager;
- /**
- * A map from client to server RPC interface class to the RPC call manager
- * that handles incoming RPC calls for that interface.
- */
- private Map<Class<?>, RpcManager> rpcManagerMap = new HashMap<Class<?>, RpcManager>();
-
- /**
- * A map from server to client RPC interface class to the RPC proxy that
- * sends ourgoing RPC calls for that interface.
- */
- private Map<Class<?>, ClientRpc> rpcProxyMap = new HashMap<Class<?>, ClientRpc>();
-
- /**
- * Shared state object to be communicated from the server to the client when
- * modified.
- */
- private ComponentState sharedState;
-
- /**
- * Pending RPC method invocations to be sent.
- */
- private ArrayList<ClientMethodInvocation> pendingInvocations = new ArrayList<ClientMethodInvocation>();
-
- private String connectorId;
-
/* Constructor */
/**
if (locale != null) {
return locale;
}
+ HasComponents parent = getParent();
if (parent != null) {
return parent.getLocale();
}
*
* @see com.vaadin.terminal.gwt.client.Connector#isConnectorEnabled()
*/
+ @Override
public boolean isConnectorEnabled() {
- if (getParent() == null) {
- // No parent -> the component cannot receive updates from the client
+ if (!isVisible()) {
+ return false;
+ } else if (!isEnabled()) {
+ return false;
+ } else if (!super.isConnectorEnabled()) {
+ return false;
+ } else if (!getParent().isComponentVisible(this)) {
return false;
} else {
- boolean thisEnabledAndVisible = isEnabled() && isVisible();
- if (!thisEnabledAndVisible) {
- return false;
- }
-
- if (!getParent().isConnectorEnabled()) {
- return false;
- }
-
- return getParent().isComponentVisible(this);
+ return true;
}
}
* Gets the component's parent component. Don't add a JavaDoc comment here,
* we use the default documentation from implemented interface.
*/
+ @Override
public HasComponents getParent() {
- return parent;
+ return (HasComponents) super.getParent();
+ }
+
+ @Override
+ public void setParent(ClientConnector parent) {
+ if (parent == null || parent instanceof HasComponents) {
+ super.setParent(parent);
+ } else {
+ throw new IllegalArgumentException(
+ "The parent of a Component must implement HasComponents, which "
+ + parent.getClass() + " doesn't do.");
+ }
}
/**
return null;
}
- /*
- * Sets the parent component. Don't add a JavaDoc comment here, we use the
- * default documentation from implemented interface.
- */
- public void setParent(HasComponents parent) {
-
- // If the parent is not changed, don't do anything
- if (parent == this.parent) {
- return;
- }
-
- if (parent != null && this.parent != null) {
- throw new IllegalStateException(getClass().getName()
- + " already has a parent.");
- }
-
- // Send detach event if the component have been connected to a window
- if (getApplication() != null) {
- detach();
- }
-
- // Connect to new parent
- this.parent = parent;
-
- // Send attach event if connected to a window
- if (getApplication() != null) {
- attach();
- }
- }
-
/**
* Gets the error message for this component.
*
* Gets the parent window of the component. Don't add a JavaDoc comment
* here, we use the default documentation from implemented interface.
*/
+ @Override
public Root getRoot() {
- if (parent == null) {
- return null;
- } else {
- return parent.getRoot();
- }
+ // Just make method from implemented Component interface public
+ return super.getRoot();
}
/*
* comment here, we use the default documentation from implemented
* interface.
*/
+ @Override
public void attach() {
- getRoot().componentAttached(this);
- requestRepaint();
+ super.attach();
if (delayedFocus) {
focus();
}
* Detach the component from application. Don't add a JavaDoc comment here,
* we use the default documentation from implemented interface.
*/
+ @Override
public void detach() {
if (actionManager != null) {
// Remove any existing viewer. Root cast is just to make the
// compiler happy
actionManager.setViewer((Root) null);
}
- getRoot().componentDetached(this);
}
/**
* @return the parent application of the component or <code>null</code>.
* @see #attach()
*/
+ @Override
public Application getApplication() {
- if (parent == null) {
- return null;
- } else {
- return parent.getApplication();
- }
+ // Just make method inherited from Component interface public
+ return super.getApplication();
}
/**
*
* @return updated component shared state
*/
+ @Override
public ComponentState getState() {
- if (null == sharedState) {
- sharedState = createState();
- }
- return sharedState;
+ return (ComponentState) super.getState();
}
/*
}
}
- /**
- * Creates the shared state bean to be used in server to client
- * communication.
- * <p>
- * By default a state object of the defined return type of
- * {@link #getState()} is created. Subclasses can override this method and
- * return a new instance of the correct state class but this should rarely
- * be necessary.
- * </p>
- * <p>
- * No configuration of the values of the state should be performed in
- * {@link #createState()}.
- *
- * @since 7.0
- *
- * @return new shared state object
- */
- protected ComponentState createState() {
- try {
- return getStateType().newInstance();
- } catch (Exception e) {
- throw new RuntimeException(
- "Error creating state of type " + getStateType().getName()
- + " for " + getClass().getName(), e);
- }
- }
-
- /* (non-Javadoc)
- * @see com.vaadin.terminal.gwt.server.ClientConnector#getStateType()
- */
- public Class<? extends ComponentState> getStateType() {
- try {
- Method m = getClass().getMethod("getState", (Class[]) null);
- Class<? extends ComponentState> type = (Class<? extends ComponentState>) m
- .getReturnType();
- return type;
- } catch (Exception e) {
- throw new RuntimeException("Error finding state type for "
- + getClass().getName(), e);
- }
- }
-
/* Documentation copied from interface */
+ @Override
public void requestRepaint() {
// Invisible components (by flag in this particular component) do not
// need repaints
if (!getState().isVisible()) {
return;
}
-
- fireRequestRepaintEvent();
- }
-
- /**
- * Fires the repaint request event.
- *
- * @param alreadyNotified
- */
- // Notify listeners only once
- private void fireRequestRepaintEvent() {
- // Notify the listeners
- if (repaintRequestListeners != null
- && !repaintRequestListeners.isEmpty()) {
- final Object[] listeners = repaintRequestListeners.toArray();
- final RepaintRequestEvent event = new RepaintRequestEvent(this);
- for (int i = 0; i < listeners.length; i++) {
- ((RepaintRequestListener) listeners[i]).repaintRequested(event);
- }
- }
- }
-
- /* Documentation copied from interface */
- public void addListener(RepaintRequestListener listener) {
- if (repaintRequestListeners == null) {
- repaintRequestListeners = new LinkedList<RepaintRequestListener>();
- }
- if (!repaintRequestListeners.contains(listener)) {
- repaintRequestListeners.add(listener);
- }
- }
-
- /* Documentation copied from interface */
- public void removeListener(RepaintRequestListener listener) {
- if (repaintRequestListeners != null) {
- repaintRequestListeners.remove(listener);
- if (repaintRequestListeners.isEmpty()) {
- repaintRequestListeners = null;
- }
- }
+ super.requestRepaint();
}
/* General event framework */
* are found.
*/
public Collection<?> getListeners(Class<?> eventType) {
- if (eventType.isAssignableFrom(RepaintRequestEvent.class)) {
- // RepaintRequestListeners are not stored in eventRouter
- if (repaintRequestListeners == null) {
- return Collections.EMPTY_LIST;
- } else {
- return Collections
- .unmodifiableCollection(repaintRequestListeners);
- }
- }
if (eventRouter == null) {
return Collections.EMPTY_LIST;
}
actionManager.removeAction(shortcut);
}
}
-
- /**
- * Registers an RPC interface implementation for this component.
- *
- * A component can listen to multiple RPC interfaces, and subclasses can
- * register additional implementations.
- *
- * @since 7.0
- *
- * @param implementation
- * RPC interface implementation
- * @param rpcInterfaceType
- * RPC interface class for which the implementation should be
- * registered
- */
- protected <T> void registerRpc(T implementation, Class<T> rpcInterfaceType) {
- rpcManagerMap.put(rpcInterfaceType, new ServerRpcManager<T>(
- implementation, rpcInterfaceType));
- }
-
- /**
- * Registers an RPC interface implementation for this component.
- *
- * A component can listen to multiple RPC interfaces, and subclasses can
- * register additional implementations.
- *
- * @since 7.0
- *
- * @param implementation
- * RPC interface implementation. Also used to deduce the type.
- */
- protected <T extends ServerRpc> void registerRpc(T implementation) {
- Class<?> cls = implementation.getClass();
- Class<?>[] interfaces = cls.getInterfaces();
- while (interfaces.length == 0) {
- // Search upwards until an interface is found. It must be found as T
- // extends ServerRpc
- cls = cls.getSuperclass();
- interfaces = cls.getInterfaces();
- }
- if (interfaces.length != 1
- || !(ServerRpc.class.isAssignableFrom(interfaces[0]))) {
- throw new RuntimeException(
- "Use registerRpc(T implementation, Class<T> rpcInterfaceType) if the Rpc implementation implements more than one interface");
- }
- Class<T> type = (Class<T>) interfaces[0];
- registerRpc(implementation, type);
- }
-
- /**
- * Returns an RPC proxy for a given server to client RPC interface for this
- * component.
- *
- * TODO more javadoc, subclasses, ...
- *
- * @param rpcInterface
- * RPC interface type
- *
- * @since 7.0
- */
- public <T extends ClientRpc> T getRpcProxy(final Class<T> rpcInterface) {
- // create, initialize and return a dynamic proxy for RPC
- try {
- if (!rpcProxyMap.containsKey(rpcInterface)) {
- Class<T> proxyClass = (Class) Proxy.getProxyClass(
- rpcInterface.getClassLoader(), rpcInterface);
- Constructor<T> constructor = proxyClass
- .getConstructor(InvocationHandler.class);
- T rpcProxy = constructor.newInstance(new RpcInvoicationHandler(
- rpcInterface));
- // cache the proxy
- rpcProxyMap.put(rpcInterface, rpcProxy);
- }
- return (T) rpcProxyMap.get(rpcInterface);
- } catch (Exception e) {
- // TODO exception handling?
- throw new RuntimeException(e);
- }
- }
-
- private class RpcInvoicationHandler implements InvocationHandler,
- Serializable {
-
- private String rpcInterfaceName;
-
- public RpcInvoicationHandler(Class<?> rpcInterface) {
- rpcInterfaceName = rpcInterface.getName().replaceAll("\\$", ".");
- }
-
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- addMethodInvocationToQueue(rpcInterfaceName, method, args);
- // TODO no need to do full repaint if only RPC calls
- requestRepaint();
- return null;
- }
-
- }
-
- /**
- * For internal use: adds a method invocation to the pending RPC call queue.
- *
- * @param interfaceName
- * RPC interface name
- * @param methodName
- * RPC method name
- * @param parameters
- * RPC vall parameters
- *
- * @since 7.0
- */
- protected void addMethodInvocationToQueue(String interfaceName,
- Method method, Object[] parameters) {
- // add to queue
- pendingInvocations.add(new ClientMethodInvocation(this, interfaceName,
- method, parameters));
- }
-
- /**
- * @see RpcTarget#getRpcManager(Class)
- *
- * @param rpcInterface
- * RPC interface for which a call was made
- * @return RPC Manager handling calls for the interface
- *
- * @since 7.0
- */
- public RpcManager getRpcManager(Class<?> rpcInterface) {
- return rpcManagerMap.get(rpcInterface);
- }
-
- public List<ClientMethodInvocation> retrievePendingRpcCalls() {
- if (pendingInvocations.isEmpty()) {
- return Collections.emptyList();
- } else {
- List<ClientMethodInvocation> result = pendingInvocations;
- pendingInvocations = new ArrayList<ClientMethodInvocation>();
- return Collections.unmodifiableList(result);
- }
- }
-
- public String getConnectorId() {
- if (connectorId == null) {
- if (getApplication() == null) {
- throw new RuntimeException(
- "Component must be attached to an application when getConnectorId() is called for the first time");
- }
- connectorId = getApplication().createConnectorId(this);
- }
- return connectorId;
- }
-
- private Logger getLogger() {
- return Logger.getLogger(AbstractComponent.class.getName());
- }
}
}
}
- /**
- * Notifies all contained components that the container is attached to a
- * window.
- *
- * @see com.vaadin.ui.Component#attach()
- */
- @Override
- public void attach() {
- super.attach();
-
- for (final Iterator<Component> i = getComponentIterator(); i.hasNext();) {
- (i.next()).attach();
- }
- }
-
- /**
- * Notifies all contained components that the container is detached from a
- * window.
- *
- * @see com.vaadin.ui.Component#detach()
- */
- @Override
- public void detach() {
- super.detach();
-
- for (final Iterator<Component> i = getComponentIterator(); i.hasNext();) {
- (i.next()).detach();
- }
- }
-
/* Events */
private static final Method COMPONENT_ATTACHED_METHOD;
true);
}
- public void requestRepaintAll() {
- requestRepaintAll(this);
- }
-
- /**
- * Helper that implements the logic needed by requestRepaintAll. Calls
- * requestRepaintAll/requestRepaint for the component container and all its
- * children recursively.
- *
- * @param container
- */
- public static void requestRepaintAll(HasComponents container) {
- container.requestRepaint();
- if (container instanceof Panel) {
- Panel p = (Panel) container;
- // #2924 Panel is invalid, really invalid.
- // Panel.getComponentIterator returns the children of content, not
- // of Panel...
- if (p.getContent() != null) {
- p.getContent().requestRepaint();
- }
- }
- for (Iterator<Component> childIterator = container
- .getComponentIterator(); childIterator.hasNext();) {
- Component c = childIterator.next();
- if (c instanceof HasComponents) {
- requestRepaintAll((HasComponents) c);
- } else {
- c.requestRepaint();
- }
- }
- }
-
- /**
- * Returns an iterator for the child components.
- *
- * @return An iterator for the child components.
- * @see #getComponentIterator()
- * @since 7.0.0
- */
public Iterator<Component> iterator() {
return getComponentIterator();
}
* </p>
*
* @return the parent component
- * @see #setParent(Component)
*/
public HasComponents getParent();
- /**
- * Sets the parent component of the component.
- *
- * <p>
- * This method automatically calls {@link #attach()} if the parent becomes
- * attached to the application, regardless of whether it was attached
- * previously. Conversely, if the parent is {@code null} and the component
- * is attached to the application, {@link #detach()} is called for the
- * component.
- * </p>
- * <p>
- * This method is rarely called directly. The
- * {@link ComponentContainer#addComponent(Component)} method is normally
- * used for adding components to a container and it will call this method
- * implicitly.
- * </p>
- *
- * <p>
- * It is not possible to change the parent without first setting the parent
- * to {@code null}.
- * </p>
- *
- * @param parent
- * the parent component
- * @throws IllegalStateException
- * if a parent is given even though the component already has a
- * parent
- */
- public void setParent(HasComponents parent);
-
/**
* Tests whether the component is in the read-only mode. The user can not
* change the value of a read-only component. As only {@link Field}
public Application getApplication();
/**
- * Notifies the component that it is connected to an application.
- *
- * <p>
- * The caller of this method is {@link #setParent(Component)} if the parent
- * is itself already attached to the application. If not, the parent will
- * call the {@link #attach()} for all its children when it is attached to
- * the application. This method is always called before the component is
- * painted for the first time.
- * </p>
+ * {@inheritDoc}
*
* <p>
* Reimplementing the {@code attach()} method is useful for tasks that need
* }
* }
* </pre>
- *
- * <p>
- * The attachment logic is implemented in {@link AbstractComponent}.
- * </p>
- *
- * @see #getApplication()
*/
public void attach();
- /**
- * Notifies the component that it is detached from the application.
- *
- * <p>
- * The {@link #getApplication()} and {@link #getRoot()} methods might return
- * <code>null</code> after this method is called.
- * </p>
- *
- * <p>
- * This method must call {@link Root#componentDetached(Component)} to let
- * the Root know that a new Component has been attached.
- * </p>
- * *
- * <p>
- * The caller of this method is {@link #setParent(Component)} if the parent
- * is in the application. When the parent is detached from the application
- * it is its response to call {@link #detach()} for all the children and to
- * detach itself from the terminal.
- * </p>
- */
- public void detach();
-
/**
* Gets the locale of the component.
*
*/
public String getDebugId();
- /**
- * Requests that the component should be repainted as soon as possible.
- */
- public void requestRepaint();
-
- /**
- * Repaint request event is thrown when the connector needs to be repainted.
- * This is typically done when the <code>paint</code> method would return
- * dissimilar UIDL from the previous call of the method.
- */
- @SuppressWarnings("serial")
- public static class RepaintRequestEvent extends EventObject {
-
- /**
- * Constructs a new event.
- *
- * @param source
- * the paintable needing repaint.
- */
- public RepaintRequestEvent(ClientConnector source) {
- super(source);
- }
-
- /**
- * Gets the connector needing repainting.
- *
- * @return Paintable for which the <code>paint</code> method will return
- * dissimilar UIDL from the previous call of the method.
- */
- public ClientConnector getConnector() {
- return (ClientConnector) getSource();
- }
- }
-
- /**
- * Listens repaint requests. The <code>repaintRequested</code> method is
- * called when the paintable needs to be repainted. This is typically done
- * when the <code>paint</code> method would return dissimilar UIDL from the
- * previous call of the method.
- */
- public interface RepaintRequestListener extends Serializable {
-
- /**
- * Receives repaint request events.
- *
- * @param event
- * the repaint request event specifying the paintable source.
- */
- public void repaintRequested(RepaintRequestEvent event);
- }
-
- /**
- * Adds repaint request listener. In order to assure that no repaint
- * requests are missed, the new repaint listener should paint the paintable
- * right after adding itself as listener.
- *
- * @param listener
- * the listener to be added.
- */
- public void addListener(RepaintRequestListener listener);
-
- /**
- * Removes repaint request listener.
- *
- * @param listener
- * the listener to be removed.
- */
- public void removeListener(RepaintRequestListener listener);
-
/* Component event framework */
/**
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.LayoutClickEventHandler;
import com.vaadin.terminal.gwt.client.ui.csslayout.CssLayoutServerRpc;
import com.vaadin.terminal.gwt.client.ui.csslayout.CssLayoutState;
-import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler;
/**
* CssLayout is a layout component that can be used in browser environment only.
public void updateState() {
super.updateState();
getState().getChildCss().clear();
- for (Component child : this) {
+ for (Iterator<Component> ci = getComponentIterator(); ci.hasNext();) {
+ Component child = ci.next();
String componentCssString = getCss(child);
if (componentCssString != null) {
getState().getChildCss().put(child, componentCssString);
@Override
public void attach() {
root = getContent();
- super.attach();
getContent().setParent(this);
- getContent().attach();
-
fireComponentAttachEvent(getContent());
+ super.attach();
}
/**
@Override
public void detach() {
super.detach();
- getContent().detach();
}
/**
return (null != getContent()) ? 1 : 0;
}
- public void requestRepaintAll() {
- AbstractComponentContainer.requestRepaintAll(this);
- }
-
/**
* Fires the component attached event. This should be called by the
* addComponent methods after the component have been added to this
import java.util.logging.Level;
import java.util.logging.Logger;
-import com.vaadin.terminal.gwt.server.AbstractCommunicationManager;
+import com.vaadin.terminal.AbstractClientConnector;
import com.vaadin.terminal.gwt.server.ClientConnector;
-import com.vaadin.ui.Component.RepaintRequestEvent;
-import com.vaadin.ui.Component.RepaintRequestListener;
/**
* A class that tracks dirty {@link ClientConnector}s. A {@link ClientConnector}
* @since 7.0.0
*
*/
-public class DirtyConnectorTracker implements RepaintRequestListener {
- private Set<Component> dirtyComponents = new HashSet<Component>();
+public class DirtyConnectorTracker {
+ private Set<ClientConnector> dirtyConnectors = new HashSet<ClientConnector>();
private Root root;
/**
this.root = root;
}
- public void repaintRequested(RepaintRequestEvent event) {
- markDirty((Component) event.getConnector());
- }
-
- public void componentAttached(Component component) {
- component.addListener(this);
- markDirty(component);
- }
-
- private void markDirty(Component component) {
+ public void markDirty(ClientConnector connector) {
if (getLogger().isLoggable(Level.FINE)) {
- if (!dirtyComponents.contains(component)) {
+ if (!dirtyConnectors.contains(connector)) {
getLogger()
- .fine(getDebugInfo(component) + " " + "is now dirty");
+ .fine(getDebugInfo(connector) + " " + "is now dirty");
}
}
- dirtyComponents.add(component);
+ dirtyConnectors.add(connector);
}
- private void markClean(Component component) {
+ public void markClean(ClientConnector connector) {
if (getLogger().isLoggable(Level.FINE)) {
- if (dirtyComponents.contains(component)) {
+ if (dirtyConnectors.contains(connector)) {
getLogger().fine(
- getDebugInfo(component) + " " + "is no longer dirty");
+ getDebugInfo(connector) + " " + "is no longer dirty");
}
}
- dirtyComponents.remove(component);
+ dirtyConnectors.remove(connector);
}
- private String getDebugInfo(Component component) {
- String message = getObjectString(component);
- if (component.getParent() != null) {
- message += " (parent: " + getObjectString(component.getParent())
+ private String getDebugInfo(ClientConnector connector) {
+ String message = getObjectString(connector);
+ if (connector.getParent() != null) {
+ message += " (parent: " + getObjectString(connector.getParent())
+ ")";
}
return message;
}
- private String getObjectString(Object component) {
- return component.getClass().getName() + "@"
- + Integer.toHexString(component.hashCode());
+ private String getObjectString(Object connector) {
+ return connector.getClass().getName() + "@"
+ + Integer.toHexString(connector.hashCode());
}
- public void componentDetached(Component component) {
- component.removeListener(this);
- markClean(component);
+ public void markAllConnectorsDirty() {
+ markConnectorsDirtyRecursively(root);
+ getLogger().fine("All connectors are now dirty");
}
- public void markAllComponentsDirty() {
- markComponentsDirtyRecursively(root);
- getLogger().fine("All components are now dirty");
- }
-
- public void markAllComponentsClean() {
- dirtyComponents.clear();
- getLogger().fine("All components are now clean");
+ public void markAllConnectorsClean() {
+ dirtyConnectors.clear();
+ getLogger().fine("All connectors are now clean");
}
/**
- * Marks all visible components dirty, starting from the given component and
+ * Marks all visible connectors dirty, starting from the given connector and
* going downwards in the hierarchy.
*
* @param c
* The component to start iterating downwards from
*/
- private void markComponentsDirtyRecursively(Component c) {
- if (!c.isVisible()) {
+ private void markConnectorsDirtyRecursively(ClientConnector c) {
+ if (c instanceof Component && !((Component) c).isVisible()) {
return;
}
markDirty(c);
- if (c instanceof HasComponents) {
- HasComponents container = (HasComponents) c;
- for (Component child : AbstractCommunicationManager
- .getChildComponents(container)) {
- markComponentsDirtyRecursively(child);
- }
+ for (ClientConnector child : AbstractClientConnector
+ .getAllChildrenIteratable(c)) {
+ markConnectorsDirtyRecursively(child);
}
-
}
- public Collection<Component> getDirtyComponents() {
- return dirtyComponents;
+ public Collection<ClientConnector> getDirtyConnectors() {
+ return dirtyConnectors;
}
}
return new ComponentIterator();
}
- public void requestRepaintAll() {
- AbstractComponentContainer.requestRepaintAll(this);
- }
-
public int getComponentCount() {
int count = 0;
if (getLayout() != null) {
* container.
*
* @return the component iterator.
+ *
+ * @deprecated Use {@link #iterator()} instead.
*/
+ @Deprecated
public Iterator<Component> getComponentIterator();
/**
*/
public boolean isComponentVisible(Component childComponent);
- /**
- * Causes a repaint of this component, and all components below it.
- *
- * This should only be used in special cases, e.g when the state of a
- * descendant depends on the state of a ancestor.
- */
- public void requestRepaintAll();
-
}
--- /dev/null
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.ui;
+
+import com.vaadin.terminal.AbstractExtension;
+import com.vaadin.terminal.gwt.client.ui.helloworldfeature.GreetAgainRpc;
+import com.vaadin.terminal.gwt.client.ui.helloworldfeature.HelloWorldRpc;
+import com.vaadin.terminal.gwt.client.ui.helloworldfeature.HelloWorldState;
+
+public class HelloWorldExtension extends AbstractExtension {
+
+ public HelloWorldExtension() {
+ registerRpc(new HelloWorldRpc() {
+ public void onMessageSent(String message) {
+ getRoot().showNotification(message);
+ }
+ });
+ }
+
+ @Override
+ public HelloWorldState getState() {
+ return (HelloWorldState) super.getState();
+ }
+
+ public void setGreeting(String greeting) {
+ getState().setGreeting(greeting);
+ requestRepaint();
+ }
+
+ public String getGreeting() {
+ return getState().getGreeting();
+ }
+
+ public void greetAgain() {
+ getRpcProxy(GreetAgainRpc.class).greetAgain();
+ }
+}
}
}
- @Override
- public void requestRepaintAll() {
- // Panel has odd structure, delegate to layout
- requestRepaint();
- if (getContent() != null) {
- getContent().requestRepaintAll();
- }
- }
-
/**
* Adds the component into this container.
*
}
}
- /**
- * Notifies the component that it is connected to an application.
- *
- * @see com.vaadin.ui.Component#attach()
- */
- @Override
- public void attach() {
- getRoot().componentAttached(this);
- // can't call parent here as this is Panels hierarchy is a hack
- requestRepaint();
- if (content != null) {
- content.attach();
- }
- }
-
- /**
- * Notifies the component that it is detached from the application.
- *
- * @see com.vaadin.ui.Component#detach()
- */
- @Override
- public void detach() {
- // can't call parent here as this is Panels hierarchy is a hack
- if (content != null) {
- content.detach();
- }
- getRoot().componentDetached(this);
- }
-
/**
* Removes all components from this container.
*
return dirtyConnectorTracker;
}
- public void componentAttached(Component component) {
- getDirtyConnectorTracker().componentAttached(component);
- }
-
- public void componentDetached(Component component) {
- getDirtyConnectorTracker().componentDetached(component);
- }
-
}
super.attach();
refreshRenderedCells();
-
- if (visibleComponents != null) {
- for (final Iterator<Component> i = visibleComponents.iterator(); i
- .hasNext();) {
- i.next().attach();
- }
- }
}
/**
@Override
public void detach() {
super.detach();
-
- if (visibleComponents != null) {
- for (final Iterator<Component> i = visibleComponents.iterator(); i
- .hasNext();) {
- i.next().detach();
- }
- }
}
/**
}
}
- public void requestRepaintAll() {
- AbstractComponentContainer.requestRepaintAll(this);
- }
-
/**
* Sets the drag start mode of the Table. Drag start mode controls how Table
* behaves as a drag source.
return new AbstractComponent() {
};
}
-
}
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.util.ObjectProperty;
import com.vaadin.data.util.PropertyFormatter;
-import com.vaadin.ui.Component.RepaintRequestEvent;
-import com.vaadin.ui.Component.RepaintRequestListener;
import com.vaadin.ui.TextField;
public class TextFieldWithPropertyFormatter extends TestCase {
protected void setUp() throws Exception {
super.setUp();
- field = new TextField();
+ field = new TextField() {
+ @Override
+ public void requestRepaint() {
+ repainted++;
+ super.requestRepaint();
+ }
+ };
formatter = new PropertyFormatter<String>() {
};
field.addListener(listener);
- field.addListener(new RepaintRequestListener() {
- public void repaintRequested(RepaintRequestEvent event) {
- repainted++;
- }
- });
listenerCalled = 0;
repainted = 0;
}
--- /dev/null
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.tests.features;
+
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.tests.components.AbstractTestRoot;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.HelloWorldExtension;
+
+public class HelloWorldFeatureTest extends AbstractTestRoot {
+
+ @Override
+ protected void setup(WrappedRequest request) {
+ final HelloWorldExtension extension = new HelloWorldExtension();
+ extension.setGreeting("Kind words");
+ addExtension(extension);
+
+ addComponent(new Button("Greet again", new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ extension.greetAgain();
+ }
+ }));
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Testing basic Feature";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}