diff options
Diffstat (limited to 'src/com/vaadin/ui')
81 files changed, 0 insertions, 36843 deletions
diff --git a/src/com/vaadin/ui/AbsoluteLayout.java b/src/com/vaadin/ui/AbsoluteLayout.java deleted file mode 100644 index 1c84ca2865..0000000000 --- a/src/com/vaadin/ui/AbsoluteLayout.java +++ /dev/null @@ -1,632 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; - -import com.vaadin.event.LayoutEvents.LayoutClickEvent; -import com.vaadin.event.LayoutEvents.LayoutClickListener; -import com.vaadin.event.LayoutEvents.LayoutClickNotifier; -import com.vaadin.shared.Connector; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.absolutelayout.AbsoluteLayoutServerRpc; -import com.vaadin.shared.ui.absolutelayout.AbsoluteLayoutState; -import com.vaadin.terminal.Sizeable; -import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler; - -/** - * AbsoluteLayout is a layout implementation that mimics html absolute - * positioning. - * - */ -@SuppressWarnings("serial") -public class AbsoluteLayout extends AbstractLayout implements - LayoutClickNotifier { - - private AbsoluteLayoutServerRpc rpc = new AbsoluteLayoutServerRpc() { - - @Override - public void layoutClick(MouseEventDetails mouseDetails, - Connector clickedConnector) { - fireEvent(LayoutClickEvent.createEvent(AbsoluteLayout.this, - mouseDetails, clickedConnector)); - } - }; - // Maps each component to a position - private LinkedHashMap<Component, ComponentPosition> componentToCoordinates = new LinkedHashMap<Component, ComponentPosition>(); - - /** - * Creates an AbsoluteLayout with full size. - */ - public AbsoluteLayout() { - registerRpc(rpc); - setSizeFull(); - } - - @Override - public AbsoluteLayoutState getState() { - return (AbsoluteLayoutState) super.getState(); - } - - /** - * Gets an iterator for going through all components enclosed in the - * absolute layout. - */ - @Override - public Iterator<Component> getComponentIterator() { - return componentToCoordinates.keySet().iterator(); - } - - /** - * Gets the number of contained components. Consistent with the iterator - * returned by {@link #getComponentIterator()}. - * - * @return the number of contained components - */ - @Override - public int getComponentCount() { - return componentToCoordinates.size(); - } - - /** - * Replaces one component with another one. The new component inherits the - * old components position. - */ - @Override - public void replaceComponent(Component oldComponent, Component newComponent) { - ComponentPosition position = getPosition(oldComponent); - removeComponent(oldComponent); - addComponent(newComponent, position); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.ui.AbstractComponentContainer#addComponent(com.vaadin.ui.Component - * ) - */ - @Override - public void addComponent(Component c) { - addComponent(c, new ComponentPosition()); - } - - /** - * Adds a component to the layout. The component can be positioned by - * providing a string formatted in CSS-format. - * <p> - * For example the string "top:10px;left:10px" will position the component - * 10 pixels from the left and 10 pixels from the top. The identifiers: - * "top","left","right" and "bottom" can be used to specify the position. - * </p> - * - * @param c - * The component to add to the layout - * @param cssPosition - * The css position string - */ - public void addComponent(Component c, String cssPosition) { - ComponentPosition position = new ComponentPosition(); - position.setCSSString(cssPosition); - addComponent(c, position); - } - - /** - * Adds the component using the given position. Ensures the position is only - * set if the component is added correctly. - * - * @param c - * The component to add - * @param position - * The position info for the component. Must not be null. - * @throws IllegalArgumentException - * If adding the component failed - */ - private void addComponent(Component c, ComponentPosition position) - throws IllegalArgumentException { - /* - * Create position instance and add it to componentToCoordinates map. We - * need to do this before we call addComponent so the attachListeners - * can access this position. #6368 - */ - internalSetPosition(c, position); - try { - super.addComponent(c); - } catch (IllegalArgumentException e) { - internalRemoveComponent(c); - throw e; - } - requestRepaint(); - } - - /** - * Removes the component from all internal data structures. Does not - * actually remove the component from the layout (this is assumed to have - * been done by the caller). - * - * @param c - * The component to remove - */ - private void internalRemoveComponent(Component c) { - componentToCoordinates.remove(c); - } - - @Override - public void updateState() { - super.updateState(); - - // This could be in internalRemoveComponent and internalSetComponent if - // Map<Connector,String> was supported. We cannot get the child - // 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 (Iterator<Component> ci = getComponentIterator(); ci.hasNext();) { - Component c = ci.next(); - connectorToPosition.put(c.getConnectorId(), getPosition(c) - .getCSSString()); - } - getState().setConnectorToCssPosition(connectorToPosition); - - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.ui.AbstractComponentContainer#removeComponent(com.vaadin.ui - * .Component) - */ - @Override - public void removeComponent(Component c) { - internalRemoveComponent(c); - super.removeComponent(c); - requestRepaint(); - } - - /** - * Gets the position of a component in the layout. Returns null if component - * is not attached to the layout. - * <p> - * Note that you cannot update the position by updating this object. Call - * {@link #setPosition(Component, ComponentPosition)} with the updated - * {@link ComponentPosition} object. - * </p> - * - * @param component - * The component which position is needed - * @return An instance of ComponentPosition containing the position of the - * component, or null if the component is not enclosed in the - * layout. - */ - public ComponentPosition getPosition(Component component) { - return componentToCoordinates.get(component); - } - - /** - * Sets the position of a component in the layout. - * - * @param component - * @param position - */ - public void setPosition(Component component, ComponentPosition position) { - if (!componentToCoordinates.containsKey(component)) { - throw new IllegalArgumentException( - "Component must be a child of this layout"); - } - internalSetPosition(component, position); - } - - /** - * Updates the position for a component. Caller must ensure component is a - * child of this layout. - * - * @param component - * The component. Must be a child for this layout. Not enforced. - * @param position - * New position. Must not be null. - */ - private void internalSetPosition(Component component, - ComponentPosition position) { - componentToCoordinates.put(component, position); - requestRepaint(); - } - - /** - * The CompontPosition class represents a components position within the - * absolute layout. It contains the attributes for left, right, top and - * bottom and the units used to specify them. - */ - public class ComponentPosition implements Serializable { - - private int zIndex = -1; - private Float topValue = null; - private Float rightValue = null; - private Float bottomValue = null; - private Float leftValue = null; - - private Unit topUnits = Unit.PIXELS; - private Unit rightUnits = Unit.PIXELS; - private Unit bottomUnits = Unit.PIXELS; - private Unit leftUnits = Unit.PIXELS; - - /** - * Sets the position attributes using CSS syntax. Attributes not - * included in the string are reset to their unset states. - * - * <code><pre> - * setCSSString("top:10px;left:20%;z-index:16;"); - * </pre></code> - * - * @param css - */ - public void setCSSString(String css) { - topValue = rightValue = bottomValue = leftValue = null; - topUnits = rightUnits = bottomUnits = leftUnits = Unit.PIXELS; - zIndex = -1; - if (css == null) { - return; - } - - String[] cssProperties = css.split(";"); - for (int i = 0; i < cssProperties.length; i++) { - String[] keyValuePair = cssProperties[i].split(":"); - String key = keyValuePair[0].trim(); - if (key.equals("")) { - continue; - } - if (key.equals("z-index")) { - zIndex = Integer.parseInt(keyValuePair[1].trim()); - } else { - String value; - if (keyValuePair.length > 1) { - value = keyValuePair[1].trim(); - } else { - value = ""; - } - String symbol = value.replaceAll("[0-9\\.\\-]+", ""); - if (!symbol.equals("")) { - value = value.substring(0, value.indexOf(symbol)) - .trim(); - } - float v = Float.parseFloat(value); - Unit unit = Unit.getUnitFromSymbol(symbol); - if (key.equals("top")) { - topValue = v; - topUnits = unit; - } else if (key.equals("right")) { - rightValue = v; - rightUnits = unit; - } else if (key.equals("bottom")) { - bottomValue = v; - bottomUnits = unit; - } else if (key.equals("left")) { - leftValue = v; - leftUnits = unit; - } - } - } - requestRepaint(); - } - - /** - * Converts the internal values into a valid CSS string. - * - * @return A valid CSS string - */ - public String getCSSString() { - String s = ""; - if (topValue != null) { - s += "top:" + topValue + topUnits.getSymbol() + ";"; - } - if (rightValue != null) { - s += "right:" + rightValue + rightUnits.getSymbol() + ";"; - } - if (bottomValue != null) { - s += "bottom:" + bottomValue + bottomUnits.getSymbol() + ";"; - } - if (leftValue != null) { - s += "left:" + leftValue + leftUnits.getSymbol() + ";"; - } - if (zIndex >= 0) { - s += "z-index:" + zIndex + ";"; - } - return s; - } - - /** - * Sets the 'top' attribute; distance from the top of the component to - * the top edge of the layout. - * - * @param topValue - * The value of the 'top' attribute - * @param topUnits - * The unit of the 'top' attribute. See UNIT_SYMBOLS for a - * description of the available units. - */ - public void setTop(Float topValue, Unit topUnits) { - this.topValue = topValue; - this.topUnits = topUnits; - requestRepaint(); - } - - /** - * Sets the 'right' attribute; distance from the right of the component - * to the right edge of the layout. - * - * @param rightValue - * The value of the 'right' attribute - * @param rightUnits - * The unit of the 'right' attribute. See UNIT_SYMBOLS for a - * description of the available units. - */ - public void setRight(Float rightValue, Unit rightUnits) { - this.rightValue = rightValue; - this.rightUnits = rightUnits; - requestRepaint(); - } - - /** - * Sets the 'bottom' attribute; distance from the bottom of the - * component to the bottom edge of the layout. - * - * @param bottomValue - * The value of the 'bottom' attribute - * @param units - * The unit of the 'bottom' attribute. See UNIT_SYMBOLS for a - * description of the available units. - */ - public void setBottom(Float bottomValue, Unit bottomUnits) { - this.bottomValue = bottomValue; - this.bottomUnits = bottomUnits; - requestRepaint(); - } - - /** - * Sets the 'left' attribute; distance from the left of the component to - * the left edge of the layout. - * - * @param leftValue - * The value of the 'left' attribute - * @param units - * The unit of the 'left' attribute. See UNIT_SYMBOLS for a - * description of the available units. - */ - public void setLeft(Float leftValue, Unit leftUnits) { - this.leftValue = leftValue; - this.leftUnits = leftUnits; - requestRepaint(); - } - - /** - * Sets the 'z-index' attribute; the visual stacking order - * - * @param zIndex - * The z-index for the component. - */ - public void setZIndex(int zIndex) { - this.zIndex = zIndex; - requestRepaint(); - } - - /** - * Sets the value of the 'top' attribute; distance from the top of the - * component to the top edge of the layout. - * - * @param topValue - * The value of the 'left' attribute - */ - public void setTopValue(Float topValue) { - this.topValue = topValue; - requestRepaint(); - } - - /** - * Gets the 'top' attributes value in current units. - * - * @see #getTopUnits() - * @return The value of the 'top' attribute, null if not set - */ - public Float getTopValue() { - return topValue; - } - - /** - * Gets the 'right' attributes value in current units. - * - * @return The value of the 'right' attribute, null if not set - * @see #getRightUnits() - */ - public Float getRightValue() { - return rightValue; - } - - /** - * Sets the 'right' attribute value (distance from the right of the - * component to the right edge of the layout). Currently active units - * are maintained. - * - * @param rightValue - * The value of the 'right' attribute - * @see #setRightUnits(int) - */ - public void setRightValue(Float rightValue) { - this.rightValue = rightValue; - requestRepaint(); - } - - /** - * Gets the 'bottom' attributes value using current units. - * - * @return The value of the 'bottom' attribute, null if not set - * @see #getBottomUnits() - */ - public Float getBottomValue() { - return bottomValue; - } - - /** - * Sets the 'bottom' attribute value (distance from the bottom of the - * component to the bottom edge of the layout). Currently active units - * are maintained. - * - * @param bottomValue - * The value of the 'bottom' attribute - * @see #setBottomUnits(int) - */ - public void setBottomValue(Float bottomValue) { - this.bottomValue = bottomValue; - requestRepaint(); - } - - /** - * Gets the 'left' attributes value using current units. - * - * @return The value of the 'left' attribute, null if not set - * @see #getLeftUnits() - */ - public Float getLeftValue() { - return leftValue; - } - - /** - * Sets the 'left' attribute value (distance from the left of the - * component to the left edge of the layout). Currently active units are - * maintained. - * - * @param leftValue - * The value of the 'left' CSS-attribute - * @see #setLeftUnits(int) - */ - public void setLeftValue(Float leftValue) { - this.leftValue = leftValue; - requestRepaint(); - } - - /** - * Gets the unit for the 'top' attribute - * - * @return See {@link Sizeable} UNIT_SYMBOLS for a description of the - * available units. - */ - public Unit getTopUnits() { - return topUnits; - } - - /** - * Sets the unit for the 'top' attribute - * - * @param topUnits - * See {@link Sizeable} UNIT_SYMBOLS for a description of the - * available units. - */ - public void setTopUnits(Unit topUnits) { - this.topUnits = topUnits; - requestRepaint(); - } - - /** - * Gets the unit for the 'right' attribute - * - * @return See {@link Sizeable} UNIT_SYMBOLS for a description of the - * available units. - */ - public Unit getRightUnits() { - return rightUnits; - } - - /** - * Sets the unit for the 'right' attribute - * - * @param rightUnits - * See {@link Sizeable} UNIT_SYMBOLS for a description of the - * available units. - */ - public void setRightUnits(Unit rightUnits) { - this.rightUnits = rightUnits; - requestRepaint(); - } - - /** - * Gets the unit for the 'bottom' attribute - * - * @return See {@link Sizeable} UNIT_SYMBOLS for a description of the - * available units. - */ - public Unit getBottomUnits() { - return bottomUnits; - } - - /** - * Sets the unit for the 'bottom' attribute - * - * @param bottomUnits - * See {@link Sizeable} UNIT_SYMBOLS for a description of the - * available units. - */ - public void setBottomUnits(Unit bottomUnits) { - this.bottomUnits = bottomUnits; - requestRepaint(); - } - - /** - * Gets the unit for the 'left' attribute - * - * @return See {@link Sizeable} UNIT_SYMBOLS for a description of the - * available units. - */ - public Unit getLeftUnits() { - return leftUnits; - } - - /** - * Sets the unit for the 'left' attribute - * - * @param leftUnits - * See {@link Sizeable} UNIT_SYMBOLS for a description of the - * available units. - */ - public void setLeftUnits(Unit leftUnits) { - this.leftUnits = leftUnits; - requestRepaint(); - } - - /** - * Gets the 'z-index' attribute. - * - * @return the zIndex The z-index attribute - */ - public int getZIndex() { - return zIndex; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return getCSSString(); - } - - } - - @Override - public void addListener(LayoutClickListener listener) { - addListener(LayoutClickEventHandler.LAYOUT_CLICK_EVENT_IDENTIFIER, - LayoutClickEvent.class, listener, - LayoutClickListener.clickMethod); - } - - @Override - public void removeListener(LayoutClickListener listener) { - removeListener(LayoutClickEventHandler.LAYOUT_CLICK_EVENT_IDENTIFIER, - LayoutClickEvent.class, listener); - } - -} diff --git a/src/com/vaadin/ui/AbstractComponent.java b/src/com/vaadin/ui/AbstractComponent.java deleted file mode 100644 index e7cb38256c..0000000000 --- a/src/com/vaadin/ui/AbstractComponent.java +++ /dev/null @@ -1,1382 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.vaadin.Application; -import com.vaadin.event.ActionManager; -import com.vaadin.event.EventRouter; -import com.vaadin.event.MethodEventSource; -import com.vaadin.event.ShortcutListener; -import com.vaadin.shared.ComponentState; -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.server.ClientConnector; -import com.vaadin.terminal.gwt.server.ComponentSizeValidator; -import com.vaadin.terminal.gwt.server.ResourceReference; -import com.vaadin.tools.ReflectTools; - -/** - * An abstract class that defines default implementation for the - * {@link Component} interface. Basic UI components that are not derived from an - * external component can inherit this class to easily qualify as Vaadin - * components. Most components in Vaadin do just that. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public abstract class AbstractComponent extends AbstractClientConnector - implements Component, MethodEventSource { - - /* Private members */ - - /** - * Application specific data object. The component does not use or modify - * this. - */ - private Object applicationData; - - /** - * The EventRouter used for the event model. - */ - private EventRouter eventRouter = null; - - /** - * The internal error message of the component. - */ - private ErrorMessage componentError = null; - - /** - * Locale of this component. - */ - private Locale locale; - - /** - * The component should receive focus (if {@link Focusable}) when attached. - */ - private boolean delayedFocus; - - /* Sizeable fields */ - - private float width = SIZE_UNDEFINED; - private float height = SIZE_UNDEFINED; - private Unit widthUnit = Unit.PIXELS; - private Unit heightUnit = Unit.PIXELS; - private static final Pattern sizePattern = Pattern - .compile("^(-?\\d+(\\.\\d+)?)(%|px|em|ex|in|cm|mm|pt|pc)?$"); - - private ComponentErrorHandler errorHandler = null; - - /** - * Keeps track of the Actions added to this component; the actual - * handling/notifying is delegated, usually to the containing window. - */ - private ActionManager actionManager; - - /* Constructor */ - - /** - * Constructs a new Component. - */ - public AbstractComponent() { - // ComponentSizeValidator.setCreationLocation(this); - } - - /* Get/Set component properties */ - - @Override - public void setDebugId(String id) { - getState().setDebugId(id); - } - - @Override - public String getDebugId() { - return getState().getDebugId(); - } - - /** - * Gets style for component. Multiple styles are joined with spaces. - * - * @return the component's styleValue of property style. - * @deprecated Use getStyleName() instead; renamed for consistency and to - * indicate that "style" should not be used to switch client - * side implementation, only to style the component. - */ - @Deprecated - public String getStyle() { - return getStyleName(); - } - - /** - * Sets and replaces all previous style names of the component. This method - * will trigger a {@link RepaintRequestEvent}. - * - * @param style - * the new style of the component. - * @deprecated Use setStyleName() instead; renamed for consistency and to - * indicate that "style" should not be used to switch client - * side implementation, only to style the component. - */ - @Deprecated - public void setStyle(String style) { - setStyleName(style); - } - - /* - * Gets the component's style. Don't add a JavaDoc comment here, we use the - * default documentation from implemented interface. - */ - @Override - public String getStyleName() { - String s = ""; - if (getState().getStyles() != null) { - for (final Iterator<String> it = getState().getStyles().iterator(); it - .hasNext();) { - s += it.next(); - if (it.hasNext()) { - s += " "; - } - } - } - return s; - } - - /* - * Sets the component's style. Don't add a JavaDoc comment here, we use the - * default documentation from implemented interface. - */ - @Override - public void setStyleName(String style) { - if (style == null || "".equals(style)) { - getState().setStyles(null); - requestRepaint(); - return; - } - if (getState().getStyles() == null) { - getState().setStyles(new ArrayList<String>()); - } - List<String> styles = getState().getStyles(); - styles.clear(); - String[] styleParts = style.split(" +"); - for (String part : styleParts) { - if (part.length() > 0) { - styles.add(part); - } - } - requestRepaint(); - } - - @Override - public void addStyleName(String style) { - if (style == null || "".equals(style)) { - return; - } - if (style.contains(" ")) { - // Split space separated style names and add them one by one. - for (String realStyle : style.split(" ")) { - addStyleName(realStyle); - } - return; - } - - if (getState().getStyles() == null) { - getState().setStyles(new ArrayList<String>()); - } - List<String> styles = getState().getStyles(); - if (!styles.contains(style)) { - styles.add(style); - requestRepaint(); - } - } - - @Override - public void removeStyleName(String style) { - if (getState().getStyles() != null) { - String[] styleParts = style.split(" +"); - for (String part : styleParts) { - if (part.length() > 0) { - getState().getStyles().remove(part); - } - } - requestRepaint(); - } - } - - /* - * Get's the component's caption. Don't add a JavaDoc comment here, we use - * the default documentation from implemented interface. - */ - @Override - public String getCaption() { - return getState().getCaption(); - } - - /** - * Sets the component's caption <code>String</code>. Caption is the visible - * name of the component. This method will trigger a - * {@link RepaintRequestEvent}. - * - * @param caption - * the new caption <code>String</code> for the component. - */ - @Override - public void setCaption(String caption) { - getState().setCaption(caption); - requestRepaint(); - } - - /* - * Don't add a JavaDoc comment here, we use the default documentation from - * implemented interface. - */ - @Override - public Locale getLocale() { - if (locale != null) { - return locale; - } - HasComponents parent = getParent(); - if (parent != null) { - return parent.getLocale(); - } - final Application app = getApplication(); - if (app != null) { - return app.getLocale(); - } - return null; - } - - /** - * Sets the locale of this component. - * - * <pre> - * // Component for which the locale is meaningful - * InlineDateField date = new InlineDateField("Datum"); - * - * // German language specified with ISO 639-1 language - * // code and ISO 3166-1 alpha-2 country code. - * date.setLocale(new Locale("de", "DE")); - * - * date.setResolution(DateField.RESOLUTION_DAY); - * layout.addComponent(date); - * </pre> - * - * - * @param locale - * the locale to become this component's locale. - */ - public void setLocale(Locale locale) { - this.locale = locale; - - // FIXME: Reload value if there is a converter - requestRepaint(); - } - - /* - * Gets the component's icon resource. Don't add a JavaDoc comment here, we - * use the default documentation from implemented interface. - */ - @Override - public Resource getIcon() { - return ResourceReference.getResource(getState().getIcon()); - } - - /** - * Sets the component's icon. This method will trigger a - * {@link RepaintRequestEvent}. - * - * @param icon - * the icon to be shown with the component's caption. - */ - @Override - public void setIcon(Resource icon) { - getState().setIcon(ResourceReference.create(icon)); - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Component#isEnabled() - */ - @Override - public boolean isEnabled() { - return getState().isEnabled(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Component#setEnabled(boolean) - */ - @Override - public void setEnabled(boolean enabled) { - if (getState().isEnabled() != enabled) { - getState().setEnabled(enabled); - requestRepaint(); - } - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.Connector#isConnectorEnabled() - */ - @Override - public boolean isConnectorEnabled() { - if (!isVisible()) { - return false; - } else if (!isEnabled()) { - return false; - } else if (!super.isConnectorEnabled()) { - return false; - } else if (!getParent().isComponentVisible(this)) { - return false; - } else { - return true; - } - } - - /* - * Tests if the component is in the immediate mode. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - public boolean isImmediate() { - return getState().isImmediate(); - } - - /** - * Sets the component's immediate mode to the specified status. This method - * will trigger a {@link RepaintRequestEvent}. - * - * @param immediate - * the boolean value specifying if the component should be in the - * immediate mode after the call. - * @see Component#isImmediate() - */ - public void setImmediate(boolean immediate) { - getState().setImmediate(immediate); - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Component#isVisible() - */ - @Override - public boolean isVisible() { - return getState().isVisible(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Component#setVisible(boolean) - */ - @Override - public void setVisible(boolean visible) { - if (getState().isVisible() == visible) { - return; - } - - getState().setVisible(visible); - requestRepaint(); - if (getParent() != null) { - // Must always repaint the parent (at least the hierarchy) when - // visibility of a child component changes. - getParent().requestRepaint(); - } - } - - /** - * <p> - * Gets the component's description, used in tooltips and can be displayed - * directly in certain other components such as forms. The description can - * be used to briefly describe the state of the component to the user. The - * description string may contain certain XML tags: - * </p> - * - * <p> - * <table border=1> - * <tr> - * <td width=120><b>Tag</b></td> - * <td width=120><b>Description</b></td> - * <td width=120><b>Example</b></td> - * </tr> - * <tr> - * <td><b></td> - * <td>bold</td> - * <td><b>bold text</b></td> - * </tr> - * <tr> - * <td><i></td> - * <td>italic</td> - * <td><i>italic text</i></td> - * </tr> - * <tr> - * <td><u></td> - * <td>underlined</td> - * <td><u>underlined text</u></td> - * </tr> - * <tr> - * <td><br></td> - * <td>linebreak</td> - * <td>N/A</td> - * </tr> - * <tr> - * <td><ul><br> - * <li>item1<br> - * <li>item1<br> - * </ul></td> - * <td>item list</td> - * <td> - * <ul> - * <li>item1 - * <li>item2 - * </ul> - * </td> - * </tr> - * </table> - * </p> - * - * <p> - * These tags may be nested. - * </p> - * - * @return component's description <code>String</code> - */ - public String getDescription() { - return getState().getDescription(); - } - - /** - * Sets the component's description. See {@link #getDescription()} for more - * information on what the description is. This method will trigger a - * {@link RepaintRequestEvent}. - * - * The description is displayed as HTML/XHTML in tooltips or directly in - * certain components so care should be taken to avoid creating the - * possibility for HTML injection and possibly XSS vulnerabilities. - * - * @param description - * the new description string for the component. - */ - public void setDescription(String description) { - getState().setDescription(description); - requestRepaint(); - } - - /* - * 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 (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."); - } - } - - /** - * Returns the closest ancestor with the given type. - * <p> - * To find the Window that contains the component, use {@code Window w = - * getParent(Window.class);} - * </p> - * - * @param <T> - * The type of the ancestor - * @param parentType - * The ancestor class we are looking for - * @return The first ancestor that can be assigned to the given class. Null - * if no ancestor with the correct type could be found. - */ - public <T extends HasComponents> T findAncestor(Class<T> parentType) { - HasComponents p = getParent(); - while (p != null) { - if (parentType.isAssignableFrom(p.getClass())) { - return parentType.cast(p); - } - p = p.getParent(); - } - return null; - } - - /** - * Gets the error message for this component. - * - * @return ErrorMessage containing the description of the error state of the - * component or null, if the component contains no errors. Extending - * classes should override this method if they support other error - * message types such as validation errors or buffering errors. The - * returned error message contains information about all the errors. - */ - public ErrorMessage getErrorMessage() { - return componentError; - } - - /** - * Gets the component's error message. - * - * @link Terminal.ErrorMessage#ErrorMessage(String, int) - * - * @return the component's error message. - */ - public ErrorMessage getComponentError() { - return componentError; - } - - /** - * Sets the component's error message. The message may contain certain XML - * tags, for more information see - * - * @link Component.ErrorMessage#ErrorMessage(String, int) - * - * @param componentError - * the new <code>ErrorMessage</code> of the component. - */ - public void setComponentError(ErrorMessage componentError) { - this.componentError = componentError; - fireComponentErrorEvent(); - requestRepaint(); - } - - /* - * Tests if the component is in read-only mode. Don't add a JavaDoc comment - * here, we use the default documentation from implemented interface. - */ - @Override - public boolean isReadOnly() { - return getState().isReadOnly(); - } - - /* - * Sets the component's read-only mode. Don't add a JavaDoc comment here, we - * use the default documentation from implemented interface. - */ - @Override - public void setReadOnly(boolean readOnly) { - getState().setReadOnly(readOnly); - requestRepaint(); - } - - /* - * 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() { - // Just make method from implemented Component interface public - return super.getRoot(); - } - - /* - * Notify the component that it's attached to a window. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - @Override - public void attach() { - super.attach(); - if (delayedFocus) { - focus(); - } - setActionManagerViewer(); - } - - /* - * Detach the component from application. Don't add a JavaDoc comment here, - * we use the default documentation from implemented interface. - */ - @Override - public void detach() { - super.detach(); - if (actionManager != null) { - // Remove any existing viewer. Root cast is just to make the - // compiler happy - actionManager.setViewer((Root) null); - } - } - - /** - * Sets the focus for this component if the component is {@link Focusable}. - */ - protected void focus() { - if (this instanceof Focusable) { - final Application app = getApplication(); - if (app != null) { - getRoot().setFocusedComponent((Focusable) this); - delayedFocus = false; - } else { - delayedFocus = true; - } - } - } - - /** - * Gets the application object to which the component is attached. - * - * <p> - * The method will return {@code null} if the component is not currently - * attached to an application. This is often a problem in constructors of - * regular components and in the initializers of custom composite - * components. A standard workaround is to move the problematic - * initialization to {@link #attach()}, as described in the documentation of - * the method. - * </p> - * <p> - * <b>This method is not meant to be overridden. Due to CDI requirements we - * cannot declare it as final even though it should be final.</b> - * </p> - * - * @return the parent application of the component or <code>null</code>. - * @see #attach() - */ - @Override - public Application getApplication() { - // Just make method inherited from Component interface public - return super.getApplication(); - } - - /** - * Build CSS compatible string representation of height. - * - * @return CSS height - */ - private String getCSSHeight() { - if (getHeightUnits() == Unit.PIXELS) { - return ((int) getHeight()) + getHeightUnits().getSymbol(); - } else { - return getHeight() + getHeightUnits().getSymbol(); - } - } - - /** - * Build CSS compatible string representation of width. - * - * @return CSS width - */ - private String getCSSWidth() { - if (getWidthUnits() == Unit.PIXELS) { - return ((int) getWidth()) + getWidthUnits().getSymbol(); - } else { - return getWidth() + getWidthUnits().getSymbol(); - } - } - - /** - * Returns the shared state bean with information to be sent from the server - * to the client. - * - * Subclasses should override this method and set any relevant fields of the - * state returned by super.getState(). - * - * @since 7.0 - * - * @return updated component shared state - */ - @Override - public ComponentState getState() { - return (ComponentState) super.getState(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Component#updateState() - */ - @Override - public void updateState() { - // TODO This logic should be on the client side and the state should - // simply be a data object with "width" and "height". - if (getHeight() >= 0 - && (getHeightUnits() != Unit.PERCENTAGE || ComponentSizeValidator - .parentCanDefineHeight(this))) { - getState().setHeight("" + getCSSHeight()); - } else { - getState().setHeight(""); - } - - if (getWidth() >= 0 - && (getWidthUnits() != Unit.PERCENTAGE || ComponentSizeValidator - .parentCanDefineWidth(this))) { - getState().setWidth("" + getCSSWidth()); - } else { - getState().setWidth(""); - } - - ErrorMessage error = getErrorMessage(); - if (null != error) { - getState().setErrorMessage(error.getFormattedHtmlMessage()); - } else { - getState().setErrorMessage(null); - } - } - - /* Documentation copied from interface */ - @Override - public void requestRepaint() { - // Invisible components (by flag in this particular component) do not - // need repaints - if (!getState().isVisible()) { - return; - } - super.requestRepaint(); - } - - /* General event framework */ - - private static final Method COMPONENT_EVENT_METHOD = ReflectTools - .findMethod(Component.Listener.class, "componentEvent", - Component.Event.class); - - /** - * <p> - * Registers a new listener with the specified activation method to listen - * events generated by this component. If the activation method does not - * have any arguments the event object will not be passed to it when it's - * called. - * </p> - * - * <p> - * This method additionally informs the event-api to route events with the - * given eventIdentifier to the components handleEvent function call. - * </p> - * - * <p> - * For more information on the inheritable event mechanism see the - * {@link com.vaadin.event com.vaadin.event package documentation}. - * </p> - * - * @param eventIdentifier - * the identifier of the event to listen for - * @param eventType - * the type of the listened event. Events of this type or its - * subclasses activate the listener. - * @param target - * the object instance who owns the activation method. - * @param method - * the activation method. - * - * @since 6.2 - */ - protected void addListener(String eventIdentifier, Class<?> eventType, - Object target, Method method) { - if (eventRouter == null) { - eventRouter = new EventRouter(); - } - boolean needRepaint = !eventRouter.hasListeners(eventType); - eventRouter.addListener(eventType, target, method); - - if (needRepaint) { - getState().addRegisteredEventListener(eventIdentifier); - requestRepaint(); - } - } - - /** - * Checks if the given {@link Event} type is listened for this component. - * - * @param eventType - * the event type to be checked - * @return true if a listener is registered for the given event type - */ - protected boolean hasListeners(Class<?> eventType) { - return eventRouter != null && eventRouter.hasListeners(eventType); - } - - /** - * Removes all registered listeners matching the given parameters. Since - * this method receives the event type and the listener object as - * parameters, it will unregister all <code>object</code>'s methods that are - * registered to listen to events of type <code>eventType</code> generated - * by this component. - * - * <p> - * This method additionally informs the event-api to stop routing events - * with the given eventIdentifier to the components handleEvent function - * call. - * </p> - * - * <p> - * For more information on the inheritable event mechanism see the - * {@link com.vaadin.event com.vaadin.event package documentation}. - * </p> - * - * @param eventIdentifier - * the identifier of the event to stop listening for - * @param eventType - * the exact event type the <code>object</code> listens to. - * @param target - * the target object that has registered to listen to events of - * type <code>eventType</code> with one or more methods. - * - * @since 6.2 - */ - protected void removeListener(String eventIdentifier, Class<?> eventType, - Object target) { - if (eventRouter != null) { - eventRouter.removeListener(eventType, target); - if (!eventRouter.hasListeners(eventType)) { - getState().removeRegisteredEventListener(eventIdentifier); - requestRepaint(); - } - } - } - - /** - * <p> - * Registers a new listener with the specified activation method to listen - * events generated by this component. If the activation method does not - * have any arguments the event object will not be passed to it when it's - * called. - * </p> - * - * <p> - * For more information on the inheritable event mechanism see the - * {@link com.vaadin.event com.vaadin.event package documentation}. - * </p> - * - * @param eventType - * the type of the listened event. Events of this type or its - * subclasses activate the listener. - * @param target - * the object instance who owns the activation method. - * @param method - * the activation method. - */ - @Override - public void addListener(Class<?> eventType, Object target, Method method) { - if (eventRouter == null) { - eventRouter = new EventRouter(); - } - eventRouter.addListener(eventType, target, method); - } - - /** - * <p> - * Convenience method for registering a new listener with the specified - * activation method to listen events generated by this component. If the - * activation method does not have any arguments the event object will not - * be passed to it when it's called. - * </p> - * - * <p> - * This version of <code>addListener</code> gets the name of the activation - * method as a parameter. The actual method is reflected from - * <code>object</code>, and unless exactly one match is found, - * <code>java.lang.IllegalArgumentException</code> is thrown. - * </p> - * - * <p> - * For more information on the inheritable event mechanism see the - * {@link com.vaadin.event com.vaadin.event package documentation}. - * </p> - * - * <p> - * Note: Using this method is discouraged because it cannot be checked - * during compilation. Use {@link #addListener(Class, Object, Method)} or - * {@link #addListener(com.vaadin.ui.Component.Listener)} instead. - * </p> - * - * @param eventType - * the type of the listened event. Events of this type or its - * subclasses activate the listener. - * @param target - * the object instance who owns the activation method. - * @param methodName - * the name of the activation method. - */ - @Override - public void addListener(Class<?> eventType, Object target, String methodName) { - if (eventRouter == null) { - eventRouter = new EventRouter(); - } - eventRouter.addListener(eventType, target, methodName); - } - - /** - * Removes all registered listeners matching the given parameters. Since - * this method receives the event type and the listener object as - * parameters, it will unregister all <code>object</code>'s methods that are - * registered to listen to events of type <code>eventType</code> generated - * by this component. - * - * <p> - * For more information on the inheritable event mechanism see the - * {@link com.vaadin.event com.vaadin.event package documentation}. - * </p> - * - * @param eventType - * the exact event type the <code>object</code> listens to. - * @param target - * the target object that has registered to listen to events of - * type <code>eventType</code> with one or more methods. - */ - @Override - public void removeListener(Class<?> eventType, Object target) { - if (eventRouter != null) { - eventRouter.removeListener(eventType, target); - } - } - - /** - * Removes one registered listener method. The given method owned by the - * given object will no longer be called when the specified events are - * generated by this component. - * - * <p> - * For more information on the inheritable event mechanism see the - * {@link com.vaadin.event com.vaadin.event package documentation}. - * </p> - * - * @param eventType - * the exact event type the <code>object</code> listens to. - * @param target - * target object that has registered to listen to events of type - * <code>eventType</code> with one or more methods. - * @param method - * the method owned by <code>target</code> that's registered to - * listen to events of type <code>eventType</code>. - */ - @Override - public void removeListener(Class<?> eventType, Object target, Method method) { - if (eventRouter != null) { - eventRouter.removeListener(eventType, target, method); - } - } - - /** - * <p> - * Removes one registered listener method. The given method owned by the - * given object will no longer be called when the specified events are - * generated by this component. - * </p> - * - * <p> - * This version of <code>removeListener</code> gets the name of the - * activation method as a parameter. The actual method is reflected from - * <code>target</code>, and unless exactly one match is found, - * <code>java.lang.IllegalArgumentException</code> is thrown. - * </p> - * - * <p> - * For more information on the inheritable event mechanism see the - * {@link com.vaadin.event com.vaadin.event package documentation}. - * </p> - * - * @param eventType - * the exact event type the <code>object</code> listens to. - * @param target - * the target object that has registered to listen to events of - * type <code>eventType</code> with one or more methods. - * @param methodName - * the name of the method owned by <code>target</code> that's - * registered to listen to events of type <code>eventType</code>. - */ - @Override - public void removeListener(Class<?> eventType, Object target, - String methodName) { - if (eventRouter != null) { - eventRouter.removeListener(eventType, target, methodName); - } - } - - /** - * Returns all listeners that are registered for the given event type or one - * of its subclasses. - * - * @param eventType - * The type of event to return listeners for. - * @return A collection with all registered listeners. Empty if no listeners - * are found. - */ - public Collection<?> getListeners(Class<?> eventType) { - if (eventRouter == null) { - return Collections.EMPTY_LIST; - } - - return eventRouter.getListeners(eventType); - } - - /** - * Sends the event to all listeners. - * - * @param event - * the Event to be sent to all listeners. - */ - protected void fireEvent(Component.Event event) { - if (eventRouter != null) { - eventRouter.fireEvent(event); - } - - } - - /* Component event framework */ - - /* - * Registers a new listener to listen events generated by this component. - * Don't add a JavaDoc comment here, we use the default documentation from - * implemented interface. - */ - @Override - public void addListener(Component.Listener listener) { - addListener(Component.Event.class, listener, COMPONENT_EVENT_METHOD); - } - - /* - * Removes a previously registered listener from this component. Don't add a - * JavaDoc comment here, we use the default documentation from implemented - * interface. - */ - @Override - public void removeListener(Component.Listener listener) { - removeListener(Component.Event.class, listener, COMPONENT_EVENT_METHOD); - } - - /** - * Emits the component event. It is transmitted to all registered listeners - * interested in such events. - */ - protected void fireComponentEvent() { - fireEvent(new Component.Event(this)); - } - - /** - * Emits the component error event. It is transmitted to all registered - * listeners interested in such events. - */ - protected void fireComponentErrorEvent() { - fireEvent(new Component.ErrorEvent(getComponentError(), this)); - } - - /** - * Sets the data object, that can be used for any application specific data. - * The component does not use or modify this data. - * - * @param data - * the Application specific data. - * @since 3.1 - */ - public void setData(Object data) { - applicationData = data; - } - - /** - * Gets the application specific data. See {@link #setData(Object)}. - * - * @return the Application specific data set with setData function. - * @since 3.1 - */ - public Object getData() { - return applicationData; - } - - /* Sizeable and other size related methods */ - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Sizeable#getHeight() - */ - @Override - public float getHeight() { - return height; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Sizeable#getHeightUnits() - */ - @Override - public Unit getHeightUnits() { - return heightUnit; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Sizeable#getWidth() - */ - @Override - public float getWidth() { - return width; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Sizeable#getWidthUnits() - */ - @Override - public Unit getWidthUnits() { - return widthUnit; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Sizeable#setHeight(float, Unit) - */ - @Override - public void setHeight(float height, Unit unit) { - if (unit == null) { - throw new IllegalArgumentException("Unit can not be null"); - } - this.height = height; - heightUnit = unit; - requestRepaint(); - // ComponentSizeValidator.setHeightLocation(this); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Sizeable#setSizeFull() - */ - @Override - public void setSizeFull() { - setWidth(100, Unit.PERCENTAGE); - setHeight(100, Unit.PERCENTAGE); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Sizeable#setSizeUndefined() - */ - @Override - public void setSizeUndefined() { - setWidth(-1, Unit.PIXELS); - setHeight(-1, Unit.PIXELS); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Sizeable#setWidth(float, Unit) - */ - @Override - public void setWidth(float width, Unit unit) { - if (unit == null) { - throw new IllegalArgumentException("Unit can not be null"); - } - this.width = width; - widthUnit = unit; - requestRepaint(); - // ComponentSizeValidator.setWidthLocation(this); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Sizeable#setWidth(java.lang.String) - */ - @Override - public void setWidth(String width) { - Size size = parseStringSize(width); - if (size != null) { - setWidth(size.getSize(), size.getUnit()); - } else { - setWidth(-1, Unit.PIXELS); - } - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Sizeable#setHeight(java.lang.String) - */ - @Override - public void setHeight(String height) { - Size size = parseStringSize(height); - if (size != null) { - setHeight(size.getSize(), size.getUnit()); - } else { - setHeight(-1, Unit.PIXELS); - } - } - - /* - * Returns array with size in index 0 unit in index 1. Null or empty string - * will produce {-1,Unit#PIXELS} - */ - private static Size parseStringSize(String s) { - if (s == null) { - return null; - } - s = s.trim(); - if ("".equals(s)) { - return null; - } - float size = 0; - Unit unit = null; - Matcher matcher = sizePattern.matcher(s); - if (matcher.find()) { - size = Float.parseFloat(matcher.group(1)); - if (size < 0) { - size = -1; - unit = Unit.PIXELS; - } else { - String symbol = matcher.group(3); - unit = Unit.getUnitFromSymbol(symbol); - } - } else { - throw new IllegalArgumentException("Invalid size argument: \"" + s - + "\" (should match " + sizePattern.pattern() + ")"); - } - return new Size(size, unit); - } - - private static class Size implements Serializable { - float size; - Unit unit; - - public Size(float size, Unit unit) { - this.size = size; - this.unit = unit; - } - - public float getSize() { - return size; - } - - public Unit getUnit() { - return unit; - } - } - - public interface ComponentErrorEvent extends Terminal.ErrorEvent { - } - - public interface ComponentErrorHandler extends Serializable { - /** - * Handle the component error - * - * @param event - * @return True if the error has been handled False, otherwise - */ - public boolean handleComponentError(ComponentErrorEvent event); - } - - /** - * Gets the error handler for the component. - * - * The error handler is dispatched whenever there is an error processing the - * data coming from the client. - * - * @return - */ - public ComponentErrorHandler getErrorHandler() { - return errorHandler; - } - - /** - * Sets the error handler for the component. - * - * The error handler is dispatched whenever there is an error processing the - * data coming from the client. - * - * If the error handler is not set, the application error handler is used to - * handle the exception. - * - * @param errorHandler - * AbstractField specific error handler - */ - public void setErrorHandler(ComponentErrorHandler errorHandler) { - this.errorHandler = errorHandler; - } - - /** - * Handle the component error event. - * - * @param error - * Error event to handle - * @return True if the error has been handled False, otherwise. If the error - * haven't been handled by this component, it will be handled in the - * application error handler. - */ - public boolean handleError(ComponentErrorEvent error) { - if (errorHandler != null) { - return errorHandler.handleComponentError(error); - } - return false; - - } - - /* - * Actions - */ - - /** - * Gets the {@link ActionManager} used to manage the - * {@link ShortcutListener}s added to this {@link Field}. - * - * @return the ActionManager in use - */ - protected ActionManager getActionManager() { - if (actionManager == null) { - actionManager = new ActionManager(); - setActionManagerViewer(); - } - return actionManager; - } - - /** - * Set a viewer for the action manager to be the parent sub window (if the - * component is in a window) or the root (otherwise). This is still a - * simplification of the real case as this should be handled by the parent - * VOverlay (on the client side) if the component is inside an VOverlay - * component. - */ - private void setActionManagerViewer() { - if (actionManager != null && getRoot() != null) { - // Attached and has action manager - Window w = findAncestor(Window.class); - if (w != null) { - actionManager.setViewer(w); - } else { - actionManager.setViewer(getRoot()); - } - } - - } - - public void addShortcutListener(ShortcutListener shortcut) { - getActionManager().addAction(shortcut); - } - - public void removeShortcutListener(ShortcutListener shortcut) { - if (actionManager != null) { - actionManager.removeAction(shortcut); - } - } -} diff --git a/src/com/vaadin/ui/AbstractComponentContainer.java b/src/com/vaadin/ui/AbstractComponentContainer.java deleted file mode 100644 index bc27242bb8..0000000000 --- a/src/com/vaadin/ui/AbstractComponentContainer.java +++ /dev/null @@ -1,351 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.lang.reflect.Method; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; - -import com.vaadin.terminal.gwt.server.ComponentSizeValidator; - -/** - * Extension to {@link AbstractComponent} that defines the default - * implementation for the methods in {@link ComponentContainer}. Basic UI - * components that need to contain other components inherit this class to easily - * qualify as a component container. - * - * @author Vaadin Ltd - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public abstract class AbstractComponentContainer extends AbstractComponent - implements ComponentContainer { - - /** - * Constructs a new component container. - */ - public AbstractComponentContainer() { - super(); - } - - /** - * Removes all components from the container. This should probably be - * re-implemented in extending classes for a more powerful implementation. - */ - @Override - public void removeAllComponents() { - final LinkedList<Component> l = new LinkedList<Component>(); - - // Adds all components - for (final Iterator<Component> i = getComponentIterator(); i.hasNext();) { - l.add(i.next()); - } - - // Removes all component - for (final Iterator<Component> i = l.iterator(); i.hasNext();) { - removeComponent(i.next()); - } - } - - /* - * Moves all components from an another container into this container. Don't - * add a JavaDoc comment here, we use the default documentation from - * implemented interface. - */ - @Override - public void moveComponentsFrom(ComponentContainer source) { - final LinkedList<Component> components = new LinkedList<Component>(); - for (final Iterator<Component> i = source.getComponentIterator(); i - .hasNext();) { - components.add(i.next()); - } - - for (final Iterator<Component> i = components.iterator(); i.hasNext();) { - final Component c = i.next(); - source.removeComponent(c); - addComponent(c); - } - } - - /* Events */ - - private static final Method COMPONENT_ATTACHED_METHOD; - - private static final Method COMPONENT_DETACHED_METHOD; - - static { - try { - COMPONENT_ATTACHED_METHOD = ComponentAttachListener.class - .getDeclaredMethod("componentAttachedToContainer", - new Class[] { ComponentAttachEvent.class }); - COMPONENT_DETACHED_METHOD = ComponentDetachListener.class - .getDeclaredMethod("componentDetachedFromContainer", - new Class[] { ComponentDetachEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException( - "Internal error finding methods in AbstractComponentContainer"); - } - } - - /* documented in interface */ - @Override - public void addListener(ComponentAttachListener listener) { - addListener(ComponentContainer.ComponentAttachEvent.class, listener, - COMPONENT_ATTACHED_METHOD); - } - - /* documented in interface */ - @Override - public void addListener(ComponentDetachListener listener) { - addListener(ComponentContainer.ComponentDetachEvent.class, listener, - COMPONENT_DETACHED_METHOD); - } - - /* documented in interface */ - @Override - public void removeListener(ComponentAttachListener listener) { - removeListener(ComponentContainer.ComponentAttachEvent.class, listener, - COMPONENT_ATTACHED_METHOD); - } - - /* documented in interface */ - @Override - public void removeListener(ComponentDetachListener listener) { - removeListener(ComponentContainer.ComponentDetachEvent.class, listener, - COMPONENT_DETACHED_METHOD); - } - - /** - * Fires the component attached event. This should be called by the - * addComponent methods after the component have been added to this - * container. - * - * @param component - * the component that has been added to this container. - */ - protected void fireComponentAttachEvent(Component component) { - fireEvent(new ComponentAttachEvent(this, component)); - } - - /** - * Fires the component detached event. This should be called by the - * removeComponent methods after the component have been removed from this - * container. - * - * @param component - * the component that has been removed from this container. - */ - protected void fireComponentDetachEvent(Component component) { - fireEvent(new ComponentDetachEvent(this, component)); - } - - /** - * This only implements the events and component parent calls. The extending - * classes must implement component list maintenance and call this method - * after component list maintenance. - * - * @see com.vaadin.ui.ComponentContainer#addComponent(Component) - */ - @Override - public void addComponent(Component c) { - if (c instanceof ComponentContainer) { - // Make sure we're not adding the component inside it's own content - for (Component parent = this; parent != null; parent = parent - .getParent()) { - if (parent == c) { - throw new IllegalArgumentException( - "Component cannot be added inside it's own content"); - } - } - } - - if (c.getParent() != null) { - // If the component already has a parent, try to remove it - ComponentContainer oldParent = (ComponentContainer) c.getParent(); - oldParent.removeComponent(c); - - } - - c.setParent(this); - fireComponentAttachEvent(c); - } - - /** - * This only implements the events and component parent calls. The extending - * classes must implement component list maintenance and call this method - * before component list maintenance. - * - * @see com.vaadin.ui.ComponentContainer#removeComponent(Component) - */ - @Override - public void removeComponent(Component c) { - if (c.getParent() == this) { - c.setParent(null); - fireComponentDetachEvent(c); - } - } - - @Override - public void setVisible(boolean visible) { - if (getState().isVisible() == visible) { - return; - } - - super.setVisible(visible); - // If the visibility state is toggled it might affect all children - // aswell, e.g. make container visible should make children visible if - // they were only hidden because the container was hidden. - requestRepaintAll(); - } - - @Override - public void setWidth(float width, Unit unit) { - /* - * child tree repaints may be needed, due to our fall back support for - * invalid relative sizes - */ - Collection<Component> dirtyChildren = null; - boolean childrenMayBecomeUndefined = false; - if (getWidth() == SIZE_UNDEFINED && width != SIZE_UNDEFINED) { - // children currently in invalid state may need repaint - dirtyChildren = getInvalidSizedChildren(false); - } else if ((width == SIZE_UNDEFINED && getWidth() != SIZE_UNDEFINED) - || (unit == Unit.PERCENTAGE - && getWidthUnits() != Unit.PERCENTAGE && !ComponentSizeValidator - .parentCanDefineWidth(this))) { - /* - * relative width children may get to invalid state if width becomes - * invalid. Width may also become invalid if units become percentage - * due to the fallback support - */ - childrenMayBecomeUndefined = true; - dirtyChildren = getInvalidSizedChildren(false); - } - super.setWidth(width, unit); - repaintChangedChildTrees(dirtyChildren, childrenMayBecomeUndefined, - false); - } - - private void repaintChangedChildTrees( - Collection<Component> invalidChildren, - boolean childrenMayBecomeUndefined, boolean vertical) { - if (childrenMayBecomeUndefined) { - Collection<Component> previouslyInvalidComponents = invalidChildren; - invalidChildren = getInvalidSizedChildren(vertical); - if (previouslyInvalidComponents != null && invalidChildren != null) { - for (Iterator<Component> iterator = invalidChildren.iterator(); iterator - .hasNext();) { - Component component = iterator.next(); - if (previouslyInvalidComponents.contains(component)) { - // still invalid don't repaint - iterator.remove(); - } - } - } - } else if (invalidChildren != null) { - Collection<Component> stillInvalidChildren = getInvalidSizedChildren(vertical); - if (stillInvalidChildren != null) { - for (Component component : stillInvalidChildren) { - // didn't become valid - invalidChildren.remove(component); - } - } - } - if (invalidChildren != null) { - repaintChildTrees(invalidChildren); - } - } - - private Collection<Component> getInvalidSizedChildren(final boolean vertical) { - HashSet<Component> components = null; - if (this instanceof Panel) { - Panel p = (Panel) this; - ComponentContainer content = p.getContent(); - boolean valid = vertical ? ComponentSizeValidator - .checkHeights(content) : ComponentSizeValidator - .checkWidths(content); - - if (!valid) { - components = new HashSet<Component>(1); - components.add(content); - } - } else { - for (Iterator<Component> componentIterator = getComponentIterator(); componentIterator - .hasNext();) { - Component component = componentIterator.next(); - boolean valid = vertical ? ComponentSizeValidator - .checkHeights(component) : ComponentSizeValidator - .checkWidths(component); - if (!valid) { - if (components == null) { - components = new HashSet<Component>(); - } - components.add(component); - } - } - } - return components; - } - - private void repaintChildTrees(Collection<Component> dirtyChildren) { - for (Component c : dirtyChildren) { - if (c instanceof ComponentContainer) { - ComponentContainer cc = (ComponentContainer) c; - cc.requestRepaintAll(); - } else { - c.requestRepaint(); - } - } - } - - @Override - public void setHeight(float height, Unit unit) { - /* - * child tree repaints may be needed, due to our fall back support for - * invalid relative sizes - */ - Collection<Component> dirtyChildren = null; - boolean childrenMayBecomeUndefined = false; - if (getHeight() == SIZE_UNDEFINED && height != SIZE_UNDEFINED) { - // children currently in invalid state may need repaint - dirtyChildren = getInvalidSizedChildren(true); - } else if ((height == SIZE_UNDEFINED && getHeight() != SIZE_UNDEFINED) - || (unit == Unit.PERCENTAGE - && getHeightUnits() != Unit.PERCENTAGE && !ComponentSizeValidator - .parentCanDefineHeight(this))) { - /* - * relative height children may get to invalid state if height - * becomes invalid. Height may also become invalid if units become - * percentage due to the fallback support. - */ - childrenMayBecomeUndefined = true; - dirtyChildren = getInvalidSizedChildren(true); - } - super.setHeight(height, unit); - repaintChangedChildTrees(dirtyChildren, childrenMayBecomeUndefined, - true); - } - - @Override - public Iterator<Component> iterator() { - return getComponentIterator(); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.ui.HasComponents#isComponentVisible(com.vaadin.ui.Component) - */ - @Override - public boolean isComponentVisible(Component childComponent) { - return true; - } -}
\ No newline at end of file diff --git a/src/com/vaadin/ui/AbstractField.java b/src/com/vaadin/ui/AbstractField.java deleted file mode 100644 index 6fe7f54df5..0000000000 --- a/src/com/vaadin/ui/AbstractField.java +++ /dev/null @@ -1,1657 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.logging.Logger; - -import com.vaadin.data.Buffered; -import com.vaadin.data.Property; -import com.vaadin.data.Validatable; -import com.vaadin.data.Validator; -import com.vaadin.data.Validator.InvalidValueException; -import com.vaadin.data.util.converter.Converter; -import com.vaadin.data.util.converter.Converter.ConversionException; -import com.vaadin.data.util.converter.ConverterUtil; -import com.vaadin.event.Action; -import com.vaadin.event.ShortcutAction; -import com.vaadin.event.ShortcutListener; -import com.vaadin.shared.AbstractFieldState; -import com.vaadin.terminal.AbstractErrorMessage; -import com.vaadin.terminal.CompositeErrorMessage; -import com.vaadin.terminal.ErrorMessage; - -/** - * <p> - * Abstract field component for implementing buffered property editors. The - * field may hold an internal value, or it may be connected to any data source - * that implements the {@link com.vaadin.data.Property}interface. - * <code>AbstractField</code> implements that interface itself, too, so - * accessing the Property value represented by it is straightforward. - * </p> - * - * <p> - * AbstractField also provides the {@link com.vaadin.data.Buffered} interface - * for buffering the data source value. By default the Field is in write - * through-mode and {@link #setWriteThrough(boolean)}should be called to enable - * buffering. - * </p> - * - * <p> - * The class also supports {@link com.vaadin.data.Validator validators} to make - * sure the value contained in the field is valid. - * </p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public abstract class AbstractField<T> extends AbstractComponent implements - Field<T>, Property.ReadOnlyStatusChangeListener, - Property.ReadOnlyStatusChangeNotifier, Action.ShortcutNotifier { - - /* Private members */ - - private static final Logger logger = Logger.getLogger(AbstractField.class - .getName()); - - /** - * Value of the abstract field. - */ - private T value; - - /** - * A converter used to convert from the data model type to the field type - * and vice versa. - */ - private Converter<T, Object> converter = null; - /** - * Connected data-source. - */ - private Property<?> dataSource = null; - - /** - * The list of validators. - */ - private LinkedList<Validator> validators = null; - - /** - * Auto commit mode. - */ - private boolean writeThroughMode = true; - - /** - * Reads the value from data-source, when it is not modified. - */ - private boolean readThroughMode = true; - - /** - * Flag to indicate that the field is currently committing its value to the - * datasource. - */ - private boolean committingValueToDataSource = false; - - /** - * Current source exception. - */ - private Buffered.SourceException currentBufferedSourceException = null; - - /** - * Are the invalid values allowed in fields ? - */ - private boolean invalidAllowed = true; - - /** - * Are the invalid values committed ? - */ - private boolean invalidCommitted = false; - - /** - * The error message for the exception that is thrown when the field is - * required but empty. - */ - private String requiredError = ""; - - /** - * The error message that is shown when the field value cannot be converted. - */ - private String conversionError = "Could not convert value to {0}"; - - /** - * Is automatic validation enabled. - */ - private boolean validationVisible = true; - - private boolean valueWasModifiedByDataSourceDuringCommit; - - /** - * Whether this field is currently registered as listening to events from - * its data source. - * - * @see #setPropertyDataSource(Property) - * @see #addPropertyListeners() - * @see #removePropertyListeners() - */ - private boolean isListeningToPropertyEvents = false; - - /* Component basics */ - - /* - * Paints the field. Don't add a JavaDoc comment here, we use the default - * documentation from the implemented interface. - */ - - /** - * Returns true if the error indicator be hidden when painting the component - * even when there are errors. - * - * This is a mostly internal method, but can be overridden in subclasses - * e.g. if the error indicator should also be shown for empty fields in some - * cases. - * - * @return true to hide the error indicator, false to use the normal logic - * to show it when there are errors - */ - protected boolean shouldHideErrors() { - // getErrorMessage() can still return something else than null based on - // validation etc. - return isRequired() && isEmpty() && getComponentError() == null; - } - - /** - * Returns the type of the Field. The methods <code>getValue</code> and - * <code>setValue</code> must be compatible with this type: one must be able - * to safely cast the value returned from <code>getValue</code> to the given - * type and pass any variable assignable to this type as an argument to - * <code>setValue</code>. - * - * @return the type of the Field - */ - @Override - public abstract Class<? extends T> getType(); - - /** - * The abstract field is read only also if the data source is in read only - * mode. - */ - @Override - public boolean isReadOnly() { - return super.isReadOnly() - || (dataSource != null && dataSource.isReadOnly()); - } - - /** - * Changes the readonly state and throw read-only status change events. - * - * @see com.vaadin.ui.Component#setReadOnly(boolean) - */ - @Override - public void setReadOnly(boolean readOnly) { - super.setReadOnly(readOnly); - fireReadOnlyStatusChange(); - } - - /** - * Tests if the invalid data is committed to datasource. - * - * @see com.vaadin.data.BufferedValidatable#isInvalidCommitted() - */ - @Override - public boolean isInvalidCommitted() { - return invalidCommitted; - } - - /** - * Sets if the invalid data should be committed to datasource. - * - * @see com.vaadin.data.BufferedValidatable#setInvalidCommitted(boolean) - */ - @Override - public void setInvalidCommitted(boolean isCommitted) { - invalidCommitted = isCommitted; - } - - /* - * Saves the current value to the data source Don't add a JavaDoc comment - * here, we use the default documentation from the implemented interface. - */ - @Override - public void commit() throws Buffered.SourceException, InvalidValueException { - if (dataSource != null && !dataSource.isReadOnly()) { - if ((isInvalidCommitted() || isValid())) { - try { - - // Commits the value to datasource. - valueWasModifiedByDataSourceDuringCommit = false; - committingValueToDataSource = true; - getPropertyDataSource().setValue(getConvertedValue()); - } catch (final Throwable e) { - - // Sets the buffering state. - SourceException sourceException = new Buffered.SourceException( - this, e); - setCurrentBufferedSourceException(sourceException); - - // Throws the source exception. - throw sourceException; - } finally { - committingValueToDataSource = false; - } - } else { - /* An invalid value and we don't allow them, throw the exception */ - validate(); - } - } - - // The abstract field is not modified anymore - if (isModified()) { - setModified(false); - } - - // If successful, remove set the buffering state to be ok - if (getCurrentBufferedSourceException() != null) { - setCurrentBufferedSourceException(null); - } - - if (valueWasModifiedByDataSourceDuringCommit) { - valueWasModifiedByDataSourceDuringCommit = false; - fireValueChange(false); - } - - } - - /* - * Updates the value from the data source. Don't add a JavaDoc comment here, - * we use the default documentation from the implemented interface. - */ - @Override - public void discard() throws Buffered.SourceException { - if (dataSource != null) { - - // Gets the correct value from datasource - T newFieldValue; - try { - - // Discards buffer by overwriting from datasource - newFieldValue = convertFromDataSource(getDataSourceValue()); - - // If successful, remove set the buffering state to be ok - if (getCurrentBufferedSourceException() != null) { - setCurrentBufferedSourceException(null); - } - } catch (final Throwable e) { - // FIXME: What should really be done here if conversion fails? - - // Sets the buffering state - currentBufferedSourceException = new Buffered.SourceException( - this, e); - requestRepaint(); - - // Throws the source exception - throw currentBufferedSourceException; - } - - final boolean wasModified = isModified(); - setModified(false); - - // If the new value differs from the previous one - if (!equals(newFieldValue, getInternalValue())) { - setInternalValue(newFieldValue); - fireValueChange(false); - } else if (wasModified) { - // If the value did not change, but the modification status did - requestRepaint(); - } - } - } - - /** - * Gets the value from the data source. This is only here because of clarity - * in the code that handles both the data model value and the field value. - * - * @return The value of the property data source - */ - private Object getDataSourceValue() { - return dataSource.getValue(); - } - - /** - * Returns the field value. This is always identical to {@link #getValue()} - * and only here because of clarity in the code that handles both the data - * model value and the field value. - * - * @return The value of the field - */ - private T getFieldValue() { - // Give the value from abstract buffers if the field if possible - if (dataSource == null || !isReadThrough() || isModified()) { - return getInternalValue(); - } - - // There is no buffered value so use whatever the data model provides - return convertFromDataSource(getDataSourceValue()); - } - - /* - * Has the field been modified since the last commit()? Don't add a JavaDoc - * comment here, we use the default documentation from the implemented - * interface. - */ - @Override - public boolean isModified() { - return getState().isModified(); - } - - private void setModified(boolean modified) { - getState().setModified(modified); - requestRepaint(); - } - - /* - * Tests if the field is in write-through mode. Don't add a JavaDoc comment - * here, we use the default documentation from the implemented interface. - */ - @Override - public boolean isWriteThrough() { - return writeThroughMode; - } - - /** - * Sets the field's write-through mode to the specified status. When - * switching the write-through mode on, a {@link #commit()} will be - * performed. - * - * @see #setBuffered(boolean) for an easier way to control read through and - * write through modes - * - * @param writeThrough - * Boolean value to indicate if the object should be in - * write-through mode after the call. - * @throws SourceException - * If the operation fails because of an exception is thrown by - * the data source. - * @throws InvalidValueException - * If the implicit commit operation fails because of a - * validation error. - * @deprecated Use {@link #setBuffered(boolean)} instead. Note that - * setReadThrough(true), setWriteThrough(true) equals - * setBuffered(false) - */ - @Override - @Deprecated - public void setWriteThrough(boolean writeThrough) - throws Buffered.SourceException, InvalidValueException { - if (writeThroughMode == writeThrough) { - return; - } - writeThroughMode = writeThrough; - if (writeThroughMode) { - commit(); - } - } - - /* - * Tests if the field is in read-through mode. Don't add a JavaDoc comment - * here, we use the default documentation from the implemented interface. - */ - @Override - public boolean isReadThrough() { - return readThroughMode; - } - - /** - * Sets the field's read-through mode to the specified status. When - * switching read-through mode on, the object's value is updated from the - * data source. - * - * @see #setBuffered(boolean) for an easier way to control read through and - * write through modes - * - * @param readThrough - * Boolean value to indicate if the object should be in - * read-through mode after the call. - * - * @throws SourceException - * If the operation fails because of an exception is thrown by - * the data source. The cause is included in the exception. - * @deprecated Use {@link #setBuffered(boolean)} instead. Note that - * setReadThrough(true), setWriteThrough(true) equals - * setBuffered(false) - */ - @Override - @Deprecated - public void setReadThrough(boolean readThrough) - throws Buffered.SourceException { - if (readThroughMode == readThrough) { - return; - } - readThroughMode = readThrough; - if (!isModified() && readThroughMode && getPropertyDataSource() != null) { - setInternalValue(convertFromDataSource(getDataSourceValue())); - fireValueChange(false); - } - } - - /** - * Sets the buffered mode of this Field. - * <p> - * When the field is in buffered mode, changes will not be committed to the - * property data source until {@link #commit()} is called. - * </p> - * <p> - * Changing buffered mode will change the read through and write through - * state for the field. - * </p> - * <p> - * Mixing calls to {@link #setBuffered(boolean)} and - * {@link #setReadThrough(boolean)} or {@link #setWriteThrough(boolean)} is - * generally a bad idea. - * </p> - * - * @param buffered - * true if buffered mode should be turned on, false otherwise - */ - @Override - public void setBuffered(boolean buffered) { - setReadThrough(!buffered); - setWriteThrough(!buffered); - } - - /** - * Checks the buffered mode of this Field. - * <p> - * This method only returns true if both read and write buffering is used. - * - * @return true if buffered mode is on, false otherwise - */ - @Override - public boolean isBuffered() { - return !isReadThrough() && !isWriteThrough(); - } - - /* Property interface implementation */ - - /** - * Returns the (field) value converted to a String using toString(). - * - * @see java.lang.Object#toString() - * @deprecated Instead use {@link #getValue()} to get the value of the - * field, {@link #getConvertedValue()} to get the field value - * converted to the data model type or - * {@link #getPropertyDataSource()} .getValue() to get the value - * of the data source. - */ - @Deprecated - @Override - public String toString() { - logger.warning("You are using AbstractField.toString() to get the value for a " - + getClass().getSimpleName() - + ". This is not recommended and will not be supported in future versions."); - final Object value = getFieldValue(); - if (value == null) { - return null; - } - return value.toString(); - } - - /** - * Gets the current value of the field. - * - * <p> - * This is the visible, modified and possible invalid value the user have - * entered to the field. - * </p> - * - * <p> - * Note that the object returned is compatible with getType(). For example, - * if the type is String, this returns Strings even when the underlying - * datasource is of some other type. In order to access the converted value, - * use {@link #getConvertedValue()} and to access the value of the property - * data source, use {@link Property#getValue()} for the property data - * source. - * </p> - * - * <p> - * Since Vaadin 7.0, no implicit conversions between other data types and - * String are performed, but a converter is used if set. - * </p> - * - * @return the current value of the field. - */ - @Override - public T getValue() { - return getFieldValue(); - } - - /** - * Sets the value of the field. - * - * @param newFieldValue - * the New value of the field. - * @throws Property.ReadOnlyException - */ - @Override - public void setValue(Object newFieldValue) - throws Property.ReadOnlyException, Converter.ConversionException { - // This check is needed as long as setValue accepts Object instead of T - if (newFieldValue != null) { - if (!getType().isAssignableFrom(newFieldValue.getClass())) { - throw new Converter.ConversionException("Value of type " - + newFieldValue.getClass() + " cannot be assigned to " - + getType().getName()); - } - } - setValue((T) newFieldValue, false); - } - - /** - * Sets the value of the field. - * - * @param newFieldValue - * the New value of the field. - * @param repaintIsNotNeeded - * True iff caller is sure that repaint is not needed. - * @throws Property.ReadOnlyException - */ - protected void setValue(T newFieldValue, boolean repaintIsNotNeeded) - throws Property.ReadOnlyException, Converter.ConversionException, - InvalidValueException { - - if (!equals(newFieldValue, getInternalValue())) { - - // Read only fields can not be changed - if (isReadOnly()) { - throw new Property.ReadOnlyException(); - } - - // Repaint is needed even when the client thinks that it knows the - // new state if validity of the component may change - if (repaintIsNotNeeded - && (isRequired() || getValidators() != null || getConverter() != null)) { - repaintIsNotNeeded = false; - } - - if (!isInvalidAllowed()) { - /* - * If invalid values are not allowed the value must be validated - * before it is set. If validation fails, the - * InvalidValueException is thrown and the internal value is not - * updated. - */ - validate(newFieldValue); - } - - // Changes the value - setInternalValue(newFieldValue); - setModified(dataSource != null); - - valueWasModifiedByDataSourceDuringCommit = false; - // In write through mode , try to commit - if (isWriteThrough() && dataSource != null - && (isInvalidCommitted() || isValid())) { - try { - - // Commits the value to datasource - committingValueToDataSource = true; - getPropertyDataSource().setValue( - convertToModel(newFieldValue)); - - // The buffer is now unmodified - setModified(false); - - } catch (final Throwable e) { - - // Sets the buffering state - currentBufferedSourceException = new Buffered.SourceException( - this, e); - requestRepaint(); - - // Throws the source exception - throw currentBufferedSourceException; - } finally { - committingValueToDataSource = false; - } - } - - // If successful, remove set the buffering state to be ok - if (getCurrentBufferedSourceException() != null) { - setCurrentBufferedSourceException(null); - } - - if (valueWasModifiedByDataSourceDuringCommit) { - /* - * Value was modified by datasource. Force repaint even if - * repaint was not requested. - */ - valueWasModifiedByDataSourceDuringCommit = repaintIsNotNeeded = false; - } - - // Fires the value change - fireValueChange(repaintIsNotNeeded); - - } - } - - private static boolean equals(Object value1, Object value2) { - if (value1 == null) { - return value2 == null; - } - return value1.equals(value2); - } - - /* External data source */ - - /** - * Gets the current data source of the field, if any. - * - * @return the current data source as a Property, or <code>null</code> if - * none defined. - */ - @Override - public Property getPropertyDataSource() { - return dataSource; - } - - /** - * <p> - * Sets the specified Property as the data source for the field. All - * uncommitted changes are replaced with a value from the new data source. - * </p> - * - * <p> - * If the datasource has any validators, the same validators are added to - * the field. Because the default behavior of the field is to allow invalid - * values, but not to allow committing them, this only adds visual error - * messages to fields and do not allow committing them as long as the value - * is invalid. After the value is valid, the error message is not shown and - * the commit can be done normally. - * </p> - * - * <p> - * If the data source implements - * {@link com.vaadin.data.Property.ValueChangeNotifier} and/or - * {@link com.vaadin.data.Property.ReadOnlyStatusChangeNotifier}, the field - * registers itself as a listener and updates itself according to the events - * it receives. To avoid memory leaks caused by references to a field no - * longer in use, the listener registrations are removed on - * {@link AbstractField#detach() detach} and re-added on - * {@link AbstractField#attach() attach}. - * </p> - * - * <p> - * Note: before 6.5 we actually called discard() method in the beginning of - * the method. This was removed to simplify implementation, avoid excess - * calls to backing property and to avoid odd value change events that were - * previously fired (developer expects 0-1 value change events if this - * method is called). Some complex field implementations might now need to - * override this method to do housekeeping similar to discard(). - * </p> - * - * @param newDataSource - * the new data source Property. - */ - @Override - public void setPropertyDataSource(Property newDataSource) { - - // Saves the old value - final Object oldValue = getInternalValue(); - - // Stop listening to the old data source - removePropertyListeners(); - - // Sets the new data source - dataSource = newDataSource; - getState().setPropertyReadOnly( - dataSource == null ? false : dataSource.isReadOnly()); - - // Check if the current converter is compatible. - if (newDataSource != null - && !ConverterUtil.canConverterHandle(getConverter(), getType(), - newDataSource.getType())) { - // Changing from e.g. Number -> Double should set a new converter, - // changing from Double -> Number can keep the old one (Property - // accepts Number) - - // Set a new converter if there is a new data source and - // there is no old converter or the old is incompatible. - setConverter(newDataSource.getType()); - } - // Gets the value from source - try { - if (dataSource != null) { - T fieldValue = convertFromDataSource(getDataSourceValue()); - setInternalValue(fieldValue); - } - setModified(false); - if (getCurrentBufferedSourceException() != null) { - setCurrentBufferedSourceException(null); - } - } catch (final Throwable e) { - setCurrentBufferedSourceException(new Buffered.SourceException( - this, e)); - setModified(true); - } - - // Listen to new data source if possible - addPropertyListeners(); - - // Copy the validators from the data source - if (dataSource instanceof Validatable) { - final Collection<Validator> validators = ((Validatable) dataSource) - .getValidators(); - if (validators != null) { - for (final Iterator<Validator> i = validators.iterator(); i - .hasNext();) { - addValidator(i.next()); - } - } - } - - // Fires value change if the value has changed - T value = getInternalValue(); - if ((value != oldValue) - && ((value != null && !value.equals(oldValue)) || value == null)) { - fireValueChange(false); - } - } - - /** - * Retrieves a converter for the field from the converter factory defined - * for the application. Clears the converter if no application reference is - * available or if the factory returns null. - * - * @param datamodelType - * The type of the data model that we want to be able to convert - * from - */ - public void setConverter(Class<?> datamodelType) { - Converter<T, ?> c = (Converter<T, ?>) ConverterUtil.getConverter( - getType(), datamodelType, getApplication()); - setConverter(c); - } - - /** - * Convert the given value from the data source type to the UI type. - * - * @param newValue - * The data source value to convert. - * @return The converted value that is compatible with the UI type or the - * original value if its type is compatible and no converter is set. - * @throws Converter.ConversionException - * if there is no converter and the type is not compatible with - * the data source type. - */ - private T convertFromDataSource(Object newValue) { - return ConverterUtil.convertFromModel(newValue, getType(), - getConverter(), getLocale()); - } - - /** - * Convert the given value from the UI type to the data source type. - * - * @param fieldValue - * The value to convert. Typically returned by - * {@link #getFieldValue()} - * @return The converted value that is compatible with the data source type. - * @throws Converter.ConversionException - * if there is no converter and the type is not compatible with - * the data source type. - */ - private Object convertToModel(T fieldValue) - throws Converter.ConversionException { - try { - Class<?> modelType = null; - Property pd = getPropertyDataSource(); - if (pd != null) { - modelType = pd.getType(); - } else if (getConverter() != null) { - modelType = getConverter().getModelType(); - } - return ConverterUtil.convertToModel(fieldValue, - (Class<Object>) modelType, getConverter(), getLocale()); - } catch (ConversionException e) { - throw new ConversionException( - getConversionError(converter.getModelType()), e); - } - } - - /** - * Returns the conversion error with {0} replaced by the data source type. - * - * @param dataSourceType - * The type of the data source - * @return The value conversion error string with parameters replaced. - */ - protected String getConversionError(Class<?> dataSourceType) { - if (dataSourceType == null) { - return getConversionError(); - } else { - return getConversionError().replace("{0}", - dataSourceType.getSimpleName()); - } - } - - /** - * Returns the current value (as returned by {@link #getValue()}) converted - * to the data source type. - * <p> - * This returns the same as {@link AbstractField#getValue()} if no converter - * has been set. The value is not necessarily the same as the data source - * value e.g. if the field is in buffered mode and has been modified. - * </p> - * - * @return The converted value that is compatible with the data source type - */ - public Object getConvertedValue() { - return convertToModel(getFieldValue()); - } - - /** - * Sets the value of the field using a value of the data source type. The - * value given is converted to the field type and then assigned to the - * field. This will update the property data source in the same way as when - * {@link #setValue(Object)} is called. - * - * @param value - * The value to set. Must be the same type as the data source. - */ - public void setConvertedValue(Object value) { - setValue(convertFromDataSource(value)); - } - - /* Validation */ - - /** - * Adds a new validator for the field's value. All validators added to a - * field are checked each time the its value changes. - * - * @param validator - * the new validator to be added. - */ - @Override - public void addValidator(Validator validator) { - if (validators == null) { - validators = new LinkedList<Validator>(); - } - validators.add(validator); - requestRepaint(); - } - - /** - * Gets the validators of the field. - * - * @return the Unmodifiable collection that holds all validators for the - * field. - */ - @Override - public Collection<Validator> getValidators() { - if (validators == null || validators.isEmpty()) { - return null; - } - return Collections.unmodifiableCollection(validators); - } - - /** - * Removes the validator from the field. - * - * @param validator - * the validator to remove. - */ - @Override - public void removeValidator(Validator validator) { - if (validators != null) { - validators.remove(validator); - } - requestRepaint(); - } - - /** - * Removes all validators from the field. - */ - public void removeAllValidators() { - if (validators != null) { - validators.clear(); - } - requestRepaint(); - } - - /** - * Tests the current value against registered validators if the field is not - * empty. If the field is empty it is considered valid if it is not required - * and invalid otherwise. Validators are never checked for empty fields. - * - * In most cases, {@link #validate()} should be used instead of - * {@link #isValid()} to also get the error message. - * - * @return <code>true</code> if all registered validators claim that the - * current value is valid or if the field is empty and not required, - * <code>false</code> otherwise. - */ - @Override - public boolean isValid() { - - try { - validate(); - return true; - } catch (InvalidValueException e) { - return false; - } - } - - /** - * Checks the validity of the Field. - * - * A field is invalid if it is set as required (using - * {@link #setRequired(boolean)} and is empty, if one or several of the - * validators added to the field indicate it is invalid or if the value - * cannot be converted provided a converter has been set. - * - * The "required" validation is a built-in validation feature. If the field - * is required and empty this method throws an EmptyValueException with the - * error message set using {@link #setRequiredError(String)}. - * - * @see com.vaadin.data.Validatable#validate() - */ - @Override - public void validate() throws Validator.InvalidValueException { - - if (isRequired() && isEmpty()) { - throw new Validator.EmptyValueException(requiredError); - } - validate(getFieldValue()); - } - - /** - * Validates that the given value pass the validators for the field. - * <p> - * This method does not check the requiredness of the field. - * - * @param fieldValue - * The value to check - * @throws Validator.InvalidValueException - * if one or several validators fail - */ - protected void validate(T fieldValue) - throws Validator.InvalidValueException { - - Object valueToValidate = fieldValue; - - // If there is a converter we start by converting the value as we want - // to validate the converted value - if (getConverter() != null) { - try { - valueToValidate = getConverter().convertToModel(fieldValue, - getLocale()); - } catch (Exception e) { - throw new InvalidValueException( - getConversionError(getConverter().getModelType())); - } - } - - List<InvalidValueException> validationExceptions = new ArrayList<InvalidValueException>(); - if (validators != null) { - // Gets all the validation errors - for (Validator v : validators) { - try { - v.validate(valueToValidate); - } catch (final Validator.InvalidValueException e) { - validationExceptions.add(e); - } - } - } - - // If there were no errors - if (validationExceptions.isEmpty()) { - return; - } - - // If only one error occurred, throw it forwards - if (validationExceptions.size() == 1) { - throw validationExceptions.get(0); - } - - InvalidValueException[] exceptionArray = validationExceptions - .toArray(new InvalidValueException[validationExceptions.size()]); - - // Create a composite validator and include all exceptions - throw new Validator.InvalidValueException(null, exceptionArray); - } - - /** - * Fields allow invalid values by default. In most cases this is wanted, - * because the field otherwise visually forget the user input immediately. - * - * @return true iff the invalid values are allowed. - * @see com.vaadin.data.Validatable#isInvalidAllowed() - */ - @Override - public boolean isInvalidAllowed() { - return invalidAllowed; - } - - /** - * Fields allow invalid values by default. In most cases this is wanted, - * because the field otherwise visually forget the user input immediately. - * <p> - * In common setting where the user wants to assure the correctness of the - * datasource, but allow temporarily invalid contents in the field, the user - * should add the validators to datasource, that should not allow invalid - * values. The validators are automatically copied to the field when the - * datasource is set. - * </p> - * - * @see com.vaadin.data.Validatable#setInvalidAllowed(boolean) - */ - @Override - public void setInvalidAllowed(boolean invalidAllowed) - throws UnsupportedOperationException { - this.invalidAllowed = invalidAllowed; - } - - /** - * Error messages shown by the fields are composites of the error message - * thrown by the superclasses (that is the component error message), - * validation errors and buffered source errors. - * - * @see com.vaadin.ui.AbstractComponent#getErrorMessage() - */ - @Override - public ErrorMessage getErrorMessage() { - - /* - * Check validation errors only if automatic validation is enabled. - * Empty, required fields will generate a validation error containing - * the requiredError string. For these fields the exclamation mark will - * be hidden but the error must still be sent to the client. - */ - Validator.InvalidValueException validationError = null; - if (isValidationVisible()) { - try { - validate(); - } catch (Validator.InvalidValueException e) { - if (!e.isInvisible()) { - validationError = e; - } - } - } - - // Check if there are any systems errors - final ErrorMessage superError = super.getErrorMessage(); - - // Return if there are no errors at all - if (superError == null && validationError == null - && getCurrentBufferedSourceException() == null) { - return null; - } - - // Throw combination of the error types - return new CompositeErrorMessage( - new ErrorMessage[] { - superError, - AbstractErrorMessage - .getErrorMessageForException(validationError), - AbstractErrorMessage - .getErrorMessageForException(getCurrentBufferedSourceException()) }); - - } - - /* Value change events */ - - private static final Method VALUE_CHANGE_METHOD; - - static { - try { - VALUE_CHANGE_METHOD = Property.ValueChangeListener.class - .getDeclaredMethod("valueChange", - new Class[] { Property.ValueChangeEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException( - "Internal error finding methods in AbstractField"); - } - } - - /* - * Adds a value change listener for the field. Don't add a JavaDoc comment - * here, we use the default documentation from the implemented interface. - */ - @Override - public void addListener(Property.ValueChangeListener listener) { - addListener(AbstractField.ValueChangeEvent.class, listener, - VALUE_CHANGE_METHOD); - } - - /* - * Removes a value change listener from the field. Don't add a JavaDoc - * comment here, we use the default documentation from the implemented - * interface. - */ - @Override - public void removeListener(Property.ValueChangeListener listener) { - removeListener(AbstractField.ValueChangeEvent.class, listener, - VALUE_CHANGE_METHOD); - } - - /** - * Emits the value change event. The value contained in the field is - * validated before the event is created. - */ - protected void fireValueChange(boolean repaintIsNotNeeded) { - fireEvent(new AbstractField.ValueChangeEvent(this)); - if (!repaintIsNotNeeded) { - requestRepaint(); - } - } - - /* Read-only status change events */ - - private static final Method READ_ONLY_STATUS_CHANGE_METHOD; - - static { - try { - READ_ONLY_STATUS_CHANGE_METHOD = Property.ReadOnlyStatusChangeListener.class - .getDeclaredMethod( - "readOnlyStatusChange", - new Class[] { Property.ReadOnlyStatusChangeEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException( - "Internal error finding methods in AbstractField"); - } - } - - /** - * React to read only status changes of the property by requesting a - * repaint. - * - * @see Property.ReadOnlyStatusChangeListener - */ - @Override - public void readOnlyStatusChange(Property.ReadOnlyStatusChangeEvent event) { - getState().setPropertyReadOnly(event.getProperty().isReadOnly()); - requestRepaint(); - } - - /** - * An <code>Event</code> object specifying the Property whose read-only - * status has changed. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public static class ReadOnlyStatusChangeEvent extends Component.Event - implements Property.ReadOnlyStatusChangeEvent, Serializable { - - /** - * New instance of text change event. - * - * @param source - * the Source of the event. - */ - public ReadOnlyStatusChangeEvent(AbstractField source) { - super(source); - } - - /** - * Property where the event occurred. - * - * @return the Source of the event. - */ - @Override - public Property getProperty() { - return (Property) getSource(); - } - } - - /* - * Adds a read-only status change listener for the field. Don't add a - * JavaDoc comment here, we use the default documentation from the - * implemented interface. - */ - @Override - public void addListener(Property.ReadOnlyStatusChangeListener listener) { - addListener(Property.ReadOnlyStatusChangeEvent.class, listener, - READ_ONLY_STATUS_CHANGE_METHOD); - } - - /* - * Removes a read-only status change listener from the field. Don't add a - * JavaDoc comment here, we use the default documentation from the - * implemented interface. - */ - @Override - public void removeListener(Property.ReadOnlyStatusChangeListener listener) { - removeListener(Property.ReadOnlyStatusChangeEvent.class, listener, - READ_ONLY_STATUS_CHANGE_METHOD); - } - - /** - * Emits the read-only status change event. The value contained in the field - * is validated before the event is created. - */ - protected void fireReadOnlyStatusChange() { - fireEvent(new AbstractField.ReadOnlyStatusChangeEvent(this)); - } - - /** - * This method listens to data source value changes and passes the changes - * forwards. - * - * Changes are not forwarded to the listeners of the field during internal - * operations of the field to avoid duplicate notifications. - * - * @param event - * the value change event telling the data source contents have - * changed. - */ - @Override - public void valueChange(Property.ValueChangeEvent event) { - if (isReadThrough()) { - if (committingValueToDataSource) { - boolean propertyNotifiesOfTheBufferedValue = equals(event - .getProperty().getValue(), getInternalValue()); - if (!propertyNotifiesOfTheBufferedValue) { - /* - * Property (or chained property like PropertyFormatter) now - * reports different value than the one the field has just - * committed to it. In this case we respect the property - * value. - * - * Still, we don't fire value change yet, but instead - * postpone it until "commit" is done. See setValue(Object, - * boolean) and commit(). - */ - readValueFromProperty(event); - valueWasModifiedByDataSourceDuringCommit = true; - } - } else if (!isModified()) { - readValueFromProperty(event); - fireValueChange(false); - } - } - } - - private void readValueFromProperty(Property.ValueChangeEvent event) { - setInternalValue(convertFromDataSource(event.getProperty().getValue())); - } - - /** - * {@inheritDoc} - */ - @Override - public void focus() { - super.focus(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Component.Focusable#getTabIndex() - */ - @Override - public int getTabIndex() { - return getState().getTabIndex(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Component.Focusable#setTabIndex(int) - */ - @Override - public void setTabIndex(int tabIndex) { - getState().setTabIndex(tabIndex); - requestRepaint(); - } - - /** - * Returns the internal field value, which might not match the data source - * value e.g. if the field has been modified and is not in write-through - * mode. - * - * This method can be overridden by subclasses together with - * {@link #setInternalValue(Object)} to compute internal field value at - * runtime. When doing so, typically also {@link #isModified()} needs to be - * overridden and care should be taken in the management of the empty state - * and buffering support. - * - * @return internal field value - */ - protected T getInternalValue() { - return value; - } - - /** - * Sets the internal field value. This is purely used by AbstractField to - * change the internal Field value. It does not trigger valuechange events. - * It can be overridden by the inheriting classes to update all dependent - * variables. - * - * Subclasses can also override {@link #getInternalValue()} if necessary. - * - * @param newValue - * the new value to be set. - */ - protected void setInternalValue(T newValue) { - value = newValue; - if (validators != null && !validators.isEmpty()) { - requestRepaint(); - } - } - - /** - * Notifies the component that it is connected to an application. - * - * @see com.vaadin.ui.Component#attach() - */ - @Override - public void attach() { - super.attach(); - - if (!isListeningToPropertyEvents) { - addPropertyListeners(); - if (!isModified() && isReadThrough()) { - // Update value from data source - discard(); - } - } - } - - @Override - public void detach() { - super.detach(); - // Stop listening to data source events on detach to avoid a potential - // memory leak. See #6155. - removePropertyListeners(); - } - - /** - * Is this field required. Required fields must filled by the user. - * - * If the field is required, it is visually indicated in the user interface. - * Furthermore, setting field to be required implicitly adds "non-empty" - * validator and thus isValid() == false or any isEmpty() fields. In those - * cases validation errors are not painted as it is obvious that the user - * must fill in the required fields. - * - * On the other hand, for the non-required fields isValid() == true if the - * field isEmpty() regardless of any attached validators. - * - * - * @return <code>true</code> if the field is required, otherwise - * <code>false</code>. - */ - @Override - public boolean isRequired() { - return getState().isRequired(); - } - - /** - * Sets the field required. Required fields must filled by the user. - * - * If the field is required, it is visually indicated in the user interface. - * Furthermore, setting field to be required implicitly adds "non-empty" - * validator and thus isValid() == false or any isEmpty() fields. In those - * cases validation errors are not painted as it is obvious that the user - * must fill in the required fields. - * - * On the other hand, for the non-required fields isValid() == true if the - * field isEmpty() regardless of any attached validators. - * - * @param required - * Is the field required. - */ - @Override - public void setRequired(boolean required) { - getState().setRequired(required); - requestRepaint(); - } - - /** - * Set the error that is show if this field is required, but empty. When - * setting requiredMessage to be "" or null, no error pop-up or exclamation - * mark is shown for a empty required field. This faults to "". Even in - * those cases isValid() returns false for empty required fields. - * - * @param requiredMessage - * Message to be shown when this field is required, but empty. - */ - @Override - public void setRequiredError(String requiredMessage) { - requiredError = requiredMessage; - requestRepaint(); - } - - @Override - public String getRequiredError() { - return requiredError; - } - - /** - * Gets the error that is shown if the field value cannot be converted to - * the data source type. - * - * @return The error that is shown if conversion of the field value fails - */ - public String getConversionError() { - return conversionError; - } - - /** - * Sets the error that is shown if the field value cannot be converted to - * the data source type. If {0} is present in the message, it will be - * replaced by the simple name of the data source type. - * - * @param valueConversionError - * Message to be shown when conversion of the value fails - */ - public void setConversionError(String valueConversionError) { - this.conversionError = valueConversionError; - requestRepaint(); - } - - /** - * Is the field empty? - * - * In general, "empty" state is same as null. As an exception, TextField - * also treats empty string as "empty". - */ - protected boolean isEmpty() { - return (getFieldValue() == null); - } - - /** - * Is automatic, visible validation enabled? - * - * If automatic validation is enabled, any validators connected to this - * component are evaluated while painting the component and potential error - * messages are sent to client. If the automatic validation is turned off, - * isValid() and validate() methods still work, but one must show the - * validation in their own code. - * - * @return True, if automatic validation is enabled. - */ - public boolean isValidationVisible() { - return validationVisible; - } - - /** - * Enable or disable automatic, visible validation. - * - * If automatic validation is enabled, any validators connected to this - * component are evaluated while painting the component and potential error - * messages are sent to client. If the automatic validation is turned off, - * isValid() and validate() methods still work, but one must show the - * validation in their own code. - * - * @param validateAutomatically - * True, if automatic validation is enabled. - */ - public void setValidationVisible(boolean validateAutomatically) { - if (validationVisible != validateAutomatically) { - requestRepaint(); - validationVisible = validateAutomatically; - } - } - - /** - * Sets the current buffered source exception. - * - * @param currentBufferedSourceException - */ - public void setCurrentBufferedSourceException( - Buffered.SourceException currentBufferedSourceException) { - this.currentBufferedSourceException = currentBufferedSourceException; - requestRepaint(); - } - - /** - * Gets the current buffered source exception. - * - * @return The current source exception - */ - protected Buffered.SourceException getCurrentBufferedSourceException() { - return currentBufferedSourceException; - } - - /** - * A ready-made {@link ShortcutListener} that focuses the given - * {@link Focusable} (usually a {@link Field}) when the keyboard shortcut is - * invoked. - * - */ - public static class FocusShortcut extends ShortcutListener { - protected Focusable focusable; - - /** - * Creates a keyboard shortcut for focusing the given {@link Focusable} - * using the shorthand notation defined in {@link ShortcutAction}. - * - * @param focusable - * to focused when the shortcut is invoked - * @param shorthandCaption - * caption with keycode and modifiers indicated - */ - public FocusShortcut(Focusable focusable, String shorthandCaption) { - super(shorthandCaption); - this.focusable = focusable; - } - - /** - * Creates a keyboard shortcut for focusing the given {@link Focusable}. - * - * @param focusable - * to focused when the shortcut is invoked - * @param keyCode - * keycode that invokes the shortcut - * @param modifiers - * modifiers required to invoke the shortcut - */ - public FocusShortcut(Focusable focusable, int keyCode, int... modifiers) { - super(null, keyCode, modifiers); - this.focusable = focusable; - } - - /** - * Creates a keyboard shortcut for focusing the given {@link Focusable}. - * - * @param focusable - * to focused when the shortcut is invoked - * @param keyCode - * keycode that invokes the shortcut - */ - public FocusShortcut(Focusable focusable, int keyCode) { - this(focusable, keyCode, null); - } - - @Override - public void handleAction(Object sender, Object target) { - focusable.focus(); - } - } - - /** - * Gets the converter used to convert the property data source value to the - * field value. - * - * @return The converter or null if none is set. - */ - public Converter<T, Object> getConverter() { - return converter; - } - - /** - * Sets the converter used to convert the field value to property data - * source type. The converter must have a presentation type that matches the - * field type. - * - * @param converter - * The new converter to use. - */ - public void setConverter(Converter<T, ?> converter) { - this.converter = (Converter<T, Object>) converter; - requestRepaint(); - } - - @Override - public AbstractFieldState getState() { - return (AbstractFieldState) super.getState(); - } - - @Override - public void updateState() { - super.updateState(); - - // Hide the error indicator if needed - getState().setHideErrors(shouldHideErrors()); - } - - /** - * Registers this as an event listener for events sent by the data source - * (if any). Does nothing if - * <code>isListeningToPropertyEvents == true</code>. - */ - private void addPropertyListeners() { - if (!isListeningToPropertyEvents) { - if (dataSource instanceof Property.ValueChangeNotifier) { - ((Property.ValueChangeNotifier) dataSource).addListener(this); - } - if (dataSource instanceof Property.ReadOnlyStatusChangeNotifier) { - ((Property.ReadOnlyStatusChangeNotifier) dataSource) - .addListener(this); - } - isListeningToPropertyEvents = true; - } - } - - /** - * Stops listening to events sent by the data source (if any). Does nothing - * if <code>isListeningToPropertyEvents == false</code>. - */ - private void removePropertyListeners() { - if (isListeningToPropertyEvents) { - if (dataSource instanceof Property.ValueChangeNotifier) { - ((Property.ValueChangeNotifier) dataSource) - .removeListener(this); - } - if (dataSource instanceof Property.ReadOnlyStatusChangeNotifier) { - ((Property.ReadOnlyStatusChangeNotifier) dataSource) - .removeListener(this); - } - isListeningToPropertyEvents = false; - } - } -} diff --git a/src/com/vaadin/ui/AbstractJavaScriptComponent.java b/src/com/vaadin/ui/AbstractJavaScriptComponent.java deleted file mode 100644 index 5ec80573ab..0000000000 --- a/src/com/vaadin/ui/AbstractJavaScriptComponent.java +++ /dev/null @@ -1,165 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import com.vaadin.shared.ui.JavaScriptComponentState; -import com.vaadin.terminal.JavaScriptCallbackHelper; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ui.JavaScriptWidget; - -/** - * Base class for Components with all client-side logic implemented using - * JavaScript. - * <p> - * When a new JavaScript component is initialized in the browser, the framework - * will look for a globally defined JavaScript function that will initialize the - * component. The name of the initialization function is formed by replacing . - * with _ in the name of the server-side class. If no such function is defined, - * each super class is used in turn until a match is found. The framework will - * thus first attempt with <code>com_example_MyComponent</code> for the - * server-side - * <code>com.example.MyComponent extends AbstractJavaScriptComponent</code> - * class. If MyComponent instead extends <code>com.example.SuperComponent</code> - * , then <code>com_example_SuperComponent</code> will also be attempted if - * <code>com_example_MyComponent</code> has not been defined. - * <p> - * JavaScript components have a very simple GWT widget ({@link JavaScriptWidget} - * ) just consisting of a <code>div</code> element to which the JavaScript code - * should initialize its own user interface. - * <p> - * The initialization function will be called with <code>this</code> pointing to - * a connector wrapper object providing integration to Vaadin with the following - * functions: - * <ul> - * <li><code>getConnectorId()</code> - returns a string with the id of the - * connector.</li> - * <li><code>getParentId([connectorId])</code> - returns a string with the id of - * the connector's parent. If <code>connectorId</code> is provided, the id of - * the parent of the corresponding connector with the passed id is returned - * instead.</li> - * <li><code>getElement([connectorId])</code> - returns the DOM Element that is - * the root of a connector's widget. <code>null</code> is returned if the - * connector can not be found or if the connector doesn't have a widget. If - * <code>connectorId</code> is not provided, the connector id of the current - * connector will be used.</li> - * <li><code>getState()</code> - returns an object corresponding to the shared - * state defined on the server. The scheme for conversion between Java and - * JavaScript types is described bellow.</li> - * <li><code>registerRpc([name, ] rpcObject)</code> - registers the - * <code>rpcObject</code> as a RPC handler. <code>rpcObject</code> should be an - * object with field containing functions for all eligible RPC functions. If - * <code>name</code> is provided, the RPC handler will only used for RPC calls - * for the RPC interface with the same fully qualified Java name. If no - * <code>name</code> is provided, the RPC handler will be used for all incoming - * RPC invocations where the RPC method name is defined as a function field in - * the handler. The scheme for conversion between Java types in the RPC - * interface definition and the JavaScript values passed as arguments to the - * handler functions is described bellow.</li> - * <li><code>getRpcProxy([name])</code> - returns an RPC proxy object. If - * <code>name</code> is provided, the proxy object will contain functions for - * all methods in the RPC interface with the same fully qualified name, provided - * a RPC handler has been registered by the server-side code. If no - * <code>name</code> is provided, the returned RPC proxy object will contain - * functions for all methods in all RPC interfaces registered for the connector - * on the server. If the same method name is present in multiple registered RPC - * interfaces, the corresponding function in the RPC proxy object will throw an - * exception when called. The scheme for conversion between Java types in the - * RPC interface and the JavaScript values that should be passed to the - * functions is described bellow.</li> - * <li><code>translateVaadinUri(uri)</code> - Translates a Vaadin URI to a URL - * that can be used in the browser. This is just way of accessing - * {@link ApplicationConnection#translateVaadinUri(String)}</li> - * </ul> - * The connector wrapper also supports these special functions: - * <ul> - * <li><code>onStateChange</code> - If the JavaScript code assigns a function to - * the field, that function is called whenever the contents of the shared state - * is changed.</li> - * <li>Any field name corresponding to a call to - * {@link #addFunction(String, JavaScriptFunction)} on the server will - * automatically be present as a function that triggers the registered function - * on the server.</li> - * <li>Any field name referred to using - * {@link #callFunction(String, Object...)} on the server will be called if a - * function has been assigned to the field.</li> - * </ul> - * <p> - * - * Values in the Shared State and in RPC calls are converted between Java and - * JavaScript using the following conventions: - * <ul> - * <li>Primitive Java numbers (byte, char, int, long, float, double) and their - * boxed types (Byte, Character, Integer, Long, Float, Double) are represented - * by JavaScript numbers.</li> - * <li>The primitive Java boolean and the boxed Boolean are represented by - * JavaScript booleans.</li> - * <li>Java Strings are represented by JavaScript strings.</li> - * <li>List, Set and all arrays in Java are represented by JavaScript arrays.</li> - * <li>Map<String, ?> in Java is represented by JavaScript object with fields - * corresponding to the map keys.</li> - * <li>Any other Java Map is represented by a JavaScript array containing two - * arrays, the first contains the keys and the second contains the values in the - * same order.</li> - * <li>A Java Bean is represented by a JavaScript object with fields - * corresponding to the bean's properties.</li> - * <li>A Java Connector is represented by a JavaScript string containing the - * connector's id.</li> - * <li>A pluggable serialization mechanism is provided for types not described - * here. Please refer to the documentation for specific types for serialization - * information.</li> - * </ul> - * - * @author Vaadin Ltd - * @version @VERSION@ - * @since 7.0.0 - */ -public abstract class AbstractJavaScriptComponent extends AbstractComponent { - private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper( - this); - - @Override - protected <T> void registerRpc(T implementation, Class<T> rpcInterfaceType) { - super.registerRpc(implementation, rpcInterfaceType); - callbackHelper.registerRpc(rpcInterfaceType); - } - - /** - * Register a {@link JavaScriptFunction} that can be called from the - * JavaScript using the provided name. A JavaScript function with the - * provided name will be added to the connector wrapper object (initially - * available as <code>this</code>). Calling that JavaScript function will - * cause the call method in the registered {@link JavaScriptFunction} to be - * invoked with the same arguments. - * - * @param functionName - * the name that should be used for client-side function - * @param function - * the {@link JavaScriptFunction} object that will be invoked - * when the JavaScript function is called - */ - protected void addFunction(String functionName, JavaScriptFunction function) { - callbackHelper.registerCallback(functionName, function); - } - - /** - * Invoke a named function that the connector JavaScript has added to the - * JavaScript connector wrapper object. The arguments should only contain - * data types that can be represented in JavaScript including primitives, - * their boxed types, arrays, String, List, Set, Map, Connector and - * JavaBeans. - * - * @param name - * the name of the function - * @param arguments - * function arguments - */ - protected void callFunction(String name, Object... arguments) { - callbackHelper.invokeCallback(name, arguments); - } - - @Override - public JavaScriptComponentState getState() { - return (JavaScriptComponentState) super.getState(); - } -} diff --git a/src/com/vaadin/ui/AbstractLayout.java b/src/com/vaadin/ui/AbstractLayout.java deleted file mode 100644 index 7b3a537d06..0000000000 --- a/src/com/vaadin/ui/AbstractLayout.java +++ /dev/null @@ -1,77 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import com.vaadin.shared.ui.AbstractLayoutState; -import com.vaadin.ui.Layout.MarginHandler; - -/** - * An abstract class that defines default implementation for the {@link Layout} - * interface. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 5.0 - */ -@SuppressWarnings("serial") -public abstract class AbstractLayout extends AbstractComponentContainer - implements Layout, MarginHandler { - - protected MarginInfo margins = new MarginInfo(false); - - @Override - public AbstractLayoutState getState() { - return (AbstractLayoutState) super.getState(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout#setMargin(boolean) - */ - @Override - public void setMargin(boolean enabled) { - margins.setMargins(enabled); - getState().setMarginsBitmask(margins.getBitMask()); - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.MarginHandler#getMargin() - */ - @Override - public MarginInfo getMargin() { - return margins; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.MarginHandler#setMargin(MarginInfo) - */ - @Override - public void setMargin(MarginInfo marginInfo) { - margins.setMargins(marginInfo); - getState().setMarginsBitmask(margins.getBitMask()); - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout#setMargin(boolean, boolean, boolean, boolean) - */ - @Override - public void setMargin(boolean topEnabled, boolean rightEnabled, - boolean bottomEnabled, boolean leftEnabled) { - margins.setMargins(topEnabled, rightEnabled, bottomEnabled, leftEnabled); - getState().setMarginsBitmask(margins.getBitMask()); - requestRepaint(); - } - -} diff --git a/src/com/vaadin/ui/AbstractMedia.java b/src/com/vaadin/ui/AbstractMedia.java deleted file mode 100644 index 71b2e38ef3..0000000000 --- a/src/com/vaadin/ui/AbstractMedia.java +++ /dev/null @@ -1,196 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.ArrayList; -import java.util.List; - -import com.vaadin.shared.communication.URLReference; -import com.vaadin.shared.ui.AbstractMediaState; -import com.vaadin.shared.ui.MediaControl; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.gwt.server.ResourceReference; - -/** - * Abstract base class for the HTML5 media components. - * - * @author Vaadin Ltd - */ -public abstract class AbstractMedia extends AbstractComponent { - - @Override - public AbstractMediaState getState() { - return (AbstractMediaState) super.getState(); - } - - /** - * Sets a single media file as the source of the media component. - * - * @param source - */ - public void setSource(Resource source) { - clearSources(); - - addSource(source); - } - - private void clearSources() { - getState().getSources().clear(); - getState().getSourceTypes().clear(); - } - - /** - * Adds an alternative media file to the sources list. Which of the sources - * is used is selected by the browser depending on which file formats it - * supports. See <a - * href="http://en.wikipedia.org/wiki/HTML5_video#Table">wikipedia</a> for a - * table of formats supported by different browsers. - * - * @param source - */ - public void addSource(Resource source) { - if (source != null) { - getState().getSources().add(new ResourceReference(source)); - getState().getSourceTypes().add(source.getMIMEType()); - requestRepaint(); - } - } - - /** - * Set multiple sources at once. Which of the sources is used is selected by - * the browser depending on which file formats it supports. See <a - * href="http://en.wikipedia.org/wiki/HTML5_video#Table">wikipedia</a> for a - * table of formats supported by different browsers. - * - * @param sources - */ - public void setSources(Resource... sources) { - clearSources(); - for (Resource source : sources) { - addSource(source); - } - } - - /** - * @return The sources pointed to in this media. - */ - public List<Resource> getSources() { - ArrayList<Resource> sources = new ArrayList<Resource>(); - for (URLReference ref : getState().getSources()) { - sources.add(((ResourceReference) ref).getResource()); - } - return sources; - } - - /** - * Sets whether or not the browser should show native media controls. - * - * @param showControls - */ - public void setShowControls(boolean showControls) { - getState().setShowControls(showControls); - requestRepaint(); - } - - /** - * @return true if the browser is to show native media controls. - */ - public boolean isShowControls() { - return getState().isShowControls(); - } - - /** - * Sets the alternative text to be displayed if the browser does not support - * HTML5. This text is rendered as HTML if - * {@link #setHtmlContentAllowed(boolean)} is set to true. With HTML - * rendering, this method can also be used to implement fallback to a - * flash-based player, see the <a href= - * "https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox#Using_Flash" - * >Mozilla Developer Network</a> for details. - * - * @param altText - */ - public void setAltText(String altText) { - getState().setAltText(altText); - requestRepaint(); - } - - /** - * @return The text/html that is displayed when a browser doesn't support - * HTML5. - */ - public String getAltText() { - return getState().getAltText(); - } - - /** - * Set whether the alternative text ({@link #setAltText(String)}) is - * rendered as HTML or not. - * - * @param htmlContentAllowed - */ - public void setHtmlContentAllowed(boolean htmlContentAllowed) { - getState().setHtmlContentAllowed(htmlContentAllowed); - requestRepaint(); - } - - /** - * @return true if the alternative text ({@link #setAltText(String)}) is to - * be rendered as HTML. - */ - public boolean isHtmlContentAllowed() { - return getState().isHtmlContentAllowed(); - } - - /** - * Sets whether the media is to automatically start playback when enough - * data has been loaded. - * - * @param autoplay - */ - public void setAutoplay(boolean autoplay) { - getState().setAutoplay(autoplay); - requestRepaint(); - } - - /** - * @return true if the media is set to automatically start playback. - */ - public boolean isAutoplay() { - return getState().isAutoplay(); - } - - /** - * Set whether to mute the audio or not. - * - * @param muted - */ - public void setMuted(boolean muted) { - getState().setMuted(muted); - requestRepaint(); - } - - /** - * @return true if the audio is muted. - */ - public boolean isMuted() { - return getState().isMuted(); - } - - /** - * Pauses the media. - */ - public void pause() { - getRpcProxy(MediaControl.class).pause(); - } - - /** - * Starts playback of the media. - */ - public void play() { - getRpcProxy(MediaControl.class).play(); - } - -} diff --git a/src/com/vaadin/ui/AbstractOrderedLayout.java b/src/com/vaadin/ui/AbstractOrderedLayout.java deleted file mode 100644 index 0581d0a279..0000000000 --- a/src/com/vaadin/ui/AbstractOrderedLayout.java +++ /dev/null @@ -1,383 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.Iterator; -import java.util.LinkedList; - -import com.vaadin.event.LayoutEvents.LayoutClickEvent; -import com.vaadin.event.LayoutEvents.LayoutClickListener; -import com.vaadin.event.LayoutEvents.LayoutClickNotifier; -import com.vaadin.shared.Connector; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutServerRpc; -import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState; -import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState.ChildComponentData; -import com.vaadin.terminal.Sizeable; -import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler; - -@SuppressWarnings("serial") -public abstract class AbstractOrderedLayout extends AbstractLayout implements - Layout.AlignmentHandler, Layout.SpacingHandler, LayoutClickNotifier { - - private AbstractOrderedLayoutServerRpc rpc = new AbstractOrderedLayoutServerRpc() { - - @Override - public void layoutClick(MouseEventDetails mouseDetails, - Connector clickedConnector) { - fireEvent(LayoutClickEvent.createEvent(AbstractOrderedLayout.this, - mouseDetails, clickedConnector)); - } - }; - - public static final Alignment ALIGNMENT_DEFAULT = Alignment.TOP_LEFT; - - /** - * Custom layout slots containing the components. - */ - protected LinkedList<Component> components = new LinkedList<Component>(); - - /* Child component alignments */ - - /** - * Mapping from components to alignments (horizontal + vertical). - */ - public AbstractOrderedLayout() { - registerRpc(rpc); - } - - @Override - public AbstractOrderedLayoutState getState() { - return (AbstractOrderedLayoutState) super.getState(); - } - - /** - * Add a component into this container. The component is added to the right - * or under the previous component. - * - * @param c - * the component to be added. - */ - @Override - public void addComponent(Component c) { - // Add to components before calling super.addComponent - // so that it is available to AttachListeners - components.add(c); - try { - super.addComponent(c); - } catch (IllegalArgumentException e) { - components.remove(c); - throw e; - } - componentAdded(c); - } - - /** - * Adds a component into this container. The component is added to the left - * or on top of the other components. - * - * @param c - * the component to be added. - */ - public void addComponentAsFirst(Component c) { - // If c is already in this, we must remove it before proceeding - // see ticket #7668 - if (c.getParent() == this) { - removeComponent(c); - } - components.addFirst(c); - try { - super.addComponent(c); - } catch (IllegalArgumentException e) { - components.remove(c); - throw e; - } - componentAdded(c); - - } - - /** - * Adds a component into indexed position in this container. - * - * @param c - * the component to be added. - * @param index - * the index of the component position. The components currently - * in and after the position are shifted forwards. - */ - public void addComponent(Component c, int index) { - // If c is already in this, we must remove it before proceeding - // see ticket #7668 - if (c.getParent() == this) { - // When c is removed, all components after it are shifted down - if (index > getComponentIndex(c)) { - index--; - } - removeComponent(c); - } - components.add(index, c); - try { - super.addComponent(c); - } catch (IllegalArgumentException e) { - components.remove(c); - throw e; - } - - componentAdded(c); - } - - private void componentRemoved(Component c) { - getState().getChildData().remove(c); - requestRepaint(); - } - - private void componentAdded(Component c) { - getState().getChildData().put(c, new ChildComponentData()); - requestRepaint(); - - } - - /** - * Removes the component from this container. - * - * @param c - * the component to be removed. - */ - @Override - public void removeComponent(Component c) { - components.remove(c); - super.removeComponent(c); - componentRemoved(c); - } - - /** - * Gets the component container iterator for going trough all the components - * in the container. - * - * @return the Iterator of the components inside the container. - */ - @Override - public Iterator<Component> getComponentIterator() { - return components.iterator(); - } - - /** - * Gets the number of contained components. Consistent with the iterator - * returned by {@link #getComponentIterator()}. - * - * @return the number of contained components - */ - @Override - public int getComponentCount() { - return components.size(); - } - - /* Documented in superclass */ - @Override - public void replaceComponent(Component oldComponent, Component newComponent) { - - // Gets the locations - int oldLocation = -1; - int newLocation = -1; - int location = 0; - for (final Iterator<Component> i = components.iterator(); i.hasNext();) { - final Component component = i.next(); - - if (component == oldComponent) { - oldLocation = location; - } - if (component == newComponent) { - newLocation = location; - } - - location++; - } - - if (oldLocation == -1) { - addComponent(newComponent); - } else if (newLocation == -1) { - removeComponent(oldComponent); - addComponent(newComponent, oldLocation); - } else { - // Both old and new are in the layout - if (oldLocation > newLocation) { - components.remove(oldComponent); - components.add(newLocation, oldComponent); - components.remove(newComponent); - components.add(oldLocation, newComponent); - } else { - components.remove(newComponent); - components.add(oldLocation, newComponent); - components.remove(oldComponent); - components.add(newLocation, oldComponent); - } - - requestRepaint(); - } - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.AlignmentHandler#setComponentAlignment(com - * .vaadin.ui.Component, int, int) - */ - @Override - public void setComponentAlignment(Component childComponent, - int horizontalAlignment, int verticalAlignment) { - Alignment a = new Alignment(horizontalAlignment + verticalAlignment); - setComponentAlignment(childComponent, a); - } - - @Override - public void setComponentAlignment(Component childComponent, - Alignment alignment) { - ChildComponentData childData = getState().getChildData().get( - childComponent); - if (childData != null) { - // Alignments are bit masks - childData.setAlignmentBitmask(alignment.getBitMask()); - requestRepaint(); - } else { - throw new IllegalArgumentException( - "Component must be added to layout before using setComponentAlignment()"); - } - - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.AlignmentHandler#getComponentAlignment(com - * .vaadin.ui.Component) - */ - @Override - public Alignment getComponentAlignment(Component childComponent) { - ChildComponentData childData = getState().getChildData().get( - childComponent); - if (childData == null) { - throw new IllegalArgumentException( - "The given component is not a child of this layout"); - } - - return new Alignment(childData.getAlignmentBitmask()); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.SpacingHandler#setSpacing(boolean) - */ - @Override - public void setSpacing(boolean spacing) { - getState().setSpacing(spacing); - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.SpacingHandler#isSpacing() - */ - @Override - public boolean isSpacing() { - return getState().isSpacing(); - } - - /** - * <p> - * This method is used to control how excess space in layout is distributed - * among components. Excess space may exist if layout is sized and contained - * non relatively sized components don't consume all available space. - * - * <p> - * Example how to distribute 1:3 (33%) for component1 and 2:3 (67%) for - * component2 : - * - * <code> - * layout.setExpandRatio(component1, 1);<br> - * layout.setExpandRatio(component2, 2); - * </code> - * - * <p> - * If no ratios have been set, the excess space is distributed evenly among - * all components. - * - * <p> - * Note, that width or height (depending on orientation) needs to be defined - * for this method to have any effect. - * - * @see Sizeable - * - * @param component - * the component in this layout which expand ratio is to be set - * @param ratio - */ - public void setExpandRatio(Component component, float ratio) { - ChildComponentData childData = getState().getChildData().get(component); - if (childData == null) { - throw new IllegalArgumentException( - "The given component is not a child of this layout"); - } - - childData.setExpandRatio(ratio); - requestRepaint(); - }; - - /** - * Returns the expand ratio of given component. - * - * @param component - * which expand ratios is requested - * @return expand ratio of given component, 0.0f by default. - */ - public float getExpandRatio(Component component) { - ChildComponentData childData = getState().getChildData().get(component); - if (childData == null) { - throw new IllegalArgumentException( - "The given component is not a child of this layout"); - } - - return childData.getExpandRatio(); - } - - @Override - public void addListener(LayoutClickListener listener) { - addListener(LayoutClickEventHandler.LAYOUT_CLICK_EVENT_IDENTIFIER, - LayoutClickEvent.class, listener, - LayoutClickListener.clickMethod); - } - - @Override - public void removeListener(LayoutClickListener listener) { - removeListener(LayoutClickEventHandler.LAYOUT_CLICK_EVENT_IDENTIFIER, - LayoutClickEvent.class, listener); - } - - /** - * Returns the index of the given component. - * - * @param component - * The component to look up. - * @return The index of the component or -1 if the component is not a child. - */ - public int getComponentIndex(Component component) { - return components.indexOf(component); - } - - /** - * Returns the component at the given position. - * - * @param index - * The position of the component. - * @return The component at the given index. - * @throws IndexOutOfBoundsException - * If the index is out of range. - */ - public Component getComponent(int index) throws IndexOutOfBoundsException { - return components.get(index); - } - -} diff --git a/src/com/vaadin/ui/AbstractSelect.java b/src/com/vaadin/ui/AbstractSelect.java deleted file mode 100644 index 0a97ceb649..0000000000 --- a/src/com/vaadin/ui/AbstractSelect.java +++ /dev/null @@ -1,2029 +0,0 @@ -/* - * @VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.Map; -import java.util.Set; - -import com.vaadin.data.Container; -import com.vaadin.data.Item; -import com.vaadin.data.Property; -import com.vaadin.data.util.IndexedContainer; -import com.vaadin.event.DataBoundTransferable; -import com.vaadin.event.Transferable; -import com.vaadin.event.dd.DragAndDropEvent; -import com.vaadin.event.dd.DropTarget; -import com.vaadin.event.dd.TargetDetailsImpl; -import com.vaadin.event.dd.acceptcriteria.ClientSideCriterion; -import com.vaadin.event.dd.acceptcriteria.ContainsDataFlavor; -import com.vaadin.event.dd.acceptcriteria.TargetDetailIs; -import com.vaadin.shared.ui.dd.VerticalDropLocation; -import com.vaadin.terminal.KeyMapper; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.ui.AbstractSelect.ItemCaptionMode; - -/** - * <p> - * A class representing a selection of items the user has selected in a UI. The - * set of choices is presented as a set of {@link com.vaadin.data.Item}s in a - * {@link com.vaadin.data.Container}. - * </p> - * - * <p> - * A <code>Select</code> component may be in single- or multiselect mode. - * Multiselect mode means that more than one item can be selected - * simultaneously. - * </p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 5.0 - */ -@SuppressWarnings("serial") -// TODO currently cannot specify type more precisely in case of multi-select -public abstract class AbstractSelect extends AbstractField<Object> implements - Container, Container.Viewer, Container.PropertySetChangeListener, - Container.PropertySetChangeNotifier, Container.ItemSetChangeNotifier, - Container.ItemSetChangeListener, Vaadin6Component { - - public enum ItemCaptionMode { - /** - * Item caption mode: Item's ID's <code>String</code> representation is - * used as caption. - */ - ID, - /** - * Item caption mode: Item's <code>String</code> representation is used - * as caption. - */ - ITEM, - /** - * Item caption mode: Index of the item is used as caption. The index - * mode can only be used with the containers implementing the - * {@link com.vaadin.data.Container.Indexed} interface. - */ - INDEX, - /** - * Item caption mode: If an Item has a caption it's used, if not, Item's - * ID's <code>String</code> representation is used as caption. <b>This - * is the default</b>. - */ - EXPLICIT_DEFAULTS_ID, - /** - * Item caption mode: Captions must be explicitly specified. - */ - EXPLICIT, - /** - * Item caption mode: Only icons are shown, captions are hidden. - */ - ICON_ONLY, - /** - * Item caption mode: Item captions are read from property specified - * with <code>setItemCaptionPropertyId</code>. - */ - PROPERTY; - } - - /** - * @deprecated from 7.0, use {@link ItemCaptionMode.ID} instead - */ - @Deprecated - public static final ItemCaptionMode ITEM_CAPTION_MODE_ID = ItemCaptionMode.ID; - - /** - * @deprecated from 7.0, use {@link ItemCaptionMode.ID} instead - */ - @Deprecated - public static final ItemCaptionMode ITEM_CAPTION_MODE_ITEM = ItemCaptionMode.ITEM; - - /** - * @deprecated from 7.0, use {@link ItemCaptionMode.ID} instead - */ - @Deprecated - public static final ItemCaptionMode ITEM_CAPTION_MODE_INDEX = ItemCaptionMode.INDEX; - - /** - * @deprecated from 7.0, use {@link ItemCaptionMode.ID} instead - */ - @Deprecated - public static final ItemCaptionMode ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID = ItemCaptionMode.EXPLICIT_DEFAULTS_ID; - - /** - * @deprecated from 7.0, use {@link ItemCaptionMode.ID} instead - */ - @Deprecated - public static final ItemCaptionMode ITEM_CAPTION_MODE_EXPLICIT = ItemCaptionMode.EXPLICIT; - - /** - * @deprecated from 7.0, use {@link ItemCaptionMode.ID} instead - */ - @Deprecated - public static final ItemCaptionMode ITEM_CAPTION_MODE_ICON_ONLY = ItemCaptionMode.ICON_ONLY; - - /** - * @deprecated from 7.0, use {@link ItemCaptionMode.ID} instead - */ - @Deprecated - public static final ItemCaptionMode ITEM_CAPTION_MODE_PROPERTY = ItemCaptionMode.PROPERTY; - - /** - * Interface for option filtering, used to filter options based on user - * entered value. The value is matched to the item caption. - * <code>FILTERINGMODE_OFF</code> (0) turns the filtering off. - * <code>FILTERINGMODE_STARTSWITH</code> (1) matches from the start of the - * caption. <code>FILTERINGMODE_CONTAINS</code> (1) matches anywhere in the - * caption. - */ - public interface Filtering extends Serializable { - public static final int FILTERINGMODE_OFF = 0; - public static final int FILTERINGMODE_STARTSWITH = 1; - public static final int FILTERINGMODE_CONTAINS = 2; - - /** - * Sets the option filtering mode. - * - * @param filteringMode - * the filtering mode to use - */ - public void setFilteringMode(int filteringMode); - - /** - * Gets the current filtering mode. - * - * @return the filtering mode in use - */ - public int getFilteringMode(); - - } - - /** - * Multi select modes that controls how multi select behaves. - */ - public enum MultiSelectMode { - /** - * The default behavior of the multi select mode - */ - DEFAULT, - - /** - * The previous more simple behavior of the multselect - */ - SIMPLE - } - - /** - * Is the select in multiselect mode? - */ - private boolean multiSelect = false; - - /** - * Select options. - */ - protected Container items; - - /** - * Is the user allowed to add new options? - */ - private boolean allowNewOptions; - - /** - * Keymapper used to map key values. - */ - protected KeyMapper<Object> itemIdMapper = new KeyMapper<Object>(); - - /** - * Item icons. - */ - private final HashMap<Object, Resource> itemIcons = new HashMap<Object, Resource>(); - - /** - * Item captions. - */ - private final HashMap<Object, String> itemCaptions = new HashMap<Object, String>(); - - /** - * Item caption mode. - */ - private ItemCaptionMode itemCaptionMode = ItemCaptionMode.EXPLICIT_DEFAULTS_ID; - - /** - * Item caption source property id. - */ - private Object itemCaptionPropertyId = null; - - /** - * Item icon source property id. - */ - private Object itemIconPropertyId = null; - - /** - * List of property set change event listeners. - */ - private Set<Container.PropertySetChangeListener> propertySetEventListeners = null; - - /** - * List of item set change event listeners. - */ - private Set<Container.ItemSetChangeListener> itemSetEventListeners = null; - - /** - * Item id that represents null selection of this select. - * - * <p> - * Data interface does not support nulls as item ids. Selecting the item - * identified by this id is the same as selecting no items at all. This - * setting only affects the single select mode. - * </p> - */ - private Object nullSelectionItemId = null; - - // Null (empty) selection is enabled by default - private boolean nullSelectionAllowed = true; - private NewItemHandler newItemHandler; - - // Caption (Item / Property) change listeners - CaptionChangeListener captionChangeListener; - - /* Constructors */ - - /** - * Creates an empty Select. The caption is not used. - */ - public AbstractSelect() { - setContainerDataSource(new IndexedContainer()); - } - - /** - * Creates an empty Select with caption. - */ - public AbstractSelect(String caption) { - setContainerDataSource(new IndexedContainer()); - setCaption(caption); - } - - /** - * Creates a new select that is connected to a data-source. - * - * @param caption - * the Caption of the component. - * @param dataSource - * the Container datasource to be selected from by this select. - */ - public AbstractSelect(String caption, Container dataSource) { - setCaption(caption); - setContainerDataSource(dataSource); - } - - /** - * Creates a new select that is filled from a collection of option values. - * - * @param caption - * the Caption of this field. - * @param options - * the Collection containing the options. - */ - public AbstractSelect(String caption, Collection<?> options) { - - // Creates the options container and add given options to it - final Container c = new IndexedContainer(); - if (options != null) { - for (final Iterator<?> i = options.iterator(); i.hasNext();) { - c.addItem(i.next()); - } - } - - setCaption(caption); - setContainerDataSource(c); - } - - /* Component methods */ - - /** - * Paints the content of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - - // Paints select attributes - if (isMultiSelect()) { - target.addAttribute("selectmode", "multi"); - } - if (isNewItemsAllowed()) { - target.addAttribute("allownewitem", true); - } - if (isNullSelectionAllowed()) { - target.addAttribute("nullselect", true); - if (getNullSelectionItemId() != null) { - target.addAttribute("nullselectitem", true); - } - } - - // Constructs selected keys array - String[] selectedKeys; - if (isMultiSelect()) { - selectedKeys = new String[((Set<?>) getValue()).size()]; - } else { - selectedKeys = new String[(getValue() == null - && getNullSelectionItemId() == null ? 0 : 1)]; - } - - // == - // first remove all previous item/property listeners - getCaptionChangeListener().clear(); - // Paints the options and create array of selected id keys - - target.startTag("options"); - int keyIndex = 0; - // Support for external null selection item id - final Collection<?> ids = getItemIds(); - if (isNullSelectionAllowed() && getNullSelectionItemId() != null - && !ids.contains(getNullSelectionItemId())) { - final Object id = getNullSelectionItemId(); - // Paints option - target.startTag("so"); - paintItem(target, id); - if (isSelected(id)) { - selectedKeys[keyIndex++] = itemIdMapper.key(id); - } - target.endTag("so"); - } - - final Iterator<?> i = getItemIds().iterator(); - // Paints the available selection options from data source - while (i.hasNext()) { - // Gets the option attribute values - final Object id = i.next(); - if (!isNullSelectionAllowed() && id != null - && id.equals(getNullSelectionItemId())) { - // Remove item if it's the null selection item but null - // selection is not allowed - continue; - } - final String key = itemIdMapper.key(id); - // add listener for each item, to cause repaint if an item changes - getCaptionChangeListener().addNotifierForItem(id); - target.startTag("so"); - paintItem(target, id); - if (isSelected(id) && keyIndex < selectedKeys.length) { - selectedKeys[keyIndex++] = key; - } - target.endTag("so"); - } - target.endTag("options"); - // == - - // Paint variables - target.addVariable(this, "selected", selectedKeys); - if (isNewItemsAllowed()) { - target.addVariable(this, "newitem", ""); - } - - } - - protected void paintItem(PaintTarget target, Object itemId) - throws PaintException { - final String key = itemIdMapper.key(itemId); - final String caption = getItemCaption(itemId); - final Resource icon = getItemIcon(itemId); - if (icon != null) { - target.addAttribute("icon", icon); - } - target.addAttribute("caption", caption); - if (itemId != null && itemId.equals(getNullSelectionItemId())) { - target.addAttribute("nullselection", true); - } - target.addAttribute("key", key); - if (isSelected(itemId)) { - target.addAttribute("selected", true); - } - } - - /** - * Invoked when the value of a variable has changed. - * - * @see com.vaadin.ui.AbstractComponent#changeVariables(java.lang.Object, - * java.util.Map) - */ - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - - // New option entered (and it is allowed) - if (isNewItemsAllowed()) { - final String newitem = (String) variables.get("newitem"); - if (newitem != null && newitem.length() > 0) { - getNewItemHandler().addNewItem(newitem); - } - } - - // Selection change - if (variables.containsKey("selected")) { - final String[] clientSideSelectedKeys = (String[]) variables - .get("selected"); - - // Multiselect mode - if (isMultiSelect()) { - - // TODO Optimize by adding repaintNotNeeded when applicable - - // Converts the key-array to id-set - final LinkedList<Object> acceptedSelections = new LinkedList<Object>(); - for (int i = 0; i < clientSideSelectedKeys.length; i++) { - final Object id = itemIdMapper - .get(clientSideSelectedKeys[i]); - if (!isNullSelectionAllowed() - && (id == null || id == getNullSelectionItemId())) { - // skip empty selection if nullselection is not allowed - requestRepaint(); - } else if (id != null && containsId(id)) { - acceptedSelections.add(id); - } - } - - if (!isNullSelectionAllowed() && acceptedSelections.size() < 1) { - // empty selection not allowed, keep old value - requestRepaint(); - return; - } - - // Limits the deselection to the set of visible items - // (non-visible items can not be deselected) - Collection<?> visibleNotSelected = getVisibleItemIds(); - if (visibleNotSelected != null) { - visibleNotSelected = new HashSet<Object>(visibleNotSelected); - // Don't remove those that will be added to preserve order - visibleNotSelected.removeAll(acceptedSelections); - - @SuppressWarnings("unchecked") - Set<Object> newsel = (Set<Object>) getValue(); - if (newsel == null) { - newsel = new LinkedHashSet<Object>(); - } else { - newsel = new LinkedHashSet<Object>(newsel); - } - newsel.removeAll(visibleNotSelected); - newsel.addAll(acceptedSelections); - setValue(newsel, true); - } - } else { - // Single select mode - if (!isNullSelectionAllowed() - && (clientSideSelectedKeys.length == 0 - || clientSideSelectedKeys[0] == null || clientSideSelectedKeys[0] == getNullSelectionItemId())) { - requestRepaint(); - return; - } - if (clientSideSelectedKeys.length == 0) { - // Allows deselection only if the deselected item is - // visible - final Object current = getValue(); - final Collection<?> visible = getVisibleItemIds(); - if (visible != null && visible.contains(current)) { - setValue(null, true); - } - } else { - final Object id = itemIdMapper - .get(clientSideSelectedKeys[0]); - if (!isNullSelectionAllowed() && id == null) { - requestRepaint(); - } else if (id != null - && id.equals(getNullSelectionItemId())) { - setValue(null, true); - } else { - setValue(id, true); - } - } - } - } - } - - /** - * TODO refine doc Setter for new item handler that is called when user adds - * new item in newItemAllowed mode. - * - * @param newItemHandler - */ - public void setNewItemHandler(NewItemHandler newItemHandler) { - this.newItemHandler = newItemHandler; - } - - /** - * TODO refine doc - * - * @return - */ - public NewItemHandler getNewItemHandler() { - if (newItemHandler == null) { - newItemHandler = new DefaultNewItemHandler(); - } - return newItemHandler; - } - - public interface NewItemHandler extends Serializable { - void addNewItem(String newItemCaption); - } - - /** - * TODO refine doc - * - * This is a default class that handles adding new items that are typed by - * user to selects container. - * - * By extending this class one may implement some logic on new item addition - * like database inserts. - * - */ - public class DefaultNewItemHandler implements NewItemHandler { - @Override - public void addNewItem(String newItemCaption) { - // Checks for readonly - if (isReadOnly()) { - throw new Property.ReadOnlyException(); - } - - // Adds new option - if (addItem(newItemCaption) != null) { - - // Sets the caption property, if used - if (getItemCaptionPropertyId() != null) { - getContainerProperty(newItemCaption, - getItemCaptionPropertyId()) - .setValue(newItemCaption); - } - if (isMultiSelect()) { - Set values = new HashSet((Collection) getValue()); - values.add(newItemCaption); - setValue(values); - } else { - setValue(newItemCaption); - } - } - } - } - - /** - * Gets the visible item ids. In Select, this returns list of all item ids, - * but can be overriden in subclasses if they paint only part of the items - * to the terminal or null if no items is visible. - */ - public Collection<?> getVisibleItemIds() { - return getItemIds(); - } - - /* Property methods */ - - /** - * Returns the type of the property. <code>getValue</code> and - * <code>setValue</code> methods must be compatible with this type: one can - * safely cast <code>getValue</code> to given type and pass any variable - * assignable to this type as a parameter to <code>setValue</code>. - * - * @return the Type of the property. - */ - @Override - public Class<?> getType() { - if (isMultiSelect()) { - return Set.class; - } else { - return Object.class; - } - } - - /** - * Gets the selected item id or in multiselect mode a set of selected ids. - * - * @see com.vaadin.ui.AbstractField#getValue() - */ - @Override - public Object getValue() { - final Object retValue = super.getValue(); - - if (isMultiSelect()) { - - // If the return value is not a set - if (retValue == null) { - return new HashSet<Object>(); - } - if (retValue instanceof Set) { - return Collections.unmodifiableSet((Set<?>) retValue); - } else if (retValue instanceof Collection) { - return new HashSet<Object>((Collection<?>) retValue); - } else { - final Set<Object> s = new HashSet<Object>(); - if (items.containsId(retValue)) { - s.add(retValue); - } - return s; - } - - } else { - return retValue; - } - } - - /** - * Sets the visible value of the property. - * - * <p> - * The value of the select is the selected item id. If the select is in - * multiselect-mode, the value is a set of selected item keys. In - * multiselect mode all collections of id:s can be assigned. - * </p> - * - * @param newValue - * the New selected item or collection of selected items. - * @see com.vaadin.ui.AbstractField#setValue(java.lang.Object) - */ - @Override - public void setValue(Object newValue) throws Property.ReadOnlyException { - if (newValue == getNullSelectionItemId()) { - newValue = null; - } - - setValue(newValue, false); - } - - /** - * Sets the visible value of the property. - * - * <p> - * The value of the select is the selected item id. If the select is in - * multiselect-mode, the value is a set of selected item keys. In - * multiselect mode all collections of id:s can be assigned. - * </p> - * - * @param newValue - * the New selected item or collection of selected items. - * @param repaintIsNotNeeded - * True if caller is sure that repaint is not needed. - * @see com.vaadin.ui.AbstractField#setValue(java.lang.Object, - * java.lang.Boolean) - */ - @Override - protected void setValue(Object newValue, boolean repaintIsNotNeeded) - throws Property.ReadOnlyException { - - if (isMultiSelect()) { - if (newValue == null) { - super.setValue(new LinkedHashSet<Object>(), repaintIsNotNeeded); - } else if (Collection.class.isAssignableFrom(newValue.getClass())) { - super.setValue(new LinkedHashSet<Object>( - (Collection<?>) newValue), repaintIsNotNeeded); - } - } else if (newValue == null || items.containsId(newValue)) { - super.setValue(newValue, repaintIsNotNeeded); - } - } - - /* Container methods */ - - /** - * Gets the item from the container with given id. If the container does not - * contain the requested item, null is returned. - * - * @param itemId - * the item id. - * @return the item from the container. - */ - @Override - public Item getItem(Object itemId) { - return items.getItem(itemId); - } - - /** - * Gets the item Id collection from the container. - * - * @return the Collection of item ids. - */ - @Override - public Collection<?> getItemIds() { - return items.getItemIds(); - } - - /** - * Gets the property Id collection from the container. - * - * @return the Collection of property ids. - */ - @Override - public Collection<?> getContainerPropertyIds() { - return items.getContainerPropertyIds(); - } - - /** - * Gets the property type. - * - * @param propertyId - * the Id identifying the property. - * @see com.vaadin.data.Container#getType(java.lang.Object) - */ - @Override - public Class<?> getType(Object propertyId) { - return items.getType(propertyId); - } - - /* - * Gets the number of items in the container. - * - * @return the Number of items in the container. - * - * @see com.vaadin.data.Container#size() - */ - @Override - public int size() { - return items.size(); - } - - /** - * Tests, if the collection contains an item with given id. - * - * @param itemId - * the Id the of item to be tested. - */ - @Override - public boolean containsId(Object itemId) { - if (itemId != null) { - return items.containsId(itemId); - } else { - return false; - } - } - - /** - * Gets the Property identified by the given itemId and propertyId from the - * Container - * - * @see com.vaadin.data.Container#getContainerProperty(Object, Object) - */ - @Override - public Property<?> getContainerProperty(Object itemId, Object propertyId) { - return items.getContainerProperty(itemId, propertyId); - } - - /** - * Adds the new property to all items. Adds a property with given id, type - * and default value to all items in the container. - * - * This functionality is optional. If the function is unsupported, it always - * returns false. - * - * @return True if the operation succeeded. - * @see com.vaadin.data.Container#addContainerProperty(java.lang.Object, - * java.lang.Class, java.lang.Object) - */ - @Override - public boolean addContainerProperty(Object propertyId, Class<?> type, - Object defaultValue) throws UnsupportedOperationException { - - final boolean retval = items.addContainerProperty(propertyId, type, - defaultValue); - if (retval && !(items instanceof Container.PropertySetChangeNotifier)) { - firePropertySetChange(); - } - return retval; - } - - /** - * Removes all items from the container. - * - * This functionality is optional. If the function is unsupported, it always - * returns false. - * - * @return True if the operation succeeded. - * @see com.vaadin.data.Container#removeAllItems() - */ - @Override - public boolean removeAllItems() throws UnsupportedOperationException { - - final boolean retval = items.removeAllItems(); - itemIdMapper.removeAll(); - if (retval) { - setValue(null); - if (!(items instanceof Container.ItemSetChangeNotifier)) { - fireItemSetChange(); - } - } - return retval; - } - - /** - * Creates a new item into container with container managed id. The id of - * the created new item is returned. The item can be fetched with getItem() - * method. if the creation fails, null is returned. - * - * @return the Id of the created item or null in case of failure. - * @see com.vaadin.data.Container#addItem() - */ - @Override - public Object addItem() throws UnsupportedOperationException { - - final Object retval = items.addItem(); - if (retval != null - && !(items instanceof Container.ItemSetChangeNotifier)) { - fireItemSetChange(); - } - return retval; - } - - /** - * Create a new item into container. The created new item is returned and - * ready for setting property values. if the creation fails, null is - * returned. In case the container already contains the item, null is - * returned. - * - * This functionality is optional. If the function is unsupported, it always - * returns null. - * - * @param itemId - * the Identification of the item to be created. - * @return the Created item with the given id, or null in case of failure. - * @see com.vaadin.data.Container#addItem(java.lang.Object) - */ - @Override - public Item addItem(Object itemId) throws UnsupportedOperationException { - - final Item retval = items.addItem(itemId); - if (retval != null - && !(items instanceof Container.ItemSetChangeNotifier)) { - fireItemSetChange(); - } - return retval; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.data.Container#removeItem(java.lang.Object) - */ - @Override - public boolean removeItem(Object itemId) - throws UnsupportedOperationException { - - unselect(itemId); - final boolean retval = items.removeItem(itemId); - itemIdMapper.remove(itemId); - if (retval && !(items instanceof Container.ItemSetChangeNotifier)) { - fireItemSetChange(); - } - return retval; - } - - /** - * Removes the property from all items. Removes a property with given id - * from all the items in the container. - * - * This functionality is optional. If the function is unsupported, it always - * returns false. - * - * @return True if the operation succeeded. - * @see com.vaadin.data.Container#removeContainerProperty(java.lang.Object) - */ - @Override - public boolean removeContainerProperty(Object propertyId) - throws UnsupportedOperationException { - - final boolean retval = items.removeContainerProperty(propertyId); - if (retval && !(items instanceof Container.PropertySetChangeNotifier)) { - firePropertySetChange(); - } - return retval; - } - - /* Container.Viewer methods */ - - /** - * Sets the Container that serves as the data source of the viewer. - * - * As a side-effect the fields value (selection) is set to null due old - * selection not necessary exists in new Container. - * - * @see com.vaadin.data.Container.Viewer#setContainerDataSource(Container) - * - * @param newDataSource - * the new data source. - */ - @Override - public void setContainerDataSource(Container newDataSource) { - if (newDataSource == null) { - newDataSource = new IndexedContainer(); - } - - getCaptionChangeListener().clear(); - - if (items != newDataSource) { - - // Removes listeners from the old datasource - if (items != null) { - if (items instanceof Container.ItemSetChangeNotifier) { - ((Container.ItemSetChangeNotifier) items) - .removeListener(this); - } - if (items instanceof Container.PropertySetChangeNotifier) { - ((Container.PropertySetChangeNotifier) items) - .removeListener(this); - } - } - - // Assigns new data source - items = newDataSource; - - // Clears itemIdMapper also - itemIdMapper.removeAll(); - - // Adds listeners - if (items != null) { - if (items instanceof Container.ItemSetChangeNotifier) { - ((Container.ItemSetChangeNotifier) items).addListener(this); - } - if (items instanceof Container.PropertySetChangeNotifier) { - ((Container.PropertySetChangeNotifier) items) - .addListener(this); - } - } - - /* - * We expect changing the data source should also clean value. See - * #810, #4607, #5281 - */ - setValue(null); - - requestRepaint(); - - } - } - - /** - * Gets the viewing data-source container. - * - * @see com.vaadin.data.Container.Viewer#getContainerDataSource() - */ - @Override - public Container getContainerDataSource() { - return items; - } - - /* Select attributes */ - - /** - * Is the select in multiselect mode? In multiselect mode - * - * @return the Value of property multiSelect. - */ - public boolean isMultiSelect() { - return multiSelect; - } - - /** - * Sets the multiselect mode. Setting multiselect mode false may lose - * selection information: if selected items set contains one or more - * selected items, only one of the selected items is kept as selected. - * - * Subclasses of AbstractSelect can choose not to support changing the - * multiselect mode, and may throw {@link UnsupportedOperationException}. - * - * @param multiSelect - * the New value of property multiSelect. - */ - public void setMultiSelect(boolean multiSelect) { - if (multiSelect && getNullSelectionItemId() != null) { - throw new IllegalStateException( - "Multiselect and NullSelectionItemId can not be set at the same time."); - } - if (multiSelect != this.multiSelect) { - - // Selection before mode change - final Object oldValue = getValue(); - - this.multiSelect = multiSelect; - - // Convert the value type - if (multiSelect) { - final Set<Object> s = new HashSet<Object>(); - if (oldValue != null) { - s.add(oldValue); - } - setValue(s); - } else { - final Set<?> s = (Set<?>) oldValue; - if (s == null || s.isEmpty()) { - setValue(null); - } else { - // Set the single select to contain only the first - // selected value in the multiselect - setValue(s.iterator().next()); - } - } - - requestRepaint(); - } - } - - /** - * Does the select allow adding new options by the user. If true, the new - * options can be added to the Container. The text entered by the user is - * used as id. Note that data-source must allow adding new items. - * - * @return True if additions are allowed. - */ - public boolean isNewItemsAllowed() { - - return allowNewOptions; - } - - /** - * Enables or disables possibility to add new options by the user. - * - * @param allowNewOptions - * the New value of property allowNewOptions. - */ - public void setNewItemsAllowed(boolean allowNewOptions) { - - // Only handle change requests - if (this.allowNewOptions != allowNewOptions) { - - this.allowNewOptions = allowNewOptions; - - requestRepaint(); - } - } - - /** - * Override the caption of an item. Setting caption explicitly overrides id, - * item and index captions. - * - * @param itemId - * the id of the item to be recaptioned. - * @param caption - * the New caption. - */ - public void setItemCaption(Object itemId, String caption) { - if (itemId != null) { - itemCaptions.put(itemId, caption); - requestRepaint(); - } - } - - /** - * Gets the caption of an item. The caption is generated as specified by the - * item caption mode. See <code>setItemCaptionMode()</code> for more - * details. - * - * @param itemId - * the id of the item to be queried. - * @return the caption for specified item. - */ - public String getItemCaption(Object itemId) { - - // Null items can not be found - if (itemId == null) { - return null; - } - - String caption = null; - - switch (getItemCaptionMode()) { - - case ID: - caption = itemId.toString(); - break; - - case INDEX: - if (items instanceof Container.Indexed) { - caption = String.valueOf(((Container.Indexed) items) - .indexOfId(itemId)); - } else { - caption = "ERROR: Container is not indexed"; - } - break; - - case ITEM: - final Item i = getItem(itemId); - if (i != null) { - caption = i.toString(); - } - break; - - case EXPLICIT: - caption = itemCaptions.get(itemId); - break; - - case EXPLICIT_DEFAULTS_ID: - caption = itemCaptions.get(itemId); - if (caption == null) { - caption = itemId.toString(); - } - break; - - case PROPERTY: - final Property<?> p = getContainerProperty(itemId, - getItemCaptionPropertyId()); - if (p != null) { - Object value = p.getValue(); - if (value != null) { - caption = value.toString(); - } - } - break; - } - - // All items must have some captions - return caption != null ? caption : ""; - } - - /** - * Sets tqhe icon for an item. - * - * @param itemId - * the id of the item to be assigned an icon. - * @param icon - * the icon to use or null. - */ - public void setItemIcon(Object itemId, Resource icon) { - if (itemId != null) { - if (icon == null) { - itemIcons.remove(itemId); - } else { - itemIcons.put(itemId, icon); - } - requestRepaint(); - } - } - - /** - * Gets the item icon. - * - * @param itemId - * the id of the item to be assigned an icon. - * @return the icon for the item or null, if not specified. - */ - public Resource getItemIcon(Object itemId) { - final Resource explicit = itemIcons.get(itemId); - if (explicit != null) { - return explicit; - } - - if (getItemIconPropertyId() == null) { - return null; - } - - final Property<?> ip = getContainerProperty(itemId, - getItemIconPropertyId()); - if (ip == null) { - return null; - } - final Object icon = ip.getValue(); - if (icon instanceof Resource) { - return (Resource) icon; - } - - return null; - } - - /** - * Sets the item caption mode. - * - * <p> - * The mode can be one of the following ones: - * <ul> - * <li><code>ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID</code> : Items - * Id-objects <code>toString</code> is used as item caption. If caption is - * explicitly specified, it overrides the id-caption. - * <li><code>ITEM_CAPTION_MODE_ID</code> : Items Id-objects - * <code>toString</code> is used as item caption.</li> - * <li><code>ITEM_CAPTION_MODE_ITEM</code> : Item-objects - * <code>toString</code> is used as item caption.</li> - * <li><code>ITEM_CAPTION_MODE_INDEX</code> : The index of the item is used - * as item caption. The index mode can only be used with the containers - * implementing <code>Container.Indexed</code> interface.</li> - * <li><code>ITEM_CAPTION_MODE_EXPLICIT</code> : The item captions must be - * explicitly specified.</li> - * <li><code>ITEM_CAPTION_MODE_PROPERTY</code> : The item captions are read - * from property, that must be specified with - * <code>setItemCaptionPropertyId</code>.</li> - * </ul> - * The <code>ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID</code> is the default - * mode. - * </p> - * - * @param mode - * the One of the modes listed above. - */ - public void setItemCaptionMode(ItemCaptionMode mode) { - if (mode != null) { - itemCaptionMode = mode; - requestRepaint(); - } - } - - /** - * Gets the item caption mode. - * - * <p> - * The mode can be one of the following ones: - * <ul> - * <li><code>ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID</code> : Items - * Id-objects <code>toString</code> is used as item caption. If caption is - * explicitly specified, it overrides the id-caption. - * <li><code>ITEM_CAPTION_MODE_ID</code> : Items Id-objects - * <code>toString</code> is used as item caption.</li> - * <li><code>ITEM_CAPTION_MODE_ITEM</code> : Item-objects - * <code>toString</code> is used as item caption.</li> - * <li><code>ITEM_CAPTION_MODE_INDEX</code> : The index of the item is used - * as item caption. The index mode can only be used with the containers - * implementing <code>Container.Indexed</code> interface.</li> - * <li><code>ITEM_CAPTION_MODE_EXPLICIT</code> : The item captions must be - * explicitly specified.</li> - * <li><code>ITEM_CAPTION_MODE_PROPERTY</code> : The item captions are read - * from property, that must be specified with - * <code>setItemCaptionPropertyId</code>.</li> - * </ul> - * The <code>ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID</code> is the default - * mode. - * </p> - * - * @return the One of the modes listed above. - */ - public ItemCaptionMode getItemCaptionMode() { - return itemCaptionMode; - } - - /** - * Sets the item caption property. - * - * <p> - * Setting the id to a existing property implicitly sets the item caption - * mode to <code>ITEM_CAPTION_MODE_PROPERTY</code>. If the object is in - * <code>ITEM_CAPTION_MODE_PROPERTY</code> mode, setting caption property id - * null resets the item caption mode to - * <code>ITEM_CAPTION_EXPLICIT_DEFAULTS_ID</code>. - * </p> - * <p> - * Note that the type of the property used for caption must be String - * </p> - * <p> - * Setting the property id to null disables this feature. The id is null by - * default - * </p> - * . - * - * @param propertyId - * the id of the property. - * - */ - public void setItemCaptionPropertyId(Object propertyId) { - if (propertyId != null) { - itemCaptionPropertyId = propertyId; - setItemCaptionMode(ITEM_CAPTION_MODE_PROPERTY); - requestRepaint(); - } else { - itemCaptionPropertyId = null; - if (getItemCaptionMode() == ITEM_CAPTION_MODE_PROPERTY) { - setItemCaptionMode(ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID); - } - requestRepaint(); - } - } - - /** - * Gets the item caption property. - * - * @return the Id of the property used as item caption source. - */ - public Object getItemCaptionPropertyId() { - return itemCaptionPropertyId; - } - - /** - * Sets the item icon property. - * - * <p> - * If the property id is set to a valid value, each item is given an icon - * got from the given property of the items. The type of the property must - * be assignable to Resource. - * </p> - * - * <p> - * Note : The icons set with <code>setItemIcon</code> function override the - * icons from the property. - * </p> - * - * <p> - * Setting the property id to null disables this feature. The id is null by - * default - * </p> - * . - * - * @param propertyId - * the id of the property that specifies icons for items or null - * @throws IllegalArgumentException - * If the propertyId is not in the container or is not of a - * valid type - */ - public void setItemIconPropertyId(Object propertyId) - throws IllegalArgumentException { - if (propertyId == null) { - itemIconPropertyId = null; - } else if (!getContainerPropertyIds().contains(propertyId)) { - throw new IllegalArgumentException( - "Property id not found in the container"); - } else if (Resource.class.isAssignableFrom(getType(propertyId))) { - itemIconPropertyId = propertyId; - } else { - throw new IllegalArgumentException( - "Property type must be assignable to Resource"); - } - requestRepaint(); - } - - /** - * Gets the item icon property. - * - * <p> - * If the property id is set to a valid value, each item is given an icon - * got from the given property of the items. The type of the property must - * be assignable to Icon. - * </p> - * - * <p> - * Note : The icons set with <code>setItemIcon</code> function override the - * icons from the property. - * </p> - * - * <p> - * Setting the property id to null disables this feature. The id is null by - * default - * </p> - * . - * - * @return the Id of the property containing the item icons. - */ - public Object getItemIconPropertyId() { - return itemIconPropertyId; - } - - /** - * Tests if an item is selected. - * - * <p> - * In single select mode testing selection status of the item identified by - * {@link #getNullSelectionItemId()} returns true if the value of the - * property is null. - * </p> - * - * @param itemId - * the Id the of the item to be tested. - * @see #getNullSelectionItemId() - * @see #setNullSelectionItemId(Object) - * - */ - public boolean isSelected(Object itemId) { - if (itemId == null) { - return false; - } - if (isMultiSelect()) { - return ((Set<?>) getValue()).contains(itemId); - } else { - final Object value = getValue(); - return itemId.equals(value == null ? getNullSelectionItemId() - : value); - } - } - - /** - * Selects an item. - * - * <p> - * In single select mode selecting item identified by - * {@link #getNullSelectionItemId()} sets the value of the property to null. - * </p> - * - * @param itemId - * the identifier of Item to be selected. - * @see #getNullSelectionItemId() - * @see #setNullSelectionItemId(Object) - * - */ - public void select(Object itemId) { - if (!isMultiSelect()) { - setValue(itemId); - } else if (!isSelected(itemId) && itemId != null - && items.containsId(itemId)) { - final Set<Object> s = new HashSet<Object>((Set<?>) getValue()); - s.add(itemId); - setValue(s); - } - } - - /** - * Unselects an item. - * - * @param itemId - * the identifier of the Item to be unselected. - * @see #getNullSelectionItemId() - * @see #setNullSelectionItemId(Object) - * - */ - public void unselect(Object itemId) { - if (isSelected(itemId)) { - if (isMultiSelect()) { - final Set<Object> s = new HashSet<Object>((Set<?>) getValue()); - s.remove(itemId); - setValue(s); - } else { - setValue(null); - } - } - } - - /** - * Notifies this listener that the Containers contents has changed. - * - * @see com.vaadin.data.Container.PropertySetChangeListener#containerPropertySetChange(com.vaadin.data.Container.PropertySetChangeEvent) - */ - @Override - public void containerPropertySetChange( - Container.PropertySetChangeEvent event) { - firePropertySetChange(); - } - - /** - * Adds a new Property set change listener for this Container. - * - * @see com.vaadin.data.Container.PropertySetChangeNotifier#addListener(com.vaadin.data.Container.PropertySetChangeListener) - */ - @Override - public void addListener(Container.PropertySetChangeListener listener) { - if (propertySetEventListeners == null) { - propertySetEventListeners = new LinkedHashSet<Container.PropertySetChangeListener>(); - } - propertySetEventListeners.add(listener); - } - - /** - * Removes a previously registered Property set change listener. - * - * @see com.vaadin.data.Container.PropertySetChangeNotifier#removeListener(com.vaadin.data.Container.PropertySetChangeListener) - */ - @Override - public void removeListener(Container.PropertySetChangeListener listener) { - if (propertySetEventListeners != null) { - propertySetEventListeners.remove(listener); - if (propertySetEventListeners.isEmpty()) { - propertySetEventListeners = null; - } - } - } - - /** - * Adds an Item set change listener for the object. - * - * @see com.vaadin.data.Container.ItemSetChangeNotifier#addListener(com.vaadin.data.Container.ItemSetChangeListener) - */ - @Override - public void addListener(Container.ItemSetChangeListener listener) { - if (itemSetEventListeners == null) { - itemSetEventListeners = new LinkedHashSet<Container.ItemSetChangeListener>(); - } - itemSetEventListeners.add(listener); - } - - /** - * Removes the Item set change listener from the object. - * - * @see com.vaadin.data.Container.ItemSetChangeNotifier#removeListener(com.vaadin.data.Container.ItemSetChangeListener) - */ - @Override - public void removeListener(Container.ItemSetChangeListener listener) { - if (itemSetEventListeners != null) { - itemSetEventListeners.remove(listener); - if (itemSetEventListeners.isEmpty()) { - itemSetEventListeners = null; - } - } - } - - @Override - public Collection<?> getListeners(Class<?> eventType) { - if (Container.ItemSetChangeEvent.class.isAssignableFrom(eventType)) { - if (itemSetEventListeners == null) { - return Collections.EMPTY_LIST; - } else { - return Collections - .unmodifiableCollection(itemSetEventListeners); - } - } else if (Container.PropertySetChangeEvent.class - .isAssignableFrom(eventType)) { - if (propertySetEventListeners == null) { - return Collections.EMPTY_LIST; - } else { - return Collections - .unmodifiableCollection(propertySetEventListeners); - } - } - - return super.getListeners(eventType); - } - - /** - * Lets the listener know a Containers Item set has changed. - * - * @see com.vaadin.data.Container.ItemSetChangeListener#containerItemSetChange(com.vaadin.data.Container.ItemSetChangeEvent) - */ - @Override - public void containerItemSetChange(Container.ItemSetChangeEvent event) { - // Clears the item id mapping table - itemIdMapper.removeAll(); - - // Notify all listeners - fireItemSetChange(); - } - - /** - * Fires the property set change event. - */ - protected void firePropertySetChange() { - if (propertySetEventListeners != null - && !propertySetEventListeners.isEmpty()) { - final Container.PropertySetChangeEvent event = new PropertySetChangeEvent(); - final Object[] listeners = propertySetEventListeners.toArray(); - for (int i = 0; i < listeners.length; i++) { - ((Container.PropertySetChangeListener) listeners[i]) - .containerPropertySetChange(event); - } - } - requestRepaint(); - } - - /** - * Fires the item set change event. - */ - protected void fireItemSetChange() { - if (itemSetEventListeners != null && !itemSetEventListeners.isEmpty()) { - final Container.ItemSetChangeEvent event = new ItemSetChangeEvent(); - final Object[] listeners = itemSetEventListeners.toArray(); - for (int i = 0; i < listeners.length; i++) { - ((Container.ItemSetChangeListener) listeners[i]) - .containerItemSetChange(event); - } - } - requestRepaint(); - } - - /** - * Implementation of item set change event. - */ - private class ItemSetChangeEvent implements Serializable, - Container.ItemSetChangeEvent { - - /** - * Gets the Property where the event occurred. - * - * @see com.vaadin.data.Container.ItemSetChangeEvent#getContainer() - */ - @Override - public Container getContainer() { - return AbstractSelect.this; - } - - } - - /** - * Implementation of property set change event. - */ - private class PropertySetChangeEvent implements - Container.PropertySetChangeEvent, Serializable { - - /** - * Retrieves the Container whose contents have been modified. - * - * @see com.vaadin.data.Container.PropertySetChangeEvent#getContainer() - */ - @Override - public Container getContainer() { - return AbstractSelect.this; - } - - } - - /** - * For multi-selectable fields, also an empty collection of values is - * considered to be an empty field. - * - * @see AbstractField#isEmpty(). - */ - @Override - protected boolean isEmpty() { - if (!multiSelect) { - return super.isEmpty(); - } else { - Object value = getValue(); - return super.isEmpty() - || (value instanceof Collection && ((Collection<?>) value) - .isEmpty()); - } - } - - /** - * Allow or disallow empty selection by the user. If the select is in - * single-select mode, you can make an item represent the empty selection by - * calling <code>setNullSelectionItemId()</code>. This way you can for - * instance set an icon and caption for the null selection item. - * - * @param nullSelectionAllowed - * whether or not to allow empty selection - * @see #setNullSelectionItemId(Object) - * @see #isNullSelectionAllowed() - */ - public void setNullSelectionAllowed(boolean nullSelectionAllowed) { - if (nullSelectionAllowed != this.nullSelectionAllowed) { - this.nullSelectionAllowed = nullSelectionAllowed; - requestRepaint(); - } - } - - /** - * Checks if null empty selection is allowed by the user. - * - * @return whether or not empty selection is allowed - * @see #setNullSelectionAllowed(boolean) - */ - public boolean isNullSelectionAllowed() { - return nullSelectionAllowed; - } - - /** - * Returns the item id that represents null value of this select in single - * select mode. - * - * <p> - * Data interface does not support nulls as item ids. Selecting the item - * identified by this id is the same as selecting no items at all. This - * setting only affects the single select mode. - * </p> - * - * @return the Object Null value item id. - * @see #setNullSelectionItemId(Object) - * @see #isSelected(Object) - * @see #select(Object) - */ - public Object getNullSelectionItemId() { - return nullSelectionItemId; - } - - /** - * Sets the item id that represents null value of this select. - * - * <p> - * Data interface does not support nulls as item ids. Selecting the item - * identified by this id is the same as selecting no items at all. This - * setting only affects the single select mode. - * </p> - * - * @param nullSelectionItemId - * the nullSelectionItemId to set. - * @see #getNullSelectionItemId() - * @see #isSelected(Object) - * @see #select(Object) - */ - public void setNullSelectionItemId(Object nullSelectionItemId) { - if (nullSelectionItemId != null && isMultiSelect()) { - throw new IllegalStateException( - "Multiselect and NullSelectionItemId can not be set at the same time."); - } - this.nullSelectionItemId = nullSelectionItemId; - } - - /** - * Notifies the component that it is connected to an application. - * - * @see com.vaadin.ui.AbstractField#attach() - */ - @Override - public void attach() { - super.attach(); - } - - /** - * Detaches the component from application. - * - * @see com.vaadin.ui.AbstractComponent#detach() - */ - @Override - public void detach() { - getCaptionChangeListener().clear(); - super.detach(); - } - - // Caption change listener - protected CaptionChangeListener getCaptionChangeListener() { - if (captionChangeListener == null) { - captionChangeListener = new CaptionChangeListener(); - } - return captionChangeListener; - } - - /** - * This is a listener helper for Item and Property changes that should cause - * a repaint. It should be attached to all items that are displayed, and the - * default implementation does this in paintContent(). Especially - * "lazyloading" components should take care to add and remove listeners as - * appropriate. Call addNotifierForItem() for each painted item (and - * remember to clear). - * - * NOTE: singleton, use getCaptionChangeListener(). - * - */ - protected class CaptionChangeListener implements - Item.PropertySetChangeListener, Property.ValueChangeListener { - - // TODO clean this up - type is either Item.PropertySetChangeNotifier or - // Property.ValueChangeNotifier - HashSet<Object> captionChangeNotifiers = new HashSet<Object>(); - - public void addNotifierForItem(Object itemId) { - switch (getItemCaptionMode()) { - case ITEM: - final Item i = getItem(itemId); - if (i == null) { - return; - } - if (i instanceof Item.PropertySetChangeNotifier) { - ((Item.PropertySetChangeNotifier) i) - .addListener(getCaptionChangeListener()); - captionChangeNotifiers.add(i); - } - Collection<?> pids = i.getItemPropertyIds(); - if (pids != null) { - for (Iterator<?> it = pids.iterator(); it.hasNext();) { - Property<?> p = i.getItemProperty(it.next()); - if (p != null - && p instanceof Property.ValueChangeNotifier) { - ((Property.ValueChangeNotifier) p) - .addListener(getCaptionChangeListener()); - captionChangeNotifiers.add(p); - } - } - - } - break; - case PROPERTY: - final Property<?> p = getContainerProperty(itemId, - getItemCaptionPropertyId()); - if (p != null && p instanceof Property.ValueChangeNotifier) { - ((Property.ValueChangeNotifier) p) - .addListener(getCaptionChangeListener()); - captionChangeNotifiers.add(p); - } - break; - - } - } - - public void clear() { - for (Iterator<Object> it = captionChangeNotifiers.iterator(); it - .hasNext();) { - Object notifier = it.next(); - if (notifier instanceof Item.PropertySetChangeNotifier) { - ((Item.PropertySetChangeNotifier) notifier) - .removeListener(getCaptionChangeListener()); - } else { - ((Property.ValueChangeNotifier) notifier) - .removeListener(getCaptionChangeListener()); - } - } - captionChangeNotifiers.clear(); - } - - @Override - public void valueChange(com.vaadin.data.Property.ValueChangeEvent event) { - requestRepaint(); - } - - @Override - public void itemPropertySetChange( - com.vaadin.data.Item.PropertySetChangeEvent event) { - requestRepaint(); - } - - } - - /** - * Criterion which accepts a drop only if the drop target is (one of) the - * given Item identifier(s). Criterion can be used only on a drop targets - * that extends AbstractSelect like {@link Table} and {@link Tree}. The - * target and identifiers of valid Items are given in constructor. - * - * @since 6.3 - */ - public static class TargetItemIs extends AbstractItemSetCriterion { - - /** - * @param select - * the select implementation that is used as a drop target - * @param itemId - * the identifier(s) that are valid drop locations - */ - public TargetItemIs(AbstractSelect select, Object... itemId) { - super(select, itemId); - } - - @Override - public boolean accept(DragAndDropEvent dragEvent) { - AbstractSelectTargetDetails dropTargetData = (AbstractSelectTargetDetails) dragEvent - .getTargetDetails(); - if (dropTargetData.getTarget() != select) { - return false; - } - return itemIds.contains(dropTargetData.getItemIdOver()); - } - - } - - /** - * Abstract helper class to implement item id based criterion. - * - * Note, inner class used not to open itemIdMapper for public access. - * - * @since 6.3 - * - */ - private static abstract class AbstractItemSetCriterion extends - ClientSideCriterion { - protected final Collection<Object> itemIds = new HashSet<Object>(); - protected AbstractSelect select; - - public AbstractItemSetCriterion(AbstractSelect select, Object... itemId) { - if (itemIds == null || select == null) { - throw new IllegalArgumentException( - "Accepted item identifiers must be accepted."); - } - Collections.addAll(itemIds, itemId); - this.select = select; - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - super.paintContent(target); - String[] keys = new String[itemIds.size()]; - int i = 0; - for (Object itemId : itemIds) { - String key = select.itemIdMapper.key(itemId); - keys[i++] = key; - } - target.addAttribute("keys", keys); - target.addAttribute("s", select); - } - - } - - /** - * This criterion accepts a only a {@link Transferable} that contains given - * Item (practically its identifier) from a specific AbstractSelect. - * - * @since 6.3 - */ - public static class AcceptItem extends AbstractItemSetCriterion { - - /** - * @param select - * the select from which the item id's are checked - * @param itemId - * the item identifier(s) of the select that are accepted - */ - public AcceptItem(AbstractSelect select, Object... itemId) { - super(select, itemId); - } - - @Override - public boolean accept(DragAndDropEvent dragEvent) { - DataBoundTransferable transferable = (DataBoundTransferable) dragEvent - .getTransferable(); - if (transferable.getSourceComponent() != select) { - return false; - } - return itemIds.contains(transferable.getItemId()); - } - - /** - * A simple accept criterion which ensures that {@link Transferable} - * contains an {@link Item} (or actually its identifier). In other words - * the criterion check that drag is coming from a {@link Container} like - * {@link Tree} or {@link Table}. - */ - public static final ClientSideCriterion ALL = new ContainsDataFlavor( - "itemId"); - - } - - /** - * TargetDetails implementation for subclasses of {@link AbstractSelect} - * that implement {@link DropTarget}. - * - * @since 6.3 - */ - public class AbstractSelectTargetDetails extends TargetDetailsImpl { - - /** - * The item id over which the drag event happened. - */ - protected Object idOver; - - /** - * Constructor that automatically converts itemIdOver key to - * corresponding item Id - * - */ - protected AbstractSelectTargetDetails(Map<String, Object> rawVariables) { - super(rawVariables, (DropTarget) AbstractSelect.this); - // eagar fetch itemid, mapper may be emptied - String keyover = (String) getData("itemIdOver"); - if (keyover != null) { - idOver = itemIdMapper.get(keyover); - } - } - - /** - * If the drag operation is currently over an {@link Item}, this method - * returns the identifier of that {@link Item}. - * - */ - public Object getItemIdOver() { - return idOver; - } - - /** - * Returns a detailed vertical location where the drop happened on Item. - */ - public VerticalDropLocation getDropLocation() { - String detail = (String) getData("detail"); - if (detail == null) { - return null; - } - return VerticalDropLocation.valueOf(detail); - } - - } - - /** - * An accept criterion to accept drops only on a specific vertical location - * of an item. - * <p> - * This accept criterion is currently usable in Tree and Table - * implementations. - */ - public static class VerticalLocationIs extends TargetDetailIs { - public static VerticalLocationIs TOP = new VerticalLocationIs( - VerticalDropLocation.TOP); - public static VerticalLocationIs BOTTOM = new VerticalLocationIs( - VerticalDropLocation.BOTTOM); - public static VerticalLocationIs MIDDLE = new VerticalLocationIs( - VerticalDropLocation.MIDDLE); - - private VerticalLocationIs(VerticalDropLocation l) { - super("detail", l.name()); - } - } - - /** - * Implement this interface and pass it to Tree.setItemDescriptionGenerator - * or Table.setItemDescriptionGenerator to generate mouse over descriptions - * ("tooltips") for the rows and cells in Table or for the items in Tree. - */ - public interface ItemDescriptionGenerator extends Serializable { - - /** - * Called by Table when a cell (and row) is painted or a item is painted - * in Tree - * - * @param source - * The source of the generator, the Tree or Table the - * generator is attached to - * @param itemId - * The itemId of the painted cell - * @param propertyId - * The propertyId of the cell, null when getting row - * description - * @return The description or "tooltip" of the item. - */ - public String generateDescription(Component source, Object itemId, - Object propertyId); - } -} diff --git a/src/com/vaadin/ui/AbstractSplitPanel.java b/src/com/vaadin/ui/AbstractSplitPanel.java deleted file mode 100644 index 90dc38ff65..0000000000 --- a/src/com/vaadin/ui/AbstractSplitPanel.java +++ /dev/null @@ -1,521 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.Iterator; - -import com.vaadin.event.ComponentEventListener; -import com.vaadin.event.MouseEvents.ClickEvent; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.splitpanel.AbstractSplitPanelRpc; -import com.vaadin.shared.ui.splitpanel.AbstractSplitPanelState; -import com.vaadin.shared.ui.splitpanel.AbstractSplitPanelState.SplitterState; -import com.vaadin.terminal.Sizeable; -import com.vaadin.terminal.gwt.client.ui.ClickEventHandler; -import com.vaadin.tools.ReflectTools; - -/** - * AbstractSplitPanel. - * - * <code>AbstractSplitPanel</code> is base class for a component container that - * can contain two components. The components are split by a divider element. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 6.5 - */ -public abstract class AbstractSplitPanel extends AbstractComponentContainer { - - // TODO use Unit in AbstractSplitPanelState and remove these - private Unit posUnit; - private Unit posMinUnit; - private Unit posMaxUnit; - - private AbstractSplitPanelRpc rpc = new AbstractSplitPanelRpc() { - - @Override - public void splitterClick(MouseEventDetails mouseDetails) { - fireEvent(new SplitterClickEvent(AbstractSplitPanel.this, - mouseDetails)); - } - - @Override - public void setSplitterPosition(float position) { - getSplitterState().setPosition(position); - } - }; - - public AbstractSplitPanel() { - registerRpc(rpc); - setSplitPosition(50, Unit.PERCENTAGE, false); - setSplitPositionLimits(0, Unit.PERCENTAGE, 100, Unit.PERCENTAGE); - } - - /** - * Modifiable and Serializable Iterator for the components, used by - * {@link AbstractSplitPanel#getComponentIterator()}. - */ - private class ComponentIterator implements Iterator<Component>, - Serializable { - - int i = 0; - - @Override - public boolean hasNext() { - if (i < getComponentCount()) { - return true; - } - return false; - } - - @Override - public Component next() { - if (!hasNext()) { - return null; - } - i++; - if (i == 1) { - return (getFirstComponent() == null ? getSecondComponent() - : getFirstComponent()); - } else if (i == 2) { - return getSecondComponent(); - } - return null; - } - - @Override - public void remove() { - if (i == 1) { - if (getFirstComponent() != null) { - setFirstComponent(null); - i = 0; - } else { - setSecondComponent(null); - } - } else if (i == 2) { - setSecondComponent(null); - } - } - } - - /** - * Add a component into this container. The component is added to the right - * or under the previous component. - * - * @param c - * the component to be added. - */ - - @Override - public void addComponent(Component c) { - if (getFirstComponent() == null) { - setFirstComponent(c); - } else if (getSecondComponent() == null) { - setSecondComponent(c); - } else { - throw new UnsupportedOperationException( - "Split panel can contain only two components"); - } - } - - /** - * Sets the first component of this split panel. Depending on the direction - * the first component is shown at the top or to the left. - * - * @param c - * The component to use as first component - */ - public void setFirstComponent(Component c) { - if (getFirstComponent() == c) { - // Nothing to do - return; - } - - if (getFirstComponent() != null) { - // detach old - removeComponent(getFirstComponent()); - } - getState().setFirstChild(c); - if (c != null) { - super.addComponent(c); - } - - requestRepaint(); - } - - /** - * Sets the second component of this split panel. Depending on the direction - * the second component is shown at the bottom or to the left. - * - * @param c - * The component to use as first component - */ - public void setSecondComponent(Component c) { - if (getSecondComponent() == c) { - // Nothing to do - return; - } - - if (getSecondComponent() != null) { - // detach old - removeComponent(getSecondComponent()); - } - getState().setSecondChild(c); - if (c != null) { - super.addComponent(c); - } - requestRepaint(); - } - - /** - * Gets the first component of this split panel. Depending on the direction - * this is either the component shown at the top or to the left. - * - * @return the first component of this split panel - */ - public Component getFirstComponent() { - return (Component) getState().getFirstChild(); - } - - /** - * Gets the second component of this split panel. Depending on the direction - * this is either the component shown at the top or to the left. - * - * @return the second component of this split panel - */ - public Component getSecondComponent() { - return (Component) getState().getSecondChild(); - } - - /** - * Removes the component from this container. - * - * @param c - * the component to be removed. - */ - - @Override - public void removeComponent(Component c) { - super.removeComponent(c); - if (c == getFirstComponent()) { - getState().setFirstChild(null); - } else if (c == getSecondComponent()) { - getState().setSecondChild(null); - } - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.ComponentContainer#getComponentIterator() - */ - - @Override - public Iterator<Component> getComponentIterator() { - return new ComponentIterator(); - } - - /** - * Gets the number of contained components. Consistent with the iterator - * returned by {@link #getComponentIterator()}. - * - * @return the number of contained components (zero, one or two) - */ - - @Override - public int getComponentCount() { - int count = 0; - if (getFirstComponent() != null) { - count++; - } - if (getSecondComponent() != null) { - count++; - } - return count; - } - - /* Documented in superclass */ - - @Override - public void replaceComponent(Component oldComponent, Component newComponent) { - if (oldComponent == getFirstComponent()) { - setFirstComponent(newComponent); - } else if (oldComponent == getSecondComponent()) { - setSecondComponent(newComponent); - } - requestRepaint(); - } - - /** - * Moves the position of the splitter. - * - * @param pos - * the new size of the first region in the unit that was last - * used (default is percentage). Fractions are only allowed when - * unit is percentage. - */ - public void setSplitPosition(float pos) { - setSplitPosition(pos, posUnit, false); - } - - /** - * Moves the position of the splitter. - * - * @param pos - * the new size of the region in the unit that was last used - * (default is percentage). Fractions are only allowed when unit - * is percentage. - * - * @param reverse - * if set to true the split splitter position is measured by the - * second region else it is measured by the first region - */ - public void setSplitPosition(float pos, boolean reverse) { - setSplitPosition(pos, posUnit, reverse); - } - - /** - * Moves the position of the splitter with given position and unit. - * - * @param pos - * the new size of the first region. Fractions are only allowed - * when unit is percentage. - * @param unit - * the unit (from {@link Sizeable}) in which the size is given. - */ - public void setSplitPosition(float pos, Unit unit) { - setSplitPosition(pos, unit, false); - } - - /** - * Moves the position of the splitter with given position and unit. - * - * @param pos - * the new size of the first region. Fractions are only allowed - * when unit is percentage. - * @param unit - * the unit (from {@link Sizeable}) in which the size is given. - * @param reverse - * if set to true the split splitter position is measured by the - * second region else it is measured by the first region - * - */ - public void setSplitPosition(float pos, Unit unit, boolean reverse) { - if (unit != Unit.PERCENTAGE && unit != Unit.PIXELS) { - throw new IllegalArgumentException( - "Only percentage and pixel units are allowed"); - } - if (unit != Unit.PERCENTAGE) { - pos = Math.round(pos); - } - SplitterState splitterState = getSplitterState(); - splitterState.setPosition(pos); - splitterState.setPositionUnit(unit.getSymbol()); - splitterState.setPositionReversed(reverse); - posUnit = unit; - - requestRepaint(); - } - - /** - * Returns the current position of the splitter, in - * {@link #getSplitPositionUnit()} units. - * - * @return position of the splitter - */ - public float getSplitPosition() { - return getSplitterState().getPosition(); - } - - /** - * Returns the unit of position of the splitter - * - * @return unit of position of the splitter - */ - public Unit getSplitPositionUnit() { - return posUnit; - } - - /** - * Sets the minimum split position to the given position and unit. If the - * split position is reversed, maximum and minimum are also reversed. - * - * @param pos - * the minimum position of the split - * @param unit - * the unit (from {@link Sizeable}) in which the size is given. - * Allowed units are UNITS_PERCENTAGE and UNITS_PIXELS - */ - public void setMinSplitPosition(int pos, Unit unit) { - setSplitPositionLimits(pos, unit, getSplitterState().getMaxPosition(), - posMaxUnit); - } - - /** - * Returns the current minimum position of the splitter, in - * {@link #getMinSplitPositionUnit()} units. - * - * @return the minimum position of the splitter - */ - public float getMinSplitPosition() { - return getSplitterState().getMinPosition(); - } - - /** - * Returns the unit of the minimum position of the splitter. - * - * @return the unit of the minimum position of the splitter - */ - public Unit getMinSplitPositionUnit() { - return posMinUnit; - } - - /** - * Sets the maximum split position to the given position and unit. If the - * split position is reversed, maximum and minimum are also reversed. - * - * @param pos - * the maximum position of the split - * @param unit - * the unit (from {@link Sizeable}) in which the size is given. - * Allowed units are UNITS_PERCENTAGE and UNITS_PIXELS - */ - public void setMaxSplitPosition(float pos, Unit unit) { - setSplitPositionLimits(getSplitterState().getMinPosition(), posMinUnit, - pos, unit); - } - - /** - * Returns the current maximum position of the splitter, in - * {@link #getMaxSplitPositionUnit()} units. - * - * @return the maximum position of the splitter - */ - public float getMaxSplitPosition() { - return getSplitterState().getMaxPosition(); - } - - /** - * Returns the unit of the maximum position of the splitter - * - * @return the unit of the maximum position of the splitter - */ - public Unit getMaxSplitPositionUnit() { - return posMaxUnit; - } - - /** - * Sets the maximum and minimum position of the splitter. If the split - * position is reversed, maximum and minimum are also reversed. - * - * @param minPos - * the new minimum position - * @param minPosUnit - * the unit (from {@link Sizeable}) in which the minimum position - * is given. - * @param maxPos - * the new maximum position - * @param maxPosUnit - * the unit (from {@link Sizeable}) in which the maximum position - * is given. - */ - private void setSplitPositionLimits(float minPos, Unit minPosUnit, - float maxPos, Unit maxPosUnit) { - if ((minPosUnit != Unit.PERCENTAGE && minPosUnit != Unit.PIXELS) - || (maxPosUnit != Unit.PERCENTAGE && maxPosUnit != Unit.PIXELS)) { - throw new IllegalArgumentException( - "Only percentage and pixel units are allowed"); - } - - SplitterState state = getSplitterState(); - - state.setMinPosition(minPos); - state.setMinPositionUnit(minPosUnit.getSymbol()); - posMinUnit = minPosUnit; - - state.setMaxPosition(maxPos); - state.setMaxPositionUnit(maxPosUnit.getSymbol()); - posMaxUnit = maxPosUnit; - - requestRepaint(); - } - - /** - * Lock the SplitPanels position, disabling the user from dragging the split - * handle. - * - * @param locked - * Set <code>true</code> if locked, <code>false</code> otherwise. - */ - public void setLocked(boolean locked) { - getSplitterState().setLocked(locked); - requestRepaint(); - } - - /** - * Is the SplitPanel handle locked (user not allowed to change split - * position by dragging). - * - * @return <code>true</code> if locked, <code>false</code> otherwise. - */ - public boolean isLocked() { - return getSplitterState().isLocked(); - } - - /** - * <code>SplitterClickListener</code> interface for listening for - * <code>SplitterClickEvent</code> fired by a <code>SplitPanel</code>. - * - * @see SplitterClickEvent - * @since 6.2 - */ - public interface SplitterClickListener extends ComponentEventListener { - - public static final Method clickMethod = ReflectTools.findMethod( - SplitterClickListener.class, "splitterClick", - SplitterClickEvent.class); - - /** - * SplitPanel splitter has been clicked - * - * @param event - * SplitterClickEvent event. - */ - public void splitterClick(SplitterClickEvent event); - } - - public class SplitterClickEvent extends ClickEvent { - - public SplitterClickEvent(Component source, - MouseEventDetails mouseEventDetails) { - super(source, mouseEventDetails); - } - - } - - public void addListener(SplitterClickListener listener) { - addListener(ClickEventHandler.CLICK_EVENT_IDENTIFIER, - SplitterClickEvent.class, listener, - SplitterClickListener.clickMethod); - } - - public void removeListener(SplitterClickListener listener) { - removeListener(ClickEventHandler.CLICK_EVENT_IDENTIFIER, - SplitterClickEvent.class, listener); - } - - @Override - public AbstractSplitPanelState getState() { - return (AbstractSplitPanelState) super.getState(); - } - - private SplitterState getSplitterState() { - return getState().getSplitterState(); - } -} diff --git a/src/com/vaadin/ui/AbstractTextField.java b/src/com/vaadin/ui/AbstractTextField.java deleted file mode 100644 index 2326c07d97..0000000000 --- a/src/com/vaadin/ui/AbstractTextField.java +++ /dev/null @@ -1,674 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.Map; - -import com.vaadin.event.FieldEvents.BlurEvent; -import com.vaadin.event.FieldEvents.BlurListener; -import com.vaadin.event.FieldEvents.BlurNotifier; -import com.vaadin.event.FieldEvents.FocusEvent; -import com.vaadin.event.FieldEvents.FocusListener; -import com.vaadin.event.FieldEvents.FocusNotifier; -import com.vaadin.event.FieldEvents.TextChangeEvent; -import com.vaadin.event.FieldEvents.TextChangeListener; -import com.vaadin.event.FieldEvents.TextChangeNotifier; -import com.vaadin.shared.ui.textfield.AbstractTextFieldState; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.gwt.client.ui.textfield.VTextField; - -public abstract class AbstractTextField extends AbstractField<String> implements - BlurNotifier, FocusNotifier, TextChangeNotifier, Vaadin6Component { - - /** - * Null representation. - */ - private String nullRepresentation = "null"; - /** - * Is setting to null from non-null value allowed by setting with null - * representation . - */ - private boolean nullSettingAllowed = false; - /** - * The text content when the last messages to the server was sent. Cleared - * when value is changed. - */ - private String lastKnownTextContent; - - /** - * The position of the cursor when the last message to the server was sent. - */ - private int lastKnownCursorPosition; - - /** - * Flag indicating that a text change event is pending to be triggered. - * Cleared by {@link #setInternalValue(Object)} and when the event is fired. - */ - private boolean textChangeEventPending; - - private boolean isFiringTextChangeEvent = false; - - private TextChangeEventMode textChangeEventMode = TextChangeEventMode.LAZY; - - private final int DEFAULT_TEXTCHANGE_TIMEOUT = 400; - - private int textChangeEventTimeout = DEFAULT_TEXTCHANGE_TIMEOUT; - - /** - * Temporarily holds the new selection position. Cleared on paint. - */ - private int selectionPosition = -1; - - /** - * Temporarily holds the new selection length. - */ - private int selectionLength; - - /** - * Flag used to determine whether we are currently handling a state change - * triggered by a user. Used to properly fire text change event before value - * change event triggered by the client side. - */ - private boolean changingVariables; - - protected AbstractTextField() { - super(); - } - - @Override - public AbstractTextFieldState getState() { - return (AbstractTextFieldState) super.getState(); - } - - @Override - public void updateState() { - super.updateState(); - - String value = getValue(); - if (value == null) { - value = getNullRepresentation(); - } - getState().setText(value); - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - - if (selectionPosition != -1) { - target.addAttribute("selpos", selectionPosition); - target.addAttribute("sellen", selectionLength); - selectionPosition = -1; - } - - if (hasListeners(TextChangeEvent.class)) { - target.addAttribute(VTextField.ATTR_TEXTCHANGE_EVENTMODE, - getTextChangeEventMode().toString()); - target.addAttribute(VTextField.ATTR_TEXTCHANGE_TIMEOUT, - getTextChangeTimeout()); - if (lastKnownTextContent != null) { - /* - * The field has be repainted for some reason (e.g. caption, - * size, stylename), but the value has not been changed since - * the last text change event. Let the client side know about - * the value the server side knows. Client side may then ignore - * the actual value, depending on its state. - */ - target.addAttribute( - VTextField.ATTR_NO_VALUE_CHANGE_BETWEEN_PAINTS, true); - } - } - - } - - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - changingVariables = true; - - try { - - if (variables.containsKey(VTextField.VAR_CURSOR)) { - Integer object = (Integer) variables.get(VTextField.VAR_CURSOR); - lastKnownCursorPosition = object.intValue(); - } - - if (variables.containsKey(VTextField.VAR_CUR_TEXT)) { - /* - * NOTE, we might want to develop this further so that on a - * value change event the whole text content don't need to be - * sent from the client to server. Just "commit" the value from - * currentText to the value. - */ - handleInputEventTextChange(variables); - } - - // Sets the text - if (variables.containsKey("text") && !isReadOnly()) { - - // Only do the setting if the string representation of the value - // has been updated - String newValue = (String) variables.get("text"); - - // server side check for max length - if (getMaxLength() != -1 && newValue.length() > getMaxLength()) { - newValue = newValue.substring(0, getMaxLength()); - } - final String oldValue = getValue(); - if (newValue != null - && (oldValue == null || isNullSettingAllowed()) - && newValue.equals(getNullRepresentation())) { - newValue = null; - } - if (newValue != oldValue - && (newValue == null || !newValue.equals(oldValue))) { - boolean wasModified = isModified(); - setValue(newValue, true); - - // If the modified status changes, or if we have a - // formatter, repaint is needed after all. - if (wasModified != isModified()) { - requestRepaint(); - } - } - } - firePendingTextChangeEvent(); - - if (variables.containsKey(FocusEvent.EVENT_ID)) { - fireEvent(new FocusEvent(this)); - } - if (variables.containsKey(BlurEvent.EVENT_ID)) { - fireEvent(new BlurEvent(this)); - } - } finally { - changingVariables = false; - - } - - } - - @Override - public Class<String> getType() { - return String.class; - } - - /** - * Gets the null-string representation. - * - * <p> - * The null-valued strings are represented on the user interface by - * replacing the null value with this string. If the null representation is - * set null (not 'null' string), painting null value throws exception. - * </p> - * - * <p> - * The default value is string 'null'. - * </p> - * - * @return the String Textual representation for null strings. - * @see TextField#isNullSettingAllowed() - */ - public String getNullRepresentation() { - return nullRepresentation; - } - - /** - * Is setting nulls with null-string representation allowed. - * - * <p> - * If this property is true, writing null-representation string to text - * field always sets the field value to real null. If this property is - * false, null setting is not made, but the null values are maintained. - * Maintenance of null-values is made by only converting the textfield - * contents to real null, if the text field matches the null-string - * representation and the current value of the field is null. - * </p> - * - * <p> - * By default this setting is false - * </p> - * - * @return boolean Should the null-string represenation be always converted - * to null-values. - * @see TextField#getNullRepresentation() - */ - public boolean isNullSettingAllowed() { - return nullSettingAllowed; - } - - /** - * Sets the null-string representation. - * - * <p> - * The null-valued strings are represented on the user interface by - * replacing the null value with this string. If the null representation is - * set null (not 'null' string), painting null value throws exception. - * </p> - * - * <p> - * The default value is string 'null' - * </p> - * - * @param nullRepresentation - * Textual representation for null strings. - * @see TextField#setNullSettingAllowed(boolean) - */ - public void setNullRepresentation(String nullRepresentation) { - this.nullRepresentation = nullRepresentation; - requestRepaint(); - } - - /** - * Sets the null conversion mode. - * - * <p> - * If this property is true, writing null-representation string to text - * field always sets the field value to real null. If this property is - * false, null setting is not made, but the null values are maintained. - * Maintenance of null-values is made by only converting the textfield - * contents to real null, if the text field matches the null-string - * representation and the current value of the field is null. - * </p> - * - * <p> - * By default this setting is false. - * </p> - * - * @param nullSettingAllowed - * Should the null-string representation always be converted to - * null-values. - * @see TextField#getNullRepresentation() - */ - public void setNullSettingAllowed(boolean nullSettingAllowed) { - this.nullSettingAllowed = nullSettingAllowed; - requestRepaint(); - } - - @Override - protected boolean isEmpty() { - return super.isEmpty() || getValue().length() == 0; - } - - /** - * Returns the maximum number of characters in the field. Value -1 is - * considered unlimited. Terminal may however have some technical limits. - * - * @return the maxLength - */ - public int getMaxLength() { - return getState().getMaxLength(); - } - - /** - * Sets the maximum number of characters in the field. Value -1 is - * considered unlimited. Terminal may however have some technical limits. - * - * @param maxLength - * the maxLength to set - */ - public void setMaxLength(int maxLength) { - getState().setMaxLength(maxLength); - requestRepaint(); - } - - /** - * Gets the number of columns in the editor. If the number of columns is set - * 0, the actual number of displayed columns is determined implicitly by the - * adapter. - * - * @return the number of columns in the editor. - */ - public int getColumns() { - return getState().getColumns(); - } - - /** - * Sets the number of columns in the editor. If the number of columns is set - * 0, the actual number of displayed columns is determined implicitly by the - * adapter. - * - * @param columns - * the number of columns to set. - */ - public void setColumns(int columns) { - if (columns < 0) { - columns = 0; - } - getState().setColumns(columns); - requestRepaint(); - } - - /** - * Gets the current input prompt. - * - * @see #setInputPrompt(String) - * @return the current input prompt, or null if not enabled - */ - public String getInputPrompt() { - return getState().getInputPrompt(); - } - - /** - * Sets the input prompt - a textual prompt that is displayed when the field - * would otherwise be empty, to prompt the user for input. - * - * @param inputPrompt - */ - public void setInputPrompt(String inputPrompt) { - getState().setInputPrompt(inputPrompt); - requestRepaint(); - } - - /* ** Text Change Events ** */ - - private void firePendingTextChangeEvent() { - if (textChangeEventPending && !isFiringTextChangeEvent) { - isFiringTextChangeEvent = true; - textChangeEventPending = false; - try { - fireEvent(new TextChangeEventImpl(this)); - } finally { - isFiringTextChangeEvent = false; - } - } - } - - @Override - protected void setInternalValue(String newValue) { - if (changingVariables && !textChangeEventPending) { - - /* - * TODO check for possible (minor?) issue (not tested) - * - * -field with e.g. PropertyFormatter. - * - * -TextChangeListener and it changes value. - * - * -if formatter again changes the value, do we get an extra - * simulated text change event ? - */ - - /* - * Fire a "simulated" text change event before value change event if - * change is coming from the client side. - * - * Iff there is both value change and textChangeEvent in same - * variable burst, it is a text field in non immediate mode and the - * text change event "flushed" queued value change event. In this - * case textChangeEventPending flag is already on and text change - * event will be fired after the value change event. - */ - if (newValue == null && lastKnownTextContent != null - && !lastKnownTextContent.equals(getNullRepresentation())) { - // Value was changed from something to null representation - lastKnownTextContent = getNullRepresentation(); - textChangeEventPending = true; - } else if (newValue != null - && !newValue.toString().equals(lastKnownTextContent)) { - // Value was changed to something else than null representation - lastKnownTextContent = newValue.toString(); - textChangeEventPending = true; - } - firePendingTextChangeEvent(); - } - - super.setInternalValue(newValue); - } - - @Override - public void setValue(Object newValue) throws ReadOnlyException { - super.setValue(newValue); - /* - * Make sure w reset lastKnownTextContent field on value change. The - * clearing must happen here as well because TextChangeListener can - * revert the original value. Client must respect the value in this - * case. AbstractField optimizes value change if the existing value is - * reset. Also we need to force repaint if the flag is on. - */ - if (lastKnownTextContent != null) { - lastKnownTextContent = null; - requestRepaint(); - } - } - - private void handleInputEventTextChange(Map<String, Object> variables) { - /* - * TODO we could vastly optimize the communication of values by using - * some sort of diffs instead of always sending the whole text content. - * Also on value change events we could use the mechanism. - */ - String object = (String) variables.get(VTextField.VAR_CUR_TEXT); - lastKnownTextContent = object; - textChangeEventPending = true; - } - - /** - * Sets the mode how the TextField triggers {@link TextChangeEvent}s. - * - * @param inputEventMode - * the new mode - * - * @see TextChangeEventMode - */ - public void setTextChangeEventMode(TextChangeEventMode inputEventMode) { - textChangeEventMode = inputEventMode; - requestRepaint(); - } - - /** - * @return the mode used to trigger {@link TextChangeEvent}s. - */ - public TextChangeEventMode getTextChangeEventMode() { - return textChangeEventMode; - } - - /** - * Different modes how the TextField can trigger {@link TextChangeEvent}s. - */ - public enum TextChangeEventMode { - - /** - * An event is triggered on each text content change, most commonly key - * press events. - */ - EAGER, - /** - * Each text change event in the UI causes the event to be communicated - * to the application after a timeout. The length of the timeout can be - * controlled with {@link TextField#setInputEventTimeout(int)}. Only the - * last input event is reported to the server side if several text - * change events happen during the timeout. - * <p> - * In case of a {@link ValueChangeEvent} the schedule is not kept - * strictly. Before a {@link ValueChangeEvent} a {@link TextChangeEvent} - * is triggered if the text content has changed since the previous - * TextChangeEvent regardless of the schedule. - */ - TIMEOUT, - /** - * An event is triggered when there is a pause of text modifications. - * The length of the pause can be modified with - * {@link TextField#setInputEventTimeout(int)}. Like with the - * {@link #TIMEOUT} mode, an event is forced before - * {@link ValueChangeEvent}s, even if the user did not keep a pause - * while entering the text. - * <p> - * This is the default mode. - */ - LAZY - } - - @Override - public void addListener(TextChangeListener listener) { - addListener(TextChangeListener.EVENT_ID, TextChangeEvent.class, - listener, TextChangeListener.EVENT_METHOD); - } - - @Override - public void removeListener(TextChangeListener listener) { - removeListener(TextChangeListener.EVENT_ID, TextChangeEvent.class, - listener); - } - - /** - * The text change timeout modifies how often text change events are - * communicated to the application when {@link #getTextChangeEventMode()} is - * {@link TextChangeEventMode#LAZY} or {@link TextChangeEventMode#TIMEOUT}. - * - * - * @see #getTextChangeEventMode() - * - * @param timeout - * the timeout in milliseconds - */ - public void setTextChangeTimeout(int timeout) { - textChangeEventTimeout = timeout; - requestRepaint(); - } - - /** - * Gets the timeout used to fire {@link TextChangeEvent}s when the - * {@link #getTextChangeEventMode()} is {@link TextChangeEventMode#LAZY} or - * {@link TextChangeEventMode#TIMEOUT}. - * - * @return the timeout value in milliseconds - */ - public int getTextChangeTimeout() { - return textChangeEventTimeout; - } - - public class TextChangeEventImpl extends TextChangeEvent { - private String curText; - private int cursorPosition; - - private TextChangeEventImpl(final AbstractTextField tf) { - super(tf); - curText = tf.getCurrentTextContent(); - cursorPosition = tf.getCursorPosition(); - } - - @Override - public AbstractTextField getComponent() { - return (AbstractTextField) super.getComponent(); - } - - @Override - public String getText() { - return curText; - } - - @Override - public int getCursorPosition() { - return cursorPosition; - } - - } - - /** - * Gets the current (or the last known) text content in the field. - * <p> - * Note the text returned by this method is not necessary the same that is - * returned by the {@link #getValue()} method. The value is updated when the - * terminal fires a value change event via e.g. blurring the field or by - * pressing enter. The value returned by this method is updated also on - * {@link TextChangeEvent}s. Due to this high dependency to the terminal - * implementation this method is (at least at this point) not published. - * - * @return the text which is currently displayed in the field. - */ - private String getCurrentTextContent() { - if (lastKnownTextContent != null) { - return lastKnownTextContent; - } else { - Object text = getValue(); - if (text == null) { - return getNullRepresentation(); - } - return text.toString(); - } - } - - /** - * Selects all text in the field. - * - * @since 6.4 - */ - public void selectAll() { - String text = getValue() == null ? "" : getValue().toString(); - setSelectionRange(0, text.length()); - } - - /** - * Sets the range of text to be selected. - * - * As a side effect the field will become focused. - * - * @since 6.4 - * - * @param pos - * the position of the first character to be selected - * @param length - * the number of characters to be selected - */ - public void setSelectionRange(int pos, int length) { - selectionPosition = pos; - selectionLength = length; - focus(); - requestRepaint(); - } - - /** - * Sets the cursor position in the field. As a side effect the field will - * become focused. - * - * @since 6.4 - * - * @param pos - * the position for the cursor - * */ - public void setCursorPosition(int pos) { - setSelectionRange(pos, 0); - lastKnownCursorPosition = pos; - } - - /** - * Returns the last known cursor position of the field. - * - * <p> - * Note that due to the client server nature or the GWT terminal, Vaadin - * cannot provide the exact value of the cursor position in most situations. - * The value is updated only when the client side terminal communicates to - * TextField, like on {@link ValueChangeEvent}s and {@link TextChangeEvent} - * s. This may change later if a deep push integration is built to Vaadin. - * - * @return the cursor position - */ - public int getCursorPosition() { - return lastKnownCursorPosition; - } - - @Override - public void addListener(FocusListener listener) { - addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, - FocusListener.focusMethod); - } - - @Override - public void removeListener(FocusListener listener) { - removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); - } - - @Override - public void addListener(BlurListener listener) { - addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, - BlurListener.blurMethod); - } - - @Override - public void removeListener(BlurListener listener) { - removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); - } - -} diff --git a/src/com/vaadin/ui/Accordion.java b/src/com/vaadin/ui/Accordion.java deleted file mode 100644 index b937c7bc2b..0000000000 --- a/src/com/vaadin/ui/Accordion.java +++ /dev/null @@ -1,19 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -/** - * An accordion is a component similar to a {@link TabSheet}, but with a - * vertical orientation and the selected component presented between tabs. - * - * Closable tabs are not supported by the accordion. - * - * The {@link Accordion} can be styled with the .v-accordion, .v-accordion-item, - * .v-accordion-item-first and .v-accordion-item-caption styles. - * - * @see TabSheet - */ -public class Accordion extends TabSheet { - -} diff --git a/src/com/vaadin/ui/Alignment.java b/src/com/vaadin/ui/Alignment.java deleted file mode 100644 index 0d73da8504..0000000000 --- a/src/com/vaadin/ui/Alignment.java +++ /dev/null @@ -1,158 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import java.io.Serializable; - -import com.vaadin.shared.ui.AlignmentInfo.Bits; - -/** - * Class containing information about alignment of a component. Use the - * pre-instantiated classes. - */ -@SuppressWarnings("serial") -public final class Alignment implements Serializable { - - public static final Alignment TOP_RIGHT = new Alignment(Bits.ALIGNMENT_TOP - + Bits.ALIGNMENT_RIGHT); - public static final Alignment TOP_LEFT = new Alignment(Bits.ALIGNMENT_TOP - + Bits.ALIGNMENT_LEFT); - public static final Alignment TOP_CENTER = new Alignment(Bits.ALIGNMENT_TOP - + Bits.ALIGNMENT_HORIZONTAL_CENTER); - public static final Alignment MIDDLE_RIGHT = new Alignment( - Bits.ALIGNMENT_VERTICAL_CENTER + Bits.ALIGNMENT_RIGHT); - public static final Alignment MIDDLE_LEFT = new Alignment( - Bits.ALIGNMENT_VERTICAL_CENTER + Bits.ALIGNMENT_LEFT); - public static final Alignment MIDDLE_CENTER = new Alignment( - Bits.ALIGNMENT_VERTICAL_CENTER + Bits.ALIGNMENT_HORIZONTAL_CENTER); - public static final Alignment BOTTOM_RIGHT = new Alignment( - Bits.ALIGNMENT_BOTTOM + Bits.ALIGNMENT_RIGHT); - public static final Alignment BOTTOM_LEFT = new Alignment( - Bits.ALIGNMENT_BOTTOM + Bits.ALIGNMENT_LEFT); - public static final Alignment BOTTOM_CENTER = new Alignment( - Bits.ALIGNMENT_BOTTOM + Bits.ALIGNMENT_HORIZONTAL_CENTER); - - private final int bitMask; - - public Alignment(int bitMask) { - this.bitMask = bitMask; - } - - /** - * Returns a bitmask representation of the alignment value. Used internally - * by terminal. - * - * @return the bitmask representation of the alignment value - */ - public int getBitMask() { - return bitMask; - } - - /** - * Checks if component is aligned to the top of the available space. - * - * @return true if aligned top - */ - public boolean isTop() { - return (bitMask & Bits.ALIGNMENT_TOP) == Bits.ALIGNMENT_TOP; - } - - /** - * Checks if component is aligned to the bottom of the available space. - * - * @return true if aligned bottom - */ - public boolean isBottom() { - return (bitMask & Bits.ALIGNMENT_BOTTOM) == Bits.ALIGNMENT_BOTTOM; - } - - /** - * Checks if component is aligned to the left of the available space. - * - * @return true if aligned left - */ - public boolean isLeft() { - return (bitMask & Bits.ALIGNMENT_LEFT) == Bits.ALIGNMENT_LEFT; - } - - /** - * Checks if component is aligned to the right of the available space. - * - * @return true if aligned right - */ - public boolean isRight() { - return (bitMask & Bits.ALIGNMENT_RIGHT) == Bits.ALIGNMENT_RIGHT; - } - - /** - * Checks if component is aligned middle (vertically center) of the - * available space. - * - * @return true if aligned bottom - */ - public boolean isMiddle() { - return (bitMask & Bits.ALIGNMENT_VERTICAL_CENTER) == Bits.ALIGNMENT_VERTICAL_CENTER; - } - - /** - * Checks if component is aligned center (horizontally) of the available - * space. - * - * @return true if aligned center - */ - public boolean isCenter() { - return (bitMask & Bits.ALIGNMENT_HORIZONTAL_CENTER) == Bits.ALIGNMENT_HORIZONTAL_CENTER; - } - - /** - * Returns string representation of vertical alignment. - * - * @return vertical alignment as CSS value - */ - public String getVerticalAlignment() { - if (isBottom()) { - return "bottom"; - } else if (isMiddle()) { - return "middle"; - } - return "top"; - } - - /** - * Returns string representation of horizontal alignment. - * - * @return horizontal alignment as CSS value - */ - public String getHorizontalAlignment() { - if (isRight()) { - return "right"; - } else if (isCenter()) { - return "center"; - } - return "left"; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if ((obj == null) || (obj.getClass() != this.getClass())) { - return false; - } - Alignment a = (Alignment) obj; - return bitMask == a.bitMask; - } - - @Override - public int hashCode() { - return bitMask; - } - - @Override - public String toString() { - return String.valueOf(bitMask); - } - -} diff --git a/src/com/vaadin/ui/Audio.java b/src/com/vaadin/ui/Audio.java deleted file mode 100644 index ac2ee869a6..0000000000 --- a/src/com/vaadin/ui/Audio.java +++ /dev/null @@ -1,55 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import com.vaadin.terminal.Resource; - -/** - * The Audio component translates into an HTML5 <audio> element and as - * such is only supported in browsers that support HTML5 media markup. Browsers - * that do not support HTML5 display the text or HTML set by calling - * {@link #setAltText(String)}. - * - * A flash-player fallback can be implemented by setting HTML content allowed ( - * {@link #setHtmlContentAllowed(boolean)} and calling - * {@link #setAltText(String)} with the flash player markup. An example of flash - * fallback can be found at the <a href= - * "https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox#Using_Flash" - * >Mozilla Developer Network</a>. - * - * Multiple sources can be specified. Which of the sources is used is selected - * by the browser depending on which file formats it supports. See <a - * href="http://en.wikipedia.org/wiki/HTML5_video#Table">wikipedia</a> for a - * table of formats supported by different browsers. - * - * @author Vaadin Ltd - * @since 6.7.0 - */ -public class Audio extends AbstractMedia { - - public Audio() { - this("", null); - } - - /** - * @param caption - * The caption of the audio component. - */ - public Audio(String caption) { - this(caption, null); - } - - /** - * @param caption - * The caption of the audio component - * @param source - * The audio file to play. - */ - public Audio(String caption, Resource source) { - setCaption(caption); - setSource(source); - setShowControls(true); - } -} diff --git a/src/com/vaadin/ui/Button.java b/src/com/vaadin/ui/Button.java deleted file mode 100644 index 0cb667d527..0000000000 --- a/src/com/vaadin/ui/Button.java +++ /dev/null @@ -1,539 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.lang.reflect.Method; - -import com.vaadin.event.Action; -import com.vaadin.event.FieldEvents; -import com.vaadin.event.FieldEvents.BlurEvent; -import com.vaadin.event.FieldEvents.BlurListener; -import com.vaadin.event.FieldEvents.FocusAndBlurServerRpcImpl; -import com.vaadin.event.FieldEvents.FocusEvent; -import com.vaadin.event.FieldEvents.FocusListener; -import com.vaadin.event.ShortcutAction; -import com.vaadin.event.ShortcutAction.KeyCode; -import com.vaadin.event.ShortcutAction.ModifierKey; -import com.vaadin.event.ShortcutListener; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.button.ButtonServerRpc; -import com.vaadin.shared.ui.button.ButtonState; -import com.vaadin.tools.ReflectTools; -import com.vaadin.ui.Component.Focusable; - -/** - * A generic button component. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public class Button extends AbstractComponent implements - FieldEvents.BlurNotifier, FieldEvents.FocusNotifier, Focusable, - Action.ShortcutNotifier { - - private ButtonServerRpc rpc = new ButtonServerRpc() { - - @Override - public void click(MouseEventDetails mouseEventDetails) { - fireClick(mouseEventDetails); - } - - @Override - public void disableOnClick() { - // Could be optimized so the button is not repainted because of - // this (client side has already disabled the button) - setEnabled(false); - } - }; - - FocusAndBlurServerRpcImpl focusBlurRpc = new FocusAndBlurServerRpcImpl(this) { - - @Override - protected void fireEvent(Event event) { - Button.this.fireEvent(event); - } - }; - - /** - * Creates a new push button. - */ - public Button() { - registerRpc(rpc); - registerRpc(focusBlurRpc); - } - - /** - * Creates a new push button with the given caption. - * - * @param caption - * the Button caption. - */ - public Button(String caption) { - this(); - setCaption(caption); - } - - /** - * Creates a new push button with a click listener. - * - * @param caption - * the Button caption. - * @param listener - * the Button click listener. - */ - public Button(String caption, ClickListener listener) { - this(caption); - addListener(listener); - } - - /** - * Click event. This event is thrown, when the button is clicked. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class ClickEvent extends Component.Event { - - private final MouseEventDetails details; - - /** - * New instance of text change event. - * - * @param source - * the Source of the event. - */ - public ClickEvent(Component source) { - super(source); - details = null; - } - - /** - * Constructor with mouse details - * - * @param source - * The source where the click took place - * @param details - * Details about the mouse click - */ - public ClickEvent(Component source, MouseEventDetails details) { - super(source); - this.details = details; - } - - /** - * Gets the Button where the event occurred. - * - * @return the Source of the event. - */ - public Button getButton() { - return (Button) getSource(); - } - - /** - * Returns the mouse position (x coordinate) when the click took place. - * The position is relative to the browser client area. - * - * @return The mouse cursor x position or -1 if unknown - */ - public int getClientX() { - if (null != details) { - return details.getClientX(); - } else { - return -1; - } - } - - /** - * Returns the mouse position (y coordinate) when the click took place. - * The position is relative to the browser client area. - * - * @return The mouse cursor y position or -1 if unknown - */ - public int getClientY() { - if (null != details) { - return details.getClientY(); - } else { - return -1; - } - } - - /** - * Returns the relative mouse position (x coordinate) when the click - * took place. The position is relative to the clicked component. - * - * @return The mouse cursor x position relative to the clicked layout - * component or -1 if no x coordinate available - */ - public int getRelativeX() { - if (null != details) { - return details.getRelativeX(); - } else { - return -1; - } - } - - /** - * Returns the relative mouse position (y coordinate) when the click - * took place. The position is relative to the clicked component. - * - * @return The mouse cursor y position relative to the clicked layout - * component or -1 if no y coordinate available - */ - public int getRelativeY() { - if (null != details) { - return details.getRelativeY(); - } else { - return -1; - } - } - - /** - * Checks if the Alt key was down when the mouse event took place. - * - * @return true if Alt was down when the event occured, false otherwise - * or if unknown - */ - public boolean isAltKey() { - if (null != details) { - return details.isAltKey(); - } else { - return false; - } - } - - /** - * Checks if the Ctrl key was down when the mouse event took place. - * - * @return true if Ctrl was pressed when the event occured, false - * otherwise or if unknown - */ - public boolean isCtrlKey() { - if (null != details) { - return details.isCtrlKey(); - } else { - return false; - } - } - - /** - * Checks if the Meta key was down when the mouse event took place. - * - * @return true if Meta was pressed when the event occured, false - * otherwise or if unknown - */ - public boolean isMetaKey() { - if (null != details) { - return details.isMetaKey(); - } else { - return false; - } - } - - /** - * Checks if the Shift key was down when the mouse event took place. - * - * @return true if Shift was pressed when the event occured, false - * otherwise or if unknown - */ - public boolean isShiftKey() { - if (null != details) { - return details.isShiftKey(); - } else { - return false; - } - } - } - - /** - * Interface for listening for a {@link ClickEvent} fired by a - * {@link Component}. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface ClickListener extends Serializable { - - public static final Method BUTTON_CLICK_METHOD = ReflectTools - .findMethod(ClickListener.class, "buttonClick", - ClickEvent.class); - - /** - * Called when a {@link Button} has been clicked. A reference to the - * button is given by {@link ClickEvent#getButton()}. - * - * @param event - * An event containing information about the click. - */ - public void buttonClick(ClickEvent event); - - } - - /** - * Adds the button click listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(ClickListener listener) { - addListener(ClickEvent.class, listener, - ClickListener.BUTTON_CLICK_METHOD); - } - - /** - * Removes the button click listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(ClickListener listener) { - removeListener(ClickEvent.class, listener, - ClickListener.BUTTON_CLICK_METHOD); - } - - /** - * Simulates a button click, notifying all server-side listeners. - * - * No action is taken is the button is disabled. - */ - public void click() { - if (isEnabled() && !isReadOnly()) { - fireClick(); - } - } - - /** - * Fires a click event to all listeners without any event details. - * - * In subclasses, override {@link #fireClick(MouseEventDetails)} instead of - * this method. - */ - protected void fireClick() { - fireEvent(new Button.ClickEvent(this)); - } - - /** - * Fires a click event to all listeners. - * - * @param details - * MouseEventDetails from which keyboard modifiers and other - * information about the mouse click can be obtained. If the - * button was clicked by a keyboard event, some of the fields may - * be empty/undefined. - */ - protected void fireClick(MouseEventDetails details) { - fireEvent(new Button.ClickEvent(this, details)); - } - - @Override - public void addListener(BlurListener listener) { - addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, - BlurListener.blurMethod); - } - - @Override - public void removeListener(BlurListener listener) { - removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); - } - - @Override - public void addListener(FocusListener listener) { - addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, - FocusListener.focusMethod); - } - - @Override - public void removeListener(FocusListener listener) { - removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); - - } - - /* - * Actions - */ - - protected ClickShortcut clickShortcut; - - /** - * Makes it possible to invoke a click on this button by pressing the given - * {@link KeyCode} and (optional) {@link ModifierKey}s.<br/> - * The shortcut is global (bound to the containing Window). - * - * @param keyCode - * the keycode for invoking the shortcut - * @param modifiers - * the (optional) modifiers for invoking the shortcut, null for - * none - */ - public void setClickShortcut(int keyCode, int... modifiers) { - if (clickShortcut != null) { - removeShortcutListener(clickShortcut); - } - clickShortcut = new ClickShortcut(this, keyCode, modifiers); - addShortcutListener(clickShortcut); - getState().setClickShortcutKeyCode(clickShortcut.getKeyCode()); - } - - /** - * Removes the keyboard shortcut previously set with - * {@link #setClickShortcut(int, int...)}. - */ - public void removeClickShortcut() { - if (clickShortcut != null) { - removeShortcutListener(clickShortcut); - clickShortcut = null; - getState().setClickShortcutKeyCode(0); - } - } - - /** - * A {@link ShortcutListener} specifically made to define a keyboard - * shortcut that invokes a click on the given button. - * - */ - public static class ClickShortcut extends ShortcutListener { - protected Button button; - - /** - * Creates a keyboard shortcut for clicking the given button using the - * shorthand notation defined in {@link ShortcutAction}. - * - * @param button - * to be clicked when the shortcut is invoked - * @param shorthandCaption - * the caption with shortcut keycode and modifiers indicated - */ - public ClickShortcut(Button button, String shorthandCaption) { - super(shorthandCaption); - this.button = button; - } - - /** - * Creates a keyboard shortcut for clicking the given button using the - * given {@link KeyCode} and {@link ModifierKey}s. - * - * @param button - * to be clicked when the shortcut is invoked - * @param keyCode - * KeyCode to react to - * @param modifiers - * optional modifiers for shortcut - */ - public ClickShortcut(Button button, int keyCode, int... modifiers) { - super(null, keyCode, modifiers); - this.button = button; - } - - /** - * Creates a keyboard shortcut for clicking the given button using the - * given {@link KeyCode}. - * - * @param button - * to be clicked when the shortcut is invoked - * @param keyCode - * KeyCode to react to - */ - public ClickShortcut(Button button, int keyCode) { - this(button, keyCode, null); - } - - @Override - public void handleAction(Object sender, Object target) { - button.click(); - } - } - - /** - * Determines if a button is automatically disabled when clicked. See - * {@link #setDisableOnClick(boolean)} for details. - * - * @return true if the button is disabled when clicked, false otherwise - */ - public boolean isDisableOnClick() { - return getState().isDisableOnClick(); - } - - /** - * Determines if a button is automatically disabled when clicked. If this is - * set to true the button will be automatically disabled when clicked, - * typically to prevent (accidental) extra clicks on a button. - * - * @param disableOnClick - * true to disable button when it is clicked, false otherwise - */ - public void setDisableOnClick(boolean disableOnClick) { - getState().setDisableOnClick(disableOnClick); - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Component.Focusable#getTabIndex() - */ - @Override - public int getTabIndex() { - return getState().getTabIndex(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Component.Focusable#setTabIndex(int) - */ - @Override - public void setTabIndex(int tabIndex) { - getState().setTabIndex(tabIndex); - requestRepaint(); - } - - @Override - public void focus() { - // Overridden only to make public - super.focus(); - } - - @Override - public ButtonState getState() { - return (ButtonState) super.getState(); - } - - /** - * Set whether the caption text is rendered as HTML or not. You might need - * to retheme button to allow higher content than the original text style. - * - * If set to true, the captions are passed to the browser as html and the - * developer is responsible for ensuring no harmful html is used. If set to - * false, the content is passed to the browser as plain text. - * - * @param htmlContentAllowed - * <code>true</code> if caption is rendered as HTML, - * <code>false</code> otherwise - */ - public void setHtmlContentAllowed(boolean htmlContentAllowed) { - if (getState().isHtmlContentAllowed() != htmlContentAllowed) { - getState().setHtmlContentAllowed(htmlContentAllowed); - requestRepaint(); - } - } - - /** - * Return HTML rendering setting - * - * @return <code>true</code> if the caption text is to be rendered as HTML, - * <code>false</code> otherwise - */ - public boolean isHtmlContentAllowed() { - return getState().isHtmlContentAllowed(); - } - -} diff --git a/src/com/vaadin/ui/CheckBox.java b/src/com/vaadin/ui/CheckBox.java deleted file mode 100644 index 30ac9b4626..0000000000 --- a/src/com/vaadin/ui/CheckBox.java +++ /dev/null @@ -1,141 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import com.vaadin.data.Property; -import com.vaadin.event.FieldEvents.BlurEvent; -import com.vaadin.event.FieldEvents.BlurListener; -import com.vaadin.event.FieldEvents.FocusAndBlurServerRpcImpl; -import com.vaadin.event.FieldEvents.FocusEvent; -import com.vaadin.event.FieldEvents.FocusListener; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.checkbox.CheckBoxServerRpc; -import com.vaadin.shared.ui.checkbox.CheckBoxState; - -public class CheckBox extends AbstractField<Boolean> { - - private CheckBoxServerRpc rpc = new CheckBoxServerRpc() { - - @Override - public void setChecked(boolean checked, - MouseEventDetails mouseEventDetails) { - if (isReadOnly()) { - return; - } - - final Boolean oldValue = getValue(); - final Boolean newValue = checked; - - if (!newValue.equals(oldValue)) { - // The event is only sent if the switch state is changed - setValue(newValue); - } - - } - }; - - FocusAndBlurServerRpcImpl focusBlurRpc = new FocusAndBlurServerRpcImpl(this) { - @Override - protected void fireEvent(Event event) { - CheckBox.this.fireEvent(event); - } - }; - - /** - * Creates a new checkbox. - */ - public CheckBox() { - registerRpc(rpc); - registerRpc(focusBlurRpc); - setValue(Boolean.FALSE); - } - - /** - * Creates a new checkbox with a set caption. - * - * @param caption - * the Checkbox caption. - */ - public CheckBox(String caption) { - this(); - setCaption(caption); - } - - /** - * Creates a new checkbox with a caption and a set initial state. - * - * @param caption - * the caption of the checkbox - * @param initialState - * the initial state of the checkbox - */ - public CheckBox(String caption, boolean initialState) { - this(caption); - setValue(initialState); - } - - /** - * Creates a new checkbox that is connected to a boolean property. - * - * @param state - * the Initial state of the switch-button. - * @param dataSource - */ - public CheckBox(String caption, Property<?> dataSource) { - this(caption); - setPropertyDataSource(dataSource); - } - - @Override - public Class<Boolean> getType() { - return Boolean.class; - } - - @Override - public CheckBoxState getState() { - return (CheckBoxState) super.getState(); - } - - @Override - protected void setInternalValue(Boolean newValue) { - super.setInternalValue(newValue); - if (newValue == null) { - newValue = false; - } - getState().setChecked(newValue); - } - - public void addListener(BlurListener listener) { - addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, - BlurListener.blurMethod); - } - - public void removeListener(BlurListener listener) { - removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); - } - - public void addListener(FocusListener listener) { - addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, - FocusListener.focusMethod); - } - - public void removeListener(FocusListener listener) { - removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); - } - - /** - * Get the boolean value of the button state. - * - * @return True iff the button is pressed down or checked. - * - * @deprecated Use {@link #getValue()} instead and, if needed, handle null - * values. - */ - @Deprecated - public boolean booleanValue() { - Boolean value = getValue(); - return (null == value) ? false : value.booleanValue(); - } -} diff --git a/src/com/vaadin/ui/ComboBox.java b/src/com/vaadin/ui/ComboBox.java deleted file mode 100644 index 6286dad124..0000000000 --- a/src/com/vaadin/ui/ComboBox.java +++ /dev/null @@ -1,116 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.Collection; - -import com.vaadin.data.Container; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.gwt.client.ui.combobox.VFilterSelect; - -/** - * A filtering dropdown single-select. Suitable for newItemsAllowed, but it's - * turned of by default to avoid mistakes. Items are filtered based on user - * input, and loaded dynamically ("lazy-loading") from the server. You can turn - * on newItemsAllowed and change filtering mode (and also turn it off), but you - * can not turn on multi-select mode. - * - */ -@SuppressWarnings("serial") -public class ComboBox extends Select { - - private String inputPrompt = null; - - /** - * If text input is not allowed, the ComboBox behaves like a pretty - * NativeSelect - the user can not enter any text and clicking the text - * field opens the drop down with options - */ - private boolean textInputAllowed = true; - - public ComboBox() { - setNewItemsAllowed(false); - } - - public ComboBox(String caption, Collection<?> options) { - super(caption, options); - setNewItemsAllowed(false); - } - - public ComboBox(String caption, Container dataSource) { - super(caption, dataSource); - setNewItemsAllowed(false); - } - - public ComboBox(String caption) { - super(caption); - setNewItemsAllowed(false); - } - - /** - * Gets the current input prompt. - * - * @see #setInputPrompt(String) - * @return the current input prompt, or null if not enabled - */ - public String getInputPrompt() { - return inputPrompt; - } - - /** - * Sets the input prompt - a textual prompt that is displayed when the - * select would otherwise be empty, to prompt the user for input. - * - * @param inputPrompt - * the desired input prompt, or null to disable - */ - public void setInputPrompt(String inputPrompt) { - this.inputPrompt = inputPrompt; - requestRepaint(); - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - if (inputPrompt != null) { - target.addAttribute("prompt", inputPrompt); - } - super.paintContent(target); - - if (!textInputAllowed) { - target.addAttribute(VFilterSelect.ATTR_NO_TEXT_INPUT, true); - } - } - - /** - * Sets whether it is possible to input text into the field or whether the - * field area of the component is just used to show what is selected. By - * disabling text input, the comboBox will work in the same way as a - * {@link NativeSelect} - * - * @see #isTextInputAllowed() - * - * @param textInputAllowed - * true to allow entering text, false to just show the current - * selection - */ - public void setTextInputAllowed(boolean textInputAllowed) { - this.textInputAllowed = textInputAllowed; - requestRepaint(); - } - - /** - * Returns true if the user can enter text into the field to either filter - * the selections or enter a new value if {@link #isNewItemsAllowed()} - * returns true. If text input is disabled, the comboBox will work in the - * same way as a {@link NativeSelect} - * - * @return - */ - public boolean isTextInputAllowed() { - return textInputAllowed; - } - -} diff --git a/src/com/vaadin/ui/Component.java b/src/com/vaadin/ui/Component.java deleted file mode 100644 index a2c257ab68..0000000000 --- a/src/com/vaadin/ui/Component.java +++ /dev/null @@ -1,1047 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.util.EventListener; -import java.util.EventObject; -import java.util.Locale; - -import com.vaadin.Application; -import com.vaadin.event.FieldEvents; -import com.vaadin.shared.ComponentState; -import com.vaadin.terminal.ErrorMessage; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.Sizeable; -import com.vaadin.terminal.VariableOwner; -import com.vaadin.terminal.gwt.server.ClientConnector; - -/** - * {@code Component} is the top-level interface that is and must be implemented - * by all Vaadin components. {@code Component} is paired with - * {@link AbstractComponent}, which provides a default implementation for all - * the methods defined in this interface. - * - * <p> - * Components are laid out in the user interface hierarchically. The layout is - * managed by layout components, or more generally by components that implement - * the {@link ComponentContainer} interface. Such a container is the - * <i>parent</i> of the contained components. - * </p> - * - * <p> - * The {@link #getParent()} method allows retrieving the parent component of a - * component. While there is a {@link #setParent(Component) setParent()}, you - * rarely need it as you normally add components with the - * {@link ComponentContainer#addComponent(Component) addComponent()} method of - * the layout or other {@code ComponentContainer}, which automatically sets the - * parent. - * </p> - * - * <p> - * A component becomes <i>attached</i> to an application (and the - * {@link #attach()} is called) when it or one of its parents is attached to the - * main window of the application through its containment hierarchy. - * </p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -public interface Component extends ClientConnector, Sizeable, Serializable { - - /** - * Gets all user-defined CSS style names of a component. If the component - * has multiple style names defined, the return string is a space-separated - * list of style names. Built-in style names defined in Vaadin or GWT are - * not returned. - * - * <p> - * The style names are returned only in the basic form in which they were - * added; each user-defined style name shows as two CSS style class names in - * the rendered HTML: one as it was given and one prefixed with the - * component-specific style name. Only the former is returned. - * </p> - * - * @return the style name or a space-separated list of user-defined style - * names of the component - * @see #setStyleName(String) - * @see #addStyleName(String) - * @see #removeStyleName(String) - */ - public String getStyleName(); - - /** - * Sets one or more user-defined style names of the component, replacing any - * previous user-defined styles. Multiple styles can be specified as a - * space-separated list of style names. The style names must be valid CSS - * class names and should not conflict with any built-in style names in - * Vaadin or GWT. - * - * <pre> - * Label label = new Label("This text has a lot of style"); - * label.setStyleName("myonestyle myotherstyle"); - * </pre> - * - * <p> - * Each style name will occur in two versions: one as specified and one that - * is prefixed with the style name of the component. For example, if you - * have a {@code Button} component and give it "{@code mystyle}" style, the - * component will have both "{@code mystyle}" and "{@code v-button-mystyle}" - * styles. You could then style the component either with: - * </p> - * - * <pre> - * .myonestyle {background: blue;} - * </pre> - * - * <p> - * or - * </p> - * - * <pre> - * .v-button-myonestyle {background: blue;} - * </pre> - * - * <p> - * It is normally a good practice to use {@link #addStyleName(String) - * addStyleName()} rather than this setter, as different software - * abstraction layers can then add their own styles without accidentally - * removing those defined in other layers. - * </p> - * - * <p> - * This method will trigger a {@link RepaintRequestEvent}. - * </p> - * - * @param style - * the new style or styles of the component as a space-separated - * list - * @see #getStyleName() - * @see #addStyleName(String) - * @see #removeStyleName(String) - */ - public void setStyleName(String style); - - /** - * Adds a style name to component. The style name will be rendered as a HTML - * class name, which can be used in a CSS definition. - * - * <pre> - * Label label = new Label("This text has style"); - * label.addStyleName("mystyle"); - * </pre> - * - * <p> - * Each style name will occur in two versions: one as specified and one that - * is prefixed wil the style name of the component. For example, if you have - * a {@code Button} component and give it "{@code mystyle}" style, the - * component will have both "{@code mystyle}" and "{@code v-button-mystyle}" - * styles. You could then style the component either with: - * </p> - * - * <pre> - * .mystyle {font-style: italic;} - * </pre> - * - * <p> - * or - * </p> - * - * <pre> - * .v-button-mystyle {font-style: italic;} - * </pre> - * - * <p> - * This method will trigger a {@link RepaintRequestEvent}. - * </p> - * - * @param style - * the new style to be added to the component - * @see #getStyleName() - * @see #setStyleName(String) - * @see #removeStyleName(String) - */ - public void addStyleName(String style); - - /** - * Removes one or more style names from component. Multiple styles can be - * specified as a space-separated list of style names. - * - * <p> - * The parameter must be a valid CSS style name. Only user-defined style - * names added with {@link #addStyleName(String) addStyleName()} or - * {@link #setStyleName(String) setStyleName()} can be removed; built-in - * style names defined in Vaadin or GWT can not be removed. - * </p> - * - * * This method will trigger a {@link RepaintRequestEvent}. - * - * @param style - * the style name or style names to be removed - * @see #getStyleName() - * @see #setStyleName(String) - * @see #addStyleName(String) - */ - public void removeStyleName(String style); - - /** - * Tests whether the component is enabled or not. A user can not interact - * with disabled components. Disabled components are rendered in a style - * that indicates the status, usually in gray color. Children of a disabled - * component are also disabled. Components are enabled by default. - * - * <p> - * As a security feature, all updates for disabled components are blocked on - * the server-side. - * </p> - * - * <p> - * Note that this method only returns the status of the component and does - * not take parents into account. Even though this method returns true the - * component can be disabled to the user if a parent is disabled. - * </p> - * - * @return <code>true</code> if the component and its parent are enabled, - * <code>false</code> otherwise. - * @see VariableOwner#isEnabled() - */ - public boolean isEnabled(); - - /** - * Enables or disables the component. The user can not interact disabled - * components, which are shown with a style that indicates the status, - * usually shaded in light gray color. Components are enabled by default. - * - * <pre> - * Button enabled = new Button("Enabled"); - * enabled.setEnabled(true); // The default - * layout.addComponent(enabled); - * - * Button disabled = new Button("Disabled"); - * disabled.setEnabled(false); - * layout.addComponent(disabled); - * </pre> - * - * <p> - * This method will trigger a {@link RepaintRequestEvent} for the component - * and, if it is a {@link ComponentContainer}, for all its children - * recursively. - * </p> - * - * @param enabled - * a boolean value specifying if the component should be enabled - * or not - */ - public void setEnabled(boolean enabled); - - /** - * Tests the <i>visibility</i> property of the component. - * - * <p> - * Visible components are drawn in the user interface, while invisible ones - * are not. The effect is not merely a cosmetic CSS change - no information - * about an invisible component will be sent to the client. The effect is - * thus the same as removing the component from its parent. Making a - * component invisible through this property can alter the positioning of - * other components. - * </p> - * - * <p> - * A component is visible only if all its parents are also visible. This is - * not checked by this method though, so even if this method returns true, - * the component can be hidden from the user because a parent is set to - * invisible. - * </p> - * - * @return <code>true</code> if the component has been set to be visible in - * the user interface, <code>false</code> if not - * @see #setVisible(boolean) - * @see #attach() - */ - public boolean isVisible(); - - /** - * Sets the visibility of the component. - * - * <p> - * Visible components are drawn in the user interface, while invisible ones - * are not. The effect is not merely a cosmetic CSS change - no information - * about an invisible component will be sent to the client. The effect is - * thus the same as removing the component from its parent. - * </p> - * - * <pre> - * TextField readonly = new TextField("Read-Only"); - * readonly.setValue("You can't see this!"); - * readonly.setVisible(false); - * layout.addComponent(readonly); - * </pre> - * - * <p> - * A component is visible only if all of its parents are also visible. If a - * component is explicitly set to be invisible, changes in the visibility of - * its parents will not change the visibility of the component. - * </p> - * - * @param visible - * the boolean value specifying if the component should be - * visible after the call or not. - * @see #isVisible() - */ - public void setVisible(boolean visible); - - /** - * Gets the parent component of the component. - * - * <p> - * Components can be nested but a component can have only one parent. A - * component that contains other components, that is, can be a parent, - * should usually inherit the {@link ComponentContainer} interface. - * </p> - * - * @return the parent component - */ - @Override - public HasComponents getParent(); - - /** - * 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} - * components normally have a value that can be input or changed by the - * user, this is mostly relevant only to field components, though not - * restricted to them. - * - * <p> - * Notice that the read-only mode only affects whether the user can change - * the <i>value</i> of the component; it is possible to, for example, scroll - * a read-only table. - * </p> - * - * <p> - * The method will return {@code true} if the component or any of its - * parents is in the read-only mode. - * </p> - * - * @return <code>true</code> if the component or any of its parents is in - * read-only mode, <code>false</code> if not. - * @see #setReadOnly(boolean) - */ - public boolean isReadOnly(); - - /** - * Sets the read-only mode of the component to the specified mode. The user - * can not change the value of a read-only component. - * - * <p> - * As only {@link Field} components normally have a value that can be input - * or changed by the user, this is mostly relevant only to field components, - * though not restricted to them. - * </p> - * - * <p> - * Notice that the read-only mode only affects whether the user can change - * the <i>value</i> of the component; it is possible to, for example, scroll - * a read-only table. - * </p> - * - * <p> - * This method will trigger a {@link RepaintRequestEvent}. - * </p> - * - * @param readOnly - * a boolean value specifying whether the component is put - * read-only mode or not - */ - public void setReadOnly(boolean readOnly); - - /** - * Gets the caption of the component. - * - * <p> - * See {@link #setCaption(String)} for a detailed description of the - * caption. - * </p> - * - * @return the caption of the component or {@code null} if the caption is - * not set. - * @see #setCaption(String) - */ - public String getCaption(); - - /** - * Sets the caption of the component. - * - * <p> - * A <i>caption</i> is an explanatory textual label accompanying a user - * interface component, usually shown above, left of, or inside the - * component. <i>Icon</i> (see {@link #setIcon(Resource) setIcon()} is - * closely related to caption and is usually displayed horizontally before - * or after it, depending on the component and the containing layout. - * </p> - * - * <p> - * The caption can usually also be given as the first parameter to a - * constructor, though some components do not support it. - * </p> - * - * <pre> - * RichTextArea area = new RichTextArea(); - * area.setCaption("You can edit stuff here"); - * area.setValue("<h1>Helpful Heading</h1>" - * + "<p>All this is for you to edit.</p>"); - * </pre> - * - * <p> - * The contents of a caption are automatically quoted, so no raw XHTML can - * be rendered in a caption. The validity of the used character encoding, - * usually UTF-8, is not checked. - * </p> - * - * <p> - * The caption of a component is, by default, managed and displayed by the - * layout component or component container in which the component is placed. - * For example, the {@link VerticalLayout} component shows the captions - * left-aligned above the contained components, while the {@link FormLayout} - * component shows the captions on the left side of the vertically laid - * components, with the captions and their associated components - * left-aligned in their own columns. The {@link CustomComponent} does not - * manage the caption of its composition root, so if the root component has - * a caption, it will not be rendered. Some components, such as - * {@link Button} and {@link Panel}, manage the caption themselves and - * display it inside the component. - * </p> - * - * <p> - * This method will trigger a {@link RepaintRequestEvent}. A - * reimplementation should call the superclass implementation. - * </p> - * - * @param caption - * the new caption for the component. If the caption is - * {@code null}, no caption is shown and it does not normally - * take any space - */ - public void setCaption(String caption); - - /** - * Gets the icon resource of the component. - * - * <p> - * See {@link #setIcon(Resource)} for a detailed description of the icon. - * </p> - * - * @return the icon resource of the component or {@code null} if the - * component has no icon - * @see #setIcon(Resource) - */ - public Resource getIcon(); - - /** - * Sets the icon of the component. - * - * <p> - * An icon is an explanatory graphical label accompanying a user interface - * component, usually shown above, left of, or inside the component. Icon is - * closely related to caption (see {@link #setCaption(String) setCaption()}) - * and is usually displayed horizontally before or after it, depending on - * the component and the containing layout. - * </p> - * - * <p> - * The image is loaded by the browser from a resource, typically a - * {@link com.vaadin.terminal.ThemeResource}. - * </p> - * - * <pre> - * // Component with an icon from a custom theme - * TextField name = new TextField("Name"); - * name.setIcon(new ThemeResource("icons/user.png")); - * layout.addComponent(name); - * - * // Component with an icon from another theme ('runo') - * Button ok = new Button("OK"); - * ok.setIcon(new ThemeResource("../runo/icons/16/ok.png")); - * layout.addComponent(ok); - * </pre> - * - * <p> - * The icon of a component is, by default, managed and displayed by the - * layout component or component container in which the component is placed. - * For example, the {@link VerticalLayout} component shows the icons - * left-aligned above the contained components, while the {@link FormLayout} - * component shows the icons on the left side of the vertically laid - * components, with the icons and their associated components left-aligned - * in their own columns. The {@link CustomComponent} does not manage the - * icon of its composition root, so if the root component has an icon, it - * will not be rendered. - * </p> - * - * <p> - * An icon will be rendered inside an HTML element that has the - * {@code v-icon} CSS style class. The containing layout may enclose an icon - * and a caption inside elements related to the caption, such as - * {@code v-caption} . - * </p> - * - * This method will trigger a {@link RepaintRequestEvent}. - * - * @param icon - * the icon of the component. If null, no icon is shown and it - * does not normally take any space. - * @see #getIcon() - * @see #setCaption(String) - */ - public void setIcon(Resource icon); - - /** - * Gets the Root the component is attached to. - * - * <p> - * If the component is not attached to a Root through a component - * containment hierarchy, <code>null</code> is returned. - * </p> - * - * @return the Root of the component or <code>null</code> if it is not - * attached to a Root - */ - @Override - public Root getRoot(); - - /** - * Gets the application object to which the component is attached. - * - * <p> - * The method will return {@code null} if the component is not currently - * attached to an application. - * </p> - * - * <p> - * Getting a null value is often a problem in constructors of regular - * components and in the initializers of custom composite components. A - * standard workaround is to use {@link Application#getCurrent()} to - * retrieve the application instance that the current request relates to. - * Another way is to move the problematic initialization to - * {@link #attach()}, as described in the documentation of the method. - * </p> - * - * @return the parent application of the component or <code>null</code>. - * @see #attach() - */ - public Application getApplication(); - - /** - * {@inheritDoc} - * - * <p> - * Reimplementing the {@code attach()} method is useful for tasks that need - * to get a reference to the parent, window, or application object with the - * {@link #getParent()}, {@link #getRoot()}, and {@link #getApplication()} - * methods. A component does not yet know these objects in the constructor, - * so in such case, the methods will return {@code null}. For example, the - * following is invalid: - * </p> - * - * <pre> - * public class AttachExample extends CustomComponent { - * public AttachExample() { - * // ERROR: We can't access the application object yet. - * ClassResource r = new ClassResource("smiley.jpg", getApplication()); - * Embedded image = new Embedded("Image:", r); - * setCompositionRoot(image); - * } - * } - * </pre> - * - * <p> - * Adding a component to an application triggers calling the - * {@link #attach()} method for the component. Correspondingly, removing a - * component from a container triggers calling the {@link #detach()} method. - * If the parent of an added component is already connected to the - * application, the {@code attach()} is called immediately from - * {@link #setParent(Component)}. - * </p> - * <p> - * This method must call {@link Root#componentAttached(Component)} to let - * the Root know that a new Component has been attached. - * </p> - * - * - * <pre> - * public class AttachExample extends CustomComponent { - * public AttachExample() { - * } - * - * @Override - * public void attach() { - * super.attach(); // Must call. - * - * // Now we know who ultimately owns us. - * ClassResource r = new ClassResource("smiley.jpg", getApplication()); - * Embedded image = new Embedded("Image:", r); - * setCompositionRoot(image); - * } - * } - * </pre> - */ - @Override - public void attach(); - - /** - * Gets the locale of the component. - * - * <p> - * If a component does not have a locale set, the locale of its parent is - * returned, and so on. Eventually, if no parent has locale set, the locale - * of the application is returned. If the application does not have a locale - * set, it is determined by <code>Locale.getDefault()</code>. - * </p> - * - * <p> - * As the component must be attached before its locale can be acquired, - * using this method in the internationalization of component captions, etc. - * is generally not feasible. For such use case, we recommend using an - * otherwise acquired reference to the application locale. - * </p> - * - * @return Locale of this component or {@code null} if the component and - * none of its parents has a locale set and the component is not yet - * attached to an application. - */ - public Locale getLocale(); - - /** - * Returns the current shared state bean for the component. The state (or - * changes to it) is communicated from the server to the client. - * - * Subclasses can use a more specific return type for this method. - * - * @return The state object for the component - * - * @since 7.0 - */ - @Override - public ComponentState getState(); - - /** - * Called before the shared state is sent to the client. Gives the component - * an opportunity to set computed/dynamic state values e.g. state values - * that depend on other component features. - * <p> - * This method must not alter the component hierarchy in any way. - * </p> - * - * @since 7.0 - */ - public void updateState(); - - /** - * Adds an unique id for component that get's transferred to terminal for - * testing purposes. Keeping identifiers unique is the responsibility of the - * programmer. - * - * @param id - * An alphanumeric id - */ - public void setDebugId(String id); - - /** - * Get's currently set debug identifier - * - * @return current debug id, null if not set - */ - public String getDebugId(); - - /* Component event framework */ - - /** - * Superclass of all component originated events. - * - * <p> - * Events are the basis of all user interaction handling in Vaadin. To - * handle events, you provide a listener object that receives the events of - * the particular event type. - * </p> - * - * <pre> - * Button button = new Button("Click Me!"); - * button.addListener(new Button.ClickListener() { - * public void buttonClick(ClickEvent event) { - * getWindow().showNotification("Thank You!"); - * } - * }); - * layout.addComponent(button); - * </pre> - * - * <p> - * Notice that while each of the event types have their corresponding - * listener types; the listener interfaces are not required to inherit the - * {@code Component.Listener} interface. - * </p> - * - * @see Component.Listener - */ - @SuppressWarnings("serial") - public class Event extends EventObject { - - /** - * Constructs a new event with the specified source component. - * - * @param source - * the source component of the event - */ - public Event(Component source) { - super(source); - } - - /** - * Gets the component where the event occurred. - * - * @return the source component of the event - */ - public Component getComponent() { - return (Component) getSource(); - } - } - - /** - * Listener interface for receiving <code>Component.Event</code>s. - * - * <p> - * Listener interfaces are the basis of all user interaction handling in - * Vaadin. You have or create a listener object that receives the events. - * All event types have their corresponding listener types; they are not, - * however, required to inherit the {@code Component.Listener} interface, - * and they rarely do so. - * </p> - * - * <p> - * This generic listener interface is useful typically when you wish to - * handle events from different component types in a single listener method - * ({@code componentEvent()}. If you handle component events in an anonymous - * listener class, you normally use the component specific listener class, - * such as {@link com.vaadin.ui.Button.ClickEvent}. - * </p> - * - * <pre> - * class Listening extends CustomComponent implements Listener { - * Button ok; // Stored for determining the source of an event - * - * Label status; // For displaying info about the event - * - * public Listening() { - * VerticalLayout layout = new VerticalLayout(); - * - * // Some miscellaneous component - * TextField name = new TextField("Say it all here"); - * name.addListener(this); - * name.setImmediate(true); - * layout.addComponent(name); - * - * // Handle button clicks as generic events instead - * // of Button.ClickEvent events - * ok = new Button("OK"); - * ok.addListener(this); - * layout.addComponent(ok); - * - * // For displaying information about an event - * status = new Label(""); - * layout.addComponent(status); - * - * setCompositionRoot(layout); - * } - * - * public void componentEvent(Event event) { - * // Act according to the source of the event - * if (event.getSource() == ok - * && event.getClass() == Button.ClickEvent.class) - * getWindow().showNotification("Click!"); - * - * // Display source component and event class names - * status.setValue("Event from " + event.getSource().getClass().getName() - * + ": " + event.getClass().getName()); - * } - * } - * - * Listening listening = new Listening(); - * layout.addComponent(listening); - * </pre> - * - * @see Component#addListener(Listener) - */ - public interface Listener extends EventListener, Serializable { - - /** - * Notifies the listener of a component event. - * - * <p> - * As the event can typically come from one of many source components, - * you may need to differentiate between the event source by component - * reference, class, etc. - * </p> - * - * <pre> - * public void componentEvent(Event event) { - * // Act according to the source of the event - * if (event.getSource() == ok && event.getClass() == Button.ClickEvent.class) - * getWindow().showNotification("Click!"); - * - * // Display source component and event class names - * status.setValue("Event from " + event.getSource().getClass().getName() - * + ": " + event.getClass().getName()); - * } - * </pre> - * - * @param event - * the event that has occured. - */ - public void componentEvent(Component.Event event); - } - - /** - * Registers a new (generic) component event listener for the component. - * - * <pre> - * class Listening extends CustomComponent implements Listener { - * // Stored for determining the source of an event - * Button ok; - * - * Label status; // For displaying info about the event - * - * public Listening() { - * VerticalLayout layout = new VerticalLayout(); - * - * // Some miscellaneous component - * TextField name = new TextField("Say it all here"); - * name.addListener(this); - * name.setImmediate(true); - * layout.addComponent(name); - * - * // Handle button clicks as generic events instead - * // of Button.ClickEvent events - * ok = new Button("OK"); - * ok.addListener(this); - * layout.addComponent(ok); - * - * // For displaying information about an event - * status = new Label(""); - * layout.addComponent(status); - * - * setCompositionRoot(layout); - * } - * - * public void componentEvent(Event event) { - * // Act according to the source of the event - * if (event.getSource() == ok) - * getWindow().showNotification("Click!"); - * - * status.setValue("Event from " + event.getSource().getClass().getName() - * + ": " + event.getClass().getName()); - * } - * } - * - * Listening listening = new Listening(); - * layout.addComponent(listening); - * </pre> - * - * @param listener - * the new Listener to be registered. - * @see Component.Event - * @see #removeListener(Listener) - */ - public void addListener(Component.Listener listener); - - /** - * Removes a previously registered component event listener from this - * component. - * - * @param listener - * the listener to be removed. - * @see #addListener(Listener) - */ - public void removeListener(Component.Listener listener); - - /** - * Class of all component originated error events. - * - * <p> - * The component error event is normally fired by - * {@link AbstractComponent#setComponentError(ErrorMessage)}. The component - * errors are set by the framework in some situations and can be set by user - * code. They are indicated in a component with an error indicator. - * </p> - */ - @SuppressWarnings("serial") - public class ErrorEvent extends Event { - - private final ErrorMessage message; - - /** - * Constructs a new event with a specified source component. - * - * @param message - * the error message. - * @param component - * the source component. - */ - public ErrorEvent(ErrorMessage message, Component component) { - super(component); - this.message = message; - } - - /** - * Gets the error message. - * - * @return the error message. - */ - public ErrorMessage getErrorMessage() { - return message; - } - } - - /** - * Listener interface for receiving <code>Component.Errors</code>s. - */ - public interface ErrorListener extends EventListener, Serializable { - - /** - * Notifies the listener of a component error. - * - * @param event - * the event that has occured. - */ - public void componentError(Component.ErrorEvent event); - } - - /** - * A sub-interface implemented by components that can obtain input focus. - * This includes all {@link Field} components as well as some other - * components, such as {@link Upload}. - * - * <p> - * Focus can be set with {@link #focus()}. This interface does not provide - * an accessor that would allow finding out the currently focused component; - * focus information can be acquired for some (but not all) {@link Field} - * components through the {@link com.vaadin.event.FieldEvents.FocusListener} - * and {@link com.vaadin.event.FieldEvents.BlurListener} interfaces. - * </p> - * - * @see FieldEvents - */ - public interface Focusable extends Component { - - /** - * Sets the focus to this component. - * - * <pre> - * Form loginBox = new Form(); - * loginBox.setCaption("Login"); - * layout.addComponent(loginBox); - * - * // Create the first field which will be focused - * TextField username = new TextField("User name"); - * loginBox.addField("username", username); - * - * // Set focus to the user name - * username.focus(); - * - * TextField password = new TextField("Password"); - * loginBox.addField("password", password); - * - * Button login = new Button("Login"); - * loginBox.getFooter().addComponent(login); - * </pre> - * - * <p> - * Notice that this interface does not provide an accessor that would - * allow finding out the currently focused component. Focus information - * can be acquired for some (but not all) {@link Field} components - * through the {@link com.vaadin.event.FieldEvents.FocusListener} and - * {@link com.vaadin.event.FieldEvents.BlurListener} interfaces. - * </p> - * - * @see com.vaadin.event.FieldEvents - * @see com.vaadin.event.FieldEvents.FocusEvent - * @see com.vaadin.event.FieldEvents.FocusListener - * @see com.vaadin.event.FieldEvents.BlurEvent - * @see com.vaadin.event.FieldEvents.BlurListener - */ - public void focus(); - - /** - * Gets the <i>tabulator index</i> of the {@code Focusable} component. - * - * @return tab index set for the {@code Focusable} component - * @see #setTabIndex(int) - */ - public int getTabIndex(); - - /** - * Sets the <i>tabulator index</i> of the {@code Focusable} component. - * The tab index property is used to specify the order in which the - * fields are focused when the user presses the Tab key. Components with - * a defined tab index are focused sequentially first, and then the - * components with no tab index. - * - * <pre> - * Form loginBox = new Form(); - * loginBox.setCaption("Login"); - * layout.addComponent(loginBox); - * - * // Create the first field which will be focused - * TextField username = new TextField("User name"); - * loginBox.addField("username", username); - * - * // Set focus to the user name - * username.focus(); - * - * TextField password = new TextField("Password"); - * loginBox.addField("password", password); - * - * Button login = new Button("Login"); - * loginBox.getFooter().addComponent(login); - * - * // An additional component which natural focus order would - * // be after the button. - * CheckBox remember = new CheckBox("Remember me"); - * loginBox.getFooter().addComponent(remember); - * - * username.setTabIndex(1); - * password.setTabIndex(2); - * remember.setTabIndex(3); // Different than natural place - * login.setTabIndex(4); - * </pre> - * - * <p> - * After all focusable user interface components are done, the browser - * can begin again from the component with the smallest tab index, or it - * can take the focus out of the page, for example, to the location bar. - * </p> - * - * <p> - * If the tab index is not set (is set to zero), the default tab order - * is used. The order is somewhat browser-dependent, but generally - * follows the HTML structure of the page. - * </p> - * - * <p> - * A negative value means that the component is completely removed from - * the tabulation order and can not be reached by pressing the Tab key - * at all. - * </p> - * - * @param tabIndex - * the tab order of this component. Indexes usually start - * from 1. Zero means that default tab order should be used. - * A negative value means that the field should not be - * included in the tabbing sequence. - * @see #getTabIndex() - */ - public void setTabIndex(int tabIndex); - - } - -} diff --git a/src/com/vaadin/ui/ComponentContainer.java b/src/com/vaadin/ui/ComponentContainer.java deleted file mode 100644 index 8182d54b56..0000000000 --- a/src/com/vaadin/ui/ComponentContainer.java +++ /dev/null @@ -1,222 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; - -/** - * Extension to the {@link Component} interface which adds to it the capacity to - * contain other components. All UI elements that can have child elements - * implement this interface. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -public interface ComponentContainer extends HasComponents { - - /** - * Adds the component into this container. - * - * @param c - * the component to be added. - */ - public void addComponent(Component c); - - /** - * Removes the component from this container. - * - * @param c - * the component to be removed. - */ - public void removeComponent(Component c); - - /** - * Removes all components from this container. - */ - public void removeAllComponents(); - - /** - * Replaces the component in the container with another one without changing - * position. - * - * <p> - * This method replaces component with another one is such way that the new - * component overtakes the position of the old component. If the old - * component is not in the container, the new component is added to the - * container. If the both component are already in the container, their - * positions are swapped. Component attach and detach events should be taken - * care as with add and remove. - * </p> - * - * @param oldComponent - * the old component that will be replaced. - * @param newComponent - * the new component to be replaced. - */ - public void replaceComponent(Component oldComponent, Component newComponent); - - /** - * Gets the number of children this {@link ComponentContainer} has. This - * must be symmetric with what {@link #getComponentIterator()} returns. - * - * @return The number of child components this container has. - * @since 7.0.0 - */ - public int getComponentCount(); - - /** - * Moves all components from an another container into this container. The - * components are removed from <code>source</code>. - * - * @param source - * the container which contains the components that are to be - * moved to this container. - */ - public void moveComponentsFrom(ComponentContainer source); - - /** - * Listens the component attach events. - * - * @param listener - * the listener to add. - */ - public void addListener(ComponentAttachListener listener); - - /** - * Stops the listening component attach events. - * - * @param listener - * the listener to removed. - */ - public void removeListener(ComponentAttachListener listener); - - /** - * Listens the component detach events. - */ - public void addListener(ComponentDetachListener listener); - - /** - * Stops the listening component detach events. - */ - public void removeListener(ComponentDetachListener listener); - - /** - * Component attach listener interface. - */ - public interface ComponentAttachListener extends Serializable { - - /** - * A new component is attached to container. - * - * @param event - * the component attach event. - */ - public void componentAttachedToContainer(ComponentAttachEvent event); - } - - /** - * Component detach listener interface. - */ - public interface ComponentDetachListener extends Serializable { - - /** - * A component has been detached from container. - * - * @param event - * the component detach event. - */ - public void componentDetachedFromContainer(ComponentDetachEvent event); - } - - /** - * Component attach event sent when a component is attached to container. - */ - @SuppressWarnings("serial") - public class ComponentAttachEvent extends Component.Event { - - private final Component component; - - /** - * Creates a new attach event. - * - * @param container - * the component container the component has been detached - * to. - * @param attachedComponent - * the component that has been attached. - */ - public ComponentAttachEvent(ComponentContainer container, - Component attachedComponent) { - super(container); - component = attachedComponent; - } - - /** - * Gets the component container. - * - * @param the - * component container. - */ - public ComponentContainer getContainer() { - return (ComponentContainer) getSource(); - } - - /** - * Gets the attached component. - * - * @param the - * attach component. - */ - public Component getAttachedComponent() { - return component; - } - } - - /** - * Component detach event sent when a component is detached from container. - */ - @SuppressWarnings("serial") - public class ComponentDetachEvent extends Component.Event { - - private final Component component; - - /** - * Creates a new detach event. - * - * @param container - * the component container the component has been detached - * from. - * @param detachedComponent - * the component that has been detached. - */ - public ComponentDetachEvent(ComponentContainer container, - Component detachedComponent) { - super(container); - component = detachedComponent; - } - - /** - * Gets the component container. - * - * @param the - * component container. - */ - public ComponentContainer getContainer() { - return (ComponentContainer) getSource(); - } - - /** - * Gets the detached component. - * - * @return the detached component. - */ - public Component getDetachedComponent() { - return component; - } - } - -} diff --git a/src/com/vaadin/ui/ConnectorTracker.java b/src/com/vaadin/ui/ConnectorTracker.java deleted file mode 100644 index e3d1bf86db..0000000000 --- a/src/com/vaadin/ui/ConnectorTracker.java +++ /dev/null @@ -1,320 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import java.io.Serializable; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.vaadin.terminal.AbstractClientConnector; -import com.vaadin.terminal.gwt.client.ServerConnector; -import com.vaadin.terminal.gwt.server.ClientConnector; - -/** - * A class which takes care of book keeping of {@link ClientConnector}s for a - * Root. - * <p> - * Provides {@link #getConnector(String)} which can be used to lookup a - * connector from its id. This is for framework use only and should not be - * needed in applications. - * </p> - * <p> - * Tracks which {@link ClientConnector}s are dirty so they can be updated to the - * client when the following response is sent. A connector is dirty when an - * operation has been performed on it on the server and as a result of this - * operation new information needs to be sent to its {@link ServerConnector}. - * </p> - * - * @author Vaadin Ltd - * @version @VERSION@ - * @since 7.0.0 - * - */ -public class ConnectorTracker implements Serializable { - - private final HashMap<String, ClientConnector> connectorIdToConnector = new HashMap<String, ClientConnector>(); - private Set<ClientConnector> dirtyConnectors = new HashSet<ClientConnector>(); - - private Root root; - - /** - * Gets a logger for this class - * - * @return A logger instance for logging within this class - * - */ - public static Logger getLogger() { - return Logger.getLogger(ConnectorTracker.class.getName()); - } - - /** - * Creates a new ConnectorTracker for the given root. A tracker is always - * attached to a root and the root cannot be changed during the lifetime of - * a {@link ConnectorTracker}. - * - * @param root - * The root to attach to. Cannot be null. - */ - public ConnectorTracker(Root root) { - this.root = root; - } - - /** - * Register the given connector. - * <p> - * The lookup method {@link #getConnector(String)} only returns registered - * connectors. - * </p> - * - * @param connector - * The connector to register. - */ - public void registerConnector(ClientConnector connector) { - String connectorId = connector.getConnectorId(); - ClientConnector previouslyRegistered = connectorIdToConnector - .get(connectorId); - if (previouslyRegistered == null) { - connectorIdToConnector.put(connectorId, connector); - getLogger().fine( - "Registered " + connector.getClass().getSimpleName() + " (" - + connectorId + ")"); - } else if (previouslyRegistered != connector) { - throw new RuntimeException("A connector with id " + connectorId - + " is already registered!"); - } else { - getLogger().warning( - "An already registered connector was registered again: " - + connector.getClass().getSimpleName() + " (" - + connectorId + ")"); - } - - } - - /** - * Unregister the given connector. - * - * <p> - * The lookup method {@link #getConnector(String)} only returns registered - * connectors. - * </p> - * - * @param connector - * The connector to unregister - */ - public void unregisterConnector(ClientConnector connector) { - String connectorId = connector.getConnectorId(); - if (!connectorIdToConnector.containsKey(connectorId)) { - getLogger().warning( - "Tried to unregister " - + connector.getClass().getSimpleName() + " (" - + connectorId + ") which is not registered"); - return; - } - if (connectorIdToConnector.get(connectorId) != connector) { - throw new RuntimeException("The given connector with id " - + connectorId - + " is not the one that was registered for that id"); - } - - getLogger().fine( - "Unregistered " + connector.getClass().getSimpleName() + " (" - + connectorId + ")"); - connectorIdToConnector.remove(connectorId); - } - - /** - * Gets a connector by its id. - * - * @param connectorId - * The connector id to look for - * @return The connector with the given id or null if no connector has the - * given id - */ - public ClientConnector getConnector(String connectorId) { - return connectorIdToConnector.get(connectorId); - } - - /** - * Cleans the connector map from all connectors that are no longer attached - * to the application. This should only be called by the framework. - */ - public void cleanConnectorMap() { - // remove detached components from paintableIdMap so they - // can be GC'ed - Iterator<String> iterator = connectorIdToConnector.keySet().iterator(); - - while (iterator.hasNext()) { - String connectorId = iterator.next(); - ClientConnector connector = connectorIdToConnector.get(connectorId); - if (getRootForConnector(connector) != root) { - // If connector is no longer part of this root, - // remove it from the map. If it is re-attached to the - // application at some point it will be re-added through - // registerConnector(connector) - - // This code should never be called as cleanup should take place - // in detach() - getLogger() - .warning( - "cleanConnectorMap unregistered connector " - + getConnectorAndParentInfo(connector) - + "). This should have been done when the connector was detached."); - iterator.remove(); - } - } - - } - - /** - * Finds the root that the connector is attached to. - * - * @param connector - * The connector to lookup - * @return The root the connector is attached to or null if it is not - * attached to any root. - */ - private Root getRootForConnector(ClientConnector connector) { - if (connector == null) { - return null; - } - if (connector instanceof Component) { - return ((Component) connector).getRoot(); - } - - return getRootForConnector(connector.getParent()); - } - - /** - * Mark the connector as dirty. - * - * @see #getDirtyConnectors() - * - * @param connector - * The connector that should be marked clean. - */ - public void markDirty(ClientConnector connector) { - if (getLogger().isLoggable(Level.FINE)) { - if (!dirtyConnectors.contains(connector)) { - getLogger().fine( - getConnectorAndParentInfo(connector) + " " - + "is now dirty"); - } - } - - dirtyConnectors.add(connector); - } - - /** - * Mark the connector as clean. - * - * @param connector - * The connector that should be marked clean. - */ - public void markClean(ClientConnector connector) { - if (getLogger().isLoggable(Level.FINE)) { - if (dirtyConnectors.contains(connector)) { - getLogger().fine( - getConnectorAndParentInfo(connector) + " " - + "is no longer dirty"); - } - } - - dirtyConnectors.remove(connector); - } - - /** - * Returns {@link #getConnectorString(ClientConnector)} for the connector - * and its parent (if it has a parent). - * - * @param connector - * The connector - * @return A string describing the connector and its parent - */ - private String getConnectorAndParentInfo(ClientConnector connector) { - String message = getConnectorString(connector); - if (connector.getParent() != null) { - message += " (parent: " + getConnectorString(connector.getParent()) - + ")"; - } - return message; - } - - /** - * Returns a string with the connector name and id. Useful mostly for - * debugging and logging. - * - * @param connector - * The connector - * @return A string that describes the connector - */ - private String getConnectorString(ClientConnector connector) { - if (connector == null) { - return "(null)"; - } - - String connectorId; - try { - connectorId = connector.getConnectorId(); - } catch (RuntimeException e) { - // This happens if the connector is not attached to the application. - // SHOULD not happen in this case but theoretically can. - connectorId = "@" + Integer.toHexString(connector.hashCode()); - } - return connector.getClass().getName() + "(" + connectorId + ")"; - } - - /** - * Mark all connectors in this root as dirty. - */ - public void markAllConnectorsDirty() { - markConnectorsDirtyRecursively(root); - getLogger().fine("All connectors are now dirty"); - } - - /** - * Mark all connectors in this root as clean. - */ - public void markAllConnectorsClean() { - dirtyConnectors.clear(); - getLogger().fine("All connectors are now clean"); - } - - /** - * 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 markConnectorsDirtyRecursively(ClientConnector c) { - if (c instanceof Component && !((Component) c).isVisible()) { - return; - } - markDirty(c); - for (ClientConnector child : AbstractClientConnector - .getAllChildrenIterable(c)) { - markConnectorsDirtyRecursively(child); - } - } - - /** - * Returns a collection of all connectors which have been marked as dirty. - * <p> - * The state and pending RPC calls for dirty connectors are sent to the - * client in the following request. - * </p> - * - * @return A collection of all dirty connectors for this root. This list may - * contain invisible connectors. - */ - public Collection<ClientConnector> getDirtyConnectors() { - return dirtyConnectors; - } - -} diff --git a/src/com/vaadin/ui/CssLayout.java b/src/com/vaadin/ui/CssLayout.java deleted file mode 100644 index 356f0a3843..0000000000 --- a/src/com/vaadin/ui/CssLayout.java +++ /dev/null @@ -1,308 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import java.util.Iterator; -import java.util.LinkedList; - -import com.vaadin.event.LayoutEvents.LayoutClickEvent; -import com.vaadin.event.LayoutEvents.LayoutClickListener; -import com.vaadin.event.LayoutEvents.LayoutClickNotifier; -import com.vaadin.shared.Connector; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.csslayout.CssLayoutServerRpc; -import com.vaadin.shared.ui.csslayout.CssLayoutState; -import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler; - -/** - * CssLayout is a layout component that can be used in browser environment only. - * It simply renders components and their captions into a same div element. - * Component layout can then be adjusted with css. - * <p> - * In comparison to {@link HorizontalLayout} and {@link VerticalLayout} - * <ul> - * <li>rather similar server side api - * <li>no spacing, alignment or expand ratios - * <li>much simpler DOM that can be styled by skilled web developer - * <li>no abstraction of browser differences (developer must ensure that the - * result works properly on each browser) - * <li>different kind of handling for relative sizes (that are set from server - * side) (*) - * <li>noticeably faster rendering time in some situations as we rely more on - * the browser's rendering engine. - * </ul> - * <p> - * With {@link CustomLayout} one can often achieve similar results (good looking - * layouts with web technologies), but with CustomLayout developer needs to work - * with fixed templates. - * <p> - * By extending CssLayout one can also inject some css rules straight to child - * components using {@link #getCss(Component)}. - * - * <p> - * (*) Relative sizes (set from server side) are treated bit differently than in - * other layouts in Vaadin. In cssLayout the size is calculated relatively to - * CSS layouts content area which is pretty much as in html and css. In other - * layouts the size of component is calculated relatively to the "slot" given by - * layout. - * <p> - * Also note that client side framework in Vaadin modifies inline style - * properties width and height. This happens on each update to component. If one - * wants to set component sizes with CSS, component must have undefined size on - * server side (which is not the default for all components) and the size must - * be defined with class styles - not by directly injecting width and height. - * - * @since 6.1 brought in from "FastLayouts" incubator project - * - */ -public class CssLayout extends AbstractLayout implements LayoutClickNotifier { - - private CssLayoutServerRpc rpc = new CssLayoutServerRpc() { - - @Override - public void layoutClick(MouseEventDetails mouseDetails, - Connector clickedConnector) { - fireEvent(LayoutClickEvent.createEvent(CssLayout.this, - mouseDetails, clickedConnector)); - } - }; - /** - * Custom layout slots containing the components. - */ - protected LinkedList<Component> components = new LinkedList<Component>(); - - public CssLayout() { - registerRpc(rpc); - } - - /** - * Add a component into this container. The component is added to the right - * or under the previous component. - * - * @param c - * the component to be added. - */ - @Override - public void addComponent(Component c) { - // Add to components before calling super.addComponent - // so that it is available to AttachListeners - components.add(c); - try { - super.addComponent(c); - requestRepaint(); - } catch (IllegalArgumentException e) { - components.remove(c); - throw e; - } - } - - /** - * Adds a component into this container. The component is added to the left - * or on top of the other components. - * - * @param c - * the component to be added. - */ - public void addComponentAsFirst(Component c) { - // If c is already in this, we must remove it before proceeding - // see ticket #7668 - if (c.getParent() == this) { - removeComponent(c); - } - components.addFirst(c); - try { - super.addComponent(c); - requestRepaint(); - } catch (IllegalArgumentException e) { - components.remove(c); - throw e; - } - } - - /** - * Adds a component into indexed position in this container. - * - * @param c - * the component to be added. - * @param index - * the index of the component position. The components currently - * in and after the position are shifted forwards. - */ - public void addComponent(Component c, int index) { - // If c is already in this, we must remove it before proceeding - // see ticket #7668 - if (c.getParent() == this) { - // When c is removed, all components after it are shifted down - if (index > getComponentIndex(c)) { - index--; - } - removeComponent(c); - } - components.add(index, c); - try { - super.addComponent(c); - requestRepaint(); - } catch (IllegalArgumentException e) { - components.remove(c); - throw e; - } - } - - /** - * Removes the component from this container. - * - * @param c - * the component to be removed. - */ - @Override - public void removeComponent(Component c) { - components.remove(c); - super.removeComponent(c); - requestRepaint(); - } - - /** - * Gets the component container iterator for going trough all the components - * in the container. - * - * @return the Iterator of the components inside the container. - */ - @Override - public Iterator<Component> getComponentIterator() { - return components.iterator(); - } - - /** - * Gets the number of contained components. Consistent with the iterator - * returned by {@link #getComponentIterator()}. - * - * @return the number of contained components - */ - @Override - public int getComponentCount() { - return components.size(); - } - - @Override - public void updateState() { - super.updateState(); - getState().getChildCss().clear(); - 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 CssLayoutState getState() { - return (CssLayoutState) super.getState(); - } - - /** - * Returns styles to be applied to given component. Override this method to - * inject custom style rules to components. - * - * <p> - * Note that styles are injected over previous styles before actual child - * rendering. Previous styles are not cleared, but overridden. - * - * <p> - * Note that one most often achieves better code style, by separating - * styling to theme (with custom theme and {@link #addStyleName(String)}. - * With own custom styles it is also very easy to break browser - * compatibility. - * - * @param c - * the component - * @return css rules to be applied to component - */ - protected String getCss(Component c) { - return null; - } - - /* Documented in superclass */ - @Override - public void replaceComponent(Component oldComponent, Component newComponent) { - - // Gets the locations - int oldLocation = -1; - int newLocation = -1; - int location = 0; - for (final Iterator<Component> i = components.iterator(); i.hasNext();) { - final Component component = i.next(); - - if (component == oldComponent) { - oldLocation = location; - } - if (component == newComponent) { - newLocation = location; - } - - location++; - } - - if (oldLocation == -1) { - addComponent(newComponent); - } else if (newLocation == -1) { - removeComponent(oldComponent); - addComponent(newComponent, oldLocation); - } else { - if (oldLocation > newLocation) { - components.remove(oldComponent); - components.add(newLocation, oldComponent); - components.remove(newComponent); - components.add(oldLocation, newComponent); - } else { - components.remove(newComponent); - components.add(oldLocation, newComponent); - components.remove(oldComponent); - components.add(newLocation, oldComponent); - } - - requestRepaint(); - } - } - - @Override - public void addListener(LayoutClickListener listener) { - addListener(LayoutClickEventHandler.LAYOUT_CLICK_EVENT_IDENTIFIER, - LayoutClickEvent.class, listener, - LayoutClickListener.clickMethod); - } - - @Override - public void removeListener(LayoutClickListener listener) { - removeListener(LayoutClickEventHandler.LAYOUT_CLICK_EVENT_IDENTIFIER, - LayoutClickEvent.class, listener); - } - - /** - * Returns the index of the given component. - * - * @param component - * The component to look up. - * @return The index of the component or -1 if the component is not a child. - */ - public int getComponentIndex(Component component) { - return components.indexOf(component); - } - - /** - * Returns the component at the given position. - * - * @param index - * The position of the component. - * @return The component at the given index. - * @throws IndexOutOfBoundsException - * If the index is out of range. - */ - public Component getComponent(int index) throws IndexOutOfBoundsException { - return components.get(index); - } - -} diff --git a/src/com/vaadin/ui/CustomComponent.java b/src/com/vaadin/ui/CustomComponent.java deleted file mode 100644 index 40b5dcd636..0000000000 --- a/src/com/vaadin/ui/CustomComponent.java +++ /dev/null @@ -1,189 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.util.Iterator; - -/** - * Custom component provides simple implementation of Component interface for - * creation of new UI components by composition of existing components. - * <p> - * The component is used by inheriting the CustomComponent class and setting - * composite root inside the Custom component. The composite root itself can - * contain more components, but their interfaces are hidden from the users. - * </p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public class CustomComponent extends AbstractComponentContainer { - - /** - * The root component implementing the custom component. - */ - private Component root = null; - - /** - * Constructs a new custom component. - * - * <p> - * The component is implemented by wrapping the methods of the composition - * root component given as parameter. The composition root must be set - * before the component can be used. - * </p> - */ - public CustomComponent() { - // expand horizontally by default - setWidth(100, UNITS_PERCENTAGE); - } - - /** - * Constructs a new custom component. - * - * <p> - * The component is implemented by wrapping the methods of the composition - * root component given as parameter. The composition root must not be null - * and can not be changed after the composition. - * </p> - * - * @param compositionRoot - * the root of the composition component tree. - */ - public CustomComponent(Component compositionRoot) { - this(); - setCompositionRoot(compositionRoot); - } - - /** - * Returns the composition root. - * - * @return the Component Composition root. - */ - protected Component getCompositionRoot() { - return root; - } - - /** - * Sets the compositions root. - * <p> - * The composition root must be set to non-null value before the component - * can be used. The composition root can only be set once. - * </p> - * - * @param compositionRoot - * the root of the composition component tree. - */ - protected void setCompositionRoot(Component compositionRoot) { - if (compositionRoot != root) { - if (root != null) { - // remove old component - super.removeComponent(root); - } - if (compositionRoot != null) { - // set new component - super.addComponent(compositionRoot); - } - root = compositionRoot; - requestRepaint(); - } - } - - /* Basic component features ------------------------------------------ */ - - private class ComponentIterator implements Iterator<Component>, - Serializable { - boolean first = getCompositionRoot() != null; - - @Override - public boolean hasNext() { - return first; - } - - @Override - public Component next() { - first = false; - return root; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - @Override - public Iterator<Component> getComponentIterator() { - return new ComponentIterator(); - } - - /** - * Gets the number of contained components. Consistent with the iterator - * returned by {@link #getComponentIterator()}. - * - * @return the number of contained components (zero or one) - */ - @Override - public int getComponentCount() { - return (root != null ? 1 : 0); - } - - /** - * This method is not supported by CustomComponent. - * - * @see com.vaadin.ui.ComponentContainer#replaceComponent(com.vaadin.ui.Component, - * com.vaadin.ui.Component) - */ - @Override - public void replaceComponent(Component oldComponent, Component newComponent) { - throw new UnsupportedOperationException(); - } - - /** - * This method is not supported by CustomComponent. Use - * {@link CustomComponent#setCompositionRoot(Component)} to set - * CustomComponents "child". - * - * @see com.vaadin.ui.AbstractComponentContainer#addComponent(com.vaadin.ui.Component) - */ - @Override - public void addComponent(Component c) { - throw new UnsupportedOperationException(); - } - - /** - * This method is not supported by CustomComponent. - * - * @see com.vaadin.ui.AbstractComponentContainer#moveComponentsFrom(com.vaadin.ui.ComponentContainer) - */ - @Override - public void moveComponentsFrom(ComponentContainer source) { - throw new UnsupportedOperationException(); - } - - /** - * This method is not supported by CustomComponent. - * - * @see com.vaadin.ui.AbstractComponentContainer#removeAllComponents() - */ - @Override - public void removeAllComponents() { - throw new UnsupportedOperationException(); - } - - /** - * This method is not supported by CustomComponent. - * - * @see com.vaadin.ui.AbstractComponentContainer#removeComponent(com.vaadin.ui.Component) - */ - @Override - public void removeComponent(Component c) { - throw new UnsupportedOperationException(); - } - -} diff --git a/src/com/vaadin/ui/CustomField.java b/src/com/vaadin/ui/CustomField.java deleted file mode 100644 index ab3797a58c..0000000000 --- a/src/com/vaadin/ui/CustomField.java +++ /dev/null @@ -1,237 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.Iterator; - -import com.vaadin.data.Property; - -/** - * A {@link Field} whose UI content can be constructed by the user, enabling the - * creation of e.g. form fields by composing Vaadin components. Customization of - * both the visual presentation and the logic of the field is possible. - * - * Subclasses must implement {@link #getType()} and {@link #initContent()}. - * - * Most custom fields can simply compose a user interface that calls the methods - * {@link #setInternalValue(Object)} and {@link #getInternalValue()} when - * necessary. - * - * It is also possible to override {@link #validate()}, - * {@link #setInternalValue(Object)}, {@link #commit()}, - * {@link #setPropertyDataSource(Property)}, {@link #isEmpty()} and other logic - * of the field. Methods overriding {@link #setInternalValue(Object)} should - * also call the corresponding superclass method. - * - * @param <T> - * field value type - * - * @since 7.0 - */ -public abstract class CustomField<T> extends AbstractField<T> implements - ComponentContainer { - - /** - * The root component implementing the custom component. - */ - private Component root = null; - - /** - * Constructs a new custom field. - * - * <p> - * The component is implemented by wrapping the methods of the composition - * root component given as parameter. The composition root must be set - * before the component can be used. - * </p> - */ - public CustomField() { - // expand horizontally by default - setWidth(100, Unit.PERCENTAGE); - } - - /** - * Constructs the content and notifies it that the {@link CustomField} is - * attached to a window. - * - * @see com.vaadin.ui.Component#attach() - */ - @Override - public void attach() { - // First call super attach to notify all children (none if content has - // not yet been created) - super.attach(); - - // If the content has not yet been created, we create and attach it at - // this point. - if (root == null) { - // Ensure content is created and its parent is set. - // The getContent() call creates the content and attaches the - // content - fireComponentAttachEvent(getContent()); - } - } - - /** - * Returns the content (UI) of the custom component. - * - * @return Component - */ - protected Component getContent() { - if (null == root) { - root = initContent(); - root.setParent(this); - } - return root; - } - - /** - * Create the content component or layout for the field. Subclasses of - * {@link CustomField} should implement this method. - * - * Note that this method is called when the CustomField is attached to a - * layout or when {@link #getContent()} is called explicitly for the first - * time. It is only called once for a {@link CustomField}. - * - * @return {@link Component} representing the UI of the CustomField - */ - protected abstract Component initContent(); - - // Size related methods - // TODO might not be necessary to override but following the pattern from - // AbstractComponentContainer - - @Override - public void setHeight(float height, Unit unit) { - super.setHeight(height, unit); - requestRepaintAll(); - } - - @Override - public void setWidth(float height, Unit unit) { - super.setWidth(height, unit); - requestRepaintAll(); - } - - // ComponentContainer methods - - private class ComponentIterator implements Iterator<Component>, - Serializable { - boolean first = (root != null); - - @Override - public boolean hasNext() { - return first; - } - - @Override - public Component next() { - first = false; - return getContent(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - @Override - public Iterator<Component> getComponentIterator() { - return new ComponentIterator(); - } - - @Override - public Iterator<Component> iterator() { - return getComponentIterator(); - } - - @Override - public int getComponentCount() { - return (null != getContent()) ? 1 : 0; - } - - /** - * Fires the component attached event. This should be called by the - * addComponent methods after the component have been added to this - * container. - * - * @param component - * the component that has been added to this container. - */ - protected void fireComponentAttachEvent(Component component) { - fireEvent(new ComponentAttachEvent(this, component)); - } - - // TODO remove these methods when ComponentContainer interface is cleaned up - - @Override - public void addComponent(Component c) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeComponent(Component c) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeAllComponents() { - throw new UnsupportedOperationException(); - } - - @Override - public void replaceComponent(Component oldComponent, Component newComponent) { - throw new UnsupportedOperationException(); - } - - @Override - public void moveComponentsFrom(ComponentContainer source) { - throw new UnsupportedOperationException(); - } - - private static final Method COMPONENT_ATTACHED_METHOD; - - static { - try { - COMPONENT_ATTACHED_METHOD = ComponentAttachListener.class - .getDeclaredMethod("componentAttachedToContainer", - new Class[] { ComponentAttachEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException( - "Internal error finding methods in CustomField"); - } - } - - @Override - public void addListener(ComponentAttachListener listener) { - addListener(ComponentContainer.ComponentAttachEvent.class, listener, - COMPONENT_ATTACHED_METHOD); - } - - @Override - public void removeListener(ComponentAttachListener listener) { - removeListener(ComponentContainer.ComponentAttachEvent.class, listener, - COMPONENT_ATTACHED_METHOD); - } - - @Override - public void addListener(ComponentDetachListener listener) { - // content never detached - } - - @Override - public void removeListener(ComponentDetachListener listener) { - // content never detached - } - - @Override - public boolean isComponentVisible(Component childComponent) { - return true; - } -} diff --git a/src/com/vaadin/ui/CustomLayout.java b/src/com/vaadin/ui/CustomLayout.java deleted file mode 100644 index d7830603f0..0000000000 --- a/src/com/vaadin/ui/CustomLayout.java +++ /dev/null @@ -1,329 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -import com.vaadin.shared.ui.customlayout.CustomLayoutState; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.gwt.server.JsonPaintTarget; - -/** - * <p> - * A container component with freely designed layout and style. The layout - * consists of items with textually represented locations. Each item contains - * one sub-component, which can be any Vaadin component, such as a layout. The - * adapter and theme are responsible for rendering the layout with a given style - * by placing the items in the defined locations. - * </p> - * - * <p> - * The placement of the locations is not fixed - different themes can define the - * locations in a way that is suitable for them. One typical example would be to - * create visual design for a web site as a custom layout: the visual design - * would define locations for "menu", "body", and "title", for example. The - * layout would then be implemented as an XHTML template for each theme. - * </p> - * - * <p> - * The default theme handles the styles that are not defined by drawing the - * subcomponents just as in OrderedLayout. - * </p> - * - * @author Vaadin Ltd. - * @author Duy B. Vo (<a - * href="mailto:devduy@gmail.com?subject=Vaadin">devduy@gmail.com</a>) - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public class CustomLayout extends AbstractLayout implements Vaadin6Component { - - private static final int BUFFER_SIZE = 10000; - - /** - * Custom layout slots containing the components. - */ - private final HashMap<String, Component> slots = new HashMap<String, Component>(); - - /** - * Default constructor only used by subclasses. Subclasses are responsible - * for setting the appropriate fields. Either - * {@link #setTemplateName(String)}, that makes layout fetch the template - * from theme, or {@link #setTemplateContents(String)}. - */ - protected CustomLayout() { - setWidth(100, UNITS_PERCENTAGE); - } - - /** - * Constructs a custom layout with the template given in the stream. - * - * @param templateStream - * Stream containing template data. Must be using UTF-8 encoding. - * To use a String as a template use for instance new - * ByteArrayInputStream("<template>".getBytes()). - * @param streamLength - * Length of the templateStream - * @throws IOException - */ - public CustomLayout(InputStream templateStream) throws IOException { - this(); - initTemplateContentsFromInputStream(templateStream); - } - - /** - * Constructor for custom layout with given template name. Template file is - * fetched from "<theme>/layout/<templateName>". - */ - public CustomLayout(String template) { - this(); - setTemplateName(template); - } - - protected void initTemplateContentsFromInputStream( - InputStream templateStream) throws IOException { - InputStreamReader reader = new InputStreamReader(templateStream, - "UTF-8"); - StringBuilder b = new StringBuilder(BUFFER_SIZE); - - char[] cbuf = new char[BUFFER_SIZE]; - int offset = 0; - - while (true) { - int nrRead = reader.read(cbuf, offset, BUFFER_SIZE); - b.append(cbuf, 0, nrRead); - if (nrRead < BUFFER_SIZE) { - break; - } - } - - setTemplateContents(b.toString()); - } - - @Override - public CustomLayoutState getState() { - return (CustomLayoutState) super.getState(); - } - - /** - * Adds the component into this container to given location. If the location - * is already populated, the old component is removed. - * - * @param c - * the component to be added. - * @param location - * the location of the component. - */ - public void addComponent(Component c, String location) { - final Component old = slots.get(location); - if (old != null) { - removeComponent(old); - } - slots.put(location, c); - getState().getChildLocations().put(c, location); - c.setParent(this); - fireComponentAttachEvent(c); - requestRepaint(); - } - - /** - * Adds the component into this container. The component is added without - * specifying the location (empty string is then used as location). Only one - * component can be added to the default "" location and adding more - * components into that location overwrites the old components. - * - * @param c - * the component to be added. - */ - @Override - public void addComponent(Component c) { - this.addComponent(c, ""); - } - - /** - * Removes the component from this container. - * - * @param c - * the component to be removed. - */ - @Override - public void removeComponent(Component c) { - if (c == null) { - return; - } - slots.values().remove(c); - getState().getChildLocations().remove(c); - super.removeComponent(c); - requestRepaint(); - } - - /** - * Removes the component from this container from given location. - * - * @param location - * the Location identifier of the component. - */ - public void removeComponent(String location) { - this.removeComponent(slots.get(location)); - } - - /** - * Gets the component container iterator for going trough all the components - * in the container. - * - * @return the Iterator of the components inside the container. - */ - @Override - public Iterator<Component> getComponentIterator() { - return slots.values().iterator(); - } - - /** - * Gets the number of contained components. Consistent with the iterator - * returned by {@link #getComponentIterator()}. - * - * @return the number of contained components - */ - @Override - public int getComponentCount() { - return slots.values().size(); - } - - /** - * Gets the child-component by its location. - * - * @param location - * the name of the location where the requested component - * resides. - * @return the Component in the given location or null if not found. - */ - public Component getComponent(String location) { - return slots.get(location); - } - - /* Documented in superclass */ - @Override - public void replaceComponent(Component oldComponent, Component newComponent) { - - // Gets the locations - String oldLocation = null; - String newLocation = null; - for (final Iterator<String> i = slots.keySet().iterator(); i.hasNext();) { - final String location = i.next(); - final Component component = slots.get(location); - if (component == oldComponent) { - oldLocation = location; - } - if (component == newComponent) { - newLocation = location; - } - } - - if (oldLocation == null) { - addComponent(newComponent); - } else if (newLocation == null) { - removeComponent(oldLocation); - addComponent(newComponent, oldLocation); - } else { - slots.put(newLocation, oldComponent); - slots.put(oldLocation, newComponent); - getState().getChildLocations().put(newComponent, oldLocation); - getState().getChildLocations().put(oldComponent, newLocation); - requestRepaint(); - } - } - - /** Get the name of the template */ - public String getTemplateName() { - return getState().getTemplateName(); - } - - /** Get the contents of the template */ - public String getTemplateContents() { - return getState().getTemplateContents(); - } - - /** - * Set the name of the template used to draw custom layout. - * - * With GWT-adapter, the template with name 'templatename' is loaded from - * VAADIN/themes/themename/layouts/templatename.html. If the theme has not - * been set (with Application.setTheme()), themename is 'default'. - * - * @param templateName - */ - public void setTemplateName(String templateName) { - getState().setTemplateName(templateName); - getState().setTemplateContents(null); - requestRepaint(); - } - - /** - * Set the contents of the template used to draw the custom layout. - * - * @param templateContents - */ - public void setTemplateContents(String templateContents) { - getState().setTemplateContents(templateContents); - getState().setTemplateName(null); - requestRepaint(); - } - - /** - * Although most layouts support margins, CustomLayout does not. The - * behaviour of this layout is determined almost completely by the actual - * template. - * - * @throws UnsupportedOperationException - */ - @Override - public void setMargin(boolean enabled) { - throw new UnsupportedOperationException( - "CustomLayout does not support margins."); - } - - /** - * Although most layouts support margins, CustomLayout does not. The - * behaviour of this layout is determined almost completely by the actual - * template. - * - * @throws UnsupportedOperationException - */ - @Override - public void setMargin(boolean topEnabled, boolean rightEnabled, - boolean bottomEnabled, boolean leftEnabled) { - throw new UnsupportedOperationException( - "CustomLayout does not support margins."); - } - - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - // Nothing to see here - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - // Workaround to make the CommunicationManager read the template file - // and send it to the client - String templateName = getState().getTemplateName(); - if (templateName != null && templateName.length() != 0) { - Set<Object> usedResources = ((JsonPaintTarget) target) - .getUsedResources(); - String resourceName = "layouts/" + templateName + ".html"; - usedResources.add(resourceName); - } - } - -} diff --git a/src/com/vaadin/ui/DateField.java b/src/com/vaadin/ui/DateField.java deleted file mode 100644 index d0a22f3c29..0000000000 --- a/src/com/vaadin/ui/DateField.java +++ /dev/null @@ -1,869 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.TimeZone; - -import com.vaadin.data.Property; -import com.vaadin.data.Validator; -import com.vaadin.data.Validator.InvalidValueException; -import com.vaadin.data.util.converter.Converter; -import com.vaadin.event.FieldEvents; -import com.vaadin.event.FieldEvents.BlurEvent; -import com.vaadin.event.FieldEvents.BlurListener; -import com.vaadin.event.FieldEvents.FocusEvent; -import com.vaadin.event.FieldEvents.FocusListener; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.gwt.client.ui.datefield.VDateField; - -/** - * <p> - * A date editor component that can be bound to any {@link Property} that is - * compatible with <code>java.util.Date</code>. - * </p> - * <p> - * Since <code>DateField</code> extends <code>AbstractField</code> it implements - * the {@link com.vaadin.data.Buffered}interface. - * </p> - * <p> - * A <code>DateField</code> is in write-through mode by default, so - * {@link com.vaadin.ui.AbstractField#setWriteThrough(boolean)}must be called to - * enable buffering. - * </p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public class DateField extends AbstractField<Date> implements - FieldEvents.BlurNotifier, FieldEvents.FocusNotifier, Vaadin6Component { - - /** - * Resolutions for DateFields - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 7.0 - */ - public enum Resolution { - SECOND(Calendar.SECOND), MINUTE(Calendar.MINUTE), HOUR( - Calendar.HOUR_OF_DAY), DAY(Calendar.DAY_OF_MONTH), MONTH( - Calendar.MONTH), YEAR(Calendar.YEAR); - - private int calendarField; - - private Resolution(int calendarField) { - this.calendarField = calendarField; - } - - /** - * Returns the field in {@link Calendar} that corresponds to this - * resolution. - * - * @return one of the field numbers used by Calendar - */ - public int getCalendarField() { - return calendarField; - } - - /** - * Returns the resolutions that are higher or equal to the given - * resolution, starting from the given resolution. In other words - * passing DAY to this methods returns DAY,MONTH,YEAR - * - * @param r - * The resolution to start from - * @return An iterable for the resolutions higher or equal to r - */ - public static Iterable<Resolution> getResolutionsHigherOrEqualTo( - Resolution r) { - List<Resolution> resolutions = new ArrayList<DateField.Resolution>(); - Resolution[] values = Resolution.values(); - for (int i = r.ordinal(); i < values.length; i++) { - resolutions.add(values[i]); - } - return resolutions; - } - - /** - * Returns the resolutions that are lower than the given resolution, - * starting from the given resolution. In other words passing DAY to - * this methods returns HOUR,MINUTE,SECOND. - * - * @param r - * The resolution to start from - * @return An iterable for the resolutions lower than r - */ - public static List<Resolution> getResolutionsLowerThan(Resolution r) { - List<Resolution> resolutions = new ArrayList<DateField.Resolution>(); - Resolution[] values = Resolution.values(); - for (int i = r.ordinal() - 1; i >= 0; i--) { - resolutions.add(values[i]); - } - return resolutions; - } - }; - - /** - * Resolution identifier: seconds. - * - * @deprecated Use {@link Resolution#SECOND} - */ - @Deprecated - public static final Resolution RESOLUTION_SEC = Resolution.SECOND; - - /** - * Resolution identifier: minutes. - * - * @deprecated Use {@link Resolution#MINUTE} - */ - @Deprecated - public static final Resolution RESOLUTION_MIN = Resolution.MINUTE; - - /** - * Resolution identifier: hours. - * - * @deprecated Use {@link Resolution#HOUR} - */ - @Deprecated - public static final Resolution RESOLUTION_HOUR = Resolution.HOUR; - - /** - * Resolution identifier: days. - * - * @deprecated Use {@link Resolution#DAY} - */ - @Deprecated - public static final Resolution RESOLUTION_DAY = Resolution.DAY; - - /** - * Resolution identifier: months. - * - * @deprecated Use {@link Resolution#MONTH} - */ - @Deprecated - public static final Resolution RESOLUTION_MONTH = Resolution.MONTH; - - /** - * Resolution identifier: years. - * - * @deprecated Use {@link Resolution#YEAR} - */ - @Deprecated - public static final Resolution RESOLUTION_YEAR = Resolution.YEAR; - - /** - * Specified smallest modifiable unit for the date field. - */ - private Resolution resolution = Resolution.DAY; - - /** - * The internal calendar to be used in java.utl.Date conversions. - */ - private transient Calendar calendar; - - /** - * Overridden format string - */ - private String dateFormat; - - private boolean lenient = false; - - private String dateString = null; - - /** - * Was the last entered string parsable? If this flag is false, datefields - * internal validator does not pass. - */ - private boolean uiHasValidDateString = true; - - /** - * Determines if week numbers are shown in the date selector. - */ - private boolean showISOWeekNumbers = false; - - private String currentParseErrorMessage; - - private String defaultParseErrorMessage = "Date format not recognized"; - - private TimeZone timeZone = null; - - private static Map<Resolution, String> variableNameForResolution = new HashMap<DateField.Resolution, String>(); - { - variableNameForResolution.put(Resolution.SECOND, "sec"); - variableNameForResolution.put(Resolution.MINUTE, "min"); - variableNameForResolution.put(Resolution.HOUR, "hour"); - variableNameForResolution.put(Resolution.DAY, "day"); - variableNameForResolution.put(Resolution.MONTH, "month"); - variableNameForResolution.put(Resolution.YEAR, "year"); - } - - /* Constructors */ - - /** - * Constructs an empty <code>DateField</code> with no caption. - */ - public DateField() { - } - - /** - * Constructs an empty <code>DateField</code> with caption. - * - * @param caption - * the caption of the datefield. - */ - public DateField(String caption) { - setCaption(caption); - } - - /** - * Constructs a new <code>DateField</code> that's bound to the specified - * <code>Property</code> and has the given caption <code>String</code>. - * - * @param caption - * the caption <code>String</code> for the editor. - * @param dataSource - * the Property to be edited with this editor. - */ - public DateField(String caption, Property dataSource) { - this(dataSource); - setCaption(caption); - } - - /** - * Constructs a new <code>DateField</code> that's bound to the specified - * <code>Property</code> and has no caption. - * - * @param dataSource - * the Property to be edited with this editor. - */ - public DateField(Property dataSource) throws IllegalArgumentException { - if (!Date.class.isAssignableFrom(dataSource.getType())) { - throw new IllegalArgumentException("Can't use " - + dataSource.getType().getName() - + " typed property as datasource"); - } - - setPropertyDataSource(dataSource); - } - - /** - * Constructs a new <code>DateField</code> with the given caption and - * initial text contents. The editor constructed this way will not be bound - * to a Property unless - * {@link com.vaadin.data.Property.Viewer#setPropertyDataSource(Property)} - * is called to bind it. - * - * @param caption - * the caption <code>String</code> for the editor. - * @param value - * the Date value. - */ - public DateField(String caption, Date value) { - setValue(value); - setCaption(caption); - } - - /* Component basic features */ - - /* - * Paints this component. Don't add a JavaDoc comment here, we use the - * default documentation from implemented interface. - */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - - // Adds the locale as attribute - final Locale l = getLocale(); - if (l != null) { - target.addAttribute("locale", l.toString()); - } - - if (getDateFormat() != null) { - target.addAttribute("format", dateFormat); - } - - if (!isLenient()) { - target.addAttribute("strict", true); - } - - target.addAttribute(VDateField.WEEK_NUMBERS, isShowISOWeekNumbers()); - target.addAttribute("parsable", uiHasValidDateString); - /* - * TODO communicate back the invalid date string? E.g. returning back to - * app or refresh. - */ - - // Gets the calendar - final Calendar calendar = getCalendar(); - final Date currentDate = getValue(); - - // Only paint variables for the resolution and up, e.g. Resolution DAY - // paints DAY,MONTH,YEAR - for (Resolution res : Resolution - .getResolutionsHigherOrEqualTo(resolution)) { - int value = -1; - if (currentDate != null) { - value = calendar.get(res.getCalendarField()); - if (res == Resolution.MONTH) { - // Calendar month is zero based - value++; - } - } - target.addVariable(this, variableNameForResolution.get(res), value); - } - } - - @Override - protected boolean shouldHideErrors() { - return super.shouldHideErrors() && uiHasValidDateString; - } - - /* - * Invoked when a variable of the component changes. Don't add a JavaDoc - * comment here, we use the default documentation from implemented - * interface. - */ - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - - if (!isReadOnly() - && (variables.containsKey("year") - || variables.containsKey("month") - || variables.containsKey("day") - || variables.containsKey("hour") - || variables.containsKey("min") - || variables.containsKey("sec") - || variables.containsKey("msec") || variables - .containsKey("dateString"))) { - - // Old and new dates - final Date oldDate = getValue(); - Date newDate = null; - - // this enables analyzing invalid input on the server - final String newDateString = (String) variables.get("dateString"); - dateString = newDateString; - - // Gets the new date in parts - boolean hasChanges = false; - Map<Resolution, Integer> calendarFieldChanges = new HashMap<DateField.Resolution, Integer>(); - - for (Resolution r : Resolution - .getResolutionsHigherOrEqualTo(resolution)) { - // Only handle what the client is allowed to send. The same - // resolutions that are painted - String variableName = variableNameForResolution.get(r); - - if (variables.containsKey(variableName)) { - Integer value = (Integer) variables.get(variableName); - if (r == Resolution.MONTH) { - // Calendar MONTH is zero based - value--; - } - if (value >= 0) { - hasChanges = true; - calendarFieldChanges.put(r, value); - } - } - } - - // If no new variable values were received, use the previous value - if (!hasChanges) { - newDate = null; - } else { - // Clone the calendar for date operation - final Calendar cal = getCalendar(); - - // Update the value based on the received info - // Must set in this order to avoid invalid dates (or wrong - // dates if lenient is true) in calendar - for (int r = Resolution.YEAR.ordinal(); r >= 0; r--) { - Resolution res = Resolution.values()[r]; - if (calendarFieldChanges.containsKey(res)) { - - // Field resolution should be included. Others are - // skipped so that client can not make unexpected - // changes (e.g. day change even though resolution is - // year). - Integer newValue = calendarFieldChanges.get(res); - cal.set(res.getCalendarField(), newValue); - } - } - newDate = cal.getTime(); - } - - if (newDate == null && dateString != null && !"".equals(dateString)) { - try { - Date parsedDate = handleUnparsableDateString(dateString); - setValue(parsedDate, true); - - /* - * Ensure the value is sent to the client if the value is - * set to the same as the previous (#4304). Does not repaint - * if handleUnparsableDateString throws an exception. In - * this case the invalid text remains in the DateField. - */ - requestRepaint(); - } catch (Converter.ConversionException e) { - - /* - * Datefield now contains some text that could't be parsed - * into date. - */ - if (oldDate != null) { - /* - * Set the logic value to null. - */ - setValue(null); - /* - * Reset the dateString (overridden to null by setValue) - */ - dateString = newDateString; - } - - /* - * Saves the localized message of parse error. This can be - * overridden in handleUnparsableDateString. The message - * will later be used to show a validation error. - */ - currentParseErrorMessage = e.getLocalizedMessage(); - - /* - * The value of the DateField should be null if an invalid - * value has been given. Not using setValue() since we do - * not want to cause the client side value to change. - */ - uiHasValidDateString = false; - - /* - * Because of our custom implementation of isValid(), that - * also checks the parsingSucceeded flag, we must also - * notify the form (if this is used in one) that the - * validity of this field has changed. - * - * Normally fields validity doesn't change without value - * change and form depends on this implementation detail. - */ - notifyFormOfValidityChange(); - requestRepaint(); - } - } else if (newDate != oldDate - && (newDate == null || !newDate.equals(oldDate))) { - setValue(newDate, true); // Don't require a repaint, client - // updates itself - } else if (!uiHasValidDateString) { // oldDate == - // newDate == null - // Empty value set, previously contained unparsable date string, - // clear related internal fields - setValue(null); - } - } - - if (variables.containsKey(FocusEvent.EVENT_ID)) { - fireEvent(new FocusEvent(this)); - } - - if (variables.containsKey(BlurEvent.EVENT_ID)) { - fireEvent(new BlurEvent(this)); - } - } - - /** - * This method is called to handle a non-empty date string from the client - * if the client could not parse it as a Date. - * - * By default, a Converter.ConversionException is thrown, and the current - * value is not modified. - * - * This can be overridden to handle conversions, to return null (equivalent - * to empty input), to throw an exception or to fire an event. - * - * @param dateString - * @return parsed Date - * @throws Converter.ConversionException - * to keep the old value and indicate an error - */ - protected Date handleUnparsableDateString(String dateString) - throws Converter.ConversionException { - currentParseErrorMessage = null; - throw new Converter.ConversionException(getParseErrorMessage()); - } - - /* Property features */ - - /* - * Gets the edited property's type. Don't add a JavaDoc comment here, we use - * the default documentation from implemented interface. - */ - @Override - public Class<Date> getType() { - return Date.class; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.AbstractField#setValue(java.lang.Object, boolean) - */ - @Override - protected void setValue(Date newValue, boolean repaintIsNotNeeded) - throws Property.ReadOnlyException { - - /* - * First handle special case when the client side component have a date - * string but value is null (e.g. unparsable date string typed in by the - * user). No value changes should happen, but we need to do some - * internal housekeeping. - */ - if (newValue == null && !uiHasValidDateString) { - /* - * Side-effects of setInternalValue clears possible previous strings - * and flags about invalid input. - */ - setInternalValue(null); - - /* - * Due to DateField's special implementation of isValid(), - * datefields validity may change although the logical value does - * not change. This is an issue for Form which expects that validity - * of Fields cannot change unless actual value changes. - * - * So we check if this field is inside a form and the form has - * registered this as a field. In this case we repaint the form. - * Without this hacky solution the form might not be able to clean - * validation errors etc. We could avoid this by firing an extra - * value change event, but feels like at least as bad solution as - * this. - */ - notifyFormOfValidityChange(); - requestRepaint(); - return; - } - - super.setValue(newValue, repaintIsNotNeeded); - } - - /** - * Detects if this field is used in a Form (logically) and if so, notifies - * it (by repainting it) that the validity of this field might have changed. - */ - private void notifyFormOfValidityChange() { - Component parenOfDateField = getParent(); - boolean formFound = false; - while (parenOfDateField != null || formFound) { - if (parenOfDateField instanceof Form) { - Form f = (Form) parenOfDateField; - Collection<?> visibleItemProperties = f.getItemPropertyIds(); - for (Object fieldId : visibleItemProperties) { - Field<?> field = f.getField(fieldId); - if (field == this) { - /* - * this datefield is logically in a form. Do the same - * thing as form does in its value change listener that - * it registers to all fields. - */ - f.requestRepaint(); - formFound = true; - break; - } - } - } - if (formFound) { - break; - } - parenOfDateField = parenOfDateField.getParent(); - } - } - - @Override - protected void setInternalValue(Date newValue) { - // Also set the internal dateString - if (newValue != null) { - dateString = newValue.toString(); - } else { - dateString = null; - } - - if (!uiHasValidDateString) { - // clear component error and parsing flag - setComponentError(null); - uiHasValidDateString = true; - currentParseErrorMessage = null; - } - - super.setInternalValue(newValue); - } - - /** - * Gets the resolution. - * - * @return int - */ - public Resolution getResolution() { - return resolution; - } - - /** - * Sets the resolution of the DateField. - * - * The default resolution is {@link Resolution#DAY} since Vaadin 7.0. - * - * @param resolution - * the resolution to set. - */ - public void setResolution(Resolution resolution) { - this.resolution = resolution; - requestRepaint(); - } - - /** - * Returns new instance calendar used in Date conversions. - * - * Returns new clone of the calendar object initialized using the the - * current date (if available) - * - * If this is no calendar is assigned the <code>Calendar.getInstance</code> - * is used. - * - * @return the Calendar. - * @see #setCalendar(Calendar) - */ - private Calendar getCalendar() { - - // Makes sure we have an calendar instance - if (calendar == null) { - calendar = Calendar.getInstance(); - // Start by a zeroed calendar to avoid having values for lower - // resolution variables e.g. time when resolution is day - for (Resolution r : Resolution.getResolutionsLowerThan(resolution)) { - calendar.set(r.getCalendarField(), 0); - } - calendar.set(Calendar.MILLISECOND, 0); - } - - // Clone the instance - final Calendar newCal = (Calendar) calendar.clone(); - - // Assigns the current time tom calendar. - final Date currentDate = getValue(); - if (currentDate != null) { - newCal.setTime(currentDate); - } - - final TimeZone currentTimeZone = getTimeZone(); - if (currentTimeZone != null) { - newCal.setTimeZone(currentTimeZone); - } - - return newCal; - } - - /** - * Sets formatting used by some component implementations. See - * {@link SimpleDateFormat} for format details. - * - * By default it is encouraged to used default formatting defined by Locale, - * but due some JVM bugs it is sometimes necessary to use this method to - * override formatting. See Vaadin issue #2200. - * - * @param dateFormat - * the dateFormat to set - * - * @see com.vaadin.ui.AbstractComponent#setLocale(Locale)) - */ - public void setDateFormat(String dateFormat) { - this.dateFormat = dateFormat; - requestRepaint(); - } - - /** - * Returns a format string used to format date value on client side or null - * if default formatting from {@link Component#getLocale()} is used. - * - * @return the dateFormat - */ - public String getDateFormat() { - return dateFormat; - } - - /** - * Specifies whether or not date/time interpretation in component is to be - * lenient. - * - * @see Calendar#setLenient(boolean) - * @see #isLenient() - * - * @param lenient - * true if the lenient mode is to be turned on; false if it is to - * be turned off. - */ - public void setLenient(boolean lenient) { - this.lenient = lenient; - requestRepaint(); - } - - /** - * Returns whether date/time interpretation is to be lenient. - * - * @see #setLenient(boolean) - * - * @return true if the interpretation mode of this calendar is lenient; - * false otherwise. - */ - public boolean isLenient() { - return lenient; - } - - @Override - public void addListener(FocusListener listener) { - addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, - FocusListener.focusMethod); - } - - @Override - public void removeListener(FocusListener listener) { - removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); - } - - @Override - public void addListener(BlurListener listener) { - addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, - BlurListener.blurMethod); - } - - @Override - public void removeListener(BlurListener listener) { - removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); - } - - /** - * Checks whether ISO 8601 week numbers are shown in the date selector. - * - * @return true if week numbers are shown, false otherwise. - */ - public boolean isShowISOWeekNumbers() { - return showISOWeekNumbers; - } - - /** - * Sets the visibility of ISO 8601 week numbers in the date selector. ISO - * 8601 defines that a week always starts with a Monday so the week numbers - * are only shown if this is the case. - * - * @param showWeekNumbers - * true if week numbers should be shown, false otherwise. - */ - public void setShowISOWeekNumbers(boolean showWeekNumbers) { - showISOWeekNumbers = showWeekNumbers; - requestRepaint(); - } - - /** - * Validates the current value against registered validators if the field is - * not empty. Note that DateField is considered empty (value == null) and - * invalid if it contains text typed in by the user that couldn't be parsed - * into a Date value. - * - * @see com.vaadin.ui.AbstractField#validate() - */ - @Override - public void validate() throws InvalidValueException { - /* - * To work properly in form we must throw exception if there is - * currently a parsing error in the datefield. Parsing error is kind of - * an internal validator. - */ - if (!uiHasValidDateString) { - throw new UnparsableDateString(currentParseErrorMessage); - } - super.validate(); - } - - /** - * Return the error message that is shown if the user inputted value can't - * be parsed into a Date object. If - * {@link #handleUnparsableDateString(String)} is overridden and it throws a - * custom exception, the message returned by - * {@link Exception#getLocalizedMessage()} will be used instead of the value - * returned by this method. - * - * @see #setParseErrorMessage(String) - * - * @return the error message that the DateField uses when it can't parse the - * textual input from user to a Date object - */ - public String getParseErrorMessage() { - return defaultParseErrorMessage; - } - - /** - * Sets the default error message used if the DateField cannot parse the - * text input by user to a Date field. Note that if the - * {@link #handleUnparsableDateString(String)} method is overridden, the - * localized message from its exception is used. - * - * @see #getParseErrorMessage() - * @see #handleUnparsableDateString(String) - * @param parsingErrorMessage - */ - public void setParseErrorMessage(String parsingErrorMessage) { - defaultParseErrorMessage = parsingErrorMessage; - } - - /** - * Sets the time zone used by this date field. The time zone is used to - * convert the absolute time in a Date object to a logical time displayed in - * the selector and to convert the select time back to a Date object. - * - * If no time zone has been set, the current default time zone returned by - * {@code TimeZone.getDefault()} is used. - * - * @see #getTimeZone() - * @param timeZone - * the time zone to use for time calculations. - */ - public void setTimeZone(TimeZone timeZone) { - this.timeZone = timeZone; - requestRepaint(); - } - - /** - * Gets the time zone used by this field. The time zone is used to convert - * the absolute time in a Date object to a logical time displayed in the - * selector and to convert the select time back to a Date object. - * - * If {@code null} is returned, the current default time zone returned by - * {@code TimeZone.getDefault()} is used. - * - * @return the current time zone - */ - public TimeZone getTimeZone() { - return timeZone; - } - - public static class UnparsableDateString extends - Validator.InvalidValueException { - - public UnparsableDateString(String message) { - super(message); - } - - } -} diff --git a/src/com/vaadin/ui/DefaultFieldFactory.java b/src/com/vaadin/ui/DefaultFieldFactory.java deleted file mode 100644 index e17f08c1c6..0000000000 --- a/src/com/vaadin/ui/DefaultFieldFactory.java +++ /dev/null @@ -1,146 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import java.util.Date; - -import com.vaadin.data.Container; -import com.vaadin.data.Item; -import com.vaadin.data.Property; - -/** - * This class contains a basic implementation for both {@link FormFieldFactory} - * and {@link TableFieldFactory}. The class is singleton, use {@link #get()} - * method to get reference to the instance. - * - * <p> - * There are also some static helper methods available for custom built field - * factories. - * - */ -public class DefaultFieldFactory implements FormFieldFactory, TableFieldFactory { - - private static final DefaultFieldFactory instance = new DefaultFieldFactory(); - - /** - * Singleton method to get an instance of DefaultFieldFactory. - * - * @return an instance of DefaultFieldFactory - */ - public static DefaultFieldFactory get() { - return instance; - } - - protected DefaultFieldFactory() { - } - - @Override - public Field<?> createField(Item item, Object propertyId, - Component uiContext) { - Class<?> type = item.getItemProperty(propertyId).getType(); - Field<?> field = createFieldByPropertyType(type); - field.setCaption(createCaptionByPropertyId(propertyId)); - return field; - } - - @Override - public Field<?> createField(Container container, Object itemId, - Object propertyId, Component uiContext) { - Property<?> containerProperty = container.getContainerProperty(itemId, - propertyId); - Class<?> type = containerProperty.getType(); - Field<?> field = createFieldByPropertyType(type); - field.setCaption(createCaptionByPropertyId(propertyId)); - return field; - } - - /** - * If name follows method naming conventions, convert the name to spaced - * upper case text. For example, convert "firstName" to "First Name" - * - * @param propertyId - * @return the formatted caption string - */ - public static String createCaptionByPropertyId(Object propertyId) { - String name = propertyId.toString(); - if (name.length() > 0) { - - int dotLocation = name.lastIndexOf('.'); - if (dotLocation > 0 && dotLocation < name.length() - 1) { - name = name.substring(dotLocation + 1); - } - if (name.indexOf(' ') < 0 - && name.charAt(0) == Character.toLowerCase(name.charAt(0)) - && name.charAt(0) != Character.toUpperCase(name.charAt(0))) { - StringBuffer out = new StringBuffer(); - out.append(Character.toUpperCase(name.charAt(0))); - int i = 1; - - while (i < name.length()) { - int j = i; - for (; j < name.length(); j++) { - char c = name.charAt(j); - if (Character.toLowerCase(c) != c - && Character.toUpperCase(c) == c) { - break; - } - } - if (j == name.length()) { - out.append(name.substring(i)); - } else { - out.append(name.substring(i, j)); - out.append(" " + name.charAt(j)); - } - i = j + 1; - } - - name = out.toString(); - } - } - return name; - } - - /** - * Creates fields based on the property type. - * <p> - * The default field type is {@link TextField}. Other field types generated - * by this method: - * <p> - * <b>Boolean</b>: {@link CheckBox}.<br/> - * <b>Date</b>: {@link DateField}(resolution: day).<br/> - * <b>Item</b>: {@link Form}. <br/> - * <b>default field type</b>: {@link TextField}. - * <p> - * - * @param type - * the type of the property - * @return the most suitable generic {@link Field} for given type - */ - public static Field<?> createFieldByPropertyType(Class<?> type) { - // Null typed properties can not be edited - if (type == null) { - return null; - } - - // Item field - if (Item.class.isAssignableFrom(type)) { - return new Form(); - } - - // Date field - if (Date.class.isAssignableFrom(type)) { - final DateField df = new DateField(); - df.setResolution(DateField.RESOLUTION_DAY); - return df; - } - - // Boolean field - if (Boolean.class.isAssignableFrom(type)) { - return new CheckBox(); - } - - return new TextField(); - } - -} diff --git a/src/com/vaadin/ui/DragAndDropWrapper.java b/src/com/vaadin/ui/DragAndDropWrapper.java deleted file mode 100644 index 67229a45fe..0000000000 --- a/src/com/vaadin/ui/DragAndDropWrapper.java +++ /dev/null @@ -1,407 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import java.io.OutputStream; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; - -import com.vaadin.event.Transferable; -import com.vaadin.event.TransferableImpl; -import com.vaadin.event.dd.DragSource; -import com.vaadin.event.dd.DropHandler; -import com.vaadin.event.dd.DropTarget; -import com.vaadin.event.dd.TargetDetails; -import com.vaadin.event.dd.TargetDetailsImpl; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.dd.HorizontalDropLocation; -import com.vaadin.shared.ui.dd.VerticalDropLocation; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.StreamVariable; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.gwt.client.ui.draganddropwrapper.VDragAndDropWrapper; - -@SuppressWarnings("serial") -public class DragAndDropWrapper extends CustomComponent implements DropTarget, - DragSource, Vaadin6Component { - - public class WrapperTransferable extends TransferableImpl { - - private Html5File[] files; - - public WrapperTransferable(Component sourceComponent, - Map<String, Object> rawVariables) { - super(sourceComponent, rawVariables); - Integer fc = (Integer) rawVariables.get("filecount"); - if (fc != null) { - files = new Html5File[fc]; - for (int i = 0; i < fc; i++) { - Html5File file = new Html5File( - (String) rawVariables.get("fn" + i), // name - (Integer) rawVariables.get("fs" + i), // size - (String) rawVariables.get("ft" + i)); // mime - String id = (String) rawVariables.get("fi" + i); - files[i] = file; - receivers.put(id, file); - requestRepaint(); // paint Receivers - } - } - } - - /** - * The component in wrapper that is being dragged or null if the - * transferable is not a component (most likely an html5 drag). - * - * @return - */ - public Component getDraggedComponent() { - Component object = (Component) getData("component"); - return object; - } - - /** - * @return the mouse down event that started the drag and drop operation - */ - public MouseEventDetails getMouseDownEvent() { - return MouseEventDetails.deSerialize((String) getData("mouseDown")); - } - - public Html5File[] getFiles() { - return files; - } - - public String getText() { - String data = (String) getData("Text"); // IE, html5 - if (data == null) { - // check for "text/plain" (webkit) - data = (String) getData("text/plain"); - } - return data; - } - - public String getHtml() { - String data = (String) getData("Html"); // IE, html5 - if (data == null) { - // check for "text/plain" (webkit) - data = (String) getData("text/html"); - } - return data; - } - - } - - private Map<String, Html5File> receivers = new HashMap<String, Html5File>(); - - public class WrapperTargetDetails extends TargetDetailsImpl { - - public WrapperTargetDetails(Map<String, Object> rawDropData) { - super(rawDropData, DragAndDropWrapper.this); - } - - /** - * @return the absolute position of wrapper on the page - */ - public Integer getAbsoluteLeft() { - return (Integer) getData("absoluteLeft"); - } - - /** - * - * @return the absolute position of wrapper on the page - */ - public Integer getAbsoluteTop() { - return (Integer) getData("absoluteTop"); - } - - /** - * @return details about the actual event that caused the event details. - * Practically mouse move or mouse up. - */ - public MouseEventDetails getMouseEvent() { - return MouseEventDetails - .deSerialize((String) getData("mouseEvent")); - } - - /** - * @return a detail about the drags vertical position over the wrapper. - */ - public VerticalDropLocation getVerticalDropLocation() { - return VerticalDropLocation - .valueOf((String) getData("verticalLocation")); - } - - /** - * @return a detail about the drags horizontal position over the - * wrapper. - */ - public HorizontalDropLocation getHorizontalDropLocation() { - return HorizontalDropLocation - .valueOf((String) getData("horizontalLocation")); - } - - /** - * @deprecated use {@link #getVerticalDropLocation()} instead - */ - @Deprecated - public VerticalDropLocation verticalDropLocation() { - return getVerticalDropLocation(); - } - - /** - * @deprecated use {@link #getHorizontalDropLocation()} instead - */ - @Deprecated - public HorizontalDropLocation horizontalDropLocation() { - return getHorizontalDropLocation(); - } - - } - - public enum DragStartMode { - /** - * {@link DragAndDropWrapper} does not start drag events at all - */ - NONE, - /** - * The component on which the drag started will be shown as drag image. - */ - COMPONENT, - /** - * The whole wrapper is used as a drag image when dragging. - */ - WRAPPER, - /** - * The whole wrapper is used to start an HTML5 drag. - * - * NOTE: In Internet Explorer 6 to 8, this prevents user interactions - * with the wrapper's contents. For example, clicking a button inside - * the wrapper will no longer work. - */ - HTML5, - } - - private final Map<String, Object> html5DataFlavors = new LinkedHashMap<String, Object>(); - private DragStartMode dragStartMode = DragStartMode.NONE; - - /** - * Wraps given component in a {@link DragAndDropWrapper}. - * - * @param root - * the component to be wrapped - */ - public DragAndDropWrapper(Component root) { - super(root); - } - - /** - * Sets data flavors available in the DragAndDropWrapper is used to start an - * HTML5 style drags. Most commonly the "Text" flavor should be set. - * Multiple data types can be set. - * - * @param type - * the string identifier of the drag "payload". E.g. "Text" or - * "text/html" - * @param value - * the value - */ - public void setHTML5DataFlavor(String type, Object value) { - html5DataFlavors.put(type, value); - requestRepaint(); - } - - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - // TODO Remove once Vaadin6Component is no longer implemented - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - target.addAttribute(VDragAndDropWrapper.DRAG_START_MODE, - dragStartMode.ordinal()); - if (getDropHandler() != null) { - getDropHandler().getAcceptCriterion().paint(target); - } - if (receivers != null && receivers.size() > 0) { - for (Iterator<Entry<String, Html5File>> it = receivers.entrySet() - .iterator(); it.hasNext();) { - Entry<String, com.vaadin.ui.Html5File> entry = it.next(); - String id = entry.getKey(); - Html5File html5File = entry.getValue(); - if (html5File.getStreamVariable() != null) { - target.addVariable(this, "rec-" + id, new ProxyReceiver( - html5File)); - // these are cleaned from receivers once the upload has - // started - } else { - // instructs the client side not to send the file - target.addVariable(this, "rec-" + id, (String) null); - // forget the file from subsequent paints - it.remove(); - } - } - } - target.addAttribute(VDragAndDropWrapper.HTML5_DATA_FLAVORS, - html5DataFlavors); - } - - private DropHandler dropHandler; - - @Override - public DropHandler getDropHandler() { - return dropHandler; - } - - public void setDropHandler(DropHandler dropHandler) { - this.dropHandler = dropHandler; - requestRepaint(); - } - - @Override - public TargetDetails translateDropTargetDetails( - Map<String, Object> clientVariables) { - return new WrapperTargetDetails(clientVariables); - } - - @Override - public Transferable getTransferable(final Map<String, Object> rawVariables) { - return new WrapperTransferable(this, rawVariables); - } - - public void setDragStartMode(DragStartMode dragStartMode) { - this.dragStartMode = dragStartMode; - requestRepaint(); - } - - public DragStartMode getDragStartMode() { - return dragStartMode; - } - - final class ProxyReceiver implements StreamVariable { - - private Html5File file; - - public ProxyReceiver(Html5File file) { - this.file = file; - } - - private boolean listenProgressOfUploadedFile; - - @Override - public OutputStream getOutputStream() { - if (file.getStreamVariable() == null) { - return null; - } - return file.getStreamVariable().getOutputStream(); - } - - @Override - public boolean listenProgress() { - return file.getStreamVariable().listenProgress(); - } - - @Override - public void onProgress(StreamingProgressEvent event) { - file.getStreamVariable().onProgress( - new ReceivingEventWrapper(event)); - } - - @Override - public void streamingStarted(StreamingStartEvent event) { - listenProgressOfUploadedFile = file.getStreamVariable() != null; - if (listenProgressOfUploadedFile) { - file.getStreamVariable().streamingStarted( - new ReceivingEventWrapper(event)); - } - // no need tell to the client about this receiver on next paint - receivers.remove(file); - // let the terminal GC the streamvariable and not to accept other - // file uploads to this variable - event.disposeStreamVariable(); - } - - @Override - public void streamingFinished(StreamingEndEvent event) { - if (listenProgressOfUploadedFile) { - file.getStreamVariable().streamingFinished( - new ReceivingEventWrapper(event)); - } - } - - @Override - public void streamingFailed(final StreamingErrorEvent event) { - if (listenProgressOfUploadedFile) { - file.getStreamVariable().streamingFailed( - new ReceivingEventWrapper(event)); - } - } - - @Override - public boolean isInterrupted() { - return file.getStreamVariable().isInterrupted(); - } - - /* - * With XHR2 file posts we can't provide as much information from the - * terminal as with multipart request. This helper class wraps the - * terminal event and provides the lacking information from the - * Html5File. - */ - class ReceivingEventWrapper implements StreamingErrorEvent, - StreamingEndEvent, StreamingStartEvent, StreamingProgressEvent { - - private StreamingEvent wrappedEvent; - - ReceivingEventWrapper(StreamingEvent e) { - wrappedEvent = e; - } - - @Override - public String getMimeType() { - return file.getType(); - } - - @Override - public String getFileName() { - return file.getFileName(); - } - - @Override - public long getContentLength() { - return file.getFileSize(); - } - - public StreamVariable getReceiver() { - return ProxyReceiver.this; - } - - @Override - public Exception getException() { - if (wrappedEvent instanceof StreamingErrorEvent) { - return ((StreamingErrorEvent) wrappedEvent).getException(); - } - return null; - } - - @Override - public long getBytesReceived() { - return wrappedEvent.getBytesReceived(); - } - - /** - * Calling this method has no effect. DD files are receive only once - * anyway. - */ - @Override - public void disposeStreamVariable() { - - } - } - - } - -} diff --git a/src/com/vaadin/ui/Embedded.java b/src/com/vaadin/ui/Embedded.java deleted file mode 100644 index 6088c5aa66..0000000000 --- a/src/com/vaadin/ui/Embedded.java +++ /dev/null @@ -1,531 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import com.vaadin.event.MouseEvents.ClickEvent; -import com.vaadin.event.MouseEvents.ClickListener; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.embedded.EmbeddedServerRpc; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.gwt.client.ui.ClickEventHandler; -import com.vaadin.terminal.gwt.client.ui.embedded.EmbeddedConnector; - -/** - * Component for embedding external objects. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public class Embedded extends AbstractComponent implements Vaadin6Component { - - /** - * General object type. - */ - public static final int TYPE_OBJECT = 0; - - /** - * Image types. - */ - public static final int TYPE_IMAGE = 1; - - /** - * Browser ("iframe") type. - */ - public static final int TYPE_BROWSER = 2; - - /** - * Type of the object. - */ - private int type = TYPE_OBJECT; - - /** - * Source of the embedded object. - */ - private Resource source = null; - - /** - * Generic object attributes. - */ - private String mimeType = null; - - private String standby = null; - - /** - * Hash of object parameters. - */ - private final Map<String, String> parameters = new HashMap<String, String>(); - - /** - * Applet or other client side runnable properties. - */ - private String codebase = null; - - private String codetype = null; - - private String classId = null; - - private String archive = null; - - private String altText; - - private EmbeddedServerRpc rpc = new EmbeddedServerRpc() { - @Override - public void click(MouseEventDetails mouseDetails) { - fireEvent(new ClickEvent(Embedded.this, mouseDetails)); - } - }; - - /** - * Creates a new empty Embedded object. - */ - public Embedded() { - registerRpc(rpc); - } - - /** - * Creates a new empty Embedded object with caption. - * - * @param caption - */ - public Embedded(String caption) { - this(); - setCaption(caption); - } - - /** - * Creates a new Embedded object whose contents is loaded from given - * resource. The dimensions are assumed if possible. The type is guessed - * from resource. - * - * @param caption - * @param source - * the Source of the embedded object. - */ - public Embedded(String caption, Resource source) { - this(caption); - setSource(source); - } - - /** - * Invoked when the component state should be painted. - */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - - switch (type) { - case TYPE_IMAGE: - target.addAttribute("type", "image"); - break; - case TYPE_BROWSER: - target.addAttribute("type", "browser"); - break; - default: - break; - } - - if (getSource() != null) { - target.addAttribute("src", getSource()); - } - - if (mimeType != null && !"".equals(mimeType)) { - target.addAttribute("mimetype", mimeType); - } - if (classId != null && !"".equals(classId)) { - target.addAttribute("classid", classId); - } - if (codebase != null && !"".equals(codebase)) { - target.addAttribute("codebase", codebase); - } - if (codetype != null && !"".equals(codetype)) { - target.addAttribute("codetype", codetype); - } - if (standby != null && !"".equals(standby)) { - target.addAttribute("standby", standby); - } - if (archive != null && !"".equals(archive)) { - target.addAttribute("archive", archive); - } - if (altText != null && !"".equals(altText)) { - target.addAttribute(EmbeddedConnector.ALTERNATE_TEXT, altText); - } - - // Params - for (final Iterator<String> i = getParameterNames(); i.hasNext();) { - target.startTag("embeddedparam"); - final String key = i.next(); - target.addAttribute("name", key); - target.addAttribute("value", getParameter(key)); - target.endTag("embeddedparam"); - } - } - - /** - * Sets this component's "alt-text", that is, an alternate text that can be - * presented instead of this component's normal content, for accessibility - * purposes. Does not work when {@link #setType(int)} has been called with - * {@link #TYPE_BROWSER}. - * - * @param altText - * A short, human-readable description of this component's - * content. - * @since 6.8 - */ - public void setAlternateText(String altText) { - if (altText != this.altText - || (altText != null && !altText.equals(this.altText))) { - this.altText = altText; - requestRepaint(); - } - } - - /** - * Gets this component's "alt-text". - * - * @see #setAlternateText(String) - */ - public String getAlternateText() { - return altText; - } - - /** - * Sets an object parameter. Parameters are optional information, and they - * are passed to the instantiated object. Parameters are are stored as name - * value pairs. This overrides the previous value assigned to this - * parameter. - * - * @param name - * the name of the parameter. - * @param value - * the value of the parameter. - */ - public void setParameter(String name, String value) { - parameters.put(name, value); - requestRepaint(); - } - - /** - * Gets the value of an object parameter. Parameters are optional - * information, and they are passed to the instantiated object. Parameters - * are are stored as name value pairs. - * - * @return the Value of parameter or null if not found. - */ - public String getParameter(String name) { - return parameters.get(name); - } - - /** - * Removes an object parameter from the list. - * - * @param name - * the name of the parameter to remove. - */ - public void removeParameter(String name) { - parameters.remove(name); - requestRepaint(); - } - - /** - * Gets the embedded object parameter names. - * - * @return the Iterator of parameters names. - */ - public Iterator<String> getParameterNames() { - return parameters.keySet().iterator(); - } - - /** - * This attribute specifies the base path used to resolve relative URIs - * specified by the classid, data, and archive attributes. When absent, its - * default value is the base URI of the current document. - * - * @return the code base. - */ - public String getCodebase() { - return codebase; - } - - /** - * Gets the MIME-Type of the code. - * - * @return the MIME-Type of the code. - */ - public String getCodetype() { - return codetype; - } - - /** - * Gets the MIME-Type of the object. - * - * @return the MIME-Type of the object. - */ - public String getMimeType() { - return mimeType; - } - - /** - * This attribute specifies a message that a user agent may render while - * loading the object's implementation and data. - * - * @return The text displayed when loading - */ - public String getStandby() { - return standby; - } - - /** - * This attribute specifies the base path used to resolve relative URIs - * specified by the classid, data, and archive attributes. When absent, its - * default value is the base URI of the current document. - * - * @param codebase - * The base path - */ - public void setCodebase(String codebase) { - if (codebase != this.codebase - || (codebase != null && !codebase.equals(this.codebase))) { - this.codebase = codebase; - requestRepaint(); - } - } - - /** - * This attribute specifies the content type of data expected when - * downloading the object specified by classid. This attribute is optional - * but recommended when classid is specified since it allows the user agent - * to avoid loading information for unsupported content types. When absent, - * it defaults to the value of the type attribute. - * - * @param codetype - * the codetype to set. - */ - public void setCodetype(String codetype) { - if (codetype != this.codetype - || (codetype != null && !codetype.equals(this.codetype))) { - this.codetype = codetype; - requestRepaint(); - } - } - - /** - * Sets the mimeType, the MIME-Type of the object. - * - * @param mimeType - * the mimeType to set. - */ - public void setMimeType(String mimeType) { - if (mimeType != this.mimeType - || (mimeType != null && !mimeType.equals(this.mimeType))) { - this.mimeType = mimeType; - if ("application/x-shockwave-flash".equals(mimeType)) { - /* - * Automatically add wmode transparent as we use lots of - * floating layers in Vaadin. If developers need better flash - * performance, they can override this value programmatically - * back to "window" (the defautl). - */ - if (getParameter("wmode") == null) { - setParameter("wmode", "transparent"); - } - } - requestRepaint(); - } - } - - /** - * This attribute specifies a message that a user agent may render while - * loading the object's implementation and data. - * - * @param standby - * The text to display while loading - */ - public void setStandby(String standby) { - if (standby != this.standby - || (standby != null && !standby.equals(this.standby))) { - this.standby = standby; - requestRepaint(); - } - } - - /** - * This attribute may be used to specify the location of an object's - * implementation via a URI. - * - * @return the classid. - */ - public String getClassId() { - return classId; - } - - /** - * This attribute may be used to specify the location of an object's - * implementation via a URI. - * - * @param classId - * the classId to set. - */ - public void setClassId(String classId) { - if (classId != this.classId - || (classId != null && !classId.equals(this.classId))) { - this.classId = classId; - requestRepaint(); - } - } - - /** - * Gets the resource contained in the embedded object. - * - * @return the Resource - */ - public Resource getSource() { - return source; - } - - /** - * Gets the type of the embedded object. - * <p> - * This can be one of the following: - * <ul> - * <li>TYPE_OBJECT <i>(This is the default)</i> - * <li>TYPE_IMAGE - * </ul> - * </p> - * - * @return the type. - */ - public int getType() { - return type; - } - - /** - * Sets the object source resource. The dimensions are assumed if possible. - * The type is guessed from resource. - * - * @param source - * the source to set. - */ - public void setSource(Resource source) { - if (source != null && !source.equals(this.source)) { - this.source = source; - final String mt = source.getMIMEType(); - - if (mimeType == null) { - mimeType = mt; - } - - if (mt.equals("image/svg+xml")) { - type = TYPE_OBJECT; - } else if ((mt.substring(0, mt.indexOf("/")) - .equalsIgnoreCase("image"))) { - type = TYPE_IMAGE; - } else { - // Keep previous type - } - requestRepaint(); - } - } - - /** - * Sets the object type. - * <p> - * This can be one of the following: - * <ul> - * <li>TYPE_OBJECT <i>(This is the default)</i> - * <li>TYPE_IMAGE - * <li>TYPE_BROWSER - * </ul> - * </p> - * - * @param type - * the type to set. - */ - public void setType(int type) { - if (type != TYPE_OBJECT && type != TYPE_IMAGE && type != TYPE_BROWSER) { - throw new IllegalArgumentException("Unsupported type"); - } - if (type != this.type) { - this.type = type; - requestRepaint(); - } - } - - /** - * This attribute may be used to specify a space-separated list of URIs for - * archives containing resources relevant to the object, which may include - * the resources specified by the classid and data attributes. Preloading - * archives will generally result in reduced load times for objects. - * Archives specified as relative URIs should be interpreted relative to the - * codebase attribute. - * - * @return Space-separated list of URIs with resources relevant to the - * object - */ - public String getArchive() { - return archive; - } - - /** - * This attribute may be used to specify a space-separated list of URIs for - * archives containing resources relevant to the object, which may include - * the resources specified by the classid and data attributes. Preloading - * archives will generally result in reduced load times for objects. - * Archives specified as relative URIs should be interpreted relative to the - * codebase attribute. - * - * @param archive - * Space-separated list of URIs with resources relevant to the - * object - */ - public void setArchive(String archive) { - if (archive != this.archive - || (archive != null && !archive.equals(this.archive))) { - this.archive = archive; - requestRepaint(); - } - } - - /** - * Add a click listener to the component. The listener is called whenever - * the user clicks inside the component. Depending on the content the event - * may be blocked and in that case no event is fired. - * - * Use {@link #removeListener(ClickListener)} to remove the listener. - * - * @param listener - * The listener to add - */ - public void addListener(ClickListener listener) { - addListener(ClickEventHandler.CLICK_EVENT_IDENTIFIER, ClickEvent.class, - listener, ClickListener.clickMethod); - } - - /** - * Remove a click listener from the component. The listener should earlier - * have been added using {@link #addListener(ClickListener)}. - * - * @param listener - * The listener to remove - */ - public void removeListener(ClickListener listener) { - removeListener(ClickEventHandler.CLICK_EVENT_IDENTIFIER, - ClickEvent.class, listener); - } - - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - // TODO Remove once Vaadin6Component is no longer implemented - } - -} diff --git a/src/com/vaadin/ui/Field.java b/src/com/vaadin/ui/Field.java deleted file mode 100644 index 6dc40d192f..0000000000 --- a/src/com/vaadin/ui/Field.java +++ /dev/null @@ -1,97 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import com.vaadin.data.BufferedValidatable; -import com.vaadin.data.Property; -import com.vaadin.ui.Component.Focusable; - -/** - * TODO document - * - * @author Vaadin Ltd. - * - * @param T - * the type of values in the field, which might not be the same type - * as that of the data source if converters are used - * - * @author IT Mill Ltd. - */ -public interface Field<T> extends Component, BufferedValidatable, Property<T>, - Property.ValueChangeNotifier, Property.ValueChangeListener, - Property.Editor, Focusable { - - /** - * Is this field required. - * - * Required fields must filled by the user. - * - * @return <code>true</code> if the field is required,otherwise - * <code>false</code>. - * @since 3.1 - */ - public boolean isRequired(); - - /** - * Sets the field required. Required fields must filled by the user. - * - * @param required - * Is the field required. - * @since 3.1 - */ - public void setRequired(boolean required); - - /** - * Sets the error message to be displayed if a required field is empty. - * - * @param requiredMessage - * Error message. - * @since 5.2.6 - */ - public void setRequiredError(String requiredMessage); - - /** - * Gets the error message that is to be displayed if a required field is - * empty. - * - * @return Error message. - * @since 5.2.6 - */ - public String getRequiredError(); - - /** - * An <code>Event</code> object specifying the Field whose value has been - * changed. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - @SuppressWarnings("serial") - public static class ValueChangeEvent extends Component.Event implements - Property.ValueChangeEvent { - - /** - * Constructs a new event object with the specified source field object. - * - * @param source - * the field that caused the event. - */ - public ValueChangeEvent(Field source) { - super(source); - } - - /** - * Gets the Property which triggered the event. - * - * @return the Source Property of the event. - */ - @Override - public Property getProperty() { - return (Property) getSource(); - } - } -} diff --git a/src/com/vaadin/ui/Form.java b/src/com/vaadin/ui/Form.java deleted file mode 100644 index fbc4d5a8e6..0000000000 --- a/src/com/vaadin/ui/Form.java +++ /dev/null @@ -1,1420 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.Map; - -import com.vaadin.data.Buffered; -import com.vaadin.data.Item; -import com.vaadin.data.Property; -import com.vaadin.data.Validatable; -import com.vaadin.data.Validator; -import com.vaadin.data.Validator.InvalidValueException; -import com.vaadin.data.fieldgroup.FieldGroup; -import com.vaadin.data.util.BeanItem; -import com.vaadin.event.Action; -import com.vaadin.event.Action.Handler; -import com.vaadin.event.Action.ShortcutNotifier; -import com.vaadin.event.ActionManager; -import com.vaadin.shared.ui.form.FormState; -import com.vaadin.terminal.AbstractErrorMessage; -import com.vaadin.terminal.CompositeErrorMessage; -import com.vaadin.terminal.ErrorMessage; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.UserError; -import com.vaadin.terminal.Vaadin6Component; - -/** - * Form component provides easy way of creating and managing sets fields. - * - * <p> - * <code>Form</code> is a container for fields implementing {@link Field} - * interface. It provides support for any layouts and provides buffering - * interface for easy connection of commit and discard buttons. All the form - * fields can be customized by adding validators, setting captions and icons, - * setting immediateness, etc. Also direct mechanism for replacing existing - * fields with selections is given. - * </p> - * - * <p> - * <code>Form</code> provides customizable editor for classes implementing - * {@link com.vaadin.data.Item} interface. Also the form itself implements this - * interface for easier connectivity to other items. To use the form as editor - * for an item, just connect the item to form with - * {@link Form#setItemDataSource(Item)}. If only a part of the item needs to be - * edited, {@link Form#setItemDataSource(Item,Collection)} can be used instead. - * After the item has been connected to the form, the automatically created - * fields can be customized and new fields can be added. If you need to connect - * a class that does not implement {@link com.vaadin.data.Item} interface, most - * properties of any class following bean pattern, can be accessed trough - * {@link com.vaadin.data.util.BeanItem}. - * </p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - * @deprecated Use {@link FieldGroup} instead of {@link Form} for more - * flexibility. - */ -@Deprecated -public class Form extends AbstractField<Object> implements Item.Editor, - Buffered, Item, Validatable, Action.Notifier, HasComponents, - Vaadin6Component { - - private Object propertyValue; - - /** - * Item connected to this form as datasource. - */ - private Item itemDatasource; - - /** - * Ordered list of property ids in this editor. - */ - private final LinkedList<Object> propertyIds = new LinkedList<Object>(); - - /** - * Current buffered source exception. - */ - private Buffered.SourceException currentBufferedSourceException = null; - - /** - * Is the form in write trough mode. - */ - private boolean writeThrough = true; - - /** - * Is the form in read trough mode. - */ - private boolean readThrough = true; - - /** - * Mapping from propertyName to corresponding field. - */ - private final HashMap<Object, Field<?>> fields = new HashMap<Object, Field<?>>(); - - /** - * Form may act as an Item, its own properties are stored here. - */ - private final HashMap<Object, Property<?>> ownProperties = new HashMap<Object, Property<?>>(); - - /** - * Field factory for this form. - */ - private FormFieldFactory fieldFactory; - - /** - * Visible item properties. - */ - private Collection<?> visibleItemProperties; - - /** - * Form needs to repaint itself if child fields value changes due possible - * change in form validity. - * - * TODO introduce ValidityChangeEvent (#6239) and start using it instead. - * See e.g. DateField#notifyFormOfValidityChange(). - */ - private final ValueChangeListener fieldValueChangeListener = new ValueChangeListener() { - @Override - public void valueChange(com.vaadin.data.Property.ValueChangeEvent event) { - requestRepaint(); - } - }; - - /** - * If this is true, commit implicitly calls setValidationVisible(true). - */ - private boolean validationVisibleOnCommit = true; - - // special handling for gridlayout; remember initial cursor pos - private int gridlayoutCursorX = -1; - private int gridlayoutCursorY = -1; - - /** - * Keeps track of the Actions added to this component, and manages the - * painting and handling as well. Note that the extended AbstractField is a - * {@link ShortcutNotifier} and has a actionManager that delegates actions - * to the containing window. This one does not delegate. - */ - private ActionManager ownActionManager = new ActionManager(this); - - /** - * Constructs a new form with default layout. - * - * <p> - * By default the form uses {@link FormLayout}. - * </p> - */ - public Form() { - this(null); - setValidationVisible(false); - } - - /** - * Constructs a new form with given {@link Layout}. - * - * @param formLayout - * the layout of the form. - */ - public Form(Layout formLayout) { - this(formLayout, DefaultFieldFactory.get()); - } - - /** - * Constructs a new form with given {@link Layout} and - * {@link FormFieldFactory}. - * - * @param formLayout - * the layout of the form. - * @param fieldFactory - * the FieldFactory of the form. - */ - public Form(Layout formLayout, FormFieldFactory fieldFactory) { - super(); - setLayout(formLayout); - setFooter(null); - setFormFieldFactory(fieldFactory); - setValidationVisible(false); - setWidth(100, UNITS_PERCENTAGE); - } - - @Override - public FormState getState() { - return (FormState) super.getState(); - } - - /* Documented in interface */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - if (ownActionManager != null) { - ownActionManager.paintActions(null, target); - } - } - - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - // Actions - if (ownActionManager != null) { - ownActionManager.handleActions(variables, this); - } - } - - /** - * The error message of a Form is the error of the first field with a - * non-empty error. - * - * Empty error messages of the contained fields are skipped, because an - * empty error indicator would be confusing to the user, especially if there - * are errors that have something to display. This is also the reason why - * the calculation of the error message is separate from validation, because - * validation fails also on empty errors. - */ - @Override - public ErrorMessage getErrorMessage() { - - // Reimplement the checking of validation error by using - // getErrorMessage() recursively instead of validate(). - ErrorMessage validationError = null; - if (isValidationVisible()) { - for (final Iterator<Object> i = propertyIds.iterator(); i.hasNext();) { - Object f = fields.get(i.next()); - if (f instanceof AbstractComponent) { - AbstractComponent field = (AbstractComponent) f; - - validationError = field.getErrorMessage(); - if (validationError != null) { - // Show caption as error for fields with empty errors - if ("".equals(validationError.toString())) { - validationError = new UserError(field.getCaption()); - } - break; - } else if (f instanceof Field && !((Field<?>) f).isValid()) { - // Something is wrong with the field, but no proper - // error is given. Generate one. - validationError = new UserError(field.getCaption()); - break; - } - } - } - } - - // Return if there are no errors at all - if (getComponentError() == null && validationError == null - && currentBufferedSourceException == null) { - return null; - } - - // Throw combination of the error types - return new CompositeErrorMessage( - new ErrorMessage[] { - getComponentError(), - validationError, - AbstractErrorMessage - .getErrorMessageForException(currentBufferedSourceException) }); - } - - /** - * Controls the making validation visible implicitly on commit. - * - * Having commit() call setValidationVisible(true) implicitly is the default - * behaviour. You can disable the implicit setting by setting this property - * as false. - * - * It is useful, because you usually want to start with the form free of - * errors and only display them after the user clicks Ok. You can disable - * the implicit setting by setting this property as false. - * - * @param makeVisible - * If true (default), validation is made visible when commit() is - * called. If false, the visibility is left as it is. - */ - public void setValidationVisibleOnCommit(boolean makeVisible) { - validationVisibleOnCommit = makeVisible; - } - - /** - * Is validation made automatically visible on commit? - * - * See setValidationVisibleOnCommit(). - * - * @return true if validation is made automatically visible on commit. - */ - public boolean isValidationVisibleOnCommit() { - return validationVisibleOnCommit; - } - - /* - * Commit changes to the data source Don't add a JavaDoc comment here, we - * use the default one from the interface. - */ - @Override - public void commit() throws Buffered.SourceException, InvalidValueException { - - LinkedList<SourceException> problems = null; - - // Only commit on valid state if so requested - if (!isInvalidCommitted() && !isValid()) { - /* - * The values are not ok and we are told not to commit invalid - * values - */ - if (validationVisibleOnCommit) { - setValidationVisible(true); - } - - // Find the first invalid value and throw the exception - validate(); - } - - // Try to commit all - for (final Iterator<Object> i = propertyIds.iterator(); i.hasNext();) { - try { - final Field<?> f = (fields.get(i.next())); - // Commit only non-readonly fields. - if (!f.isReadOnly()) { - f.commit(); - } - } catch (final Buffered.SourceException e) { - if (problems == null) { - problems = new LinkedList<SourceException>(); - } - problems.add(e); - } - } - - // No problems occurred - if (problems == null) { - if (currentBufferedSourceException != null) { - currentBufferedSourceException = null; - requestRepaint(); - } - return; - } - - // Commit problems - final Throwable[] causes = new Throwable[problems.size()]; - int index = 0; - for (final Iterator<SourceException> i = problems.iterator(); i - .hasNext();) { - causes[index++] = i.next(); - } - final Buffered.SourceException e = new Buffered.SourceException(this, - causes); - currentBufferedSourceException = e; - requestRepaint(); - throw e; - } - - /* - * Discards local changes and refresh values from the data source Don't add - * a JavaDoc comment here, we use the default one from the interface. - */ - @Override - public void discard() throws Buffered.SourceException { - - LinkedList<SourceException> problems = null; - - // Try to discard all changes - for (final Iterator<Object> i = propertyIds.iterator(); i.hasNext();) { - try { - (fields.get(i.next())).discard(); - } catch (final Buffered.SourceException e) { - if (problems == null) { - problems = new LinkedList<SourceException>(); - } - problems.add(e); - } - } - - // No problems occurred - if (problems == null) { - if (currentBufferedSourceException != null) { - currentBufferedSourceException = null; - requestRepaint(); - } - return; - } - - // Discards problems occurred - final Throwable[] causes = new Throwable[problems.size()]; - int index = 0; - for (final Iterator<SourceException> i = problems.iterator(); i - .hasNext();) { - causes[index++] = i.next(); - } - final Buffered.SourceException e = new Buffered.SourceException(this, - causes); - currentBufferedSourceException = e; - requestRepaint(); - throw e; - } - - /* - * Is the object modified but not committed? Don't add a JavaDoc comment - * here, we use the default one from the interface. - */ - @Override - public boolean isModified() { - for (final Iterator<Object> i = propertyIds.iterator(); i.hasNext();) { - final Field<?> f = fields.get(i.next()); - if (f != null && f.isModified()) { - return true; - } - - } - return false; - } - - /* - * Is the editor in a read-through mode? Don't add a JavaDoc comment here, - * we use the default one from the interface. - */ - @Override - @Deprecated - public boolean isReadThrough() { - return readThrough; - } - - /* - * Is the editor in a write-through mode? Don't add a JavaDoc comment here, - * we use the default one from the interface. - */ - @Override - @Deprecated - public boolean isWriteThrough() { - return writeThrough; - } - - /* - * Sets the editor's read-through mode to the specified status. Don't add a - * JavaDoc comment here, we use the default one from the interface. - */ - @Override - public void setReadThrough(boolean readThrough) { - if (readThrough != this.readThrough) { - this.readThrough = readThrough; - for (final Iterator<Object> i = propertyIds.iterator(); i.hasNext();) { - (fields.get(i.next())).setReadThrough(readThrough); - } - } - } - - /* - * Sets the editor's read-through mode to the specified status. Don't add a - * JavaDoc comment here, we use the default one from the interface. - */ - @Override - public void setWriteThrough(boolean writeThrough) throws SourceException, - InvalidValueException { - if (writeThrough != this.writeThrough) { - this.writeThrough = writeThrough; - for (final Iterator<Object> i = propertyIds.iterator(); i.hasNext();) { - (fields.get(i.next())).setWriteThrough(writeThrough); - } - } - } - - /** - * Adds a new property to form and create corresponding field. - * - * @see com.vaadin.data.Item#addItemProperty(Object, Property) - */ - @Override - public boolean addItemProperty(Object id, Property property) { - - // Checks inputs - if (id == null || property == null) { - throw new NullPointerException("Id and property must be non-null"); - } - - // Checks that the property id is not reserved - if (propertyIds.contains(id)) { - return false; - } - - propertyIds.add(id); - ownProperties.put(id, property); - - // Gets suitable field - final Field<?> field = fieldFactory.createField(this, id, this); - if (field == null) { - return false; - } - - // Configures the field - bindPropertyToField(id, property, field); - - // Register and attach the created field - addField(id, field); - - return true; - } - - /** - * Registers the field with the form and adds the field to the form layout. - * - * <p> - * The property id must not be already used in the form. - * </p> - * - * <p> - * This field is added to the layout using the - * {@link #attachField(Object, Field)} method. - * </p> - * - * @param propertyId - * the Property id the the field. - * @param field - * the field which should be added to the form. - */ - public void addField(Object propertyId, Field<?> field) { - registerField(propertyId, field); - attachField(propertyId, field); - requestRepaint(); - } - - /** - * Register the field with the form. All registered fields are validated - * when the form is validated and also committed when the form is committed. - * - * <p> - * The property id must not be already used in the form. - * </p> - * - * - * @param propertyId - * the Property id of the field. - * @param field - * the Field that should be registered - */ - private void registerField(Object propertyId, Field<?> field) { - if (propertyId == null || field == null) { - return; - } - - fields.put(propertyId, field); - field.addListener(fieldValueChangeListener); - if (!propertyIds.contains(propertyId)) { - // adding a field directly - propertyIds.addLast(propertyId); - } - - // Update the read and write through status and immediate to match the - // form. - // Should this also include invalidCommitted (#3993)? - field.setReadThrough(readThrough); - field.setWriteThrough(writeThrough); - if (isImmediate() && field instanceof AbstractComponent) { - ((AbstractComponent) field).setImmediate(true); - } - } - - /** - * Adds the field to the form layout. - * <p> - * The field is added to the form layout in the default position (the - * position used by {@link Layout#addComponent(Component)}. If the - * underlying layout is a {@link CustomLayout} the field is added to the - * CustomLayout location given by the string representation of the property - * id using {@link CustomLayout#addComponent(Component, String)}. - * </p> - * - * <p> - * Override this method to control how the fields are added to the layout. - * </p> - * - * @param propertyId - * @param field - */ - protected void attachField(Object propertyId, Field field) { - if (propertyId == null || field == null) { - return; - } - - Layout layout = getLayout(); - if (layout instanceof CustomLayout) { - ((CustomLayout) layout).addComponent(field, propertyId.toString()); - } else { - layout.addComponent(field); - } - - } - - /** - * The property identified by the property id. - * - * <p> - * The property data source of the field specified with property id is - * returned. If there is a (with specified property id) having no data - * source, the field is returned instead of the data source. - * </p> - * - * @see com.vaadin.data.Item#getItemProperty(Object) - */ - @Override - public Property<?> getItemProperty(Object id) { - final Field<?> field = fields.get(id); - if (field == null) { - // field does not exist or it is not (yet) created for this property - return ownProperties.get(id); - } - final Property<?> property = field.getPropertyDataSource(); - - if (property != null) { - return property; - } else { - return field; - } - } - - /** - * Gets the field identified by the propertyid. - * - * @param propertyId - * the id of the property. - */ - public Field<?> getField(Object propertyId) { - return fields.get(propertyId); - } - - /* Documented in interface */ - @Override - public Collection<?> getItemPropertyIds() { - return Collections.unmodifiableCollection(propertyIds); - } - - /** - * Removes the property and corresponding field from the form. - * - * @see com.vaadin.data.Item#removeItemProperty(Object) - */ - @Override - public boolean removeItemProperty(Object id) { - ownProperties.remove(id); - - final Field<?> field = fields.get(id); - - if (field != null) { - propertyIds.remove(id); - fields.remove(id); - detachField(field); - field.removeListener(fieldValueChangeListener); - return true; - } - - return false; - } - - /** - * Called when a form field is detached from a Form. Typically when a new - * Item is assigned to Form via {@link #setItemDataSource(Item)}. - * <p> - * Override this method to control how the fields are removed from the - * layout. - * </p> - * - * @param field - * the field to be detached from the forms layout. - */ - protected void detachField(final Field field) { - Component p = field.getParent(); - if (p instanceof ComponentContainer) { - ((ComponentContainer) p).removeComponent(field); - } - } - - /** - * Removes all properties and fields from the form. - * - * @return the Success of the operation. Removal of all fields succeeded if - * (and only if) the return value is <code>true</code>. - */ - public boolean removeAllProperties() { - final Object[] properties = propertyIds.toArray(); - boolean success = true; - - for (int i = 0; i < properties.length; i++) { - if (!removeItemProperty(properties[i])) { - success = false; - } - } - - return success; - } - - /* Documented in the interface */ - @Override - public Item getItemDataSource() { - return itemDatasource; - } - - /** - * Sets the item datasource for the form. - * - * <p> - * Setting item datasource clears any fields, the form might contain and - * adds all the properties as fields to the form. - * </p> - * - * @see com.vaadin.data.Item.Viewer#setItemDataSource(Item) - */ - @Override - public void setItemDataSource(Item newDataSource) { - setItemDataSource(newDataSource, - newDataSource != null ? newDataSource.getItemPropertyIds() - : null); - } - - /** - * Set the item datasource for the form, but limit the form contents to - * specified properties of the item. - * - * <p> - * Setting item datasource clears any fields, the form might contain and - * adds the specified the properties as fields to the form, in the specified - * order. - * </p> - * - * @see com.vaadin.data.Item.Viewer#setItemDataSource(Item) - */ - public void setItemDataSource(Item newDataSource, Collection<?> propertyIds) { - - if (getLayout() instanceof GridLayout) { - GridLayout gl = (GridLayout) getLayout(); - if (gridlayoutCursorX == -1) { - // first setItemDataSource, remember initial cursor - gridlayoutCursorX = gl.getCursorX(); - gridlayoutCursorY = gl.getCursorY(); - } else { - // restore initial cursor - gl.setCursorX(gridlayoutCursorX); - gl.setCursorY(gridlayoutCursorY); - } - } - - // Removes all fields first from the form - removeAllProperties(); - - // Sets the datasource - itemDatasource = newDataSource; - - // If the new datasource is null, just set null datasource - if (itemDatasource == null) { - requestRepaint(); - return; - } - - // Adds all the properties to this form - for (final Iterator<?> i = propertyIds.iterator(); i.hasNext();) { - final Object id = i.next(); - final Property<?> property = itemDatasource.getItemProperty(id); - if (id != null && property != null) { - final Field<?> f = fieldFactory.createField(itemDatasource, id, - this); - if (f != null) { - bindPropertyToField(id, property, f); - addField(id, f); - } - } - } - } - - /** - * Binds an item property to a field. The default behavior is to bind - * property straight to Field. If Property.Viewer type property (e.g. - * PropertyFormatter) is already set for field, the property is bound to - * that Property.Viewer. - * - * @param propertyId - * @param property - * @param field - * @since 6.7.3 - */ - protected void bindPropertyToField(final Object propertyId, - final Property property, final Field field) { - // check if field has a property that is Viewer set. In that case we - // expect developer has e.g. PropertyFormatter that he wishes to use and - // assign the property to the Viewer instead. - boolean hasFilterProperty = field.getPropertyDataSource() != null - && (field.getPropertyDataSource() instanceof Property.Viewer); - if (hasFilterProperty) { - ((Property.Viewer) field.getPropertyDataSource()) - .setPropertyDataSource(property); - } else { - field.setPropertyDataSource(property); - } - } - - /** - * Gets the layout of the form. - * - * <p> - * By default form uses <code>OrderedLayout</code> with <code>form</code> - * -style. - * </p> - * - * @return the Layout of the form. - */ - public Layout getLayout() { - return (Layout) getState().getLayout(); - } - - /** - * Sets the layout of the form. - * - * <p> - * If set to null then Form uses a FormLayout by default. - * </p> - * - * @param layout - * the layout of the form. - */ - public void setLayout(Layout layout) { - - // Use orderedlayout by default - if (layout == null) { - layout = new FormLayout(); - } - - // reset cursor memory - gridlayoutCursorX = -1; - gridlayoutCursorY = -1; - - // Move fields from previous layout - if (getLayout() != null) { - final Object[] properties = propertyIds.toArray(); - for (int i = 0; i < properties.length; i++) { - Field<?> f = getField(properties[i]); - detachField(f); - if (layout instanceof CustomLayout) { - ((CustomLayout) layout).addComponent(f, - properties[i].toString()); - } else { - layout.addComponent(f); - } - } - - getLayout().setParent(null); - } - - // Replace the previous layout - layout.setParent(this); - getState().setLayout(layout); - - // Hierarchy has changed so we need to repaint (this could be a - // hierarchy repaint only) - requestRepaint(); - } - - /** - * Sets the form field to be selectable from static list of changes. - * - * <p> - * The list values and descriptions are given as array. The value-array must - * contain the current value of the field and the lengths of the arrays must - * match. Null values are not supported. - * </p> - * - * Note: since Vaadin 7.0, returns an {@link AbstractSelect} instead of a - * {@link Select}. - * - * @param propertyId - * the id of the property. - * @param values - * @param descriptions - * @return the select property generated - */ - public AbstractSelect replaceWithSelect(Object propertyId, Object[] values, - Object[] descriptions) { - - // Checks the parameters - if (propertyId == null || values == null || descriptions == null) { - throw new NullPointerException("All parameters must be non-null"); - } - if (values.length != descriptions.length) { - throw new IllegalArgumentException( - "Value and description list are of different size"); - } - - // Gets the old field - final Field<?> oldField = fields.get(propertyId); - if (oldField == null) { - throw new IllegalArgumentException("Field with given propertyid '" - + propertyId.toString() + "' can not be found."); - } - final Object value = oldField.getPropertyDataSource() == null ? oldField - .getValue() : oldField.getPropertyDataSource().getValue(); - - // Checks that the value exists and check if the select should - // be forced in multiselect mode - boolean found = false; - boolean isMultiselect = false; - for (int i = 0; i < values.length && !found; i++) { - if (values[i] == value - || (value != null && value.equals(values[i]))) { - found = true; - } - } - if (value != null && !found) { - if (value instanceof Collection) { - for (final Iterator<?> it = ((Collection<?>) value).iterator(); it - .hasNext();) { - final Object val = it.next(); - found = false; - for (int i = 0; i < values.length && !found; i++) { - if (values[i] == val - || (val != null && val.equals(values[i]))) { - found = true; - } - } - if (!found) { - throw new IllegalArgumentException( - "Currently selected value '" + val - + "' of property '" - + propertyId.toString() - + "' was not found"); - } - } - isMultiselect = true; - } else { - throw new IllegalArgumentException("Current value '" + value - + "' of property '" + propertyId.toString() - + "' was not found"); - } - } - - // Creates the new field matching to old field parameters - final AbstractSelect newField = isMultiselect ? new ListSelect() - : new Select(); - newField.setCaption(oldField.getCaption()); - newField.setReadOnly(oldField.isReadOnly()); - newField.setReadThrough(oldField.isReadThrough()); - newField.setWriteThrough(oldField.isWriteThrough()); - - // Creates the options list - newField.addContainerProperty("desc", String.class, ""); - newField.setItemCaptionPropertyId("desc"); - for (int i = 0; i < values.length; i++) { - Object id = values[i]; - final Item item; - if (id == null) { - id = newField.addItem(); - item = newField.getItem(id); - newField.setNullSelectionItemId(id); - } else { - item = newField.addItem(id); - } - - if (item != null) { - item.getItemProperty("desc").setValue( - descriptions[i].toString()); - } - } - - // Sets the property data source - final Property<?> property = oldField.getPropertyDataSource(); - oldField.setPropertyDataSource(null); - newField.setPropertyDataSource(property); - - // Replaces the old field with new one - getLayout().replaceComponent(oldField, newField); - fields.put(propertyId, newField); - newField.addListener(fieldValueChangeListener); - oldField.removeListener(fieldValueChangeListener); - - return newField; - } - - /** - * Checks the validity of the Form and all of its fields. - * - * @see com.vaadin.data.Validatable#validate() - */ - @Override - public void validate() throws InvalidValueException { - super.validate(); - for (final Iterator<Object> i = propertyIds.iterator(); i.hasNext();) { - (fields.get(i.next())).validate(); - } - } - - /** - * Checks the validabtable object accept invalid values. - * - * @see com.vaadin.data.Validatable#isInvalidAllowed() - */ - @Override - public boolean isInvalidAllowed() { - return true; - } - - /** - * Should the validabtable object accept invalid values. - * - * @see com.vaadin.data.Validatable#setInvalidAllowed(boolean) - */ - @Override - public void setInvalidAllowed(boolean invalidValueAllowed) - throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - } - - /** - * Sets the component's to read-only mode to the specified state. - * - * @see com.vaadin.ui.Component#setReadOnly(boolean) - */ - @Override - public void setReadOnly(boolean readOnly) { - super.setReadOnly(readOnly); - for (final Iterator<?> i = propertyIds.iterator(); i.hasNext();) { - (fields.get(i.next())).setReadOnly(readOnly); - } - } - - /** - * Sets the field factory used by this Form to genarate Fields for - * properties. - * - * {@link FormFieldFactory} is used to create fields for form properties. - * {@link DefaultFieldFactory} is used by default. - * - * @param fieldFactory - * the new factory used to create the fields. - * @see Field - * @see FormFieldFactory - */ - public void setFormFieldFactory(FormFieldFactory fieldFactory) { - this.fieldFactory = fieldFactory; - } - - /** - * Get the field factory of the form. - * - * @return the FormFieldFactory Factory used to create the fields. - */ - public FormFieldFactory getFormFieldFactory() { - return fieldFactory; - } - - /** - * Gets the field type. - * - * @see com.vaadin.ui.AbstractField#getType() - */ - @Override - public Class<?> getType() { - if (getPropertyDataSource() != null) { - return getPropertyDataSource().getType(); - } - return Object.class; - } - - /** - * Sets the internal value. - * - * This is relevant when the Form is used as Field. - * - * @see com.vaadin.ui.AbstractField#setInternalValue(java.lang.Object) - */ - @Override - protected void setInternalValue(Object newValue) { - // Stores the old value - final Object oldValue = propertyValue; - - // Sets the current Value - super.setInternalValue(newValue); - propertyValue = newValue; - - // Ignores form updating if data object has not changed. - if (oldValue != newValue) { - setFormDataSource(newValue, getVisibleItemProperties()); - } - } - - /** - * Gets the first focusable field in form. If there are enabled, - * non-read-only fields, the first one of them is returned. Otherwise, the - * field for the first property (or null if none) is returned. - * - * @return the Field. - */ - private Field<?> getFirstFocusableField() { - if (getItemPropertyIds() != null) { - for (Object id : getItemPropertyIds()) { - if (id != null) { - Field<?> field = getField(id); - if (field.isEnabled() && !field.isReadOnly()) { - return field; - } - } - } - // fallback: first field if none of the fields is enabled and - // writable - Object id = getItemPropertyIds().iterator().next(); - if (id != null) { - return getField(id); - } - } - return null; - } - - /** - * Updates the internal form datasource. - * - * Method setFormDataSource. - * - * @param data - * @param properties - */ - protected void setFormDataSource(Object data, Collection<?> properties) { - - // If data is an item use it. - Item item = null; - if (data instanceof Item) { - item = (Item) data; - } else if (data != null) { - item = new BeanItem<Object>(data); - } - - // Sets the datasource to form - if (item != null && properties != null) { - // Shows only given properties - this.setItemDataSource(item, properties); - } else { - // Shows all properties - this.setItemDataSource(item); - } - } - - /** - * Returns the visibleProperties. - * - * @return the Collection of visible Item properites. - */ - public Collection<?> getVisibleItemProperties() { - return visibleItemProperties; - } - - /** - * Sets the visibleProperties. - * - * @param visibleProperties - * the visibleProperties to set. - */ - public void setVisibleItemProperties(Collection<?> visibleProperties) { - visibleItemProperties = visibleProperties; - Object value = getValue(); - if (value == null) { - value = itemDatasource; - } - setFormDataSource(value, getVisibleItemProperties()); - } - - /** - * Sets the visibleProperties. - * - * @param visibleProperties - * the visibleProperties to set. - */ - public void setVisibleItemProperties(Object[] visibleProperties) { - LinkedList<Object> v = new LinkedList<Object>(); - for (int i = 0; i < visibleProperties.length; i++) { - v.add(visibleProperties[i]); - } - setVisibleItemProperties(v); - } - - /** - * Focuses the first field in the form. - * - * @see com.vaadin.ui.Component.Focusable#focus() - */ - @Override - public void focus() { - final Field<?> f = getFirstFocusableField(); - if (f != null) { - f.focus(); - } - } - - /** - * Sets the Tabulator index of this Focusable component. - * - * @see com.vaadin.ui.Component.Focusable#setTabIndex(int) - */ - @Override - public void setTabIndex(int tabIndex) { - super.setTabIndex(tabIndex); - for (final Iterator<?> i = getItemPropertyIds().iterator(); i.hasNext();) { - (getField(i.next())).setTabIndex(tabIndex); - } - } - - /** - * Setting the form to be immediate also sets all the fields of the form to - * the same state. - */ - @Override - public void setImmediate(boolean immediate) { - super.setImmediate(immediate); - for (Iterator<Field<?>> i = fields.values().iterator(); i.hasNext();) { - Field<?> f = i.next(); - if (f instanceof AbstractComponent) { - ((AbstractComponent) f).setImmediate(immediate); - } - } - } - - /** Form is empty if all of its fields are empty. */ - @Override - protected boolean isEmpty() { - - for (Iterator<Field<?>> i = fields.values().iterator(); i.hasNext();) { - Field<?> f = i.next(); - if (f instanceof AbstractField) { - if (!((AbstractField<?>) f).isEmpty()) { - return false; - } - } - } - - return true; - } - - /** - * Adding validators directly to form is not supported. - * - * Add the validators to form fields instead. - */ - @Override - public void addValidator(Validator validator) { - throw new UnsupportedOperationException(); - } - - /** - * Returns a layout that is rendered below normal form contents. This area - * can be used for example to include buttons related to form contents. - * - * @return layout rendered below normal form contents. - */ - public Layout getFooter() { - return (Layout) getState().getFooter(); - } - - /** - * Sets the layout that is rendered below normal form contents. Setting this - * to null will cause an empty HorizontalLayout to be rendered in the - * footer. - * - * @param footer - * the new footer layout - */ - public void setFooter(Layout footer) { - if (getFooter() != null) { - getFooter().setParent(null); - } - if (footer == null) { - footer = new HorizontalLayout(); - } - - getState().setFooter(footer); - footer.setParent(this); - - // Hierarchy has changed so we need to repaint (this could be a - // hierarchy repaint only) - requestRepaint(); - - } - - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - if (getParent() != null && !getParent().isEnabled()) { - // some ancestor still disabled, don't update children - return; - } else { - getLayout().requestRepaintAll(); - } - } - - /* - * ACTIONS - */ - - /** - * Gets the {@link ActionManager} responsible for handling {@link Action}s - * added to this Form.<br/> - * Note that Form has another ActionManager inherited from - * {@link AbstractField}. The ownActionManager handles Actions attached to - * this Form specifically, while the ActionManager in AbstractField - * delegates to the containing Window (i.e global Actions). - * - * @return - */ - protected ActionManager getOwnActionManager() { - if (ownActionManager == null) { - ownActionManager = new ActionManager(this); - } - return ownActionManager; - } - - @Override - public void addActionHandler(Handler actionHandler) { - getOwnActionManager().addActionHandler(actionHandler); - } - - @Override - public void removeActionHandler(Handler actionHandler) { - if (ownActionManager != null) { - ownActionManager.removeActionHandler(actionHandler); - } - } - - /** - * Removes all action handlers - */ - public void removeAllActionHandlers() { - if (ownActionManager != null) { - ownActionManager.removeAllActionHandlers(); - } - } - - @Override - public <T extends Action & com.vaadin.event.Action.Listener> void addAction( - T action) { - getOwnActionManager().addAction(action); - } - - @Override - public <T extends Action & com.vaadin.event.Action.Listener> void removeAction( - T action) { - if (ownActionManager != null) { - ownActionManager.removeAction(action); - } - } - - @Override - public Iterator<Component> iterator() { - return getComponentIterator(); - } - - /** - * Modifiable and Serializable Iterator for the components, used by - * {@link Form#getComponentIterator()}. - */ - private class ComponentIterator implements Iterator<Component>, - Serializable { - - int i = 0; - - @Override - public boolean hasNext() { - if (i < getComponentCount()) { - return true; - } - return false; - } - - @Override - public Component next() { - if (!hasNext()) { - return null; - } - i++; - if (i == 1) { - return getLayout() != null ? getLayout() : getFooter(); - } else if (i == 2) { - return getFooter(); - } - return null; - } - - @Override - public void remove() { - if (i == 1) { - if (getLayout() != null) { - setLayout(null); - i = 0; - } else { - setFooter(null); - } - } else if (i == 2) { - setFooter(null); - } - } - } - - @Override - public Iterator<Component> getComponentIterator() { - return new ComponentIterator(); - } - - public int getComponentCount() { - int count = 0; - if (getLayout() != null) { - count++; - } - if (getFooter() != null) { - count++; - } - - return count; - } - - @Override - public boolean isComponentVisible(Component childComponent) { - return true; - }; -} diff --git a/src/com/vaadin/ui/FormFieldFactory.java b/src/com/vaadin/ui/FormFieldFactory.java deleted file mode 100644 index 1efa05c5f5..0000000000 --- a/src/com/vaadin/ui/FormFieldFactory.java +++ /dev/null @@ -1,41 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import java.io.Serializable; - -import com.vaadin.data.Item; - -/** - * Factory interface for creating new Field-instances based on {@link Item}, - * property id and uiContext (the component responsible for displaying fields). - * Currently this interface is used by {@link Form}, but might later be used by - * some other components for {@link Field} generation. - * - * <p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 6.0 - * @see TableFieldFactory - */ -public interface FormFieldFactory extends Serializable { - /** - * Creates a field based on the item, property id and the component (most - * commonly {@link Form}) where the Field will be presented. - * - * @param item - * the item where the property belongs to. - * @param propertyId - * the Id of the property. - * @param uiContext - * the component where the field is presented, most commonly this - * is {@link Form}. uiContext will not necessary be the parent - * component of the field, but the one that is responsible for - * creating it. - * @return Field the field suitable for editing the specified data. - */ - Field<?> createField(Item item, Object propertyId, Component uiContext); -} diff --git a/src/com/vaadin/ui/FormLayout.java b/src/com/vaadin/ui/FormLayout.java deleted file mode 100644 index c0be784a7b..0000000000 --- a/src/com/vaadin/ui/FormLayout.java +++ /dev/null @@ -1,31 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -/** - * FormLayout is used by {@link Form} to layout fields. It may also be used - * separately without {@link Form}. - * - * FormLayout is a close relative to vertical {@link OrderedLayout}, but in - * FormLayout caption is rendered on left side of component. Required and - * validation indicators are between captions and fields. - * - * FormLayout does not currently support some advanced methods from - * OrderedLayout like setExpandRatio and setComponentAlignment. - * - * FormLayout by default has component spacing on. Also margin top and margin - * bottom are by default on. - * - */ -public class FormLayout extends AbstractOrderedLayout { - - public FormLayout() { - super(); - setSpacing(true); - setMargin(true, false, true, false); - setWidth(100, UNITS_PERCENTAGE); - } - -} diff --git a/src/com/vaadin/ui/GridLayout.java b/src/com/vaadin/ui/GridLayout.java deleted file mode 100644 index 2391a9cd3a..0000000000 --- a/src/com/vaadin/ui/GridLayout.java +++ /dev/null @@ -1,1415 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.Map; -import java.util.Map.Entry; - -import com.vaadin.event.LayoutEvents.LayoutClickEvent; -import com.vaadin.event.LayoutEvents.LayoutClickListener; -import com.vaadin.event.LayoutEvents.LayoutClickNotifier; -import com.vaadin.shared.Connector; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.gridlayout.GridLayoutServerRpc; -import com.vaadin.shared.ui.gridlayout.GridLayoutState; -import com.vaadin.terminal.LegacyPaint; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler; - -/** - * A layout where the components are laid out on a grid using cell coordinates. - * - * <p> - * The GridLayout also maintains a cursor for adding components in - * left-to-right, top-to-bottom order. - * </p> - * - * <p> - * Each component in a <code>GridLayout</code> uses a defined - * {@link GridLayout.Area area} (column1,row1,column2,row2) from the grid. The - * components may not overlap with the existing components - if you try to do so - * you will get an {@link OverlapsException}. Adding a component with cursor - * automatically extends the grid by increasing the grid height. - * </p> - * - * <p> - * The grid coordinates, which are specified by a row and column index, always - * start from 0 for the topmost row and the leftmost column. - * </p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public class GridLayout extends AbstractLayout implements - Layout.AlignmentHandler, Layout.SpacingHandler, LayoutClickNotifier, - Vaadin6Component { - - private GridLayoutServerRpc rpc = new GridLayoutServerRpc() { - - @Override - public void layoutClick(MouseEventDetails mouseDetails, - Connector clickedConnector) { - fireEvent(LayoutClickEvent.createEvent(GridLayout.this, - mouseDetails, clickedConnector)); - - } - }; - /** - * Cursor X position: this is where the next component with unspecified x,y - * is inserted - */ - private int cursorX = 0; - - /** - * Cursor Y position: this is where the next component with unspecified x,y - * is inserted - */ - private int cursorY = 0; - - /** - * Contains all items that are placed on the grid. These are components with - * grid area definition. - */ - private final LinkedList<Area> areas = new LinkedList<Area>(); - - /** - * Mapping from components to their respective areas. - */ - private final LinkedList<Component> components = new LinkedList<Component>(); - - /** - * Mapping from components to alignments (horizontal + vertical). - */ - private Map<Component, Alignment> componentToAlignment = new HashMap<Component, Alignment>(); - - private static final Alignment ALIGNMENT_DEFAULT = Alignment.TOP_LEFT; - - /** - * Has there been rows inserted or deleted in the middle of the layout since - * the last paint operation. - */ - private boolean structuralChange = false; - - private Map<Integer, Float> columnExpandRatio = new HashMap<Integer, Float>(); - private Map<Integer, Float> rowExpandRatio = new HashMap<Integer, Float>(); - - /** - * Constructor for a grid of given size (number of columns and rows). - * - * The grid may grow or shrink later. Grid grows automatically if you add - * components outside its area. - * - * @param columns - * Number of columns in the grid. - * @param rows - * Number of rows in the grid. - */ - public GridLayout(int columns, int rows) { - setColumns(columns); - setRows(rows); - registerRpc(rpc); - } - - /** - * Constructs an empty (1x1) grid layout that is extended as needed. - */ - public GridLayout() { - this(1, 1); - } - - @Override - public GridLayoutState getState() { - return (GridLayoutState) super.getState(); - } - - /** - * <p> - * Adds a component to the grid in the specified area. The area is defined - * by specifying the upper left corner (column1, row1) and the lower right - * corner (column2, row2) of the area. The coordinates are zero-based. - * </p> - * - * <p> - * If the area overlaps with any of the existing components already present - * in the grid, the operation will fail and an {@link OverlapsException} is - * thrown. - * </p> - * - * @param component - * the component to be added. - * @param column1 - * the column of the upper left corner of the area <code>c</code> - * is supposed to occupy. The leftmost column has index 0. - * @param row1 - * the row of the upper left corner of the area <code>c</code> is - * supposed to occupy. The topmost row has index 0. - * @param column2 - * the column of the lower right corner of the area - * <code>c</code> is supposed to occupy. - * @param row2 - * the row of the lower right corner of the area <code>c</code> - * is supposed to occupy. - * @throws OverlapsException - * if the new component overlaps with any of the components - * already in the grid. - * @throws OutOfBoundsException - * if the cells are outside the grid area. - */ - public void addComponent(Component component, int column1, int row1, - int column2, int row2) throws OverlapsException, - OutOfBoundsException { - - if (component == null) { - throw new NullPointerException("Component must not be null"); - } - - // Checks that the component does not already exist in the container - if (components.contains(component)) { - throw new IllegalArgumentException( - "Component is already in the container"); - } - - // Creates the area - final Area area = new Area(component, column1, row1, column2, row2); - - // Checks the validity of the coordinates - if (column2 < column1 || row2 < row1) { - throw new IllegalArgumentException( - "Illegal coordinates for the component"); - } - if (column1 < 0 || row1 < 0 || column2 >= getColumns() - || row2 >= getRows()) { - throw new OutOfBoundsException(area); - } - - // Checks that newItem does not overlap with existing items - checkExistingOverlaps(area); - - // Inserts the component to right place at the list - // Respect top-down, left-right ordering - // component.setParent(this); - final Iterator<Area> i = areas.iterator(); - int index = 0; - boolean done = false; - while (!done && i.hasNext()) { - final Area existingArea = i.next(); - if ((existingArea.row1 >= row1 && existingArea.column1 > column1) - || existingArea.row1 > row1) { - areas.add(index, area); - components.add(index, component); - done = true; - } - index++; - } - if (!done) { - areas.addLast(area); - components.addLast(component); - } - - // Attempt to add to super - try { - super.addComponent(component); - } catch (IllegalArgumentException e) { - areas.remove(area); - components.remove(component); - throw e; - } - - // update cursor position, if it's within this area; use first position - // outside this area, even if it's occupied - if (cursorX >= column1 && cursorX <= column2 && cursorY >= row1 - && cursorY <= row2) { - // cursor within area - cursorX = column2 + 1; // one right of area - if (cursorX >= getColumns()) { - // overflowed columns - cursorX = 0; // first col - // move one row down, or one row under the area - cursorY = (column1 == 0 ? row2 : row1) + 1; - } else { - cursorY = row1; - } - } - - requestRepaint(); - } - - /** - * Tests if the given area overlaps with any of the items already on the - * grid. - * - * @param area - * the Area to be checked for overlapping. - * @throws OverlapsException - * if <code>area</code> overlaps with any existing area. - */ - private void checkExistingOverlaps(Area area) throws OverlapsException { - for (final Iterator<Area> i = areas.iterator(); i.hasNext();) { - final Area existingArea = i.next(); - if (existingArea.overlaps(area)) { - // Component not added, overlaps with existing component - throw new OverlapsException(existingArea); - } - } - } - - /** - * Adds the component to the grid in cells column1,row1 (NortWest corner of - * the area.) End coordinates (SouthEast corner of the area) are the same as - * column1,row1. The coordinates are zero-based. Component width and height - * is 1. - * - * @param component - * the component to be added. - * @param column - * the column index, starting from 0. - * @param row - * the row index, starting from 0. - * @throws OverlapsException - * if the new component overlaps with any of the components - * already in the grid. - * @throws OutOfBoundsException - * if the cell is outside the grid area. - */ - public void addComponent(Component component, int column, int row) - throws OverlapsException, OutOfBoundsException { - this.addComponent(component, column, row, column, row); - } - - /** - * Forces the next component to be added at the beginning of the next line. - * - * <p> - * Sets the cursor column to 0 and increments the cursor row by one. - * </p> - * - * <p> - * By calling this function you can ensure that no more components are added - * right of the previous component. - * </p> - * - * @see #space() - */ - public void newLine() { - cursorX = 0; - cursorY++; - } - - /** - * Moves the cursor forward by one. If the cursor goes out of the right grid - * border, it is moved to the first column of the next row. - * - * @see #newLine() - */ - public void space() { - cursorX++; - if (cursorX >= getColumns()) { - cursorX = 0; - cursorY++; - } - } - - /** - * Adds the component into this container to the cursor position. If the - * cursor position is already occupied, the cursor is moved forwards to find - * free position. If the cursor goes out from the bottom of the grid, the - * grid is automatically extended. - * - * @param component - * the component to be added. - */ - @Override - public void addComponent(Component component) { - - // Finds first available place from the grid - Area area; - boolean done = false; - while (!done) { - try { - area = new Area(component, cursorX, cursorY, cursorX, cursorY); - checkExistingOverlaps(area); - done = true; - } catch (final OverlapsException e) { - space(); - } - } - - // Extends the grid if needed - if (cursorX >= getColumns()) { - setColumns(cursorX + 1); - } - if (cursorY >= getRows()) { - setRows(cursorY + 1); - } - - addComponent(component, cursorX, cursorY); - } - - /** - * Removes the specified component from the layout. - * - * @param component - * the component to be removed. - */ - @Override - public void removeComponent(Component component) { - - // Check that the component is contained in the container - if (component == null || !components.contains(component)) { - return; - } - - Area area = null; - for (final Iterator<Area> i = areas.iterator(); area == null - && i.hasNext();) { - final Area a = i.next(); - if (a.getComponent() == component) { - area = a; - } - } - - components.remove(component); - if (area != null) { - areas.remove(area); - } - - componentToAlignment.remove(component); - - super.removeComponent(component); - - requestRepaint(); - } - - /** - * Removes the component specified by its cell coordinates. - * - * @param column - * the component's column, starting from 0. - * @param row - * the component's row, starting from 0. - */ - public void removeComponent(int column, int row) { - - // Finds the area - for (final Iterator<Area> i = areas.iterator(); i.hasNext();) { - final Area area = i.next(); - if (area.getColumn1() == column && area.getRow1() == row) { - removeComponent(area.getComponent()); - return; - } - } - } - - /** - * Gets an Iterator for the components contained in the layout. By using the - * Iterator it is possible to step through the contents of the layout. - * - * @return the Iterator of the components inside the layout. - */ - @Override - public Iterator<Component> getComponentIterator() { - return Collections.unmodifiableCollection(components).iterator(); - } - - /** - * Gets the number of components contained in the layout. Consistent with - * the iterator returned by {@link #getComponentIterator()}. - * - * @return the number of contained components - */ - @Override - public int getComponentCount() { - return components.size(); - } - - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - // TODO Remove once Vaadin6Component is no longer implemented - } - - /** - * Paints the contents of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - // TODO refactor attribute names in future release. - target.addAttribute("structuralChange", structuralChange); - structuralChange = false; - - // Area iterator - final Iterator<Area> areaiterator = areas.iterator(); - - // Current item to be processed (fetch first item) - Area area = areaiterator.hasNext() ? (Area) areaiterator.next() : null; - - // Collects rowspan related information here - final HashMap<Integer, Integer> cellUsed = new HashMap<Integer, Integer>(); - - // Empty cell collector - int emptyCells = 0; - - final String[] alignmentsArray = new String[components.size()]; - final Integer[] columnExpandRatioArray = new Integer[getColumns()]; - final Integer[] rowExpandRatioArray = new Integer[getRows()]; - - int realColExpandRatioSum = 0; - float colSum = getExpandRatioSum(columnExpandRatio); - if (colSum == 0) { - // no columns has been expanded, all cols have same expand - // rate - float equalSize = 1 / (float) getColumns(); - int myRatio = Math.round(equalSize * 1000); - for (int i = 0; i < getColumns(); i++) { - columnExpandRatioArray[i] = myRatio; - } - realColExpandRatioSum = myRatio * getColumns(); - } else { - for (int i = 0; i < getColumns(); i++) { - int myRatio = Math - .round((getColumnExpandRatio(i) / colSum) * 1000); - columnExpandRatioArray[i] = myRatio; - realColExpandRatioSum += myRatio; - } - } - - boolean equallyDividedRows = false; - int realRowExpandRatioSum = 0; - float rowSum = getExpandRatioSum(rowExpandRatio); - if (rowSum == 0) { - // no rows have been expanded - equallyDividedRows = true; - float equalSize = 1 / (float) getRows(); - int myRatio = Math.round(equalSize * 1000); - for (int i = 0; i < getRows(); i++) { - rowExpandRatioArray[i] = myRatio; - } - realRowExpandRatioSum = myRatio * getRows(); - } - - int index = 0; - - // Iterates every applicable row - for (int cury = 0; cury < getRows(); cury++) { - target.startTag("gr"); - - if (!equallyDividedRows) { - int myRatio = Math - .round((getRowExpandRatio(cury) / rowSum) * 1000); - rowExpandRatioArray[cury] = myRatio; - realRowExpandRatioSum += myRatio; - - } - // Iterates every applicable column - for (int curx = 0; curx < getColumns(); curx++) { - - // Checks if current item is located at curx,cury - if (area != null && (area.row1 == cury) - && (area.column1 == curx)) { - - // First check if empty cell needs to be rendered - if (emptyCells > 0) { - target.startTag("gc"); - target.addAttribute("x", curx - emptyCells); - target.addAttribute("y", cury); - if (emptyCells > 1) { - target.addAttribute("w", emptyCells); - } - target.endTag("gc"); - emptyCells = 0; - } - - // Now proceed rendering current item - final int cols = (area.column2 - area.column1) + 1; - final int rows = (area.row2 - area.row1) + 1; - target.startTag("gc"); - - target.addAttribute("x", curx); - target.addAttribute("y", cury); - - if (cols > 1) { - target.addAttribute("w", cols); - } - if (rows > 1) { - target.addAttribute("h", rows); - } - LegacyPaint.paint(area.getComponent(), target); - - alignmentsArray[index++] = String - .valueOf(getComponentAlignment(area.getComponent()) - .getBitMask()); - - target.endTag("gc"); - - // Fetch next item - if (areaiterator.hasNext()) { - area = areaiterator.next(); - } else { - area = null; - } - - // Updates the cellUsed if rowspan needed - if (rows > 1) { - int spannedx = curx; - for (int j = 1; j <= cols; j++) { - cellUsed.put(new Integer(spannedx), new Integer( - cury + rows - 1)); - spannedx++; - } - } - - // Skips the current item's spanned columns - if (cols > 1) { - curx += cols - 1; - } - - } else { - - // Checks against cellUsed, render space or ignore cell - if (cellUsed.containsKey(new Integer(curx))) { - - // Current column contains already an item, - // check if rowspan affects at current x,y position - final int rowspanDepth = cellUsed - .get(new Integer(curx)).intValue(); - - if (rowspanDepth >= cury) { - - // ignore cell - // Check if empty cell needs to be rendered - if (emptyCells > 0) { - target.startTag("gc"); - target.addAttribute("x", curx - emptyCells); - target.addAttribute("y", cury); - if (emptyCells > 1) { - target.addAttribute("w", emptyCells); - } - target.endTag("gc"); - - emptyCells = 0; - } - } else { - - // empty cell is needed - emptyCells++; - - // Removes the cellUsed key as it has become - // obsolete - cellUsed.remove(Integer.valueOf(curx)); - } - } else { - - // empty cell is needed - emptyCells++; - } - } - - } // iterates every column - - // Last column handled of current row - - // Checks if empty cell needs to be rendered - if (emptyCells > 0) { - target.startTag("gc"); - target.addAttribute("x", getColumns() - emptyCells); - target.addAttribute("y", cury); - if (emptyCells > 1) { - target.addAttribute("w", emptyCells); - } - target.endTag("gc"); - - emptyCells = 0; - } - - target.endTag("gr"); - } // iterates every row - - // Last row handled - - // correct possible rounding error - if (rowExpandRatioArray.length > 0) { - rowExpandRatioArray[0] -= realRowExpandRatioSum - 1000; - } - if (columnExpandRatioArray.length > 0) { - columnExpandRatioArray[0] -= realColExpandRatioSum - 1000; - } - - target.addAttribute("colExpand", columnExpandRatioArray); - target.addAttribute("rowExpand", rowExpandRatioArray); - - // Add child component alignment info to layout tag - target.addAttribute("alignments", alignmentsArray); - - } - - private float getExpandRatioSum(Map<Integer, Float> ratioMap) { - float sum = 0; - for (Iterator<Entry<Integer, Float>> iterator = ratioMap.entrySet() - .iterator(); iterator.hasNext();) { - sum += iterator.next().getValue(); - } - return sum; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.AlignmentHandler#getComponentAlignment(com - * .vaadin.ui.Component) - */ - @Override - public Alignment getComponentAlignment(Component childComponent) { - Alignment alignment = componentToAlignment.get(childComponent); - if (alignment == null) { - return ALIGNMENT_DEFAULT; - } else { - return alignment; - } - } - - /** - * Defines a rectangular area of cells in a GridLayout. - * - * <p> - * Also maintains a reference to the component contained in the area. - * </p> - * - * <p> - * The area is specified by the cell coordinates of its upper left corner - * (column1,row1) and lower right corner (column2,row2). As otherwise with - * GridLayout, the column and row coordinates start from zero. - * </p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class Area implements Serializable { - - /** - * The column of the upper left corner cell of the area. - */ - private final int column1; - - /** - * The row of the upper left corner cell of the area. - */ - private int row1; - - /** - * The column of the lower right corner cell of the area. - */ - private final int column2; - - /** - * The row of the lower right corner cell of the area. - */ - private int row2; - - /** - * Component painted in the area. - */ - private Component component; - - /** - * <p> - * Construct a new area on a grid. - * </p> - * - * @param component - * the component connected to the area. - * @param column1 - * The column of the upper left corner cell of the area. The - * leftmost column has index 0. - * @param row1 - * The row of the upper left corner cell of the area. The - * topmost row has index 0. - * @param column2 - * The column of the lower right corner cell of the area. The - * leftmost column has index 0. - * @param row2 - * The row of the lower right corner cell of the area. The - * topmost row has index 0. - */ - public Area(Component component, int column1, int row1, int column2, - int row2) { - this.column1 = column1; - this.row1 = row1; - this.column2 = column2; - this.row2 = row2; - this.component = component; - } - - /** - * Tests if this Area overlaps with another Area. - * - * @param other - * the other Area that is to be tested for overlap with this - * area - * @return <code>true</code> if <code>other</code> area overlaps with - * this on, <code>false</code> if it does not. - */ - public boolean overlaps(Area other) { - return column1 <= other.getColumn2() && row1 <= other.getRow2() - && column2 >= other.getColumn1() && row2 >= other.getRow1(); - - } - - /** - * Gets the component connected to the area. - * - * @return the Component. - */ - public Component getComponent() { - return component; - } - - /** - * Sets the component connected to the area. - * - * <p> - * This function only sets the value in the data structure and does not - * send any events or set parents. - * </p> - * - * @param newComponent - * the new connected overriding the existing one. - */ - protected void setComponent(Component newComponent) { - component = newComponent; - } - - /** - * @deprecated Use {@link #getColumn1()} instead. - */ - @Deprecated - public int getX1() { - return getColumn1(); - } - - /** - * Gets the column of the top-left corner cell. - * - * @return the column of the top-left corner cell. - */ - public int getColumn1() { - return column1; - } - - /** - * @deprecated Use {@link #getColumn2()} instead. - */ - @Deprecated - public int getX2() { - return getColumn2(); - } - - /** - * Gets the column of the bottom-right corner cell. - * - * @return the column of the bottom-right corner cell. - */ - public int getColumn2() { - return column2; - } - - /** - * @deprecated Use {@link #getRow1()} instead. - */ - @Deprecated - public int getY1() { - return getRow1(); - } - - /** - * Gets the row of the top-left corner cell. - * - * @return the row of the top-left corner cell. - */ - public int getRow1() { - return row1; - } - - /** - * @deprecated Use {@link #getRow2()} instead. - */ - @Deprecated - public int getY2() { - return getRow2(); - } - - /** - * Gets the row of the bottom-right corner cell. - * - * @return the row of the bottom-right corner cell. - */ - public int getRow2() { - return row2; - } - - } - - /** - * Gridlayout does not support laying components on top of each other. An - * <code>OverlapsException</code> is thrown when a component already exists - * (even partly) at the same space on a grid with the new component. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class OverlapsException extends java.lang.RuntimeException { - - private final Area existingArea; - - /** - * Constructs an <code>OverlapsException</code>. - * - * @param existingArea - */ - public OverlapsException(Area existingArea) { - this.existingArea = existingArea; - } - - @Override - public String getMessage() { - StringBuilder sb = new StringBuilder(); - Component component = existingArea.getComponent(); - sb.append(component); - sb.append("( type = "); - sb.append(component.getClass().getName()); - if (component.getCaption() != null) { - sb.append(", caption = \""); - sb.append(component.getCaption()); - sb.append("\""); - } - sb.append(")"); - sb.append(" is already added to "); - sb.append(existingArea.column1); - sb.append(","); - sb.append(existingArea.column1); - sb.append(","); - sb.append(existingArea.row1); - sb.append(","); - sb.append(existingArea.row2); - sb.append("(column1, column2, row1, row2)."); - - return sb.toString(); - } - - /** - * Gets the area . - * - * @return the existing area. - */ - public Area getArea() { - return existingArea; - } - } - - /** - * An <code>Exception</code> object which is thrown when an area exceeds the - * bounds of the grid. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class OutOfBoundsException extends java.lang.RuntimeException { - - private final Area areaOutOfBounds; - - /** - * Constructs an <code>OoutOfBoundsException</code> with the specified - * detail message. - * - * @param areaOutOfBounds - */ - public OutOfBoundsException(Area areaOutOfBounds) { - this.areaOutOfBounds = areaOutOfBounds; - } - - /** - * Gets the area that is out of bounds. - * - * @return the area out of Bound. - */ - public Area getArea() { - return areaOutOfBounds; - } - } - - /** - * Sets the number of columns in the grid. The column count can not be - * reduced if there are any areas that would be outside of the shrunk grid. - * - * @param columns - * the new number of columns in the grid. - */ - public void setColumns(int columns) { - - // The the param - if (columns < 1) { - throw new IllegalArgumentException( - "The number of columns and rows in the grid must be at least 1"); - } - - // In case of no change - if (getColumns() == columns) { - return; - } - - // Checks for overlaps - if (getColumns() > columns) { - for (final Iterator<Area> i = areas.iterator(); i.hasNext();) { - final Area area = i.next(); - if (area.column2 >= columns) { - throw new OutOfBoundsException(area); - } - } - } - - getState().setColumns(columns); - - requestRepaint(); - } - - /** - * Get the number of columns in the grid. - * - * @return the number of columns in the grid. - */ - public int getColumns() { - return getState().getColumns(); - } - - /** - * Sets the number of rows in the grid. The number of rows can not be - * reduced if there are any areas that would be outside of the shrunk grid. - * - * @param rows - * the new number of rows in the grid. - */ - public void setRows(int rows) { - - // The the param - if (rows < 1) { - throw new IllegalArgumentException( - "The number of columns and rows in the grid must be at least 1"); - } - - // In case of no change - if (getRows() == rows) { - return; - } - - // Checks for overlaps - if (getRows() > rows) { - for (final Iterator<Area> i = areas.iterator(); i.hasNext();) { - final Area area = i.next(); - if (area.row2 >= rows) { - throw new OutOfBoundsException(area); - } - } - } - - getState().setRows(rows); - - requestRepaint(); - } - - /** - * Get the number of rows in the grid. - * - * @return the number of rows in the grid. - */ - public int getRows() { - return getState().getRows(); - } - - /** - * Gets the current x-position (column) of the cursor. - * - * <p> - * The cursor position points the position for the next component that is - * added without specifying its coordinates (grid cell). When the cursor - * position is occupied, the next component will be added to first free - * position after the cursor. - * </p> - * - * @return the grid column the cursor is on, starting from 0. - */ - public int getCursorX() { - return cursorX; - } - - /** - * Sets the current cursor x-position. This is usually handled automatically - * by GridLayout. - * - * @param cursorX - */ - public void setCursorX(int cursorX) { - this.cursorX = cursorX; - } - - /** - * Gets the current y-position (row) of the cursor. - * - * <p> - * The cursor position points the position for the next component that is - * added without specifying its coordinates (grid cell). When the cursor - * position is occupied, the next component will be added to the first free - * position after the cursor. - * </p> - * - * @return the grid row the Cursor is on. - */ - public int getCursorY() { - return cursorY; - } - - /** - * Sets the current y-coordinate (row) of the cursor. This is usually - * handled automatically by GridLayout. - * - * @param cursorY - * the row number, starting from 0 for the topmost row. - */ - public void setCursorY(int cursorY) { - this.cursorY = cursorY; - } - - /* Documented in superclass */ - @Override - public void replaceComponent(Component oldComponent, Component newComponent) { - - // Gets the locations - Area oldLocation = null; - Area newLocation = null; - for (final Iterator<Area> i = areas.iterator(); i.hasNext();) { - final Area location = i.next(); - final Component component = location.getComponent(); - if (component == oldComponent) { - oldLocation = location; - } - if (component == newComponent) { - newLocation = location; - } - } - - if (oldLocation == null) { - addComponent(newComponent); - } else if (newLocation == null) { - removeComponent(oldComponent); - addComponent(newComponent, oldLocation.getColumn1(), - oldLocation.getRow1(), oldLocation.getColumn2(), - oldLocation.getRow2()); - } else { - oldLocation.setComponent(newComponent); - newLocation.setComponent(oldComponent); - requestRepaint(); - } - } - - /* - * Removes all components from this container. - * - * @see com.vaadin.ui.ComponentContainer#removeAllComponents() - */ - @Override - public void removeAllComponents() { - super.removeAllComponents(); - componentToAlignment = new HashMap<Component, Alignment>(); - cursorX = 0; - cursorY = 0; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.AlignmentHandler#setComponentAlignment(com - * .vaadin.ui.Component, int, int) - */ - @Override - public void setComponentAlignment(Component childComponent, - int horizontalAlignment, int verticalAlignment) { - componentToAlignment.put(childComponent, new Alignment( - horizontalAlignment + verticalAlignment)); - requestRepaint(); - } - - @Override - public void setComponentAlignment(Component childComponent, - Alignment alignment) { - componentToAlignment.put(childComponent, alignment); - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.SpacingHandler#setSpacing(boolean) - */ - @Override - public void setSpacing(boolean spacing) { - getState().setSpacing(spacing); - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Layout.SpacingHandler#isSpacing() - */ - @Override - public boolean isSpacing() { - return getState().isSpacing(); - } - - /** - * Inserts an empty row at the specified position in the grid. - * - * @param row - * Index of the row before which the new row will be inserted. - * The leftmost row has index 0. - */ - public void insertRow(int row) { - if (row > getRows()) { - throw new IllegalArgumentException("Cannot insert row at " + row - + " in a gridlayout with height " + getRows()); - } - - for (Iterator<Area> i = areas.iterator(); i.hasNext();) { - Area existingArea = i.next(); - // Areas ending below the row needs to be moved down or stretched - if (existingArea.row2 >= row) { - existingArea.row2++; - - // Stretch areas that span over the selected row - if (existingArea.row1 >= row) { - existingArea.row1++; - } - - } - } - - if (cursorY >= row) { - cursorY++; - } - - setRows(getRows() + 1); - structuralChange = true; - requestRepaint(); - } - - /** - * Removes a row and all the components in the row. - * - * <p> - * Components which span over several rows are removed if the selected row - * is on the first row of such a component. - * </p> - * - * <p> - * If the last row is removed then all remaining components will be removed - * and the grid will be reduced to one row. The cursor will be moved to the - * upper left cell of the grid. - * </p> - * - * @param row - * Index of the row to remove. The leftmost row has index 0. - */ - public void removeRow(int row) { - if (row >= getRows()) { - throw new IllegalArgumentException("Cannot delete row " + row - + " from a gridlayout with height " + getRows()); - } - - // Remove all components in row - for (int col = 0; col < getColumns(); col++) { - removeComponent(col, row); - } - - // Shrink or remove areas in the selected row - for (Iterator<Area> i = areas.iterator(); i.hasNext();) { - Area existingArea = i.next(); - if (existingArea.row2 >= row) { - existingArea.row2--; - - if (existingArea.row1 > row) { - existingArea.row1--; - } - } - } - - if (getRows() == 1) { - /* - * Removing the last row means that the dimensions of the Grid - * layout will be truncated to 1 empty row and the cursor is moved - * to the first cell - */ - cursorX = 0; - cursorY = 0; - } else { - setRows(getRows() - 1); - if (cursorY > row) { - cursorY--; - } - } - - structuralChange = true; - requestRepaint(); - - } - - /** - * Sets the expand ratio of given column. - * - * <p> - * The expand ratio defines how excess space is distributed among columns. - * Excess space means space that is left over from components that are not - * sized relatively. By default, the excess space is distributed evenly. - * </p> - * - * <p> - * Note that the component width of the GridLayout must be defined (fixed or - * relative, as opposed to undefined) for this method to have any effect. - * </p> - * - * @see #setWidth(float, int) - * - * @param columnIndex - * @param ratio - */ - public void setColumnExpandRatio(int columnIndex, float ratio) { - columnExpandRatio.put(columnIndex, ratio); - requestRepaint(); - } - - /** - * Returns the expand ratio of given column - * - * @see #setColumnExpandRatio(int, float) - * - * @param columnIndex - * @return the expand ratio, 0.0f by default - */ - public float getColumnExpandRatio(int columnIndex) { - Float r = columnExpandRatio.get(columnIndex); - return r == null ? 0 : r.floatValue(); - } - - /** - * Sets the expand ratio of given row. - * - * <p> - * Expand ratio defines how excess space is distributed among rows. Excess - * space means the space left over from components that are not sized - * relatively. By default, the excess space is distributed evenly. - * </p> - * - * <p> - * Note, that height needs to be defined (fixed or relative, as opposed to - * undefined height) for this method to have any effect. - * </p> - * - * @see #setHeight(float, int) - * - * @param rowIndex - * The row index, starting from 0 for the topmost row. - * @param ratio - */ - public void setRowExpandRatio(int rowIndex, float ratio) { - rowExpandRatio.put(rowIndex, ratio); - requestRepaint(); - } - - /** - * Returns the expand ratio of given row. - * - * @see #setRowExpandRatio(int, float) - * - * @param rowIndex - * The row index, starting from 0 for the topmost row. - * @return the expand ratio, 0.0f by default - */ - public float getRowExpandRatio(int rowIndex) { - Float r = rowExpandRatio.get(rowIndex); - return r == null ? 0 : r.floatValue(); - } - - /** - * Gets the Component at given index. - * - * @param x - * The column index, starting from 0 for the leftmost column. - * @param y - * The row index, starting from 0 for the topmost row. - * @return Component in given cell or null if empty - */ - public Component getComponent(int x, int y) { - for (final Iterator<Area> iterator = areas.iterator(); iterator - .hasNext();) { - final Area area = iterator.next(); - if (area.getColumn1() <= x && x <= area.getColumn2() - && area.getRow1() <= y && y <= area.getRow2()) { - return area.getComponent(); - } - } - return null; - } - - /** - * Returns information about the area where given component is laid in the - * GridLayout. - * - * @param component - * the component whose area information is requested. - * @return an Area object that contains information how component is laid in - * the grid - */ - public Area getComponentArea(Component component) { - for (final Iterator<Area> iterator = areas.iterator(); iterator - .hasNext();) { - final Area area = iterator.next(); - if (area.getComponent() == component) { - return area; - } - } - return null; - } - - @Override - public void addListener(LayoutClickListener listener) { - addListener(LayoutClickEventHandler.LAYOUT_CLICK_EVENT_IDENTIFIER, - LayoutClickEvent.class, listener, - LayoutClickListener.clickMethod); - } - - @Override - public void removeListener(LayoutClickListener listener) { - removeListener(LayoutClickEventHandler.LAYOUT_CLICK_EVENT_IDENTIFIER, - LayoutClickEvent.class, listener); - } - -} diff --git a/src/com/vaadin/ui/HasComponents.java b/src/com/vaadin/ui/HasComponents.java deleted file mode 100644 index 3ebd63bff2..0000000000 --- a/src/com/vaadin/ui/HasComponents.java +++ /dev/null @@ -1,49 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import java.util.Iterator; - -/** - * Interface that must be implemented by all {@link Component}s that contain - * other {@link Component}s. - * - * @author Vaadin Ltd - * @version @VERSION@ - * @since 7.0.0 - * - */ -public interface HasComponents extends Component, Iterable<Component> { - /** - * Gets an iterator to the collection of contained components. Using this - * iterator it is possible to step through all components contained in this - * container. - * - * @return the component iterator. - * - * @deprecated Use {@link #iterator()} instead. - */ - @Deprecated - public Iterator<Component> getComponentIterator(); - - /** - * Checks if the child component is visible. This method allows hiding a - * child component from updates and communication to and from the client. - * This is useful for components that show only a limited number of its - * children at any given time and want to allow updates only for the - * children that are visible (e.g. TabSheet has one tab open at a time). - * <p> - * Note that this will prevent updates from reaching the child even though - * the child itself is set to visible. Also if a child is set to invisible - * this will not force it to be visible. - * </p> - * - * @param childComponent - * The child component to check - * @return true if the child component is visible to the user, false - * otherwise - */ - public boolean isComponentVisible(Component childComponent); - -} diff --git a/src/com/vaadin/ui/HorizontalLayout.java b/src/com/vaadin/ui/HorizontalLayout.java deleted file mode 100644 index b9dc1c13ca..0000000000 --- a/src/com/vaadin/ui/HorizontalLayout.java +++ /dev/null @@ -1,24 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -/** - * Horizontal layout - * - * <code>HorizontalLayout</code> is a component container, which shows the - * subcomponents in the order of their addition (horizontally). - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 5.3 - */ -@SuppressWarnings("serial") -public class HorizontalLayout extends AbstractOrderedLayout { - - public HorizontalLayout() { - - } - -} diff --git a/src/com/vaadin/ui/HorizontalSplitPanel.java b/src/com/vaadin/ui/HorizontalSplitPanel.java deleted file mode 100644 index 5bd6c8a075..0000000000 --- a/src/com/vaadin/ui/HorizontalSplitPanel.java +++ /dev/null @@ -1,34 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -/** - * A horizontal split panel contains two components and lays them horizontally. - * The first component is on the left side. - * - * <pre> - * - * +---------------------++----------------------+ - * | || | - * | The first component || The second component | - * | || | - * +---------------------++----------------------+ - * - * ^ - * | - * the splitter - * - * </pre> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 6.5 - */ -public class HorizontalSplitPanel extends AbstractSplitPanel { - public HorizontalSplitPanel() { - super(); - setSizeFull(); - } -} diff --git a/src/com/vaadin/ui/Html5File.java b/src/com/vaadin/ui/Html5File.java deleted file mode 100644 index aa3fb558fa..0000000000 --- a/src/com/vaadin/ui/Html5File.java +++ /dev/null @@ -1,65 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import java.io.Serializable; - -import com.vaadin.event.dd.DropHandler; -import com.vaadin.terminal.StreamVariable; - -/** - * {@link DragAndDropWrapper} can receive also files from client computer if - * appropriate HTML 5 features are supported on client side. This class wraps - * information about dragged file on server side. - */ -public class Html5File implements Serializable { - - private String name; - private long size; - private StreamVariable streamVariable; - private String type; - - Html5File(String name, long size, String mimeType) { - this.name = name; - this.size = size; - type = mimeType; - } - - public String getFileName() { - return name; - } - - public long getFileSize() { - return size; - } - - public String getType() { - return type; - } - - /** - * Sets the {@link StreamVariable} that into which the file contents will be - * written. Usage of StreamVariable is similar to {@link Upload} component. - * <p> - * If the {@link StreamVariable} is not set in the {@link DropHandler} the - * file contents will not be sent to server. - * <p> - * <em>Note!</em> receiving file contents is experimental feature depending - * on HTML 5 API's. It is supported only by modern web browsers like Firefox - * 3.6 and above and recent webkit based browsers (Safari 5, Chrome 6) at - * this time. - * - * @param streamVariable - * the callback that returns stream where the implementation - * writes the file contents as it arrives. - */ - public void setStreamVariable(StreamVariable streamVariable) { - this.streamVariable = streamVariable; - } - - public StreamVariable getStreamVariable() { - return streamVariable; - } - -}
\ No newline at end of file diff --git a/src/com/vaadin/ui/InlineDateField.java b/src/com/vaadin/ui/InlineDateField.java deleted file mode 100644 index cf61703318..0000000000 --- a/src/com/vaadin/ui/InlineDateField.java +++ /dev/null @@ -1,46 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.Date; - -import com.vaadin.data.Property; - -/** - * <p> - * A date entry component, which displays the actual date selector inline. - * - * </p> - * - * @see DateField - * @see PopupDateField - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 5.0 - */ -public class InlineDateField extends DateField { - - public InlineDateField() { - super(); - } - - public InlineDateField(Property dataSource) throws IllegalArgumentException { - super(dataSource); - } - - public InlineDateField(String caption, Date value) { - super(caption, value); - } - - public InlineDateField(String caption, Property dataSource) { - super(caption, dataSource); - } - - public InlineDateField(String caption) { - super(caption); - } - -} diff --git a/src/com/vaadin/ui/JavaScript.java b/src/com/vaadin/ui/JavaScript.java deleted file mode 100644 index 0b4669728a..0000000000 --- a/src/com/vaadin/ui/JavaScript.java +++ /dev/null @@ -1,157 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.HashMap; -import java.util.Map; - -import com.vaadin.external.json.JSONArray; -import com.vaadin.external.json.JSONException; -import com.vaadin.shared.communication.ServerRpc; -import com.vaadin.shared.extension.javascriptmanager.ExecuteJavaScriptRpc; -import com.vaadin.shared.extension.javascriptmanager.JavaScriptManagerState; -import com.vaadin.terminal.AbstractExtension; -import com.vaadin.terminal.Page; - -/** - * Provides access to JavaScript functionality in the web browser. To get an - * instance of JavaScript, either use Page.getJavaScript() or - * JavaScript.getCurrent() as a shorthand for getting the JavaScript object - * corresponding to the current Page. - * - * @author Vaadin Ltd - * @version @VERSION@ - * @since 7.0.0 - */ -public class JavaScript extends AbstractExtension { - private Map<String, JavaScriptFunction> functions = new HashMap<String, JavaScriptFunction>(); - - // Can not be defined in client package as this JSONArray is not available - // in GWT - public interface JavaScriptCallbackRpc extends ServerRpc { - public void call(String name, JSONArray arguments); - } - - /** - * Creates a new JavaScript object. You should typically not this, but - * instead use the JavaScript object already associated with your Page - * object. - */ - public JavaScript() { - registerRpc(new JavaScriptCallbackRpc() { - @Override - public void call(String name, JSONArray arguments) { - JavaScriptFunction function = functions.get(name); - // TODO handle situation if name is not registered - try { - function.call(arguments); - } catch (JSONException e) { - throw new IllegalArgumentException(e); - } - } - }); - } - - @Override - public JavaScriptManagerState getState() { - return (JavaScriptManagerState) super.getState(); - } - - /** - * Add a new function to the global JavaScript namespace (i.e. the window - * object). The <code>call</code> method in the passed - * {@link JavaScriptFunction} object will be invoked with the same - * parameters whenever the JavaScript function is called in the browser. - * - * A function added with the name <code>"myFunction"</code> can thus be - * invoked with the following JavaScript code: - * <code>window.myFunction(argument1, argument2)</code>. - * - * If the name parameter contains dots, simple objects are created on demand - * to allow calling the function using the same name (e.g. - * <code>window.myObject.myFunction</code>). - * - * @param name - * the name that the function should get in the global JavaScript - * namespace. - * @param function - * the JavaScriptFunction that will be invoked if the JavaScript - * function is called. - */ - public void addFunction(String name, JavaScriptFunction function) { - functions.put(name, function); - if (getState().getNames().add(name)) { - requestRepaint(); - } - } - - /** - * Removes a JavaScripFunction from the browser's global JavaScript - * namespace. - * - * If the name contains dots and intermediate objects were created by - * {@link #addFunction(String, JavaScriptFunction)}, these objects will not - * be removed by this method. - * - * @param name - * the name of the callback to remove - */ - public void removeFunction(String name) { - functions.remove(name); - if (getState().getNames().remove(name)) { - requestRepaint(); - } - } - - /** - * Executes the given JavaScript code in the browser. - * - * @param script - * The JavaScript code to run. - */ - public void execute(String script) { - getRpcProxy(ExecuteJavaScriptRpc.class).executeJavaScript(script); - } - - /** - * Executes the given JavaScript code in the browser. - * - * @param script - * The JavaScript code to run. - */ - public static void eval(String script) { - getCurrent().execute(script); - } - - /** - * Get the JavaScript object for the current Page, or null if there is no - * current page. - * - * @see Page#getCurrent() - * - * @return the JavaScript object corresponding to the current Page, or - * <code>null</code> if there is no current page. - */ - public static JavaScript getCurrent() { - Page page = Page.getCurrent(); - if (page == null) { - return null; - } - return page.getJavaScript(); - } - - /** - * JavaScript is not designed to be removed. - * - * @throws UnsupportedOperationException - * when invoked - */ - @Override - public void removeFromTarget() { - throw new UnsupportedOperationException( - "JavaScript is not designed to be removed."); - } - -} diff --git a/src/com/vaadin/ui/JavaScriptFunction.java b/src/com/vaadin/ui/JavaScriptFunction.java deleted file mode 100644 index e39ae9b87b..0000000000 --- a/src/com/vaadin/ui/JavaScriptFunction.java +++ /dev/null @@ -1,41 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; - -import com.vaadin.external.json.JSONArray; -import com.vaadin.external.json.JSONException; -import com.vaadin.terminal.AbstractJavaScriptExtension; - -/** - * Defines a method that is called by a client-side JavaScript function. When - * the corresponding JavaScript function is called, the {@link #call(JSONArray)} - * method is invoked. - * - * @see JavaScript#addFunction(String, JavaScriptCallback) - * @see AbstractJavaScriptComponent#addFunction(String, JavaScriptCallback) - * @see AbstractJavaScriptExtension#addFunction(String, JavaScriptCallback) - * - * @author Vaadin Ltd - * @version @VERSION@ - * @since 7.0.0 - */ -public interface JavaScriptFunction extends Serializable { - /** - * Invoked whenever the corresponding JavaScript function is called in the - * browser. - * <p> - * Because of the asynchronous nature of the communication between client - * and server, no return value can be sent back to the browser. - * - * @param arguments - * an array with JSON representations of the arguments with which - * the JavaScript function was called. - * @throws JSONException - * if the arguments can not be interpreted - */ - public void call(JSONArray arguments) throws JSONException; -} diff --git a/src/com/vaadin/ui/Label.java b/src/com/vaadin/ui/Label.java deleted file mode 100644 index 7e50a37805..0000000000 --- a/src/com/vaadin/ui/Label.java +++ /dev/null @@ -1,483 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.lang.reflect.Method; -import java.util.logging.Logger; - -import com.vaadin.data.Property; -import com.vaadin.data.util.converter.Converter; -import com.vaadin.data.util.converter.ConverterUtil; -import com.vaadin.shared.ui.label.ContentMode; -import com.vaadin.shared.ui.label.LabelState; - -/** - * Label component for showing non-editable short texts. - * - * The label content can be set to the modes specified by {@link ContentMode} - * - * <p> - * The contents of the label may contain simple formatting: - * <ul> - * <li><b><b></b> Bold - * <li><b><i></b> Italic - * <li><b><u></b> Underlined - * <li><b><br/></b> Linebreak - * <li><b><ul><li>item 1</li><li>item 2</li></ul></b> List of - * items - * </ul> - * The <b>b</b>,<b>i</b>,<b>u</b> and <b>li</b> tags can contain all the tags in - * the list recursively. - * </p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public class Label extends AbstractComponent implements Property<String>, - Property.Viewer, Property.ValueChangeListener, - Property.ValueChangeNotifier, Comparable<Label> { - - private static final Logger logger = Logger - .getLogger(Label.class.getName()); - - /** - * @deprecated From 7.0, use {@link ContentMode#TEXT} instead - */ - @Deprecated - public static final ContentMode CONTENT_TEXT = ContentMode.TEXT; - - /** - * @deprecated From 7.0, use {@link ContentMode#PREFORMATTED} instead - */ - @Deprecated - public static final ContentMode CONTENT_PREFORMATTED = ContentMode.PREFORMATTED; - - /** - * @deprecated From 7.0, use {@link ContentMode#XHTML} instead - */ - @Deprecated - public static final ContentMode CONTENT_XHTML = ContentMode.XHTML; - - /** - * @deprecated From 7.0, use {@link ContentMode#XML} instead - */ - @Deprecated - public static final ContentMode CONTENT_XML = ContentMode.XML; - - /** - * @deprecated From 7.0, use {@link ContentMode#RAW} instead - */ - @Deprecated - public static final ContentMode CONTENT_RAW = ContentMode.RAW; - - /** - * @deprecated From 7.0, use {@link ContentMode#TEXT} instead - */ - @Deprecated - public static final ContentMode CONTENT_DEFAULT = ContentMode.TEXT; - - /** - * A converter used to convert from the data model type to the field type - * and vice versa. Label type is always String. - */ - private Converter<String, Object> converter = null; - - private Property<String> dataSource = null; - - /** - * Creates an empty Label. - */ - public Label() { - this(""); - } - - /** - * Creates a new instance of Label with text-contents. - * - * @param content - */ - public Label(String content) { - this(content, ContentMode.TEXT); - } - - /** - * Creates a new instance of Label with text-contents read from given - * datasource. - * - * @param contentSource - */ - public Label(Property contentSource) { - this(contentSource, ContentMode.TEXT); - } - - /** - * Creates a new instance of Label with text-contents. - * - * @param content - * @param contentMode - */ - public Label(String content, ContentMode contentMode) { - setValue(content); - setContentMode(contentMode); - setWidth(100, Unit.PERCENTAGE); - } - - /** - * Creates a new instance of Label with text-contents read from given - * datasource. - * - * @param contentSource - * @param contentMode - */ - public Label(Property contentSource, ContentMode contentMode) { - setPropertyDataSource(contentSource); - setContentMode(contentMode); - setWidth(100, Unit.PERCENTAGE); - } - - @Override - public LabelState getState() { - return (LabelState) super.getState(); - } - - /** - * Gets the value of the label. - * <p> - * The value of the label is the text that is shown to the end user. - * Depending on the {@link ContentMode} it is plain text or markup. - * </p> - * - * @return the value of the label. - */ - @Override - public String getValue() { - if (getPropertyDataSource() == null) { - // Use internal value if we are running without a data source - return getState().getText(); - } - return ConverterUtil.convertFromModel(getPropertyDataSource() - .getValue(), String.class, getConverter(), getLocale()); - } - - /** - * Set the value of the label. Value of the label is the XML contents of the - * label. - * - * @param newStringValue - * the New value of the label. - */ - @Override - public void setValue(Object newStringValue) { - if (newStringValue != null && newStringValue.getClass() != String.class) { - throw new Converter.ConversionException("Value of type " - + newStringValue.getClass() + " cannot be assigned to " - + String.class.getName()); - } - if (getPropertyDataSource() == null) { - getState().setText((String) newStringValue); - requestRepaint(); - } else { - throw new IllegalStateException( - "Label is only a Property.Viewer and cannot update its data source"); - } - } - - /** - * Returns the value displayed by this label. - * - * @see java.lang.Object#toString() - * @deprecated As of 7.0.0, use {@link #getValue()} to get the value of the - * label or {@link #getPropertyDataSource()} .getValue() to get - * the value of the data source. - */ - @Deprecated - @Override - public String toString() { - logger.warning("You are using Label.toString() to get the value for a " - + getClass().getSimpleName() - + ". This is not recommended and will not be supported in future versions."); - return getValue(); - } - - /** - * Gets the type of the Property. - * - * @see com.vaadin.data.Property#getType() - */ - @Override - public Class<String> getType() { - return String.class; - } - - /** - * Gets the viewing data-source property. - * - * @return the data source property. - * @see com.vaadin.data.Property.Viewer#getPropertyDataSource() - */ - @Override - public Property getPropertyDataSource() { - return dataSource; - } - - /** - * Sets the property as data-source for viewing. - * - * @param newDataSource - * the new data source Property - * @see com.vaadin.data.Property.Viewer#setPropertyDataSource(com.vaadin.data.Property) - */ - @Override - public void setPropertyDataSource(Property newDataSource) { - // Stops listening the old data source changes - if (dataSource != null - && Property.ValueChangeNotifier.class - .isAssignableFrom(dataSource.getClass())) { - ((Property.ValueChangeNotifier) dataSource).removeListener(this); - } - - if (!ConverterUtil.canConverterHandle(getConverter(), String.class, - newDataSource.getType())) { - // Try to find a converter - Converter<String, ?> c = ConverterUtil.getConverter(String.class, - newDataSource.getType(), getApplication()); - setConverter(c); - } - dataSource = newDataSource; - - // Listens the new data source if possible - if (dataSource != null - && Property.ValueChangeNotifier.class - .isAssignableFrom(dataSource.getClass())) { - ((Property.ValueChangeNotifier) dataSource).addListener(this); - } - requestRepaint(); - } - - /** - * Gets the content mode of the Label. - * - * @return the Content mode of the label. - * - * @see ContentMode - */ - public ContentMode getContentMode() { - return getState().getContentMode(); - } - - /** - * Sets the content mode of the Label. - * - * @param contentMode - * the New content mode of the label. - * - * @see ContentMode - */ - public void setContentMode(ContentMode contentMode) { - if (contentMode == null) { - throw new IllegalArgumentException("Content mode can not be null"); - } - - getState().setContentMode(contentMode); - requestRepaint(); - } - - /* Value change events */ - - private static final Method VALUE_CHANGE_METHOD; - - static { - try { - VALUE_CHANGE_METHOD = Property.ValueChangeListener.class - .getDeclaredMethod("valueChange", - new Class[] { Property.ValueChangeEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException( - "Internal error finding methods in Label"); - } - } - - /** - * Value change event - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public static class ValueChangeEvent extends Component.Event implements - Property.ValueChangeEvent { - - /** - * New instance of text change event - * - * @param source - * the Source of the event. - */ - public ValueChangeEvent(Label source) { - super(source); - } - - /** - * Gets the Property that has been modified. - * - * @see com.vaadin.data.Property.ValueChangeEvent#getProperty() - */ - @Override - public Property getProperty() { - return (Property) getSource(); - } - } - - /** - * Adds the value change listener. - * - * @param listener - * the Listener to be added. - * @see com.vaadin.data.Property.ValueChangeNotifier#addListener(com.vaadin.data.Property.ValueChangeListener) - */ - @Override - public void addListener(Property.ValueChangeListener listener) { - addListener(Label.ValueChangeEvent.class, listener, VALUE_CHANGE_METHOD); - } - - /** - * Removes the value change listener. - * - * @param listener - * the Listener to be removed. - * @see com.vaadin.data.Property.ValueChangeNotifier#removeListener(com.vaadin.data.Property.ValueChangeListener) - */ - @Override - public void removeListener(Property.ValueChangeListener listener) { - removeListener(Label.ValueChangeEvent.class, listener, - VALUE_CHANGE_METHOD); - } - - /** - * Emits the options change event. - */ - protected void fireValueChange() { - // Set the error message - fireEvent(new Label.ValueChangeEvent(this)); - } - - /** - * Listens the value change events from data source. - * - * @see com.vaadin.data.Property.ValueChangeListener#valueChange(Property.ValueChangeEvent) - */ - @Override - public void valueChange(Property.ValueChangeEvent event) { - // Update the internal value from the data source - getState().setText(getValue()); - requestRepaint(); - - fireValueChange(); - } - - private String getComparableValue() { - String stringValue = getValue(); - if (stringValue == null) { - stringValue = ""; - } - - if (getContentMode() == ContentMode.XHTML - || getContentMode() == ContentMode.XML) { - return stripTags(stringValue); - } else { - return stringValue; - } - - } - - /** - * Compares the Label to other objects. - * - * <p> - * Labels can be compared to other labels for sorting label contents. This - * is especially handy for sorting table columns. - * </p> - * - * <p> - * In RAW, PREFORMATTED and TEXT modes, the label contents are compared as - * is. In XML, UIDL and XHTML modes, only CDATA is compared and tags - * ignored. If the other object is not a Label, its toString() return value - * is used in comparison. - * </p> - * - * @param other - * the Other object to compare to. - * @return a negative integer, zero, or a positive integer as this object is - * less than, equal to, or greater than the specified object. - * @see java.lang.Comparable#compareTo(java.lang.Object) - */ - @Override - public int compareTo(Label other) { - - String thisValue = getComparableValue(); - String otherValue = other.getComparableValue(); - - return thisValue.compareTo(otherValue); - } - - /** - * Strips the tags from the XML. - * - * @param xml - * the String containing a XML snippet. - * @return the original XML without tags. - */ - private String stripTags(String xml) { - - final StringBuffer res = new StringBuffer(); - - int processed = 0; - final int xmlLen = xml.length(); - while (processed < xmlLen) { - int next = xml.indexOf('<', processed); - if (next < 0) { - next = xmlLen; - } - res.append(xml.substring(processed, next)); - if (processed < xmlLen) { - next = xml.indexOf('>', processed); - if (next < 0) { - next = xmlLen; - } - processed = next + 1; - } - } - - return res.toString(); - } - - /** - * Gets the converter used to convert the property data source value to the - * label value. - * - * @return The converter or null if none is set. - */ - public Converter<String, Object> getConverter() { - return converter; - } - - /** - * Sets the converter used to convert the label value to the property data - * source type. The converter must have a presentation type of String. - * - * @param converter - * The new converter to use. - */ - public void setConverter(Converter<String, ?> converter) { - this.converter = (Converter<String, Object>) converter; - requestRepaint(); - } - -} diff --git a/src/com/vaadin/ui/Layout.java b/src/com/vaadin/ui/Layout.java deleted file mode 100644 index d083f9afdc..0000000000 --- a/src/com/vaadin/ui/Layout.java +++ /dev/null @@ -1,229 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; - -import com.vaadin.shared.ui.VMarginInfo; -import com.vaadin.shared.ui.AlignmentInfo.Bits; - -/** - * Extension to the {@link ComponentContainer} interface which adds the - * layouting control to the elements in the container. This is required by the - * various layout components to enable them to place other components in - * specific locations in the UI. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -public interface Layout extends ComponentContainer, Serializable { - - /** - * Enable layout margins. Affects all four sides of the layout. This will - * tell the client-side implementation to leave extra space around the - * layout. The client-side implementation decides the actual amount, and it - * can vary between themes. - * - * @param enabled - */ - public void setMargin(boolean enabled); - - /** - * Enable specific layout margins. This will tell the client-side - * implementation to leave extra space around the layout in specified edges, - * clockwise from top (top, right, bottom, left). The client-side - * implementation decides the actual amount, and it can vary between themes. - * - * @param top - * @param right - * @param bottom - * @param left - */ - public void setMargin(boolean top, boolean right, boolean bottom, - boolean left); - - /** - * AlignmentHandler is most commonly an advanced {@link Layout} that can - * align its components. - */ - public interface AlignmentHandler extends Serializable { - - /** - * Contained component should be aligned horizontally to the left. - * - * @deprecated Use of {@link Alignment} class and its constants - */ - @Deprecated - public static final int ALIGNMENT_LEFT = Bits.ALIGNMENT_LEFT; - - /** - * Contained component should be aligned horizontally to the right. - * - * @deprecated Use of {@link Alignment} class and its constants - */ - @Deprecated - public static final int ALIGNMENT_RIGHT = Bits.ALIGNMENT_RIGHT; - - /** - * Contained component should be aligned vertically to the top. - * - * @deprecated Use of {@link Alignment} class and its constants - */ - @Deprecated - public static final int ALIGNMENT_TOP = Bits.ALIGNMENT_TOP; - - /** - * Contained component should be aligned vertically to the bottom. - * - * @deprecated Use of {@link Alignment} class and its constants - */ - @Deprecated - public static final int ALIGNMENT_BOTTOM = Bits.ALIGNMENT_BOTTOM; - - /** - * Contained component should be horizontally aligned to center. - * - * @deprecated Use of {@link Alignment} class and its constants - */ - @Deprecated - public static final int ALIGNMENT_HORIZONTAL_CENTER = Bits.ALIGNMENT_HORIZONTAL_CENTER; - - /** - * Contained component should be vertically aligned to center. - * - * @deprecated Use of {@link Alignment} class and its constants - */ - @Deprecated - public static final int ALIGNMENT_VERTICAL_CENTER = Bits.ALIGNMENT_VERTICAL_CENTER; - - /** - * Set alignment for one contained component in this layout. Alignment - * is calculated as a bit mask of the two passed values. - * - * @deprecated Use {@link #setComponentAlignment(Component, Alignment)} - * instead - * - * @param childComponent - * the component to align within it's layout cell. - * @param horizontalAlignment - * the horizontal alignment for the child component (left, - * center, right). Use ALIGNMENT constants. - * @param verticalAlignment - * the vertical alignment for the child component (top, - * center, bottom). Use ALIGNMENT constants. - */ - @Deprecated - public void setComponentAlignment(Component childComponent, - int horizontalAlignment, int verticalAlignment); - - /** - * Set alignment for one contained component in this layout. Use - * predefined alignments from Alignment class. - * - * Example: <code> - * layout.setComponentAlignment(myComponent, Alignment.TOP_RIGHT); - * </code> - * - * @param childComponent - * the component to align within it's layout cell. - * @param alignment - * the Alignment value to be set - */ - public void setComponentAlignment(Component childComponent, - Alignment alignment); - - /** - * Returns the current Alignment of given component. - * - * @param childComponent - * @return the {@link Alignment} - */ - public Alignment getComponentAlignment(Component childComponent); - - } - - /** - * This type of layout supports automatic addition of space between its - * components. - * - */ - public interface SpacingHandler extends Serializable { - /** - * Enable spacing between child components within this layout. - * - * <p> - * <strong>NOTE:</strong> This will only affect the space between - * components, not the space around all the components in the layout - * (i.e. do not confuse this with the cellspacing attribute of a HTML - * Table). Use {@link #setMargin(boolean)} to add space around the - * layout. - * </p> - * - * <p> - * See the reference manual for more information about CSS rules for - * defining the amount of spacing to use. - * </p> - * - * @param enabled - * true if spacing should be turned on, false if it should be - * turned off - */ - public void setSpacing(boolean enabled); - - /** - * - * @return true if spacing between child components within this layout - * is enabled, false otherwise - */ - public boolean isSpacing(); - } - - /** - * This type of layout supports automatic addition of margins (space around - * its components). - */ - public interface MarginHandler extends Serializable { - /** - * Enable margins for this layout. - * - * <p> - * <strong>NOTE:</strong> This will only affect the space around the - * components in the layout, not space between the components in the - * layout. Use {@link #setSpacing(boolean)} to add space between the - * components in the layout. - * </p> - * - * <p> - * See the reference manual for more information about CSS rules for - * defining the size of the margin. - * </p> - * - * @param marginInfo - * MarginInfo object containing the new margins. - */ - public void setMargin(MarginInfo marginInfo); - - /** - * - * @return MarginInfo containing the currently enabled margins. - */ - public MarginInfo getMargin(); - } - - @SuppressWarnings("serial") - public static class MarginInfo extends VMarginInfo implements Serializable { - - public MarginInfo(boolean enabled) { - super(enabled, enabled, enabled, enabled); - } - - public MarginInfo(boolean top, boolean right, boolean bottom, - boolean left) { - super(top, right, bottom, left); - } - } -} diff --git a/src/com/vaadin/ui/Link.java b/src/com/vaadin/ui/Link.java deleted file mode 100644 index fd105f3255..0000000000 --- a/src/com/vaadin/ui/Link.java +++ /dev/null @@ -1,242 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.Map; - -import com.vaadin.terminal.Page; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.Vaadin6Component; - -/** - * Link is used to create external or internal URL links. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public class Link extends AbstractComponent implements Vaadin6Component { - - /* Target window border type constant: No window border */ - public static final int TARGET_BORDER_NONE = Page.BORDER_NONE; - - /* Target window border type constant: Minimal window border */ - public static final int TARGET_BORDER_MINIMAL = Page.BORDER_MINIMAL; - - /* Target window border type constant: Default window border */ - public static final int TARGET_BORDER_DEFAULT = Page.BORDER_DEFAULT; - - private Resource resource = null; - - private String targetName; - - private int targetBorder = TARGET_BORDER_DEFAULT; - - private int targetWidth = -1; - - private int targetHeight = -1; - - /** - * Creates a new link. - */ - public Link() { - - } - - /** - * Creates a new instance of Link. - * - * @param caption - * @param resource - */ - public Link(String caption, Resource resource) { - setCaption(caption); - this.resource = resource; - } - - /** - * Creates a new instance of Link that opens a new window. - * - * - * @param caption - * the Link text. - * @param targetName - * the name of the target window where the link opens to. Empty - * name of null implies that the target is opened to the window - * containing the link. - * @param width - * the Width of the target window. - * @param height - * the Height of the target window. - * @param border - * the Border style of the target window. - * - */ - public Link(String caption, Resource resource, String targetName, - int width, int height, int border) { - setCaption(caption); - this.resource = resource; - setTargetName(targetName); - setTargetWidth(width); - setTargetHeight(height); - setTargetBorder(border); - } - - /** - * Paints the content of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - - if (resource != null) { - target.addAttribute("src", resource); - } else { - return; - } - - // Target window name - final String name = getTargetName(); - if (name != null && name.length() > 0) { - target.addAttribute("name", name); - } - - // Target window size - if (getTargetWidth() >= 0) { - target.addAttribute("targetWidth", getTargetWidth()); - } - if (getTargetHeight() >= 0) { - target.addAttribute("targetHeight", getTargetHeight()); - } - - // Target window border - switch (getTargetBorder()) { - case TARGET_BORDER_MINIMAL: - target.addAttribute("border", "minimal"); - break; - case TARGET_BORDER_NONE: - target.addAttribute("border", "none"); - break; - } - } - - /** - * Returns the target window border. - * - * @return the target window border. - */ - public int getTargetBorder() { - return targetBorder; - } - - /** - * Returns the target window height or -1 if not set. - * - * @return the target window height. - */ - public int getTargetHeight() { - return targetHeight < 0 ? -1 : targetHeight; - } - - /** - * Returns the target window name. Empty name of null implies that the - * target is opened to the window containing the link. - * - * @return the target window name. - */ - public String getTargetName() { - return targetName; - } - - /** - * Returns the target window width or -1 if not set. - * - * @return the target window width. - */ - public int getTargetWidth() { - return targetWidth < 0 ? -1 : targetWidth; - } - - /** - * Sets the border of the target window. - * - * @param targetBorder - * the targetBorder to set. - */ - public void setTargetBorder(int targetBorder) { - if (targetBorder == TARGET_BORDER_DEFAULT - || targetBorder == TARGET_BORDER_MINIMAL - || targetBorder == TARGET_BORDER_NONE) { - this.targetBorder = targetBorder; - requestRepaint(); - } - } - - /** - * Sets the target window height. - * - * @param targetHeight - * the targetHeight to set. - */ - public void setTargetHeight(int targetHeight) { - this.targetHeight = targetHeight; - requestRepaint(); - } - - /** - * Sets the target window name. - * - * @param targetName - * the targetName to set. - */ - public void setTargetName(String targetName) { - this.targetName = targetName; - requestRepaint(); - } - - /** - * Sets the target window width. - * - * @param targetWidth - * the targetWidth to set. - */ - public void setTargetWidth(int targetWidth) { - this.targetWidth = targetWidth; - requestRepaint(); - } - - /** - * Returns the resource this link opens. - * - * @return the Resource. - */ - public Resource getResource() { - return resource; - } - - /** - * Sets the resource this link opens. - * - * @param resource - * the resource to set. - */ - public void setResource(Resource resource) { - this.resource = resource; - requestRepaint(); - } - - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - // TODO Remove once Vaadin6Component is no longer implemented - } -} diff --git a/src/com/vaadin/ui/ListSelect.java b/src/com/vaadin/ui/ListSelect.java deleted file mode 100644 index 35ccb34b3c..0000000000 --- a/src/com/vaadin/ui/ListSelect.java +++ /dev/null @@ -1,96 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.Collection; - -import com.vaadin.data.Container; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; - -/** - * This is a simple list select without, for instance, support for new items, - * lazyloading, and other advanced features. - */ -@SuppressWarnings("serial") -public class ListSelect extends AbstractSelect { - - private int columns = 0; - private int rows = 0; - - public ListSelect() { - super(); - } - - public ListSelect(String caption, Collection<?> options) { - super(caption, options); - } - - public ListSelect(String caption, Container dataSource) { - super(caption, dataSource); - } - - public ListSelect(String caption) { - super(caption); - } - - /** - * Sets the number of columns in the editor. If the number of columns is set - * 0, the actual number of displayed columns is determined implicitly by the - * adapter. - * - * @param columns - * the number of columns to set. - */ - public void setColumns(int columns) { - if (columns < 0) { - columns = 0; - } - if (this.columns != columns) { - this.columns = columns; - requestRepaint(); - } - } - - public int getColumns() { - return columns; - } - - public int getRows() { - return rows; - } - - /** - * Sets the number of rows in the editor. If the number of rows is set 0, - * the actual number of displayed rows is determined implicitly by the - * adapter. - * - * @param rows - * the number of rows to set. - */ - public void setRows(int rows) { - if (rows < 0) { - rows = 0; - } - if (this.rows != rows) { - this.rows = rows; - requestRepaint(); - } - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - target.addAttribute("type", "list"); - // Adds the number of columns - if (columns != 0) { - target.addAttribute("cols", columns); - } - // Adds the number of rows - if (rows != 0) { - target.addAttribute("rows", rows); - } - super.paintContent(target); - } -} diff --git a/src/com/vaadin/ui/LoginForm.java b/src/com/vaadin/ui/LoginForm.java deleted file mode 100644 index db7e5f9dd9..0000000000 --- a/src/com/vaadin/ui/LoginForm.java +++ /dev/null @@ -1,353 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.Serializable; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import com.vaadin.Application; -import com.vaadin.terminal.ApplicationResource; -import com.vaadin.terminal.DownloadStream; -import com.vaadin.terminal.RequestHandler; -import com.vaadin.terminal.WrappedRequest; -import com.vaadin.terminal.WrappedResponse; -import com.vaadin.terminal.gwt.client.ApplicationConnection; - -/** - * LoginForm is a Vaadin component to handle common problem among Ajax - * applications: browsers password managers don't fill dynamically created forms - * like all those UI elements created by Vaadin. - * <p> - * For developer it is easy to use: add component to a desired place in you UI - * and add LoginListener to validate form input. Behind the curtain LoginForm - * creates an iframe with static html that browsers detect. - * <p> - * Login form is by default 100% width and height, so consider using it inside a - * sized {@link Panel} or {@link Window}. - * <p> - * Login page html can be overridden by replacing protected getLoginHTML method. - * As the login page is actually an iframe, styles must be handled manually. By - * default component tries to guess the right place for theme css. - * - * @since 5.3 - */ -public class LoginForm extends CustomComponent { - - private String usernameCaption = "Username"; - private String passwordCaption = "Password"; - private String loginButtonCaption = "Login"; - - private Embedded iframe = new Embedded(); - - private ApplicationResource loginPage = new ApplicationResource() { - - @Override - public Application getApplication() { - return LoginForm.this.getApplication(); - } - - @Override - public int getBufferSize() { - return getLoginHTML().length; - } - - @Override - public long getCacheTime() { - return -1; - } - - @Override - public String getFilename() { - return "login"; - } - - @Override - public DownloadStream getStream() { - return new DownloadStream(new ByteArrayInputStream(getLoginHTML()), - getMIMEType(), getFilename()); - } - - @Override - public String getMIMEType() { - return "text/html; charset=utf-8"; - } - }; - - private final RequestHandler requestHandler = new RequestHandler() { - @Override - public boolean handleRequest(Application application, - WrappedRequest request, WrappedResponse response) - throws IOException { - String requestPathInfo = request.getRequestPathInfo(); - if ("/loginHandler".equals(requestPathInfo)) { - response.setCacheTime(-1); - response.setContentType("text/html; charset=utf-8"); - response.getWriter() - .write("<html><body>Login form handled." - + "<script type='text/javascript'>parent.parent.vaadin.forceSync();" - + "</script></body></html>"); - - Map<String, String[]> parameters = request.getParameterMap(); - - HashMap<String, String> params = new HashMap<String, String>(); - // expecting single params - for (Iterator<String> it = parameters.keySet().iterator(); it - .hasNext();) { - String key = it.next(); - String value = (parameters.get(key))[0]; - params.put(key, value); - } - LoginEvent event = new LoginEvent(params); - fireEvent(event); - return true; - } - return false; - } - }; - - public LoginForm() { - iframe.setType(Embedded.TYPE_BROWSER); - iframe.setSizeFull(); - setSizeFull(); - setCompositionRoot(iframe); - addStyleName("v-loginform"); - } - - /** - * Returns byte array containing login page html. If you need to override - * the login html, use the default html as basis. Login page sets its target - * with javascript. - * - * @return byte array containing login page html - */ - protected byte[] getLoginHTML() { - String appUri = getApplication().getURL().toString(); - - try { - return ("<!DOCTYPE html PUBLIC \"-//W3C//DTD " - + "XHTML 1.0 Transitional//EN\" " - + "\"http://www.w3.org/TR/xhtml1/" - + "DTD/xhtml1-transitional.dtd\">\n" + "<html>" - + "<head><script type='text/javascript'>" - + "var setTarget = function() {" + "var uri = '" - + appUri - + "loginHandler" - + "'; var f = document.getElementById('loginf');" - + "document.forms[0].action = uri;document.forms[0].username.focus();};" - + "" - + "var styles = window.parent.document.styleSheets;" - + "for(var j = 0; j < styles.length; j++) {\n" - + "if(styles[j].href) {" - + "var stylesheet = document.createElement('link');\n" - + "stylesheet.setAttribute('rel', 'stylesheet');\n" - + "stylesheet.setAttribute('type', 'text/css');\n" - + "stylesheet.setAttribute('href', styles[j].href);\n" - + "document.getElementsByTagName('head')[0].appendChild(stylesheet);\n" - + "}" - + "}\n" - + "function submitOnEnter(e) { var keycode = e.keyCode || e.which;" - + " if (keycode == 13) {document.forms[0].submit();} } \n" - + "</script>" - + "</head><body onload='setTarget();' style='margin:0;padding:0; background:transparent;' class=\"" - + ApplicationConnection.GENERATED_BODY_CLASSNAME - + "\">" - + "<div class='v-app v-app-loginpage' style=\"background:transparent;\">" - + "<iframe name='logintarget' style='width:0;height:0;" - + "border:0;margin:0;padding:0;'></iframe>" - + "<form id='loginf' target='logintarget' onkeypress=\"submitOnEnter(event)\" method=\"post\">" - + "<div>" - + usernameCaption - + "</div><div >" - + "<input class='v-textfield v-connector' style='display:block;' type='text' name='username'></div>" - + "<div>" - + passwordCaption - + "</div>" - + "<div><input class='v-textfield v-connector' style='display:block;' type='password' name='password'></div>" - + "<div><div onclick=\"document.forms[0].submit();\" tabindex=\"0\" class=\"v-button\" role=\"button\" ><span class=\"v-button-wrap\"><span class=\"v-button-caption\">" - + loginButtonCaption - + "</span></span></div></div></form></div>" + "</body></html>") - .getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("UTF-8 encoding not avalable", e); - } - } - - @Override - public void attach() { - super.attach(); - getApplication().addResource(loginPage); - getApplication().addRequestHandler(requestHandler); - iframe.setSource(loginPage); - } - - @Override - public void detach() { - getApplication().removeResource(loginPage); - getApplication().removeRequestHandler(requestHandler); - - super.detach(); - } - - /** - * This event is sent when login form is submitted. - */ - public class LoginEvent extends Event { - - private Map<String, String> params; - - private LoginEvent(Map<String, String> params) { - super(LoginForm.this); - this.params = params; - } - - /** - * Access method to form values by field names. - * - * @param name - * @return value in given field - */ - public String getLoginParameter(String name) { - if (params.containsKey(name)) { - return params.get(name); - } else { - return null; - } - } - } - - /** - * Login listener is a class capable to listen LoginEvents sent from - * LoginBox - */ - public interface LoginListener extends Serializable { - /** - * This method is fired on each login form post. - * - * @param event - */ - public void onLogin(LoginForm.LoginEvent event); - } - - private static final Method ON_LOGIN_METHOD; - - private static final String UNDEFINED_HEIGHT = "140px"; - private static final String UNDEFINED_WIDTH = "200px"; - - static { - try { - ON_LOGIN_METHOD = LoginListener.class.getDeclaredMethod("onLogin", - new Class[] { LoginEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException( - "Internal error finding methods in LoginForm"); - } - } - - /** - * Adds LoginListener to handle login logic - * - * @param listener - */ - public void addListener(LoginListener listener) { - addListener(LoginEvent.class, listener, ON_LOGIN_METHOD); - } - - /** - * Removes LoginListener - * - * @param listener - */ - public void removeListener(LoginListener listener) { - removeListener(LoginEvent.class, listener, ON_LOGIN_METHOD); - } - - @Override - public void setWidth(float width, Unit unit) { - super.setWidth(width, unit); - if (iframe != null) { - if (width < 0) { - iframe.setWidth(UNDEFINED_WIDTH); - } else { - iframe.setWidth("100%"); - } - } - } - - @Override - public void setHeight(float height, Unit unit) { - super.setHeight(height, unit); - if (iframe != null) { - if (height < 0) { - iframe.setHeight(UNDEFINED_HEIGHT); - } else { - iframe.setHeight("100%"); - } - } - } - - /** - * Returns the caption for the user name field. - * - * @return String - */ - public String getUsernameCaption() { - return usernameCaption; - } - - /** - * Sets the caption to show for the user name field. The caption cannot be - * changed after the form has been shown to the user. - * - * @param usernameCaption - */ - public void setUsernameCaption(String usernameCaption) { - this.usernameCaption = usernameCaption; - } - - /** - * Returns the caption for the password field. - * - * @return String - */ - public String getPasswordCaption() { - return passwordCaption; - } - - /** - * Sets the caption to show for the password field. The caption cannot be - * changed after the form has been shown to the user. - * - * @param passwordCaption - */ - public void setPasswordCaption(String passwordCaption) { - this.passwordCaption = passwordCaption; - } - - /** - * Returns the caption for the login button. - * - * @return String - */ - public String getLoginButtonCaption() { - return loginButtonCaption; - } - - /** - * Sets the caption (button text) to show for the login button. The caption - * cannot be changed after the form has been shown to the user. - * - * @param loginButtonCaption - */ - public void setLoginButtonCaption(String loginButtonCaption) { - this.loginButtonCaption = loginButtonCaption; - } - -} diff --git a/src/com/vaadin/ui/MenuBar.java b/src/com/vaadin/ui/MenuBar.java deleted file mode 100644 index 5b5dc13e20..0000000000 --- a/src/com/vaadin/ui/MenuBar.java +++ /dev/null @@ -1,890 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Stack; - -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.gwt.client.ui.menubar.VMenuBar; - -/** - * <p> - * A class representing a horizontal menu bar. The menu can contain MenuItem - * objects, which in turn can contain more MenuBars. These sub-level MenuBars - * are represented as vertical menu. - * </p> - */ -@SuppressWarnings("serial") -public class MenuBar extends AbstractComponent implements Vaadin6Component { - - // Items of the top-level menu - private final List<MenuItem> menuItems; - - // Number of items in this menu - private int numberOfItems = 0; - - private MenuItem moreItem; - - private boolean openRootOnHover; - - private boolean htmlContentAllowed; - - /** Paint (serialise) the component for the client. */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - target.addAttribute(VMenuBar.OPEN_ROOT_MENU_ON_HOWER, openRootOnHover); - - if (isHtmlContentAllowed()) { - target.addAttribute(VMenuBar.HTML_CONTENT_ALLOWED, true); - } - - target.startTag("options"); - - if (getWidth() > -1) { - target.startTag("moreItem"); - target.addAttribute("text", moreItem.getText()); - if (moreItem.getIcon() != null) { - target.addAttribute("icon", moreItem.getIcon()); - } - target.endTag("moreItem"); - } - - target.endTag("options"); - target.startTag("items"); - - // This generates the tree from the contents of the menu - for (MenuItem item : menuItems) { - paintItem(target, item); - } - - target.endTag("items"); - } - - private void paintItem(PaintTarget target, MenuItem item) - throws PaintException { - if (!item.isVisible()) { - return; - } - - target.startTag("item"); - - target.addAttribute("id", item.getId()); - - if (item.getStyleName() != null) { - target.addAttribute(VMenuBar.ATTRIBUTE_ITEM_STYLE, - item.getStyleName()); - } - - if (item.isSeparator()) { - target.addAttribute("separator", true); - } else { - target.addAttribute("text", item.getText()); - - Command command = item.getCommand(); - if (command != null) { - target.addAttribute("command", true); - } - - Resource icon = item.getIcon(); - if (icon != null) { - target.addAttribute(VMenuBar.ATTRIBUTE_ITEM_ICON, icon); - } - - if (!item.isEnabled()) { - target.addAttribute(VMenuBar.ATTRIBUTE_ITEM_DISABLED, true); - } - - String description = item.getDescription(); - if (description != null && description.length() > 0) { - target.addAttribute(VMenuBar.ATTRIBUTE_ITEM_DESCRIPTION, - description); - } - if (item.isCheckable()) { - // if the "checked" attribute is present (either true or false), - // the item is checkable - target.addAttribute(VMenuBar.ATTRIBUTE_CHECKED, - item.isChecked()); - } - if (item.hasChildren()) { - for (MenuItem child : item.getChildren()) { - paintItem(target, child); - } - } - - } - - target.endTag("item"); - } - - /** Deserialize changes received from client. */ - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - Stack<MenuItem> items = new Stack<MenuItem>(); - boolean found = false; - - if (variables.containsKey("clickedId")) { - - Integer clickedId = (Integer) variables.get("clickedId"); - Iterator<MenuItem> itr = getItems().iterator(); - while (itr.hasNext()) { - items.push(itr.next()); - } - - MenuItem tmpItem = null; - - // Go through all the items in the menu - while (!found && !items.empty()) { - tmpItem = items.pop(); - found = (clickedId.intValue() == tmpItem.getId()); - - if (tmpItem.hasChildren()) { - itr = tmpItem.getChildren().iterator(); - while (itr.hasNext()) { - items.push(itr.next()); - } - } - - }// while - - // If we got the clicked item, launch the command. - if (found && tmpItem.isEnabled()) { - if (tmpItem.isCheckable()) { - tmpItem.setChecked(!tmpItem.isChecked()); - } - if (null != tmpItem.getCommand()) { - tmpItem.getCommand().menuSelected(tmpItem); - } - } - }// if - }// changeVariables - - /** - * Constructs an empty, horizontal menu - */ - public MenuBar() { - menuItems = new ArrayList<MenuItem>(); - setMoreMenuItem(null); - } - - /** - * Add a new item to the menu bar. Command can be null, but a caption must - * be given. - * - * @param caption - * the text for the menu item - * @param command - * the command for the menu item - * @throws IllegalArgumentException - */ - public MenuBar.MenuItem addItem(String caption, MenuBar.Command command) { - return addItem(caption, null, command); - } - - /** - * Add a new item to the menu bar. Icon and command can be null, but a - * caption must be given. - * - * @param caption - * the text for the menu item - * @param icon - * the icon for the menu item - * @param command - * the command for the menu item - * @throws IllegalArgumentException - */ - public MenuBar.MenuItem addItem(String caption, Resource icon, - MenuBar.Command command) { - if (caption == null) { - throw new IllegalArgumentException("caption cannot be null"); - } - MenuItem newItem = new MenuItem(caption, icon, command); - menuItems.add(newItem); - requestRepaint(); - - return newItem; - - } - - /** - * Add an item before some item. If the given item does not exist the item - * is added at the end of the menu. Icon and command can be null, but a - * caption must be given. - * - * @param caption - * the text for the menu item - * @param icon - * the icon for the menu item - * @param command - * the command for the menu item - * @param itemToAddBefore - * the item that will be after the new item - * @throws IllegalArgumentException - */ - public MenuBar.MenuItem addItemBefore(String caption, Resource icon, - MenuBar.Command command, MenuBar.MenuItem itemToAddBefore) { - if (caption == null) { - throw new IllegalArgumentException("caption cannot be null"); - } - - MenuItem newItem = new MenuItem(caption, icon, command); - if (menuItems.contains(itemToAddBefore)) { - int index = menuItems.indexOf(itemToAddBefore); - menuItems.add(index, newItem); - - } else { - menuItems.add(newItem); - } - - requestRepaint(); - - return newItem; - } - - /** - * Returns a list with all the MenuItem objects in the menu bar - * - * @return a list containing the MenuItem objects in the menu bar - */ - public List<MenuItem> getItems() { - return menuItems; - } - - /** - * Remove first occurrence the specified item from the main menu - * - * @param item - * The item to be removed - */ - public void removeItem(MenuBar.MenuItem item) { - if (item != null) { - menuItems.remove(item); - } - requestRepaint(); - } - - /** - * Empty the menu bar - */ - public void removeItems() { - menuItems.clear(); - requestRepaint(); - } - - /** - * Returns the size of the menu. - * - * @return The size of the menu - */ - public int getSize() { - return menuItems.size(); - } - - /** - * Set the item that is used when collapsing the top level menu. All - * "overflowing" items will be added below this. The item command will be - * ignored. If set to null, the default item with a downwards arrow is used. - * - * The item command (if specified) is ignored. - * - * @param item - */ - public void setMoreMenuItem(MenuItem item) { - if (item != null) { - moreItem = item; - } else { - moreItem = new MenuItem("", null, null); - } - requestRepaint(); - } - - /** - * Get the MenuItem used as the collapse menu item. - * - * @return - */ - public MenuItem getMoreMenuItem() { - return moreItem; - } - - /** - * Using this method menubar can be put into a special mode where top level - * menus opens without clicking on the menu, but automatically when mouse - * cursor is moved over the menu. In this mode the menu also closes itself - * if the mouse is moved out of the opened menu. - * <p> - * Note, that on touch devices the menu still opens on a click event. - * - * @param autoOpenTopLevelMenu - * true if menus should be opened without click, the default is - * false - */ - public void setAutoOpen(boolean autoOpenTopLevelMenu) { - if (autoOpenTopLevelMenu != openRootOnHover) { - openRootOnHover = autoOpenTopLevelMenu; - requestRepaint(); - } - } - - /** - * Detects whether the menubar is in a mode where top level menus are - * automatically opened when the mouse cursor is moved over the menu. - * Normally root menu opens only by clicking on the menu. Submenus always - * open automatically. - * - * @return true if the root menus open without click, the default is false - */ - public boolean isAutoOpen() { - return openRootOnHover; - } - - /** - * Sets whether html is allowed in the item captions. If set to true, the - * captions are passed to the browser as html and the developer is - * responsible for ensuring no harmful html is used. If set to false, the - * content is passed to the browser as plain text. - * - * @param htmlContentAllowed - * true if the captions are used as html, false if used as plain - * text - */ - public void setHtmlContentAllowed(boolean htmlContentAllowed) { - this.htmlContentAllowed = htmlContentAllowed; - requestRepaint(); - } - - /** - * Checks whether item captions are interpreted as html or plain text. - * - * @return true if the captions are used as html, false if used as plain - * text - * @see #setHtmlContentAllowed(boolean) - */ - public boolean isHtmlContentAllowed() { - return htmlContentAllowed; - } - - /** - * This interface contains the layer for menu commands of the - * {@link com.vaadin.ui.MenuBar} class. It's method will fire when the user - * clicks on the containing {@link com.vaadin.ui.MenuBar.MenuItem}. The - * selected item is given as an argument. - */ - public interface Command extends Serializable { - public void menuSelected(MenuBar.MenuItem selectedItem); - } - - /** - * A composite class for menu items and sub-menus. You can set commands to - * be fired on user click by implementing the - * {@link com.vaadin.ui.MenuBar.Command} interface. You can also add - * multiple MenuItems to a MenuItem and create a sub-menu. - * - */ - public class MenuItem implements Serializable { - - /** Private members * */ - private final int itsId; - private Command itsCommand; - private String itsText; - private List<MenuItem> itsChildren; - private Resource itsIcon; - private MenuItem itsParent; - private boolean enabled = true; - private boolean visible = true; - private boolean isSeparator = false; - private String styleName; - private String description; - private boolean checkable = false; - private boolean checked = false; - - /** - * Constructs a new menu item that can optionally have an icon and a - * command associated with it. Icon and command can be null, but a - * caption must be given. - * - * @param text - * The text associated with the command - * @param command - * The command to be fired - * @throws IllegalArgumentException - */ - public MenuItem(String caption, Resource icon, MenuBar.Command command) { - if (caption == null) { - throw new IllegalArgumentException("caption cannot be null"); - } - itsId = ++numberOfItems; - itsText = caption; - itsIcon = icon; - itsCommand = command; - } - - /** - * Checks if the item has children (if it is a sub-menu). - * - * @return True if this item has children - */ - public boolean hasChildren() { - return !isSeparator() && itsChildren != null; - } - - /** - * Adds a separator to this menu. A separator is a way to visually group - * items in a menu, to make it easier for users to find what they are - * looking for in the menu. - * - * @author Jouni Koivuviita / Vaadin Ltd. - * @since 6.2.0 - */ - public MenuBar.MenuItem addSeparator() { - MenuItem item = addItem("", null, null); - item.setSeparator(true); - return item; - } - - public MenuBar.MenuItem addSeparatorBefore(MenuItem itemToAddBefore) { - MenuItem item = addItemBefore("", null, null, itemToAddBefore); - item.setSeparator(true); - return item; - } - - /** - * Add a new item inside this item, thus creating a sub-menu. Command - * can be null, but a caption must be given. - * - * @param caption - * the text for the menu item - * @param command - * the command for the menu item - */ - public MenuBar.MenuItem addItem(String caption, MenuBar.Command command) { - return addItem(caption, null, command); - } - - /** - * Add a new item inside this item, thus creating a sub-menu. Icon and - * command can be null, but a caption must be given. - * - * @param caption - * the text for the menu item - * @param icon - * the icon for the menu item - * @param command - * the command for the menu item - * @throws IllegalStateException - * If the item is checkable and thus cannot have children. - */ - public MenuBar.MenuItem addItem(String caption, Resource icon, - MenuBar.Command command) throws IllegalStateException { - if (isSeparator()) { - throw new UnsupportedOperationException( - "Cannot add items to a separator"); - } - if (isCheckable()) { - throw new IllegalStateException( - "A checkable item cannot have children"); - } - if (caption == null) { - throw new IllegalArgumentException("Caption cannot be null"); - } - - if (itsChildren == null) { - itsChildren = new ArrayList<MenuItem>(); - } - - MenuItem newItem = new MenuItem(caption, icon, command); - - // The only place where the parent is set - newItem.setParent(this); - itsChildren.add(newItem); - - requestRepaint(); - - return newItem; - } - - /** - * Add an item before some item. If the given item does not exist the - * item is added at the end of the menu. Icon and command can be null, - * but a caption must be given. - * - * @param caption - * the text for the menu item - * @param icon - * the icon for the menu item - * @param command - * the command for the menu item - * @param itemToAddBefore - * the item that will be after the new item - * @throws IllegalStateException - * If the item is checkable and thus cannot have children. - */ - public MenuBar.MenuItem addItemBefore(String caption, Resource icon, - MenuBar.Command command, MenuBar.MenuItem itemToAddBefore) - throws IllegalStateException { - if (isCheckable()) { - throw new IllegalStateException( - "A checkable item cannot have children"); - } - MenuItem newItem = null; - - if (hasChildren() && itsChildren.contains(itemToAddBefore)) { - int index = itsChildren.indexOf(itemToAddBefore); - newItem = new MenuItem(caption, icon, command); - newItem.setParent(this); - itsChildren.add(index, newItem); - } else { - newItem = addItem(caption, icon, command); - } - - requestRepaint(); - - return newItem; - } - - /** - * For the associated command. - * - * @return The associated command, or null if there is none - */ - public Command getCommand() { - return itsCommand; - } - - /** - * Gets the objects icon. - * - * @return The icon of the item, null if the item doesn't have an icon - */ - public Resource getIcon() { - return itsIcon; - } - - /** - * For the containing item. This will return null if the item is in the - * top-level menu bar. - * - * @return The containing {@link com.vaadin.ui.MenuBar.MenuItem} , or - * null if there is none - */ - public MenuBar.MenuItem getParent() { - return itsParent; - } - - /** - * This will return the children of this item or null if there are none. - * - * @return List of children items, or null if there are none - */ - public List<MenuItem> getChildren() { - return itsChildren; - } - - /** - * Gets the objects text - * - * @return The text - */ - public java.lang.String getText() { - return itsText; - } - - /** - * Returns the number of children. - * - * @return The number of child items - */ - public int getSize() { - if (itsChildren != null) { - return itsChildren.size(); - } - return -1; - } - - /** - * Get the unique identifier for this item. - * - * @return The id of this item - */ - public int getId() { - return itsId; - } - - /** - * Set the command for this item. Set null to remove. - * - * @param command - * The MenuCommand of this item - */ - public void setCommand(MenuBar.Command command) { - itsCommand = command; - } - - /** - * Sets the icon. Set null to remove. - * - * @param icon - * The icon for this item - */ - public void setIcon(Resource icon) { - itsIcon = icon; - requestRepaint(); - } - - /** - * Set the text of this object. - * - * @param text - * Text for this object - */ - public void setText(java.lang.String text) { - if (text != null) { - itsText = text; - } - requestRepaint(); - } - - /** - * Remove the first occurrence of the item. - * - * @param item - * The item to be removed - */ - public void removeChild(MenuBar.MenuItem item) { - if (item != null && itsChildren != null) { - itsChildren.remove(item); - if (itsChildren.isEmpty()) { - itsChildren = null; - } - requestRepaint(); - } - } - - /** - * Empty the list of children items. - */ - public void removeChildren() { - if (itsChildren != null) { - itsChildren.clear(); - itsChildren = null; - requestRepaint(); - } - } - - /** - * Set the parent of this item. This is called by the addItem method. - * - * @param parent - * The parent item - */ - protected void setParent(MenuBar.MenuItem parent) { - itsParent = parent; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - requestRepaint(); - } - - public boolean isEnabled() { - return enabled; - } - - public void setVisible(boolean visible) { - this.visible = visible; - requestRepaint(); - } - - public boolean isVisible() { - return visible; - } - - private void setSeparator(boolean isSeparator) { - this.isSeparator = isSeparator; - requestRepaint(); - } - - public boolean isSeparator() { - return isSeparator; - } - - public void setStyleName(String styleName) { - this.styleName = styleName; - requestRepaint(); - } - - public String getStyleName() { - return styleName; - } - - /** - * Sets the items's description. See {@link #getDescription()} for more - * information on what the description is. This method will trigger a - * {@link RepaintRequestEvent}. - * - * @param description - * the new description string for the component. - */ - public void setDescription(String description) { - this.description = description; - requestRepaint(); - } - - /** - * <p> - * Gets the items's description. The description can be used to briefly - * describe the state of the item to the user. The description string - * may contain certain XML tags: - * </p> - * - * <p> - * <table border=1> - * <tr> - * <td width=120><b>Tag</b></td> - * <td width=120><b>Description</b></td> - * <td width=120><b>Example</b></td> - * </tr> - * <tr> - * <td><b></td> - * <td>bold</td> - * <td><b>bold text</b></td> - * </tr> - * <tr> - * <td><i></td> - * <td>italic</td> - * <td><i>italic text</i></td> - * </tr> - * <tr> - * <td><u></td> - * <td>underlined</td> - * <td><u>underlined text</u></td> - * </tr> - * <tr> - * <td><br></td> - * <td>linebreak</td> - * <td>N/A</td> - * </tr> - * <tr> - * <td><ul><br> - * <li>item1<br> - * <li>item1<br> - * </ul></td> - * <td>item list</td> - * <td> - * <ul> - * <li>item1 - * <li>item2 - * </ul> - * </td> - * </tr> - * </table> - * </p> - * - * <p> - * These tags may be nested. - * </p> - * - * @return item's description <code>String</code> - */ - public String getDescription() { - return description; - } - - /** - * Gets the checkable state of the item - whether the item has checked - * and unchecked states. If an item is checkable its checked state (as - * returned by {@link #isChecked()}) is indicated in the UI. - * - * <p> - * An item is not checkable by default. - * </p> - * - * @return true if the item is checkable, false otherwise - * @since 6.6.2 - */ - public boolean isCheckable() { - return checkable; - } - - /** - * Sets the checkable state of the item. If an item is checkable its - * checked state (as returned by {@link #isChecked()}) is indicated in - * the UI. - * - * <p> - * An item is not checkable by default. - * </p> - * - * <p> - * Items with sub items cannot be checkable. - * </p> - * - * @param checkable - * true if the item should be checkable, false otherwise - * @throws IllegalStateException - * If the item has children - * @since 6.6.2 - */ - public void setCheckable(boolean checkable) - throws IllegalStateException { - if (hasChildren()) { - throw new IllegalStateException( - "A menu item with children cannot be checkable"); - } - this.checkable = checkable; - requestRepaint(); - } - - /** - * Gets the checked state of the item (checked or unchecked). Only used - * if the item is checkable (as indicated by {@link #isCheckable()}). - * The checked state is indicated in the UI with the item, if the item - * is checkable. - * - * <p> - * An item is not checked by default. - * </p> - * - * <p> - * The CSS style corresponding to the checked state is "-checked". - * </p> - * - * @return true if the item is checked, false otherwise - * @since 6.6.2 - */ - public boolean isChecked() { - return checked; - } - - /** - * Sets the checked state of the item. Only used if the item is - * checkable (indicated by {@link #isCheckable()}). The checked state is - * indicated in the UI with the item, if the item is checkable. - * - * <p> - * An item is not checked by default. - * </p> - * - * <p> - * The CSS style corresponding to the checked state is "-checked". - * </p> - * - * @return true if the item is checked, false otherwise - * @since 6.6.2 - */ - public void setChecked(boolean checked) { - this.checked = checked; - requestRepaint(); - } - - }// class MenuItem - -}// class MenuBar diff --git a/src/com/vaadin/ui/NativeButton.java b/src/com/vaadin/ui/NativeButton.java deleted file mode 100644 index 6eb4379261..0000000000 --- a/src/com/vaadin/ui/NativeButton.java +++ /dev/null @@ -1,21 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -@SuppressWarnings("serial") -public class NativeButton extends Button { - - public NativeButton() { - super(); - } - - public NativeButton(String caption) { - super(caption); - } - - public NativeButton(String caption, ClickListener listener) { - super(caption, listener); - } - -} diff --git a/src/com/vaadin/ui/NativeSelect.java b/src/com/vaadin/ui/NativeSelect.java deleted file mode 100644 index 1f85f57c97..0000000000 --- a/src/com/vaadin/ui/NativeSelect.java +++ /dev/null @@ -1,91 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.Collection; - -import com.vaadin.data.Container; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; - -/** - * This is a simple drop-down select without, for instance, support for - * multiselect, new items, lazyloading, and other advanced features. Sometimes - * "native" select without all the bells-and-whistles of the ComboBox is a - * better choice. - */ -@SuppressWarnings("serial") -public class NativeSelect extends AbstractSelect { - - // width in characters, mimics TextField - private int columns = 0; - - public NativeSelect() { - super(); - } - - public NativeSelect(String caption, Collection<?> options) { - super(caption, options); - } - - public NativeSelect(String caption, Container dataSource) { - super(caption, dataSource); - } - - public NativeSelect(String caption) { - super(caption); - } - - /** - * Sets the number of columns in the editor. If the number of columns is set - * 0, the actual number of displayed columns is determined implicitly by the - * adapter. - * - * @param columns - * the number of columns to set. - */ - public void setColumns(int columns) { - if (columns < 0) { - columns = 0; - } - if (this.columns != columns) { - this.columns = columns; - requestRepaint(); - } - } - - public int getColumns() { - return columns; - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - target.addAttribute("type", "native"); - // Adds the number of columns - if (columns != 0) { - target.addAttribute("cols", columns); - } - - super.paintContent(target); - } - - @Override - public void setMultiSelect(boolean multiSelect) - throws UnsupportedOperationException { - if (multiSelect == true) { - throw new UnsupportedOperationException("Multiselect not supported"); - } - } - - @Override - public void setNewItemsAllowed(boolean allowNewOptions) - throws UnsupportedOperationException { - if (allowNewOptions == true) { - throw new UnsupportedOperationException( - "newItemsAllowed not supported"); - } - } - -} diff --git a/src/com/vaadin/ui/Notification.java b/src/com/vaadin/ui/Notification.java deleted file mode 100644 index 502e5ff788..0000000000 --- a/src/com/vaadin/ui/Notification.java +++ /dev/null @@ -1,367 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; - -import com.vaadin.terminal.Page; -import com.vaadin.terminal.Resource; - -/** - * A notification message, used to display temporary messages to the user - for - * example "Document saved", or "Save failed". - * <p> - * The notification message can consist of several parts: caption, description - * and icon. It is usually used with only caption - one should be wary of - * filling the notification with too much information. - * </p> - * <p> - * The notification message tries to be as unobtrusive as possible, while still - * drawing needed attention. There are several basic types of messages that can - * be used in different situations: - * <ul> - * <li>TYPE_HUMANIZED_MESSAGE fades away quickly as soon as the user uses the - * mouse or types something. It can be used to show fairly unimportant messages, - * such as feedback that an operation succeeded ("Document Saved") - the kind of - * messages the user ignores once the application is familiar.</li> - * <li>TYPE_WARNING_MESSAGE is shown for a short while after the user uses the - * mouse or types something. It's default style is also more noticeable than the - * humanized message. It can be used for messages that do not contain a lot of - * important information, but should be noticed by the user. Despite the name, - * it does not have to be a warning, but can be used instead of the humanized - * message whenever you want to make the message a little more noticeable.</li> - * <li>TYPE_ERROR_MESSAGE requires to user to click it before disappearing, and - * can be used for critical messages.</li> - * <li>TYPE_TRAY_NOTIFICATION is shown for a while in the lower left corner of - * the window, and can be used for "convenience notifications" that do not have - * to be noticed immediately, and should not interfere with the current task - - * for instance to show "You have a new message in your inbox" while the user is - * working in some other area of the application.</li> - * </ul> - * </p> - * <p> - * In addition to the basic pre-configured types, a Notification can also be - * configured to show up in a custom position, for a specified time (or until - * clicked), and with a custom stylename. An icon can also be added. - * </p> - * - */ -public class Notification implements Serializable { - public static final int TYPE_HUMANIZED_MESSAGE = 1; - public static final int TYPE_WARNING_MESSAGE = 2; - public static final int TYPE_ERROR_MESSAGE = 3; - public static final int TYPE_TRAY_NOTIFICATION = 4; - - public static final int POSITION_CENTERED = 1; - public static final int POSITION_CENTERED_TOP = 2; - public static final int POSITION_CENTERED_BOTTOM = 3; - public static final int POSITION_TOP_LEFT = 4; - public static final int POSITION_TOP_RIGHT = 5; - public static final int POSITION_BOTTOM_LEFT = 6; - public static final int POSITION_BOTTOM_RIGHT = 7; - - public static final int DELAY_FOREVER = -1; - public static final int DELAY_NONE = 0; - - private String caption; - private String description; - private Resource icon; - private int position = POSITION_CENTERED; - private int delayMsec = 0; - private String styleName; - private boolean htmlContentAllowed; - - /** - * Creates a "humanized" notification message. - * - * The caption is rendered as plain text with HTML automatically escaped. - * - * @param caption - * The message to show - */ - public Notification(String caption) { - this(caption, null, TYPE_HUMANIZED_MESSAGE); - } - - /** - * Creates a notification message of the specified type. - * - * The caption is rendered as plain text with HTML automatically escaped. - * - * @param caption - * The message to show - * @param type - * The type of message - */ - public Notification(String caption, int type) { - this(caption, null, type); - } - - /** - * Creates a "humanized" notification message with a bigger caption and - * smaller description. - * - * The caption and description are rendered as plain text with HTML - * automatically escaped. - * - * @param caption - * The message caption - * @param description - * The message description - */ - public Notification(String caption, String description) { - this(caption, description, TYPE_HUMANIZED_MESSAGE); - } - - /** - * Creates a notification message of the specified type, with a bigger - * caption and smaller description. - * - * The caption and description are rendered as plain text with HTML - * automatically escaped. - * - * @param caption - * The message caption - * @param description - * The message description - * @param type - * The type of message - */ - public Notification(String caption, String description, int type) { - this(caption, description, type, false); - } - - /** - * Creates a notification message of the specified type, with a bigger - * caption and smaller description. - * - * Care should be taken to to avoid XSS vulnerabilities if html is allowed. - * - * @param caption - * The message caption - * @param description - * The message description - * @param type - * The type of message - * @param htmlContentAllowed - * Whether html in the caption and description should be - * displayed as html or as plain text - */ - public Notification(String caption, String description, int type, - boolean htmlContentAllowed) { - this.caption = caption; - this.description = description; - this.htmlContentAllowed = htmlContentAllowed; - setType(type); - } - - private void setType(int type) { - switch (type) { - case TYPE_WARNING_MESSAGE: - delayMsec = 1500; - styleName = "warning"; - break; - case TYPE_ERROR_MESSAGE: - delayMsec = -1; - styleName = "error"; - break; - case TYPE_TRAY_NOTIFICATION: - delayMsec = 3000; - position = POSITION_BOTTOM_RIGHT; - styleName = "tray"; - - case TYPE_HUMANIZED_MESSAGE: - default: - break; - } - - } - - /** - * Gets the caption part of the notification message. - * - * @return The message caption - */ - public String getCaption() { - return caption; - } - - /** - * Sets the caption part of the notification message - * - * @param caption - * The message caption - */ - public void setCaption(String caption) { - this.caption = caption; - } - - /** - * Gets the description part of the notification message. - * - * @return The message description. - */ - public String getDescription() { - return description; - } - - /** - * Sets the description part of the notification message. - * - * @param description - */ - public void setDescription(String description) { - this.description = description; - } - - /** - * Gets the position of the notification message. - * - * @return The position - */ - public int getPosition() { - return position; - } - - /** - * Sets the position of the notification message. - * - * @param position - * The desired notification position - */ - public void setPosition(int position) { - this.position = position; - } - - /** - * Gets the icon part of the notification message. - * - * @return The message icon - */ - public Resource getIcon() { - return icon; - } - - /** - * Sets the icon part of the notification message. - * - * @param icon - * The desired message icon - */ - public void setIcon(Resource icon) { - this.icon = icon; - } - - /** - * Gets the delay before the notification disappears. - * - * @return the delay in msec, -1 indicates the message has to be clicked. - */ - public int getDelayMsec() { - return delayMsec; - } - - /** - * Sets the delay before the notification disappears. - * - * @param delayMsec - * the desired delay in msec, -1 to require the user to click the - * message - */ - public void setDelayMsec(int delayMsec) { - this.delayMsec = delayMsec; - } - - /** - * Sets the style name for the notification message. - * - * @param styleName - * The desired style name. - */ - public void setStyleName(String styleName) { - this.styleName = styleName; - } - - /** - * Gets the style name for the notification message. - * - * @return - */ - public String getStyleName() { - return styleName; - } - - /** - * Sets whether html is allowed in the caption and description. If set to - * true, the texts are passed to the browser as html and the developer is - * responsible for ensuring no harmful html is used. If set to false, the - * texts are passed to the browser as plain text. - * - * @param htmlContentAllowed - * true if the texts are used as html, false if used as plain - * text - */ - public void setHtmlContentAllowed(boolean htmlContentAllowed) { - this.htmlContentAllowed = htmlContentAllowed; - } - - /** - * Checks whether caption and description are interpreted as html or plain - * text. - * - * @return true if the texts are used as html, false if used as plain text - * @see #setHtmlContentAllowed(boolean) - */ - public boolean isHtmlContentAllowed() { - return htmlContentAllowed; - } - - /** - * Shows this notification on a Page. - * - * @param page - * The page on which the notification should be shown - */ - public void show(Page page) { - // TODO Can avoid deprecated API when Notification extends Extension - page.showNotification(this); - } - - /** - * Shows a notification message on the middle of the current page. The - * message automatically disappears ("humanized message"). - * - * The caption is rendered as plain text with HTML automatically escaped. - * - * @see #Notification(String) - * @see #show(Page) - * - * @param caption - * The message - */ - public static void show(String caption) { - new Notification(caption).show(Page.getCurrent()); - } - - /** - * Shows a notification message the current page. The position and behavior - * of the message depends on the type, which is one of the basic types - * defined in {@link Notification}, for instance - * Notification.TYPE_WARNING_MESSAGE. - * - * The caption is rendered as plain text with HTML automatically escaped. - * - * @see #Notification(String, int) - * @see #show(Page) - * - * @param caption - * The message - * @param type - * The message type - */ - public static void show(String caption, int type) { - new Notification(caption, type).show(Page.getCurrent()); - } -}
\ No newline at end of file diff --git a/src/com/vaadin/ui/OptionGroup.java b/src/com/vaadin/ui/OptionGroup.java deleted file mode 100644 index e3bcdd61b7..0000000000 --- a/src/com/vaadin/ui/OptionGroup.java +++ /dev/null @@ -1,203 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import com.vaadin.data.Container; -import com.vaadin.event.FieldEvents; -import com.vaadin.event.FieldEvents.BlurEvent; -import com.vaadin.event.FieldEvents.BlurListener; -import com.vaadin.event.FieldEvents.FocusEvent; -import com.vaadin.event.FieldEvents.FocusListener; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.gwt.client.ui.optiongroup.VOptionGroup; - -/** - * Configures select to be used as an option group. - */ -@SuppressWarnings("serial") -public class OptionGroup extends AbstractSelect implements - FieldEvents.BlurNotifier, FieldEvents.FocusNotifier { - - private Set<Object> disabledItemIds = new HashSet<Object>(); - private boolean htmlContentAllowed = false; - - public OptionGroup() { - super(); - } - - public OptionGroup(String caption, Collection<?> options) { - super(caption, options); - } - - public OptionGroup(String caption, Container dataSource) { - super(caption, dataSource); - } - - public OptionGroup(String caption) { - super(caption); - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - target.addAttribute("type", "optiongroup"); - if (isHtmlContentAllowed()) { - target.addAttribute(VOptionGroup.HTML_CONTENT_ALLOWED, true); - } - super.paintContent(target); - } - - @Override - protected void paintItem(PaintTarget target, Object itemId) - throws PaintException { - super.paintItem(target, itemId); - if (!isItemEnabled(itemId)) { - target.addAttribute(VOptionGroup.ATTRIBUTE_OPTION_DISABLED, true); - } - } - - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - super.changeVariables(source, variables); - - if (variables.containsKey(FocusEvent.EVENT_ID)) { - fireEvent(new FocusEvent(this)); - } - if (variables.containsKey(BlurEvent.EVENT_ID)) { - fireEvent(new BlurEvent(this)); - } - } - - @Override - public void addListener(BlurListener listener) { - addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, - BlurListener.blurMethod); - } - - @Override - public void removeListener(BlurListener listener) { - removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); - } - - @Override - public void addListener(FocusListener listener) { - addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, - FocusListener.focusMethod); - } - - @Override - public void removeListener(FocusListener listener) { - removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); - - } - - @Override - protected void setValue(Object newValue, boolean repaintIsNotNeeded) { - if (repaintIsNotNeeded) { - /* - * Check that value from changeVariables() doesn't contain unallowed - * selections: In the multi select mode, the user has selected or - * deselected a disabled item. In the single select mode, the user - * has selected a disabled item. - */ - if (isMultiSelect()) { - Set<?> currentValueSet = (Set<?>) getValue(); - Set<?> newValueSet = (Set<?>) newValue; - for (Object itemId : currentValueSet) { - if (!isItemEnabled(itemId) && !newValueSet.contains(itemId)) { - requestRepaint(); - return; - } - } - for (Object itemId : newValueSet) { - if (!isItemEnabled(itemId) - && !currentValueSet.contains(itemId)) { - requestRepaint(); - return; - } - } - } else { - if (newValue == null) { - newValue = getNullSelectionItemId(); - } - if (!isItemEnabled(newValue)) { - requestRepaint(); - return; - } - } - } - super.setValue(newValue, repaintIsNotNeeded); - } - - /** - * Sets an item disabled or enabled. In the multiselect mode, a disabled - * item cannot be selected or deselected by the user. In the single - * selection mode, a disable item cannot be selected. - * - * However, programmatical selection or deselection of an disable item is - * possible. By default, items are enabled. - * - * @param itemId - * the id of the item to be disabled or enabled - * @param enabled - * if true the item is enabled, otherwise the item is disabled - */ - public void setItemEnabled(Object itemId, boolean enabled) { - if (itemId != null) { - if (enabled) { - disabledItemIds.remove(itemId); - } else { - disabledItemIds.add(itemId); - } - requestRepaint(); - } - } - - /** - * Returns true if the item is enabled. - * - * @param itemId - * the id of the item to be checked - * @return true if the item is enabled, false otherwise - * @see #setItemEnabled(Object, boolean) - */ - public boolean isItemEnabled(Object itemId) { - if (itemId != null) { - return !disabledItemIds.contains(itemId); - } - return true; - } - - /** - * Sets whether html is allowed in the item captions. If set to true, the - * captions are passed to the browser as html and the developer is - * responsible for ensuring no harmful html is used. If set to false, the - * content is passed to the browser as plain text. - * - * @param htmlContentAllowed - * true if the captions are used as html, false if used as plain - * text - */ - public void setHtmlContentAllowed(boolean htmlContentAllowed) { - this.htmlContentAllowed = htmlContentAllowed; - requestRepaint(); - } - - /** - * Checks whether captions are interpreted as html or plain text. - * - * @return true if the captions are used as html, false if used as plain - * text - * @see #setHtmlContentAllowed(boolean) - */ - public boolean isHtmlContentAllowed() { - return htmlContentAllowed; - } -} diff --git a/src/com/vaadin/ui/Panel.java b/src/com/vaadin/ui/Panel.java deleted file mode 100644 index 3c26b73f09..0000000000 --- a/src/com/vaadin/ui/Panel.java +++ /dev/null @@ -1,486 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.Collections; -import java.util.Iterator; -import java.util.Map; - -import com.vaadin.event.Action; -import com.vaadin.event.Action.Handler; -import com.vaadin.event.ActionManager; -import com.vaadin.event.MouseEvents.ClickEvent; -import com.vaadin.event.MouseEvents.ClickListener; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.panel.PanelServerRpc; -import com.vaadin.shared.ui.panel.PanelState; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Scrollable; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.gwt.client.ui.ClickEventHandler; -import com.vaadin.ui.Component.Focusable; - -/** - * Panel - a simple single component container. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public class Panel extends AbstractComponentContainer implements Scrollable, - ComponentContainer.ComponentAttachListener, - ComponentContainer.ComponentDetachListener, Action.Notifier, Focusable, - Vaadin6Component { - - /** - * Content of the panel. - */ - private ComponentContainer content; - - /** - * Keeps track of the Actions added to this component, and manages the - * painting and handling as well. - */ - protected ActionManager actionManager; - - private PanelServerRpc rpc = new PanelServerRpc() { - @Override - public void click(MouseEventDetails mouseDetails) { - fireEvent(new ClickEvent(Panel.this, mouseDetails)); - } - }; - - /** - * Creates a new empty panel. A VerticalLayout is used as content. - */ - public Panel() { - this((ComponentContainer) null); - } - - /** - * Creates a new empty panel which contains the given content. The content - * cannot be null. - * - * @param content - * the content for the panel. - */ - public Panel(ComponentContainer content) { - registerRpc(rpc); - setContent(content); - setWidth(100, Unit.PERCENTAGE); - getState().setTabIndex(-1); - } - - /** - * Creates a new empty panel with caption. Default layout is used. - * - * @param caption - * the caption used in the panel (HTML/XHTML). - */ - public Panel(String caption) { - this(caption, null); - } - - /** - * Creates a new empty panel with the given caption and content. - * - * @param caption - * the caption of the panel (HTML/XHTML). - * @param content - * the content used in the panel. - */ - public Panel(String caption, ComponentContainer content) { - this(content); - setCaption(caption); - } - - /** - * Sets the caption of the panel. - * - * Note that the caption is interpreted as HTML/XHTML and therefore care - * should be taken not to enable HTML injection and XSS attacks using panel - * captions. This behavior may change in future versions. - * - * @see AbstractComponent#setCaption(String) - */ - @Override - public void setCaption(String caption) { - super.setCaption(caption); - } - - /** - * Returns the content of the Panel. - * - * @return - */ - public ComponentContainer getContent() { - return content; - } - - /** - * - * Set the content of the Panel. If null is given as the new content then a - * layout is automatically created and set as the content. - * - * @param content - * The new content - */ - public void setContent(ComponentContainer newContent) { - - // If the content is null we create the default content - if (newContent == null) { - newContent = createDefaultContent(); - } - - // if (newContent == null) { - // throw new IllegalArgumentException("Content cannot be null"); - // } - - if (newContent == content) { - // don't set the same content twice - return; - } - - // detach old content if present - if (content != null) { - content.setParent(null); - content.removeListener((ComponentContainer.ComponentAttachListener) this); - content.removeListener((ComponentContainer.ComponentDetachListener) this); - } - - // Sets the panel to be parent for the content - newContent.setParent(this); - - // Sets the new content - content = newContent; - - // Adds the event listeners for new content - newContent - .addListener((ComponentContainer.ComponentAttachListener) this); - newContent - .addListener((ComponentContainer.ComponentDetachListener) this); - - content = newContent; - requestRepaint(); - } - - /** - * Create a ComponentContainer which is added by default to the Panel if - * user does not specify any content. - * - * @return - */ - private ComponentContainer createDefaultContent() { - VerticalLayout layout = new VerticalLayout(); - // Force margins by default - layout.setMargin(true); - return layout; - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.Vaadin6Component#paintContent(com.vaadin.terminal - * .PaintTarget) - */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - if (actionManager != null) { - actionManager.paintActions(null, target); - } - } - - /** - * Adds the component into this container. - * - * @param c - * the component to be added. - * @see com.vaadin.ui.AbstractComponentContainer#addComponent(com.vaadin.ui.Component) - */ - @Override - public void addComponent(Component c) { - content.addComponent(c); - // No repaint request is made as we except the underlying container to - // request repaints - } - - /** - * Removes the component from this container. - * - * @param c - * The component to be removed. - * @see com.vaadin.ui.AbstractComponentContainer#removeComponent(com.vaadin.ui.Component) - */ - @Override - public void removeComponent(Component c) { - content.removeComponent(c); - // No repaint request is made as we except the underlying container to - // request repaints - } - - /** - * Gets the component container iterator for going through all the - * components in the container. - * - * @return the Iterator of the components inside the container. - * @see com.vaadin.ui.ComponentContainer#getComponentIterator() - */ - @Override - public Iterator<Component> getComponentIterator() { - return Collections.singleton((Component) content).iterator(); - } - - /** - * Called when one or more variables handled by the implementing class are - * changed. - * - * @see com.vaadin.terminal.VariableOwner#changeVariables(Object, Map) - */ - @Override - @SuppressWarnings("unchecked") - public void changeVariables(Object source, Map<String, Object> variables) { - // Get new size - final Integer newWidth = (Integer) variables.get("width"); - final Integer newHeight = (Integer) variables.get("height"); - if (newWidth != null && newWidth.intValue() != getWidth()) { - setWidth(newWidth.intValue(), UNITS_PIXELS); - } - if (newHeight != null && newHeight.intValue() != getHeight()) { - setHeight(newHeight.intValue(), UNITS_PIXELS); - } - - // Scrolling - final Integer newScrollX = (Integer) variables.get("scrollLeft"); - final Integer newScrollY = (Integer) variables.get("scrollTop"); - if (newScrollX != null && newScrollX.intValue() != getScrollLeft()) { - // set internally, not to fire request repaint - getState().setScrollLeft(newScrollX.intValue()); - } - if (newScrollY != null && newScrollY.intValue() != getScrollTop()) { - // set internally, not to fire request repaint - getState().setScrollTop(newScrollY.intValue()); - } - - // Actions - if (actionManager != null) { - actionManager.handleActions(variables, this); - } - - } - - /* Scrolling functionality */ - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Scrollable#setScrollable(boolean) - */ - @Override - public int getScrollLeft() { - return getState().getScrollLeft(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Scrollable#setScrollable(boolean) - */ - @Override - public int getScrollTop() { - return getState().getScrollTop(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Scrollable#setScrollLeft(int) - */ - @Override - public void setScrollLeft(int scrollLeft) { - if (scrollLeft < 0) { - throw new IllegalArgumentException( - "Scroll offset must be at least 0"); - } - getState().setScrollLeft(scrollLeft); - requestRepaint(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.Scrollable#setScrollTop(int) - */ - @Override - public void setScrollTop(int scrollTop) { - if (scrollTop < 0) { - throw new IllegalArgumentException( - "Scroll offset must be at least 0"); - } - getState().setScrollTop(scrollTop); - requestRepaint(); - } - - /* Documented in superclass */ - @Override - public void replaceComponent(Component oldComponent, Component newComponent) { - - content.replaceComponent(oldComponent, newComponent); - } - - /** - * A new component is attached to container. - * - * @see com.vaadin.ui.ComponentContainer.ComponentAttachListener#componentAttachedToContainer(com.vaadin.ui.ComponentContainer.ComponentAttachEvent) - */ - @Override - public void componentAttachedToContainer(ComponentAttachEvent event) { - if (event.getContainer() == content) { - fireComponentAttachEvent(event.getAttachedComponent()); - } - } - - /** - * A component has been detached from container. - * - * @see com.vaadin.ui.ComponentContainer.ComponentDetachListener#componentDetachedFromContainer(com.vaadin.ui.ComponentContainer.ComponentDetachEvent) - */ - @Override - public void componentDetachedFromContainer(ComponentDetachEvent event) { - if (event.getContainer() == content) { - fireComponentDetachEvent(event.getDetachedComponent()); - } - } - - /** - * Removes all components from this container. - * - * @see com.vaadin.ui.ComponentContainer#removeAllComponents() - */ - @Override - public void removeAllComponents() { - content.removeAllComponents(); - } - - /* - * ACTIONS - */ - @Override - protected ActionManager getActionManager() { - if (actionManager == null) { - actionManager = new ActionManager(this); - } - return actionManager; - } - - @Override - public <T extends Action & com.vaadin.event.Action.Listener> void addAction( - T action) { - getActionManager().addAction(action); - } - - @Override - public <T extends Action & com.vaadin.event.Action.Listener> void removeAction( - T action) { - if (actionManager != null) { - actionManager.removeAction(action); - } - } - - @Override - public void addActionHandler(Handler actionHandler) { - getActionManager().addActionHandler(actionHandler); - } - - @Override - public void removeActionHandler(Handler actionHandler) { - if (actionManager != null) { - actionManager.removeActionHandler(actionHandler); - } - } - - /** - * Removes all action handlers - */ - public void removeAllActionHandlers() { - if (actionManager != null) { - actionManager.removeAllActionHandlers(); - } - } - - /** - * Add a click listener to the Panel. The listener is called whenever the - * user clicks inside the Panel. Also when the click targets a component - * inside the Panel, provided the targeted component does not prevent the - * click event from propagating. - * - * Use {@link #removeListener(ClickListener)} to remove the listener. - * - * @param listener - * The listener to add - */ - public void addListener(ClickListener listener) { - addListener(ClickEventHandler.CLICK_EVENT_IDENTIFIER, ClickEvent.class, - listener, ClickListener.clickMethod); - } - - /** - * Remove a click listener from the Panel. The listener should earlier have - * been added using {@link #addListener(ClickListener)}. - * - * @param listener - * The listener to remove - */ - public void removeListener(ClickListener listener) { - removeListener(ClickEventHandler.CLICK_EVENT_IDENTIFIER, - ClickEvent.class, listener); - } - - /** - * {@inheritDoc} - */ - @Override - public int getTabIndex() { - return getState().getTabIndex(); - } - - /** - * {@inheritDoc} - */ - @Override - public void setTabIndex(int tabIndex) { - getState().setTabIndex(tabIndex); - requestRepaint(); - } - - /** - * Moves keyboard focus to the component. {@see Focusable#focus()} - * - */ - @Override - public void focus() { - super.focus(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.ComponentContainer#getComponentCount() - */ - @Override - public int getComponentCount() { - // This is so wrong... (#2924) - return content.getComponentCount(); - } - - @Override - public PanelState getState() { - return (PanelState) super.getState(); - } - -} diff --git a/src/com/vaadin/ui/PasswordField.java b/src/com/vaadin/ui/PasswordField.java deleted file mode 100644 index c1fccebbfe..0000000000 --- a/src/com/vaadin/ui/PasswordField.java +++ /dev/null @@ -1,67 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import com.vaadin.data.Property; - -/** - * A field that is used to enter secret text information like passwords. The - * entered text is not displayed on the screen. - */ -public class PasswordField extends AbstractTextField { - - /** - * Constructs an empty PasswordField. - */ - public PasswordField() { - setValue(""); - } - - /** - * Constructs a PasswordField with given property data source. - * - * @param dataSource - * the property data source for the field - */ - public PasswordField(Property dataSource) { - setPropertyDataSource(dataSource); - } - - /** - * Constructs a PasswordField with given caption and property data source. - * - * @param caption - * the caption for the field - * @param dataSource - * the property data source for the field - */ - public PasswordField(String caption, Property dataSource) { - this(dataSource); - setCaption(caption); - } - - /** - * Constructs a PasswordField with given value and caption. - * - * @param caption - * the caption for the field - * @param value - * the value for the field - */ - public PasswordField(String caption, String value) { - setValue(value); - setCaption(caption); - } - - /** - * Constructs a PasswordField with given caption. - * - * @param caption - * the caption for the field - */ - public PasswordField(String caption) { - this(); - setCaption(caption); - } -} diff --git a/src/com/vaadin/ui/PopupDateField.java b/src/com/vaadin/ui/PopupDateField.java deleted file mode 100644 index 3688d4035f..0000000000 --- a/src/com/vaadin/ui/PopupDateField.java +++ /dev/null @@ -1,80 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.Date; - -import com.vaadin.data.Property; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; - -/** - * <p> - * A date entry component, which displays the actual date selector as a popup. - * - * </p> - * - * @see DateField - * @see InlineDateField - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 5.0 - */ -public class PopupDateField extends DateField { - - private String inputPrompt = null; - - public PopupDateField() { - super(); - } - - public PopupDateField(Property dataSource) throws IllegalArgumentException { - super(dataSource); - } - - public PopupDateField(String caption, Date value) { - super(caption, value); - } - - public PopupDateField(String caption, Property dataSource) { - super(caption, dataSource); - } - - public PopupDateField(String caption) { - super(caption); - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - super.paintContent(target); - - if (inputPrompt != null) { - target.addAttribute("prompt", inputPrompt); - } - } - - /** - * Gets the current input prompt. - * - * @see #setInputPrompt(String) - * @return the current input prompt, or null if not enabled - */ - public String getInputPrompt() { - return inputPrompt; - } - - /** - * Sets the input prompt - a textual prompt that is displayed when the field - * would otherwise be empty, to prompt the user for input. - * - * @param inputPrompt - */ - public void setInputPrompt(String inputPrompt) { - this.inputPrompt = inputPrompt; - requestRepaint(); - } - -} diff --git a/src/com/vaadin/ui/PopupView.java b/src/com/vaadin/ui/PopupView.java deleted file mode 100644 index 766181b50f..0000000000 --- a/src/com/vaadin/ui/PopupView.java +++ /dev/null @@ -1,453 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.Iterator; -import java.util.Map; - -import com.vaadin.terminal.LegacyPaint; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; - -/** - * - * A component for displaying a two different views to data. The minimized view - * is normally used to render the component, and when it is clicked the full - * view is displayed on a popup. The inner class {@link PopupView.Content} is - * used to deliver contents to this component. - * - * @author Vaadin Ltd. - */ -@SuppressWarnings("serial") -public class PopupView extends AbstractComponentContainer implements - Vaadin6Component { - - private Content content; - private boolean hideOnMouseOut; - private Component visibleComponent; - - private static final Method POPUP_VISIBILITY_METHOD; - static { - try { - POPUP_VISIBILITY_METHOD = PopupVisibilityListener.class - .getDeclaredMethod("popupVisibilityChange", - new Class[] { PopupVisibilityEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException( - "Internal error finding methods in PopupView"); - } - } - - /** - * Iterator for the visible components (zero or one components), used by - * {@link PopupView#getComponentIterator()}. - */ - private static class SingleComponentIterator implements - Iterator<Component>, Serializable { - - private final Component component; - private boolean first; - - public SingleComponentIterator(Component component) { - this.component = component; - first = (component == null); - } - - @Override - public boolean hasNext() { - return !first; - } - - @Override - public Component next() { - if (!first) { - first = true; - return component; - } else { - return null; - } - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - /* Constructors */ - - /** - * A simple way to create a PopupPanel. Note that the minimal representation - * may not be dynamically updated, in order to achieve this create your own - * Content object and use {@link PopupView#PopupView(Content)}. - * - * @param small - * the minimal textual representation as HTML - * @param large - * the full, Component-type representation - */ - public PopupView(final java.lang.String small, final Component large) { - this(new PopupView.Content() { - @Override - public java.lang.String getMinimizedValueAsHTML() { - return small; - } - - @Override - public Component getPopupComponent() { - return large; - } - }); - - } - - /** - * Creates a PopupView through the PopupView.Content interface. This allows - * the creator to dynamically change the contents of the PopupView. - * - * @param content - * the PopupView.Content that contains the information for this - */ - public PopupView(PopupView.Content content) { - super(); - hideOnMouseOut = true; - setContent(content); - } - - /** - * This method will replace the current content of the panel with a new one. - * - * @param newContent - * PopupView.Content object containing new information for the - * PopupView - * @throws IllegalArgumentException - * if the method is passed a null value, or if one of the - * content methods returns null - */ - public void setContent(PopupView.Content newContent) - throws IllegalArgumentException { - if (newContent == null) { - throw new IllegalArgumentException("Content must not be null"); - } - content = newContent; - requestRepaint(); - } - - /** - * Returns the content-package for this PopupView. - * - * @return the PopupView.Content for this object or null - */ - public PopupView.Content getContent() { - return content; - } - - /** - * @deprecated Use {@link #setPopupVisible()} instead. - */ - @Deprecated - public void setPopupVisibility(boolean visible) { - setPopupVisible(visible); - } - - /** - * @deprecated Use {@link #isPopupVisible()} instead. - */ - @Deprecated - public boolean getPopupVisibility() { - return isPopupVisible(); - } - - /** - * Set the visibility of the popup. Does not hide the minimal - * representation. - * - * @param visible - */ - public void setPopupVisible(boolean visible) { - if (isPopupVisible() != visible) { - if (visible) { - visibleComponent = content.getPopupComponent(); - if (visibleComponent == null) { - throw new java.lang.IllegalStateException( - "PopupView.Content did not return Component to set visible"); - } - super.addComponent(visibleComponent); - } else { - super.removeComponent(visibleComponent); - visibleComponent = null; - } - fireEvent(new PopupVisibilityEvent(this)); - requestRepaint(); - } - } - - /** - * Return whether the popup is visible. - * - * @return true if the popup is showing - */ - public boolean isPopupVisible() { - return visibleComponent != null; - } - - /** - * Check if this popup will be hidden when the user takes the mouse cursor - * out of the popup area. - * - * @return true if the popup is hidden on mouse out, false otherwise - */ - public boolean isHideOnMouseOut() { - return hideOnMouseOut; - } - - /** - * Should the popup automatically hide when the user takes the mouse cursor - * out of the popup area? If this is false, the user must click outside the - * popup to close it. The default is true. - * - * @param hideOnMouseOut - * - */ - public void setHideOnMouseOut(boolean hideOnMouseOut) { - this.hideOnMouseOut = hideOnMouseOut; - } - - /* - * Methods inherited from AbstractComponentContainer. These are unnecessary - * (but mandatory). Most of them are not supported in this implementation. - */ - - /** - * This class only contains other components when the popup is showing. - * - * @see com.vaadin.ui.ComponentContainer#getComponentIterator() - */ - @Override - public Iterator<Component> getComponentIterator() { - return new SingleComponentIterator(visibleComponent); - } - - /** - * Gets the number of contained components. Consistent with the iterator - * returned by {@link #getComponentIterator()}. - * - * @return the number of contained components (zero or one) - */ - @Override - public int getComponentCount() { - return (visibleComponent != null ? 1 : 0); - } - - /** - * Not supported in this implementation. - * - * @see com.vaadin.ui.AbstractComponentContainer#removeAllComponents() - * @throws UnsupportedOperationException - */ - @Override - public void removeAllComponents() { - throw new UnsupportedOperationException(); - } - - /** - * Not supported in this implementation. - * - * @see com.vaadin.ui.AbstractComponentContainer#moveComponentsFrom(com.vaadin.ui.ComponentContainer) - * @throws UnsupportedOperationException - */ - @Override - public void moveComponentsFrom(ComponentContainer source) - throws UnsupportedOperationException { - - throw new UnsupportedOperationException(); - } - - /** - * Not supported in this implementation. - * - * @see com.vaadin.ui.AbstractComponentContainer#addComponent(com.vaadin.ui.Component) - * @throws UnsupportedOperationException - */ - @Override - public void addComponent(Component c) throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - - } - - /** - * Not supported in this implementation. - * - * @see com.vaadin.ui.ComponentContainer#replaceComponent(com.vaadin.ui.Component, - * com.vaadin.ui.Component) - * @throws UnsupportedOperationException - */ - @Override - public void replaceComponent(Component oldComponent, Component newComponent) - throws UnsupportedOperationException { - - throw new UnsupportedOperationException(); - } - - /** - * Not supported in this implementation - * - * @see com.vaadin.ui.AbstractComponentContainer#removeComponent(com.vaadin.ui.Component) - */ - @Override - public void removeComponent(Component c) - throws UnsupportedOperationException { - throw new UnsupportedOperationException(); - - } - - /* - * Methods for server-client communications. - */ - - /** - * Paint (serialize) the component for the client. - * - * @see com.vaadin.ui.AbstractComponent#paintContent(com.vaadin.terminal.PaintTarget) - */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - String html = content.getMinimizedValueAsHTML(); - if (html == null) { - html = ""; - } - target.addAttribute("html", html); - target.addAttribute("hideOnMouseOut", hideOnMouseOut); - - // Only paint component to client if we know that the popup is showing - if (isPopupVisible()) { - target.startTag("popupComponent"); - LegacyPaint.paint(visibleComponent, target); - target.endTag("popupComponent"); - } - - target.addVariable(this, "popupVisibility", isPopupVisible()); - } - - /** - * Deserialize changes received from client. - * - * @see com.vaadin.ui.AbstractComponent#changeVariables(java.lang.Object, - * java.util.Map) - */ - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - if (variables.containsKey("popupVisibility")) { - setPopupVisible(((Boolean) variables.get("popupVisibility")) - .booleanValue()); - } - } - - /** - * Used to deliver customized content-packages to the PopupView. These are - * dynamically loaded when they are redrawn. The user must take care that - * neither of these methods ever return null. - */ - public interface Content extends Serializable { - - /** - * This should return a small view of the full data. - * - * @return value in HTML format - */ - public String getMinimizedValueAsHTML(); - - /** - * This should return the full Component representing the data - * - * @return a Component for the value - */ - public Component getPopupComponent(); - } - - /** - * Add a listener that is called whenever the visibility of the popup is - * changed. - * - * @param listener - * the listener to add - * @see PopupVisibilityListener - * @see PopupVisibilityEvent - * @see #removeListener(PopupVisibilityListener) - * - */ - public void addListener(PopupVisibilityListener listener) { - addListener(PopupVisibilityEvent.class, listener, - POPUP_VISIBILITY_METHOD); - } - - /** - * Removes a previously added listener, so that it no longer receives events - * when the visibility of the popup changes. - * - * @param listener - * the listener to remove - * @see PopupVisibilityListener - * @see #addListener(PopupVisibilityListener) - */ - public void removeListener(PopupVisibilityListener listener) { - removeListener(PopupVisibilityEvent.class, listener, - POPUP_VISIBILITY_METHOD); - } - - /** - * This event is received by the PopupVisibilityListeners when the - * visibility of the popup changes. You can get the new visibility directly - * with {@link #isPopupVisible()}, or get the PopupView that produced the - * event with {@link #getPopupView()}. - * - */ - public class PopupVisibilityEvent extends Event { - - public PopupVisibilityEvent(PopupView source) { - super(source); - } - - /** - * Get the PopupView instance that is the source of this event. - * - * @return the source PopupView - */ - public PopupView getPopupView() { - return (PopupView) getSource(); - } - - /** - * Returns the current visibility of the popup. - * - * @return true if the popup is visible - */ - public boolean isPopupVisible() { - return getPopupView().isPopupVisible(); - } - } - - /** - * Defines a listener that can receive a PopupVisibilityEvent when the - * visibility of the popup changes. - * - */ - public interface PopupVisibilityListener extends Serializable { - /** - * Pass to {@link PopupView#PopupVisibilityEvent} to start listening for - * popup visibility changes. - * - * @param event - * the event - * - * @see {@link PopupVisibilityEvent} - * @see {@link PopupView#addListener(PopupVisibilityListener)} - */ - public void popupVisibilityChange(PopupVisibilityEvent event); - } -} diff --git a/src/com/vaadin/ui/ProgressIndicator.java b/src/com/vaadin/ui/ProgressIndicator.java deleted file mode 100644 index fef54a267c..0000000000 --- a/src/com/vaadin/ui/ProgressIndicator.java +++ /dev/null @@ -1,257 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.Map; - -import com.vaadin.data.Property; -import com.vaadin.data.util.ObjectProperty; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; - -/** - * <code>ProgressIndicator</code> is component that shows user state of a - * process (like long computing or file upload) - * - * <code>ProgressIndicator</code> has two mainmodes. One for indeterminate - * processes and other (default) for processes which progress can be measured - * - * May view an other property that indicates progress 0...1 - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 4 - */ -@SuppressWarnings("serial") -public class ProgressIndicator extends AbstractField<Number> implements - Property.Viewer, Property.ValueChangeListener, Vaadin6Component { - - /** - * Content mode, where the label contains only plain text. The getValue() - * result is coded to XML when painting. - */ - public static final int CONTENT_TEXT = 0; - - /** - * Content mode, where the label contains preformatted text. - */ - public static final int CONTENT_PREFORMATTED = 1; - - private boolean indeterminate = false; - - private Property dataSource; - - private int pollingInterval = 1000; - - /** - * Creates an a new ProgressIndicator. - */ - public ProgressIndicator() { - setPropertyDataSource(new ObjectProperty<Float>(new Float(0), - Float.class)); - } - - /** - * Creates a new instance of ProgressIndicator with given state. - * - * @param value - */ - public ProgressIndicator(Float value) { - setPropertyDataSource(new ObjectProperty<Float>(value, Float.class)); - } - - /** - * Creates a new instance of ProgressIndicator with stae read from given - * datasource. - * - * @param contentSource - */ - public ProgressIndicator(Property contentSource) { - setPropertyDataSource(contentSource); - } - - /** - * Sets the component to read-only. Readonly is not used in - * ProgressIndicator. - * - * @param readOnly - * True to enable read-only mode, False to disable it. - */ - @Override - public void setReadOnly(boolean readOnly) { - if (dataSource == null) { - throw new IllegalStateException("Datasource must be se"); - } - dataSource.setReadOnly(readOnly); - } - - /** - * Is the component read-only ? Readonly is not used in ProgressIndicator - - * this returns allways false. - * - * @return True if the component is in read only mode. - */ - @Override - public boolean isReadOnly() { - if (dataSource == null) { - throw new IllegalStateException("Datasource must be se"); - } - return dataSource.isReadOnly(); - } - - /** - * Paints the content of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the Paint Operation fails. - */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - target.addAttribute("indeterminate", indeterminate); - target.addAttribute("pollinginterval", pollingInterval); - target.addAttribute("state", getValue().toString()); - } - - /** - * Gets the value of the ProgressIndicator. Value of the ProgressIndicator - * is Float between 0 and 1. - * - * @return the Value of the ProgressIndicator. - * @see com.vaadin.ui.AbstractField#getValue() - */ - @Override - public Number getValue() { - if (dataSource == null) { - throw new IllegalStateException("Datasource must be set"); - } - // TODO conversions to eliminate cast - return (Number) dataSource.getValue(); - } - - /** - * Sets the value of the ProgressIndicator. Value of the ProgressIndicator - * is the Float between 0 and 1. - * - * @param newValue - * the New value of the ProgressIndicator. - * @see com.vaadin.ui.AbstractField#setValue() - */ - @Override - public void setValue(Object newValue) { - if (dataSource == null) { - throw new IllegalStateException("Datasource must be set"); - } - dataSource.setValue(newValue); - } - - /** - * @see com.vaadin.ui.AbstractField#getType() - */ - @Override - public Class<? extends Number> getType() { - if (dataSource == null) { - throw new IllegalStateException("Datasource must be set"); - } - return dataSource.getType(); - } - - /** - * Gets the viewing data-source property. - * - * @return the datasource. - * @see com.vaadin.ui.AbstractField#getPropertyDataSource() - */ - @Override - public Property getPropertyDataSource() { - return dataSource; - } - - /** - * Sets the property as data-source for viewing. - * - * @param newDataSource - * the new data source. - * @see com.vaadin.ui.AbstractField#setPropertyDataSource(com.vaadin.data.Property) - */ - @Override - public void setPropertyDataSource(Property newDataSource) { - // Stops listening the old data source changes - if (dataSource != null - && Property.ValueChangeNotifier.class - .isAssignableFrom(dataSource.getClass())) { - ((Property.ValueChangeNotifier) dataSource).removeListener(this); - } - - // Sets the new data source - dataSource = newDataSource; - - // Listens the new data source if possible - if (dataSource != null - && Property.ValueChangeNotifier.class - .isAssignableFrom(dataSource.getClass())) { - ((Property.ValueChangeNotifier) dataSource).addListener(this); - } - } - - /** - * Gets the mode of ProgressIndicator. - * - * @return true if in indeterminate mode. - */ - public boolean getContentMode() { - return indeterminate; - } - - /** - * Sets wheter or not the ProgressIndicator is indeterminate. - * - * @param newValue - * true to set to indeterminate mode. - */ - public void setIndeterminate(boolean newValue) { - indeterminate = newValue; - requestRepaint(); - } - - /** - * Gets whether or not the ProgressIndicator is indeterminate. - * - * @return true to set to indeterminate mode. - */ - public boolean isIndeterminate() { - return indeterminate; - } - - /** - * Sets the interval that component checks for progress. - * - * @param newValue - * the interval in milliseconds. - */ - public void setPollingInterval(int newValue) { - pollingInterval = newValue; - requestRepaint(); - } - - /** - * Gets the interval that component checks for progress. - * - * @return the interval in milliseconds. - */ - public int getPollingInterval() { - return pollingInterval; - } - - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - // TODO Remove once Vaadin6Component is no longer implemented - - } - -} diff --git a/src/com/vaadin/ui/RichTextArea.java b/src/com/vaadin/ui/RichTextArea.java deleted file mode 100644 index cec952926b..0000000000 --- a/src/com/vaadin/ui/RichTextArea.java +++ /dev/null @@ -1,344 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.text.Format; -import java.util.Map; - -import com.vaadin.data.Property; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; - -/** - * A simple RichTextArea to edit HTML format text. - * - * Note, that using {@link TextField#setMaxLength(int)} method in - * {@link RichTextArea} may produce unexpected results as formatting is counted - * into length of field. - */ -public class RichTextArea extends AbstractField<String> implements - Vaadin6Component { - - /** - * Value formatter used to format the string contents. - */ - @Deprecated - private Format format; - - /** - * Null representation. - */ - private String nullRepresentation = "null"; - - /** - * Is setting to null from non-null value allowed by setting with null - * representation . - */ - private boolean nullSettingAllowed = false; - - /** - * Temporary flag that indicates all content will be selected after the next - * paint. Reset to false after painted. - */ - private boolean selectAll = false; - - /** - * Constructs an empty <code>RichTextArea</code> with no caption. - */ - public RichTextArea() { - setValue(""); - } - - /** - * - * Constructs an empty <code>RichTextArea</code> with the given caption. - * - * @param caption - * the caption for the editor. - */ - public RichTextArea(String caption) { - this(); - setCaption(caption); - } - - /** - * Constructs a new <code>RichTextArea</code> that's bound to the specified - * <code>Property</code> and has no caption. - * - * @param dataSource - * the data source for the editor value - */ - public RichTextArea(Property dataSource) { - setPropertyDataSource(dataSource); - } - - /** - * Constructs a new <code>RichTextArea</code> that's bound to the specified - * <code>Property</code> and has the given caption. - * - * @param caption - * the caption for the editor. - * @param dataSource - * the data source for the editor value - */ - public RichTextArea(String caption, Property dataSource) { - this(dataSource); - setCaption(caption); - } - - /** - * Constructs a new <code>RichTextArea</code> with the given caption and - * initial text contents. - * - * @param caption - * the caption for the editor. - * @param value - * the initial text content of the editor. - */ - public RichTextArea(String caption, String value) { - setValue(value); - setCaption(caption); - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - if (selectAll) { - target.addAttribute("selectAll", true); - selectAll = false; - } - - // Adds the content as variable - String value = getFormattedValue(); - if (value == null) { - value = getNullRepresentation(); - } - if (value == null) { - throw new IllegalStateException( - "Null values are not allowed if the null-representation is null"); - } - target.addVariable(this, "text", value); - - } - - @Override - public void setReadOnly(boolean readOnly) { - super.setReadOnly(readOnly); - // IE6 cannot support multi-classname selectors properly - // TODO Can be optimized now that support for I6 is dropped - if (readOnly) { - addStyleName("v-richtextarea-readonly"); - } else { - removeStyleName("v-richtextarea-readonly"); - } - } - - /** - * Selects all text in the rich text area. As a side effect, focuses the - * rich text area. - * - * @since 6.5 - */ - public void selectAll() { - /* - * Set selection range functionality is currently being - * planned/developed for GWT RTA. Only selecting all is currently - * supported. Consider moving selectAll and other selection related - * functions to AbstractTextField at that point to share the - * implementation. Some third party components extending - * AbstractTextField might however not want to support them. - */ - selectAll = true; - focus(); - requestRepaint(); - } - - /** - * Gets the formatted string value. Sets the field value by using the - * assigned Format. - * - * @return the Formatted value. - * @see #setFormat(Format) - * @see Format - * @deprecated - */ - @Deprecated - protected String getFormattedValue() { - Object v = getValue(); - if (v == null) { - return null; - } - return v.toString(); - } - - @Override - public String getValue() { - String v = super.getValue(); - if (format == null || v == null) { - return v; - } - try { - return format.format(v); - } catch (final IllegalArgumentException e) { - return v; - } - } - - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - // Sets the text - if (variables.containsKey("text") && !isReadOnly()) { - - // Only do the setting if the string representation of the value - // has been updated - String newValue = (String) variables.get("text"); - - final String oldValue = getFormattedValue(); - if (newValue != null - && (oldValue == null || isNullSettingAllowed()) - && newValue.equals(getNullRepresentation())) { - newValue = null; - } - if (newValue != oldValue - && (newValue == null || !newValue.equals(oldValue))) { - boolean wasModified = isModified(); - setValue(newValue, true); - - // If the modified status changes, or if we have a formatter, - // repaint is needed after all. - if (format != null || wasModified != isModified()) { - requestRepaint(); - } - } - } - - } - - @Override - public Class<String> getType() { - return String.class; - } - - /** - * Gets the null-string representation. - * - * <p> - * The null-valued strings are represented on the user interface by - * replacing the null value with this string. If the null representation is - * set null (not 'null' string), painting null value throws exception. - * </p> - * - * <p> - * The default value is string 'null'. - * </p> - * - * @return the String Textual representation for null strings. - * @see TextField#isNullSettingAllowed() - */ - public String getNullRepresentation() { - return nullRepresentation; - } - - /** - * Is setting nulls with null-string representation allowed. - * - * <p> - * If this property is true, writing null-representation string to text - * field always sets the field value to real null. If this property is - * false, null setting is not made, but the null values are maintained. - * Maintenance of null-values is made by only converting the textfield - * contents to real null, if the text field matches the null-string - * representation and the current value of the field is null. - * </p> - * - * <p> - * By default this setting is false - * </p> - * - * @return boolean Should the null-string represenation be always converted - * to null-values. - * @see TextField#getNullRepresentation() - */ - public boolean isNullSettingAllowed() { - return nullSettingAllowed; - } - - /** - * Sets the null-string representation. - * - * <p> - * The null-valued strings are represented on the user interface by - * replacing the null value with this string. If the null representation is - * set null (not 'null' string), painting null value throws exception. - * </p> - * - * <p> - * The default value is string 'null' - * </p> - * - * @param nullRepresentation - * Textual representation for null strings. - * @see TextField#setNullSettingAllowed(boolean) - */ - public void setNullRepresentation(String nullRepresentation) { - this.nullRepresentation = nullRepresentation; - } - - /** - * Sets the null conversion mode. - * - * <p> - * If this property is true, writing null-representation string to text - * field always sets the field value to real null. If this property is - * false, null setting is not made, but the null values are maintained. - * Maintenance of null-values is made by only converting the textfield - * contents to real null, if the text field matches the null-string - * representation and the current value of the field is null. - * </p> - * - * <p> - * By default this setting is false. - * </p> - * - * @param nullSettingAllowed - * Should the null-string represenation be always converted to - * null-values. - * @see TextField#getNullRepresentation() - */ - public void setNullSettingAllowed(boolean nullSettingAllowed) { - this.nullSettingAllowed = nullSettingAllowed; - } - - /** - * Gets the value formatter of TextField. - * - * @return the Format used to format the value. - * @deprecated replaced by {@link com.vaadin.data.util.PropertyFormatter} - */ - @Deprecated - public Format getFormat() { - return format; - } - - /** - * Gets the value formatter of TextField. - * - * @param format - * the Format used to format the value. Null disables the - * formatting. - * @deprecated replaced by {@link com.vaadin.data.util.PropertyFormatter} - */ - @Deprecated - public void setFormat(Format format) { - this.format = format; - requestRepaint(); - } - - @Override - protected boolean isEmpty() { - return super.isEmpty() || getValue().length() == 0; - } - -} diff --git a/src/com/vaadin/ui/Root.java b/src/com/vaadin/ui/Root.java deleted file mode 100644 index bd4842632b..0000000000 --- a/src/com/vaadin/ui/Root.java +++ /dev/null @@ -1,1227 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.Map; - -import com.vaadin.Application; -import com.vaadin.annotations.EagerInit; -import com.vaadin.event.Action; -import com.vaadin.event.Action.Handler; -import com.vaadin.event.ActionManager; -import com.vaadin.event.MouseEvents.ClickEvent; -import com.vaadin.event.MouseEvents.ClickListener; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.root.RootServerRpc; -import com.vaadin.shared.ui.root.RootState; -import com.vaadin.terminal.Page; -import com.vaadin.terminal.Page.BrowserWindowResizeEvent; -import com.vaadin.terminal.Page.BrowserWindowResizeListener; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.WrappedRequest; -import com.vaadin.terminal.WrappedRequest.BrowserDetails; -import com.vaadin.terminal.gwt.client.ui.root.VRoot; -import com.vaadin.ui.Window.CloseListener; - -/** - * The topmost component in any component hierarchy. There is one root for every - * Vaadin instance in a browser window. A root may either represent an entire - * browser window (or tab) or some part of a html page where a Vaadin - * application is embedded. - * <p> - * The root is the server side entry point for various client side features that - * are not represented as components added to a layout, e.g notifications, sub - * windows, and executing javascript in the browser. - * </p> - * <p> - * When a new application instance is needed, typically because the user opens - * the application in a browser window, - * {@link Application#gerRoot(WrappedRequest)} is invoked to get a root. That - * method does by default create a root according to the - * {@value Application#ROOT_PARAMETER} parameter from web.xml. - * </p> - * <p> - * After a root has been created by the application, it is initialized using - * {@link #init(WrappedRequest)}. This method is intended to be overridden by - * the developer to add components to the user interface and initialize - * non-component functionality. The component hierarchy is initialized by - * passing a {@link ComponentContainer} with the main layout of the view to - * {@link #setContent(ComponentContainer)}. - * </p> - * <p> - * If a {@link EagerInit} annotation is present on a class extending - * <code>Root</code>, the framework will use a faster initialization method - * which will not ensure that {@link BrowserDetails} are present in the - * {@link WrappedRequest} passed to the init method. - * </p> - * - * @see #init(WrappedRequest) - * @see Application#getRoot(WrappedRequest) - * - * @since 7.0 - */ -public abstract class Root extends AbstractComponentContainer implements - Action.Container, Action.Notifier, Vaadin6Component { - - /** - * Helper class to emulate the main window from Vaadin 6 using roots. This - * class should be used in the same way as Window used as a browser level - * window in Vaadin 6 with {@link com.vaadin.Application.LegacyApplication} - */ - @Deprecated - @EagerInit - public static class LegacyWindow extends Root { - private String name; - - /** - * Create a new legacy window - */ - public LegacyWindow() { - super(); - } - - /** - * Creates a new legacy window with the given caption - * - * @param caption - * the caption of the window - */ - public LegacyWindow(String caption) { - super(caption); - } - - /** - * Creates a legacy window with the given caption and content layout - * - * @param caption - * @param content - */ - public LegacyWindow(String caption, ComponentContainer content) { - super(caption, content); - } - - @Override - protected void init(WrappedRequest request) { - // Just empty - } - - /** - * Gets the unique name of the window. The name of the window is used to - * uniquely identify it. - * <p> - * The name also determines the URL that can be used for direct access - * to a window. All windows can be accessed through - * {@code http://host:port/app/win} where {@code http://host:port/app} - * is the application URL (as returned by {@link Application#getURL()} - * and {@code win} is the window name. - * </p> - * <p> - * Note! Portlets do not support direct window access through URLs. - * </p> - * - * @return the Name of the Window. - */ - public String getName() { - return name; - } - - /** - * Sets the unique name of the window. The name of the window is used to - * uniquely identify it inside the application. - * <p> - * The name also determines the URL that can be used for direct access - * to a window. All windows can be accessed through - * {@code http://host:port/app/win} where {@code http://host:port/app} - * is the application URL (as returned by {@link Application#getURL()} - * and {@code win} is the window name. - * </p> - * <p> - * This method can only be called before the window is added to an - * application. - * <p> - * Note! Portlets do not support direct window access through URLs. - * </p> - * - * @param name - * the new name for the window or null if the application - * should automatically assign a name to it - * @throws IllegalStateException - * if the window is attached to an application - */ - public void setName(String name) { - this.name = name; - // The name can not be changed in application - if (getApplication() != null) { - throw new IllegalStateException( - "Window name can not be changed while " - + "the window is in application"); - } - - } - - /** - * Gets the full URL of the window. The returned URL is window specific - * and can be used to directly refer to the window. - * <p> - * Note! This method can not be used for portlets. - * </p> - * - * @return the URL of the window or null if the window is not attached - * to an application - */ - public URL getURL() { - Application application = getApplication(); - if (application == null) { - return null; - } - - try { - return new URL(application.getURL(), getName() + "/"); - } catch (MalformedURLException e) { - throw new RuntimeException( - "Internal problem getting window URL, please report"); - } - } - - /** - * Opens the given resource in this root. The contents of this Root is - * replaced by the {@code Resource}. - * - * @param resource - * the resource to show in this root - * - * @deprecated As of 7.0, use getPage().open instead - */ - @Deprecated - public void open(Resource resource) { - getPage().open(resource); - } - - /* ********************************************************************* */ - - /** - * Opens the given resource in a window with the given name. - * <p> - * The supplied {@code windowName} is used as the target name in a - * window.open call in the client. This means that special values such - * as "_blank", "_self", "_top", "_parent" have special meaning. An - * empty or <code>null</code> window name is also a special case. - * </p> - * <p> - * "", null and "_self" as {@code windowName} all causes the resource to - * be opened in the current window, replacing any old contents. For - * downloadable content you should avoid "_self" as "_self" causes the - * client to skip rendering of any other changes as it considers them - * irrelevant (the page will be replaced by the resource). This can - * speed up the opening of a resource, but it might also put the client - * side into an inconsistent state if the window content is not - * completely replaced e.g., if the resource is downloaded instead of - * displayed in the browser. - * </p> - * <p> - * "_blank" as {@code windowName} causes the resource to always be - * opened in a new window or tab (depends on the browser and browser - * settings). - * </p> - * <p> - * "_top" and "_parent" as {@code windowName} works as specified by the - * HTML standard. - * </p> - * <p> - * Any other {@code windowName} will open the resource in a window with - * that name, either by opening a new window/tab in the browser or by - * replacing the contents of an existing window with that name. - * </p> - * - * @param resource - * the resource. - * @param windowName - * the name of the window. - * @deprecated As of 7.0, use getPage().open instead - */ - @Deprecated - public void open(Resource resource, String windowName) { - getPage().open(resource, windowName); - } - - /** - * Opens the given resource in a window with the given size, border and - * name. For more information on the meaning of {@code windowName}, see - * {@link #open(Resource, String)}. - * - * @param resource - * the resource. - * @param windowName - * the name of the window. - * @param width - * the width of the window in pixels - * @param height - * the height of the window in pixels - * @param border - * the border style of the window. See {@link #BORDER_NONE - * Window.BORDER_* constants} - * @deprecated As of 7.0, use getPage().open instead - */ - @Deprecated - public void open(Resource resource, String windowName, int width, - int height, int border) { - getPage().open(resource, windowName, width, height, border); - } - - /** - * Adds a new {@link BrowserWindowResizeListener} to this root. The - * listener will be notified whenever the browser window within which - * this root resides is resized. - * - * @param resizeListener - * the listener to add - * - * @see BrowserWindowResizeListener#browserWindowResized(BrowserWindowResizeEvent) - * @see #setResizeLazy(boolean) - * - * @deprecated As of 7.0, use the similarly named api in Page instead - */ - @Deprecated - public void addListener(BrowserWindowResizeListener resizeListener) { - getPage().addListener(resizeListener); - } - - /** - * Removes a {@link BrowserWindowResizeListener} from this root. The - * listener will no longer be notified when the browser window is - * resized. - * - * @param resizeListener - * the listener to remove - * @deprecated As of 7.0, use the similarly named api in Page instead - */ - @Deprecated - public void removeListener(BrowserWindowResizeListener resizeListener) { - getPage().removeListener(resizeListener); - } - - /** - * Gets the last known height of the browser window in which this root - * resides. - * - * @return the browser window height in pixels - * @deprecated As of 7.0, use the similarly named api in Page instead - */ - @Deprecated - public int getBrowserWindowHeight() { - return getPage().getBrowserWindowHeight(); - } - - /** - * Gets the last known width of the browser window in which this root - * resides. - * - * @return the browser window width in pixels - * - * @deprecated As of 7.0, use the similarly named api in Page instead - */ - @Deprecated - public int getBrowserWindowWidth() { - return getPage().getBrowserWindowWidth(); - } - - /** - * Executes JavaScript in this window. - * - * <p> - * This method allows one to inject javascript from the server to - * client. A client implementation is not required to implement this - * functionality, but currently all web-based clients do implement this. - * </p> - * - * <p> - * Executing javascript this way often leads to cross-browser - * compatibility issues and regressions that are hard to resolve. Use of - * this method should be avoided and instead it is recommended to create - * new widgets with GWT. For more info on creating own, reusable - * client-side widgets in Java, read the corresponding chapter in Book - * of Vaadin. - * </p> - * - * @param script - * JavaScript snippet that will be executed. - * - * @deprecated as of 7.0, use JavaScript.getCurrent().execute(String) - * instead - */ - @Deprecated - public void executeJavaScript(String script) { - getPage().getJavaScript().execute(script); - } - - @Override - public void setCaption(String caption) { - // Override to provide backwards compatibility - getState().setCaption(caption); - getPage().setTitle(caption); - } - - } - - /** - * The application to which this root belongs - */ - private Application application; - - /** - * List of windows in this root. - */ - private final LinkedHashSet<Window> windows = new LinkedHashSet<Window>(); - - /** - * The component that should be scrolled into view after the next repaint. - * Null if nothing should be scrolled into view. - */ - private Component scrollIntoView; - - /** - * The id of this root, used to find the server side instance of the root - * form which a request originates. A negative value indicates that the root - * id has not yet been assigned by the Application. - * - * @see Application#nextRootId - */ - private int rootId = -1; - - /** - * Keeps track of the Actions added to this component, and manages the - * painting and handling as well. - */ - protected ActionManager actionManager; - - /** - * Thread local for keeping track of the current root. - */ - private static final ThreadLocal<Root> currentRoot = new ThreadLocal<Root>(); - - /** Identifies the click event */ - private static final String CLICK_EVENT_ID = VRoot.CLICK_EVENT_ID; - - private ConnectorTracker connectorTracker = new ConnectorTracker(this); - - private Page page = new Page(this); - - private RootServerRpc rpc = new RootServerRpc() { - @Override - public void click(MouseEventDetails mouseDetails) { - fireEvent(new ClickEvent(Root.this, mouseDetails)); - } - }; - - /** - * Creates a new empty root without a caption. This root will have a - * {@link VerticalLayout} with margins enabled as its content. - */ - public Root() { - this((ComponentContainer) null); - } - - /** - * Creates a new root with the given component container as its content. - * - * @param content - * the content container to use as this roots content. - * - * @see #setContent(ComponentContainer) - */ - public Root(ComponentContainer content) { - registerRpc(rpc); - setSizeFull(); - setContent(content); - } - - /** - * Creates a new empty root with the given caption. This root will have a - * {@link VerticalLayout} with margins enabled as its content. - * - * @param caption - * the caption of the root, used as the page title if there's - * nothing but the application on the web page - * - * @see #setCaption(String) - */ - public Root(String caption) { - this((ComponentContainer) null); - setCaption(caption); - } - - /** - * Creates a new root with the given caption and content. - * - * @param caption - * the caption of the root, used as the page title if there's - * nothing but the application on the web page - * @param content - * the content container to use as this roots content. - * - * @see #setContent(ComponentContainer) - * @see #setCaption(String) - */ - public Root(String caption, ComponentContainer content) { - this(content); - setCaption(caption); - } - - @Override - public RootState getState() { - return (RootState) super.getState(); - } - - @Override - public Class<? extends RootState> getStateType() { - // This is a workaround for a problem with creating the correct state - // object during build - return RootState.class; - } - - /** - * Overridden to return a value instead of referring to the parent. - * - * @return this root - * - * @see com.vaadin.ui.AbstractComponent#getRoot() - */ - @Override - public Root getRoot() { - return this; - } - - @Override - public void replaceComponent(Component oldComponent, Component newComponent) { - throw new UnsupportedOperationException(); - } - - @Override - public Application getApplication() { - return application; - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - page.paintContent(target); - - if (scrollIntoView != null) { - target.addAttribute("scrollTo", scrollIntoView); - scrollIntoView = null; - } - - if (pendingFocus != null) { - // ensure focused component is still attached to this main window - if (pendingFocus.getRoot() == this - || (pendingFocus.getRoot() != null && pendingFocus - .getRoot().getParent() == this)) { - target.addAttribute("focused", pendingFocus); - } - pendingFocus = null; - } - - if (actionManager != null) { - actionManager.paintActions(null, target); - } - - if (isResizeLazy()) { - target.addAttribute(VRoot.RESIZE_LAZY, true); - } - } - - /** - * Fire a click event to all click listeners. - * - * @param object - * The raw "value" of the variable change from the client side. - */ - private void fireClick(Map<String, Object> parameters) { - MouseEventDetails mouseDetails = MouseEventDetails - .deSerialize((String) parameters.get("mouseDetails")); - fireEvent(new ClickEvent(this, mouseDetails)); - } - - @Override - @SuppressWarnings("unchecked") - public void changeVariables(Object source, Map<String, Object> variables) { - if (variables.containsKey(CLICK_EVENT_ID)) { - fireClick((Map<String, Object>) variables.get(CLICK_EVENT_ID)); - } - - // Actions - if (actionManager != null) { - actionManager.handleActions(variables, this); - } - - if (variables.containsKey(VRoot.FRAGMENT_VARIABLE)) { - String fragment = (String) variables.get(VRoot.FRAGMENT_VARIABLE); - getPage().setFragment(fragment, true); - } - - if (variables.containsKey("height") || variables.containsKey("width")) { - getPage().setBrowserWindowSize((Integer) variables.get("width"), - (Integer) variables.get("height")); - } - - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.ComponentContainer#getComponentIterator() - */ - @Override - public Iterator<Component> getComponentIterator() { - // TODO could directly create some kind of combined iterator instead of - // creating a new ArrayList - ArrayList<Component> components = new ArrayList<Component>(); - - if (getContent() != null) { - components.add(getContent()); - } - - components.addAll(windows); - - return components.iterator(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.ComponentContainer#getComponentCount() - */ - @Override - public int getComponentCount() { - return windows.size() + (getContent() == null ? 0 : 1); - } - - /** - * Sets the application to which this root is assigned. It is not legal to - * change the application once it has been set nor to set a - * <code>null</code> application. - * <p> - * This method is mainly intended for internal use by the framework. - * </p> - * - * @param application - * the application to set - * - * @throws IllegalStateException - * if the application has already been set - * - * @see #getApplication() - */ - public void setApplication(Application application) { - if ((application == null) == (this.application == null)) { - throw new IllegalStateException("Application has already been set"); - } else { - this.application = application; - } - - if (application != null) { - attach(); - } else { - detach(); - } - } - - /** - * Sets the id of this root within its application. The root id is used to - * route requests to the right root. - * <p> - * This method is mainly intended for internal use by the framework. - * </p> - * - * @param rootId - * the id of this root - * - * @throws IllegalStateException - * if the root id has already been set - * - * @see #getRootId() - */ - public void setRootId(int rootId) { - if (this.rootId != -1) { - throw new IllegalStateException("Root id has already been defined"); - } - this.rootId = rootId; - } - - /** - * Gets the id of the root, used to identify this root within its - * application when processing requests. The root id should be present in - * every request to the server that originates from this root. - * {@link Application#getRootForRequest(WrappedRequest)} uses this id to - * find the route to which the request belongs. - * - * @return - */ - public int getRootId() { - return rootId; - } - - /** - * Adds a window as a subwindow inside this root. To open a new browser - * window or tab, you should instead use {@link open(Resource)} with an url - * pointing to this application and ensure - * {@link Application#getRoot(WrappedRequest)} returns an appropriate root - * for the request. - * - * @param window - * @throws IllegalArgumentException - * if the window is already added to an application - * @throws NullPointerException - * if the given <code>Window</code> is <code>null</code>. - */ - public void addWindow(Window window) throws IllegalArgumentException, - NullPointerException { - - if (window == null) { - throw new NullPointerException("Argument must not be null"); - } - - if (window.getApplication() != null) { - throw new IllegalArgumentException( - "Window is already attached to an application."); - } - - attachWindow(window); - } - - /** - * Helper method to attach a window. - * - * @param w - * the window to add - */ - private void attachWindow(Window w) { - windows.add(w); - w.setParent(this); - requestRepaint(); - } - - /** - * Remove the given subwindow from this root. - * - * Since Vaadin 6.5, {@link CloseListener}s are called also when explicitly - * removing a window by calling this method. - * - * Since Vaadin 6.5, returns a boolean indicating if the window was removed - * or not. - * - * @param window - * Window to be removed. - * @return true if the subwindow was removed, false otherwise - */ - public boolean removeWindow(Window window) { - if (!windows.remove(window)) { - // Window window is not a subwindow of this root. - return false; - } - window.setParent(null); - window.fireClose(); - requestRepaint(); - - return true; - } - - /** - * Gets all the windows added to this root. - * - * @return an unmodifiable collection of windows - */ - public Collection<Window> getWindows() { - return Collections.unmodifiableCollection(windows); - } - - @Override - public void focus() { - super.focus(); - } - - /** - * Component that should be focused after the next repaint. Null if no focus - * change should take place. - */ - private Focusable pendingFocus; - - private boolean resizeLazy = false; - - /** - * This method is used by Component.Focusable objects to request focus to - * themselves. Focus renders must be handled at window level (instead of - * Component.Focusable) due we want the last focused component to be focused - * in client too. Not the one that is rendered last (the case we'd get if - * implemented in Focusable only). - * - * To focus component from Vaadin application, use Focusable.focus(). See - * {@link Focusable}. - * - * @param focusable - * to be focused on next paint - */ - public void setFocusedComponent(Focusable focusable) { - pendingFocus = focusable; - requestRepaint(); - } - - /** - * Scrolls any component between the component and root to a suitable - * position so the component is visible to the user. The given component - * must belong to this root. - * - * @param component - * the component to be scrolled into view - * @throws IllegalArgumentException - * if {@code component} does not belong to this root - */ - public void scrollIntoView(Component component) - throws IllegalArgumentException { - if (component.getRoot() != this) { - throw new IllegalArgumentException( - "The component where to scroll must belong to this root."); - } - scrollIntoView = component; - requestRepaint(); - } - - /** - * Gets the content of this root. The content is a component container that - * serves as the outermost item of the visual contents of this root. - * - * @return a component container to use as content - * - * @see #setContent(ComponentContainer) - * @see #createDefaultLayout() - */ - public ComponentContainer getContent() { - return (ComponentContainer) getState().getContent(); - } - - /** - * Helper method to create the default content layout that is used if no - * content has not been explicitly defined. - * - * @return a newly created layout - */ - private static VerticalLayout createDefaultLayout() { - VerticalLayout layout = new VerticalLayout(); - layout.setMargin(true); - return layout; - } - - /** - * Sets the content of this root. The content is a component container that - * serves as the outermost item of the visual contents of this root. If no - * content has been set, a {@link VerticalLayout} with margins enabled will - * be used by default - see {@link #createDefaultLayout()}. The content can - * also be set in a constructor. - * - * @return a component container to use as content - * - * @see #Root(ComponentContainer) - * @see #createDefaultLayout() - */ - public void setContent(ComponentContainer content) { - if (content == null) { - content = createDefaultLayout(); - } - - if (getState().getContent() != null) { - super.removeComponent((Component) getState().getContent()); - } - getState().setContent(content); - if (content != null) { - super.addComponent(content); - } - - requestRepaint(); - } - - /** - * Adds a component to this root. The component is not added directly to the - * root, but instead to the content container ({@link #getContent()}). - * - * @param component - * the component to add to this root - * - * @see #getContent() - */ - @Override - public void addComponent(Component component) { - getContent().addComponent(component); - } - - /** - * This implementation removes the component from the content container ( - * {@link #getContent()}) instead of from the actual root. - */ - @Override - public void removeComponent(Component component) { - getContent().removeComponent(component); - } - - /** - * This implementation removes the components from the content container ( - * {@link #getContent()}) instead of from the actual root. - */ - @Override - public void removeAllComponents() { - getContent().removeAllComponents(); - } - - /** - * Internal initialization method, should not be overridden. This method is - * not declared as final because that would break compatibility with e.g. - * CDI. - * - * @param request - * the initialization request - */ - public void doInit(WrappedRequest request) { - getPage().init(request); - - // Call the init overridden by the application developer - init(request); - } - - /** - * Initializes this root. This method is intended to be overridden by - * subclasses to build the view and configure non-component functionality. - * Performing the initialization in a constructor is not suggested as the - * state of the root is not properly set up when the constructor is invoked. - * <p> - * The {@link WrappedRequest} can be used to get information about the - * request that caused this root to be created. By default, the - * {@link BrowserDetails} will be available in the request. If the browser - * details are not required, loading the application in the browser can take - * some shortcuts giving a faster initial rendering. This can be indicated - * by adding the {@link EagerInit} annotation to the Root class. - * </p> - * - * @param request - * the wrapped request that caused this root to be created - */ - protected abstract void init(WrappedRequest request); - - /** - * Sets the thread local for the current root. This method is used by the - * framework to set the current application whenever a new request is - * processed and it is cleared when the request has been processed. - * <p> - * The application developer can also use this method to define the current - * root outside the normal request handling, e.g. when initiating custom - * background threads. - * </p> - * - * @param root - * the root to register as the current root - * - * @see #getCurrent() - * @see ThreadLocal - */ - public static void setCurrent(Root root) { - currentRoot.set(root); - } - - /** - * Gets the currently used root. The current root is automatically defined - * when processing requests to the server. In other cases, (e.g. from - * background threads), the current root is not automatically defined. - * - * @return the current root instance if available, otherwise - * <code>null</code> - * - * @see #setCurrent(Root) - */ - public static Root getCurrent() { - return currentRoot.get(); - } - - public void setScrollTop(int scrollTop) { - throw new RuntimeException("Not yet implemented"); - } - - @Override - protected ActionManager getActionManager() { - if (actionManager == null) { - actionManager = new ActionManager(this); - } - return actionManager; - } - - @Override - public <T extends Action & com.vaadin.event.Action.Listener> void addAction( - T action) { - getActionManager().addAction(action); - } - - @Override - public <T extends Action & com.vaadin.event.Action.Listener> void removeAction( - T action) { - if (actionManager != null) { - actionManager.removeAction(action); - } - } - - @Override - public void addActionHandler(Handler actionHandler) { - getActionManager().addActionHandler(actionHandler); - } - - @Override - public void removeActionHandler(Handler actionHandler) { - if (actionManager != null) { - actionManager.removeActionHandler(actionHandler); - } - } - - /** - * Should resize operations be lazy, i.e. should there be a delay before - * layout sizes are recalculated. Speeds up resize operations in slow UIs - * with the penalty of slightly decreased usability. - * <p> - * Default value: <code>false</code> - * - * @param resizeLazy - * true to use a delay before recalculating sizes, false to - * calculate immediately. - */ - public void setResizeLazy(boolean resizeLazy) { - this.resizeLazy = resizeLazy; - requestRepaint(); - } - - /** - * Checks whether lazy resize is enabled. - * - * @return <code>true</code> if lazy resize is enabled, <code>false</code> - * if lazy resize is not enabled - */ - public boolean isResizeLazy() { - return resizeLazy; - } - - /** - * Add a click listener to the Root. The listener is called whenever the - * user clicks inside the Root. Also when the click targets a component - * inside the Root, provided the targeted component does not prevent the - * click event from propagating. - * - * Use {@link #removeListener(ClickListener)} to remove the listener. - * - * @param listener - * The listener to add - */ - public void addListener(ClickListener listener) { - addListener(CLICK_EVENT_ID, ClickEvent.class, listener, - ClickListener.clickMethod); - } - - /** - * Remove a click listener from the Root. The listener should earlier have - * been added using {@link #addListener(ClickListener)}. - * - * @param listener - * The listener to remove - */ - public void removeListener(ClickListener listener) { - removeListener(CLICK_EVENT_ID, ClickEvent.class, listener); - } - - @Override - public boolean isConnectorEnabled() { - // TODO How can a Root be invisible? What does it mean? - return isVisible() && isEnabled(); - } - - public ConnectorTracker getConnectorTracker() { - return connectorTracker; - } - - public Page getPage() { - return page; - } - - /** - * Setting the caption of a Root is not supported. To set the title of the - * HTML page, use Page.setTitle - * - * @deprecated as of 7.0.0, use {@link Page#setTitle(String)} - */ - @Override - @Deprecated - public void setCaption(String caption) { - throw new IllegalStateException( - "You can not set the title of a Root. To set the title of the HTML page, use Page.setTitle"); - } - - /** - * Shows a notification message on the middle of the root. The message - * automatically disappears ("humanized message"). - * - * Care should be taken to to avoid XSS vulnerabilities as the caption is - * rendered as html. - * - * @see #showNotification(Notification) - * @see Notification - * - * @param caption - * The message - * - * @deprecated As of 7.0, use Notification.show instead but be aware that - * Notification.show does not allow HTML. - */ - @Deprecated - public void showNotification(String caption) { - Notification notification = new Notification(caption); - notification.setHtmlContentAllowed(true);// Backwards compatibility - getPage().showNotification(notification); - } - - /** - * Shows a notification message the root. The position and behavior of the - * message depends on the type, which is one of the basic types defined in - * {@link Notification}, for instance Notification.TYPE_WARNING_MESSAGE. - * - * Care should be taken to to avoid XSS vulnerabilities as the caption is - * rendered as html. - * - * @see #showNotification(Notification) - * @see Notification - * - * @param caption - * The message - * @param type - * The message type - * - * @deprecated As of 7.0, use Notification.show instead but be aware that - * Notification.show does not allow HTML. - */ - @Deprecated - public void showNotification(String caption, int type) { - Notification notification = new Notification(caption, type); - notification.setHtmlContentAllowed(true);// Backwards compatibility - getPage().showNotification(notification); - } - - /** - * Shows a notification consisting of a bigger caption and a smaller - * description on the middle of the root. The message automatically - * disappears ("humanized message"). - * - * Care should be taken to to avoid XSS vulnerabilities as the caption and - * description are rendered as html. - * - * @see #showNotification(Notification) - * @see Notification - * - * @param caption - * The caption of the message - * @param description - * The message description - * - * @deprecated As of 7.0, use new Notification(...).show(Page) instead but - * be aware that HTML by default not allowed. - */ - @Deprecated - public void showNotification(String caption, String description) { - Notification notification = new Notification(caption, description); - notification.setHtmlContentAllowed(true);// Backwards compatibility - getPage().showNotification(notification); - } - - /** - * Shows a notification consisting of a bigger caption and a smaller - * description. The position and behavior of the message depends on the - * type, which is one of the basic types defined in {@link Notification} , - * for instance Notification.TYPE_WARNING_MESSAGE. - * - * Care should be taken to to avoid XSS vulnerabilities as the caption and - * description are rendered as html. - * - * @see #showNotification(Notification) - * @see Notification - * - * @param caption - * The caption of the message - * @param description - * The message description - * @param type - * The message type - * - * @deprecated As of 7.0, use new Notification(...).show(Page) instead but - * be aware that HTML by default not allowed. - */ - @Deprecated - public void showNotification(String caption, String description, int type) { - Notification notification = new Notification(caption, description, type); - notification.setHtmlContentAllowed(true);// Backwards compatibility - getPage().showNotification(notification); - } - - /** - * Shows a notification consisting of a bigger caption and a smaller - * description. The position and behavior of the message depends on the - * type, which is one of the basic types defined in {@link Notification} , - * for instance Notification.TYPE_WARNING_MESSAGE. - * - * Care should be taken to avoid XSS vulnerabilities if html content is - * allowed. - * - * @see #showNotification(Notification) - * @see Notification - * - * @param caption - * The message caption - * @param description - * The message description - * @param type - * The type of message - * @param htmlContentAllowed - * Whether html in the caption and description should be - * displayed as html or as plain text - * - * @deprecated As of 7.0, use new Notification(...).show(Page). - */ - @Deprecated - public void showNotification(String caption, String description, int type, - boolean htmlContentAllowed) { - getPage() - .showNotification( - new Notification(caption, description, type, - htmlContentAllowed)); - } - - /** - * Shows a notification message. - * - * @see Notification - * @see #showNotification(String) - * @see #showNotification(String, int) - * @see #showNotification(String, String) - * @see #showNotification(String, String, int) - * - * @param notification - * The notification message to show - * - * @deprecated As of 7.0, use Notification.show instead - */ - @Deprecated - public void showNotification(Notification notification) { - getPage().showNotification(notification); - } - -} diff --git a/src/com/vaadin/ui/Select.java b/src/com/vaadin/ui/Select.java deleted file mode 100644 index f60935c64b..0000000000 --- a/src/com/vaadin/ui/Select.java +++ /dev/null @@ -1,803 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.vaadin.data.Container; -import com.vaadin.data.util.filter.SimpleStringFilter; -import com.vaadin.event.FieldEvents; -import com.vaadin.event.FieldEvents.BlurEvent; -import com.vaadin.event.FieldEvents.BlurListener; -import com.vaadin.event.FieldEvents.FocusEvent; -import com.vaadin.event.FieldEvents.FocusListener; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; - -/** - * <p> - * A class representing a selection of items the user has selected in a UI. The - * set of choices is presented as a set of {@link com.vaadin.data.Item}s in a - * {@link com.vaadin.data.Container}. - * </p> - * - * <p> - * A <code>Select</code> component may be in single- or multiselect mode. - * Multiselect mode means that more than one item can be selected - * simultaneously. - * </p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public class Select extends AbstractSelect implements AbstractSelect.Filtering, - FieldEvents.BlurNotifier, FieldEvents.FocusNotifier { - - /** - * Holds value of property pageLength. 0 disables paging. - */ - protected int pageLength = 10; - - private int columns = 0; - - // Current page when the user is 'paging' trough options - private int currentPage = -1; - - private int filteringMode = FILTERINGMODE_STARTSWITH; - - private String filterstring; - private String prevfilterstring; - - /** - * Number of options that pass the filter, excluding the null item if any. - */ - private int filteredSize; - - /** - * Cache of filtered options, used only by the in-memory filtering system. - */ - private List<Object> filteredOptions; - - /** - * Flag to indicate that request repaint is called by filter request only - */ - private boolean optionRequest; - - /** - * True if the container is being filtered temporarily and item set change - * notifications should be suppressed. - */ - private boolean filteringContainer; - - /** - * Flag to indicate whether to scroll the selected item visible (select the - * page on which it is) when opening the popup or not. Only applies to - * single select mode. - * - * This requires finding the index of the item, which can be expensive in - * many large lazy loading containers. - */ - private boolean scrollToSelectedItem = true; - - /* Constructors */ - - /* Component methods */ - - public Select() { - super(); - } - - public Select(String caption, Collection<?> options) { - super(caption, options); - } - - public Select(String caption, Container dataSource) { - super(caption, dataSource); - } - - public Select(String caption) { - super(caption); - } - - /** - * Paints the content of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - if (isMultiSelect()) { - // background compatibility hack. This object shouldn't be used for - // multiselect lists anymore (ListSelect instead). This fallbacks to - // a simpler paint method in super class. - super.paintContent(target); - // Fix for #4553 - target.addAttribute("type", "legacy-multi"); - return; - } - - // clear caption change listeners - getCaptionChangeListener().clear(); - - // The tab ordering number - if (getTabIndex() != 0) { - target.addAttribute("tabindex", getTabIndex()); - } - - // If the field is modified, but not committed, set modified attribute - if (isModified()) { - target.addAttribute("modified", true); - } - - if (isNewItemsAllowed()) { - target.addAttribute("allownewitem", true); - } - - boolean needNullSelectOption = false; - if (isNullSelectionAllowed()) { - target.addAttribute("nullselect", true); - needNullSelectOption = (getNullSelectionItemId() == null); - if (!needNullSelectOption) { - target.addAttribute("nullselectitem", true); - } - } - - // Constructs selected keys array - String[] selectedKeys; - if (isMultiSelect()) { - selectedKeys = new String[((Set<?>) getValue()).size()]; - } else { - selectedKeys = new String[(getValue() == null - && getNullSelectionItemId() == null ? 0 : 1)]; - } - - target.addAttribute("pagelength", pageLength); - - target.addAttribute("filteringmode", getFilteringMode()); - - // Paints the options and create array of selected id keys - int keyIndex = 0; - - target.startTag("options"); - - if (currentPage < 0) { - optionRequest = false; - currentPage = 0; - filterstring = ""; - } - - boolean nullFilteredOut = filterstring != null - && !"".equals(filterstring) - && filteringMode != FILTERINGMODE_OFF; - // null option is needed and not filtered out, even if not on current - // page - boolean nullOptionVisible = needNullSelectOption && !nullFilteredOut; - - // first try if using container filters is possible - List<?> options = getOptionsWithFilter(nullOptionVisible); - if (null == options) { - // not able to use container filters, perform explicit in-memory - // filtering - options = getFilteredOptions(); - filteredSize = options.size(); - options = sanitetizeList(options, nullOptionVisible); - } - - final boolean paintNullSelection = needNullSelectOption - && currentPage == 0 && !nullFilteredOut; - - if (paintNullSelection) { - target.startTag("so"); - target.addAttribute("caption", ""); - target.addAttribute("key", ""); - target.endTag("so"); - } - - final Iterator<?> i = options.iterator(); - // Paints the available selection options from data source - - while (i.hasNext()) { - - final Object id = i.next(); - - if (!isNullSelectionAllowed() && id != null - && id.equals(getNullSelectionItemId()) && !isSelected(id)) { - continue; - } - - // Gets the option attribute values - final String key = itemIdMapper.key(id); - final String caption = getItemCaption(id); - final Resource icon = getItemIcon(id); - getCaptionChangeListener().addNotifierForItem(id); - - // Paints the option - target.startTag("so"); - if (icon != null) { - target.addAttribute("icon", icon); - } - target.addAttribute("caption", caption); - if (id != null && id.equals(getNullSelectionItemId())) { - target.addAttribute("nullselection", true); - } - target.addAttribute("key", key); - if (isSelected(id) && keyIndex < selectedKeys.length) { - target.addAttribute("selected", true); - selectedKeys[keyIndex++] = key; - } - target.endTag("so"); - } - target.endTag("options"); - - target.addAttribute("totalitems", size() - + (needNullSelectOption ? 1 : 0)); - if (filteredSize > 0 || nullOptionVisible) { - target.addAttribute("totalMatches", filteredSize - + (nullOptionVisible ? 1 : 0)); - } - - // Paint variables - target.addVariable(this, "selected", selectedKeys); - if (isNewItemsAllowed()) { - target.addVariable(this, "newitem", ""); - } - - target.addVariable(this, "filter", filterstring); - target.addVariable(this, "page", currentPage); - - currentPage = -1; // current page is always set by client - - optionRequest = true; - } - - /** - * Returns the filtered options for the current page using a container - * filter. - * - * As a size effect, {@link #filteredSize} is set to the total number of - * items passing the filter. - * - * The current container must be {@link Filterable} and {@link Indexed}, and - * the filtering mode must be suitable for container filtering (tested with - * {@link #canUseContainerFilter()}). - * - * Use {@link #getFilteredOptions()} and - * {@link #sanitetizeList(List, boolean)} if this is not the case. - * - * @param needNullSelectOption - * @return filtered list of options (may be empty) or null if cannot use - * container filters - */ - protected List<?> getOptionsWithFilter(boolean needNullSelectOption) { - Container container = getContainerDataSource(); - - if (pageLength == 0) { - // no paging: return all items - filteredSize = container.size(); - return new ArrayList<Object>(container.getItemIds()); - } - - if (!(container instanceof Filterable) - || !(container instanceof Indexed) - || getItemCaptionMode() != ITEM_CAPTION_MODE_PROPERTY) { - return null; - } - - Filterable filterable = (Filterable) container; - - Filter filter = buildFilter(filterstring, filteringMode); - - // adding and removing filters leads to extraneous item set - // change events from the underlying container, but the ComboBox does - // not process or propagate them based on the flag filteringContainer - if (filter != null) { - filteringContainer = true; - filterable.addContainerFilter(filter); - } - - Indexed indexed = (Indexed) container; - - int indexToEnsureInView = -1; - - // if not an option request (item list when user changes page), go - // to page with the selected item after filtering if accepted by - // filter - Object selection = getValue(); - if (isScrollToSelectedItem() && !optionRequest && !isMultiSelect() - && selection != null) { - // ensure proper page - indexToEnsureInView = indexed.indexOfId(selection); - } - - filteredSize = container.size(); - currentPage = adjustCurrentPage(currentPage, needNullSelectOption, - indexToEnsureInView, filteredSize); - int first = getFirstItemIndexOnCurrentPage(needNullSelectOption, - filteredSize); - int last = getLastItemIndexOnCurrentPage(needNullSelectOption, - filteredSize, first); - - List<Object> options = new ArrayList<Object>(); - for (int i = first; i <= last && i < filteredSize; ++i) { - options.add(indexed.getIdByIndex(i)); - } - - // to the outside, filtering should not be visible - if (filter != null) { - filterable.removeContainerFilter(filter); - filteringContainer = false; - } - - return options; - } - - /** - * Constructs a filter instance to use when using a Filterable container in - * the <code>ITEM_CAPTION_MODE_PROPERTY</code> mode. - * - * Note that the client side implementation expects the filter string to - * apply to the item caption string it sees, so changing the behavior of - * this method can cause problems. - * - * @param filterString - * @param filteringMode - * @return - */ - protected Filter buildFilter(String filterString, int filteringMode) { - Filter filter = null; - - if (null != filterString && !"".equals(filterString)) { - switch (filteringMode) { - case FILTERINGMODE_OFF: - break; - case FILTERINGMODE_STARTSWITH: - filter = new SimpleStringFilter(getItemCaptionPropertyId(), - filterString, true, true); - break; - case FILTERINGMODE_CONTAINS: - filter = new SimpleStringFilter(getItemCaptionPropertyId(), - filterString, true, false); - break; - } - } - return filter; - } - - @Override - public void containerItemSetChange(Container.ItemSetChangeEvent event) { - if (!filteringContainer) { - super.containerItemSetChange(event); - } - } - - /** - * Makes correct sublist of given list of options. - * - * If paint is not an option request (affected by page or filter change), - * page will be the one where possible selection exists. - * - * Detects proper first and last item in list to return right page of - * options. Also, if the current page is beyond the end of the list, it will - * be adjusted. - * - * @param options - * @param needNullSelectOption - * flag to indicate if nullselect option needs to be taken into - * consideration - */ - private List<?> sanitetizeList(List<?> options, boolean needNullSelectOption) { - - if (pageLength != 0 && options.size() > pageLength) { - - int indexToEnsureInView = -1; - - // if not an option request (item list when user changes page), go - // to page with the selected item after filtering if accepted by - // filter - Object selection = getValue(); - if (isScrollToSelectedItem() && !optionRequest && !isMultiSelect() - && selection != null) { - // ensure proper page - indexToEnsureInView = options.indexOf(selection); - } - - int size = options.size(); - currentPage = adjustCurrentPage(currentPage, needNullSelectOption, - indexToEnsureInView, size); - int first = getFirstItemIndexOnCurrentPage(needNullSelectOption, - size); - int last = getLastItemIndexOnCurrentPage(needNullSelectOption, - size, first); - return options.subList(first, last + 1); - } else { - return options; - } - } - - /** - * Returns the index of the first item on the current page. The index is to - * the underlying (possibly filtered) contents. The null item, if any, does - * not have an index but takes up a slot on the first page. - * - * @param needNullSelectOption - * true if a null option should be shown before any other options - * (takes up the first slot on the first page, not counted in - * index) - * @param size - * number of items after filtering (not including the null item, - * if any) - * @return first item to show on the UI (index to the filtered list of - * options, not taking the null item into consideration if any) - */ - private int getFirstItemIndexOnCurrentPage(boolean needNullSelectOption, - int size) { - // Not all options are visible, find out which ones are on the - // current "page". - int first = currentPage * pageLength; - if (needNullSelectOption && currentPage > 0) { - first--; - } - return first; - } - - /** - * Returns the index of the last item on the current page. The index is to - * the underlying (possibly filtered) contents. If needNullSelectOption is - * true, the null item takes up the first slot on the first page, - * effectively reducing the first page size by one. - * - * @param needNullSelectOption - * true if a null option should be shown before any other options - * (takes up the first slot on the first page, not counted in - * index) - * @param size - * number of items after filtering (not including the null item, - * if any) - * @param first - * index in the filtered view of the first item of the page - * @return index in the filtered view of the last item on the page - */ - private int getLastItemIndexOnCurrentPage(boolean needNullSelectOption, - int size, int first) { - // page length usable for non-null items - int effectivePageLength = pageLength - - (needNullSelectOption && (currentPage == 0) ? 1 : 0); - return Math.min(size - 1, first + effectivePageLength - 1); - } - - /** - * Adjusts the index of the current page if necessary: make sure the current - * page is not after the end of the contents, and optionally go to the page - * containg a specific item. There are no side effects but the adjusted page - * index is returned. - * - * @param page - * page number to use as the starting point - * @param needNullSelectOption - * true if a null option should be shown before any other options - * (takes up the first slot on the first page, not counted in - * index) - * @param indexToEnsureInView - * index of an item that should be included on the page (in the - * data set, not counting the null item if any), -1 for none - * @param size - * number of items after filtering (not including the null item, - * if any) - */ - private int adjustCurrentPage(int page, boolean needNullSelectOption, - int indexToEnsureInView, int size) { - if (indexToEnsureInView != -1) { - int newPage = (indexToEnsureInView + (needNullSelectOption ? 1 : 0)) - / pageLength; - page = newPage; - } - // adjust the current page if beyond the end of the list - if (page * pageLength > size) { - page = (size + (needNullSelectOption ? 1 : 0)) / pageLength; - } - return page; - } - - /** - * Filters the options in memory and returns the full filtered list. - * - * This can be less efficient than using container filters, so use - * {@link #getOptionsWithFilter(boolean)} if possible (filterable container - * and suitable item caption mode etc.). - * - * @return - */ - protected List<?> getFilteredOptions() { - if (null == filterstring || "".equals(filterstring) - || FILTERINGMODE_OFF == filteringMode) { - prevfilterstring = null; - filteredOptions = new LinkedList<Object>(getItemIds()); - return filteredOptions; - } - - if (filterstring.equals(prevfilterstring)) { - return filteredOptions; - } - - Collection<?> items; - if (prevfilterstring != null - && filterstring.startsWith(prevfilterstring)) { - items = filteredOptions; - } else { - items = getItemIds(); - } - prevfilterstring = filterstring; - - filteredOptions = new LinkedList<Object>(); - for (final Iterator<?> it = items.iterator(); it.hasNext();) { - final Object itemId = it.next(); - String caption = getItemCaption(itemId); - if (caption == null || caption.equals("")) { - continue; - } else { - caption = caption.toLowerCase(); - } - switch (filteringMode) { - case FILTERINGMODE_CONTAINS: - if (caption.indexOf(filterstring) > -1) { - filteredOptions.add(itemId); - } - break; - case FILTERINGMODE_STARTSWITH: - default: - if (caption.startsWith(filterstring)) { - filteredOptions.add(itemId); - } - break; - } - } - - return filteredOptions; - } - - /** - * Invoked when the value of a variable has changed. - * - * @see com.vaadin.ui.AbstractComponent#changeVariables(java.lang.Object, - * java.util.Map) - */ - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - // Not calling super.changeVariables due the history of select - // component hierarchy - - // Selection change - if (variables.containsKey("selected")) { - final String[] ka = (String[]) variables.get("selected"); - - if (isMultiSelect()) { - // Multiselect mode - - // TODO Optimize by adding repaintNotNeeded whan applicaple - - // Converts the key-array to id-set - final LinkedList<Object> s = new LinkedList<Object>(); - for (int i = 0; i < ka.length; i++) { - final Object id = itemIdMapper.get(ka[i]); - if (id != null && containsId(id)) { - s.add(id); - } - } - - // Limits the deselection to the set of visible items - // (non-visible items can not be deselected) - final Collection<?> visible = getVisibleItemIds(); - if (visible != null) { - @SuppressWarnings("unchecked") - Set<Object> newsel = (Set<Object>) getValue(); - if (newsel == null) { - newsel = new HashSet<Object>(); - } else { - newsel = new HashSet<Object>(newsel); - } - newsel.removeAll(visible); - newsel.addAll(s); - setValue(newsel, true); - } - } else { - // Single select mode - if (ka.length == 0) { - - // Allows deselection only if the deselected item is visible - final Object current = getValue(); - final Collection<?> visible = getVisibleItemIds(); - if (visible != null && visible.contains(current)) { - setValue(null, true); - } - } else { - final Object id = itemIdMapper.get(ka[0]); - if (id != null && id.equals(getNullSelectionItemId())) { - setValue(null, true); - } else { - setValue(id, true); - } - } - } - } - - String newFilter; - if ((newFilter = (String) variables.get("filter")) != null) { - // this is a filter request - currentPage = ((Integer) variables.get("page")).intValue(); - filterstring = newFilter; - if (filterstring != null) { - filterstring = filterstring.toLowerCase(); - } - optionRepaint(); - } else if (isNewItemsAllowed()) { - // New option entered (and it is allowed) - final String newitem = (String) variables.get("newitem"); - if (newitem != null && newitem.length() > 0) { - getNewItemHandler().addNewItem(newitem); - // rebuild list - filterstring = null; - prevfilterstring = null; - } - } - - if (variables.containsKey(FocusEvent.EVENT_ID)) { - fireEvent(new FocusEvent(this)); - } - if (variables.containsKey(BlurEvent.EVENT_ID)) { - fireEvent(new BlurEvent(this)); - } - - } - - @Override - public void requestRepaint() { - super.requestRepaint(); - optionRequest = false; - prevfilterstring = filterstring; - filterstring = null; - } - - private void optionRepaint() { - super.requestRepaint(); - } - - @Override - public void setFilteringMode(int filteringMode) { - this.filteringMode = filteringMode; - } - - @Override - public int getFilteringMode() { - return filteringMode; - } - - /** - * Note, one should use more generic setWidth(String) method instead of - * this. This now days actually converts columns to width with em css unit. - * - * Sets the number of columns in the editor. If the number of columns is set - * 0, the actual number of displayed columns is determined implicitly by the - * adapter. - * - * @deprecated - * - * @param columns - * the number of columns to set. - */ - @Deprecated - public void setColumns(int columns) { - if (columns < 0) { - columns = 0; - } - if (this.columns != columns) { - this.columns = columns; - setWidth(columns, Select.UNITS_EM); - requestRepaint(); - } - } - - /** - * @deprecated see setter function - * @return - */ - @Deprecated - public int getColumns() { - return columns; - } - - @Override - public void addListener(BlurListener listener) { - addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, - BlurListener.blurMethod); - } - - @Override - public void removeListener(BlurListener listener) { - removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); - } - - @Override - public void addListener(FocusListener listener) { - addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, - FocusListener.focusMethod); - } - - @Override - public void removeListener(FocusListener listener) { - removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); - - } - - /** - * @deprecated use {@link ListSelect}, {@link OptionGroup} or - * {@link TwinColSelect} instead - * @see com.vaadin.ui.AbstractSelect#setMultiSelect(boolean) - * @throws UnsupportedOperationException - * if trying to activate multiselect mode - */ - @Deprecated - @Override - public void setMultiSelect(boolean multiSelect) { - if (multiSelect) { - throw new UnsupportedOperationException("Multiselect not supported"); - } - } - - /** - * @deprecated use {@link ListSelect}, {@link OptionGroup} or - * {@link TwinColSelect} instead - * - * @see com.vaadin.ui.AbstractSelect#isMultiSelect() - */ - @Deprecated - @Override - public boolean isMultiSelect() { - return super.isMultiSelect(); - } - - /** - * Sets whether to scroll the selected item visible (directly open the page - * on which it is) when opening the combo box popup or not. Only applies to - * single select mode. - * - * This requires finding the index of the item, which can be expensive in - * many large lazy loading containers. - * - * @param scrollToSelectedItem - * true to find the page with the selected item when opening the - * selection popup - */ - public void setScrollToSelectedItem(boolean scrollToSelectedItem) { - this.scrollToSelectedItem = scrollToSelectedItem; - } - - /** - * Returns true if the select should find the page with the selected item - * when opening the popup (single select combo box only). - * - * @see #setScrollToSelectedItem(boolean) - * - * @return true if the page with the selected item will be shown when - * opening the popup - */ - public boolean isScrollToSelectedItem() { - return scrollToSelectedItem; - } - -} diff --git a/src/com/vaadin/ui/Slider.java b/src/com/vaadin/ui/Slider.java deleted file mode 100644 index 94afe4e2bd..0000000000 --- a/src/com/vaadin/ui/Slider.java +++ /dev/null @@ -1,372 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.Map; - -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; - -/** - * A component for selecting a numerical value within a range. - * - * Example code: <code> - * class MyPlayer extends CustomComponent implements ValueChangeListener { - * - * Label volumeIndicator = new Label(); - * Slider slider; - * - * public MyPlayer() { - * VerticalLayout vl = new VerticalLayout(); - * setCompositionRoot(vl); - * slider = new Slider("Volume", 0, 100); - * slider.setImmediate(true); - * slider.setValue(new Double(50)); - * vl.addComponent(slider); - * vl.addComponent(volumeIndicator); - * volumeIndicator.setValue("Current volume:" + 50.0); - * slider.addListener(this); - * - * } - * - * public void setVolume(double d) { - * volumeIndicator.setValue("Current volume: " + d); - * } - * - * public void valueChange(ValueChangeEvent event) { - * Double d = (Double) event.getProperty().getValue(); - * setVolume(d.doubleValue()); - * } - * } - * - * </code> - * - * @author Vaadin Ltd. - */ -public class Slider extends AbstractField<Double> implements Vaadin6Component { - - public static final int ORIENTATION_HORIZONTAL = 0; - - public static final int ORIENTATION_VERTICAL = 1; - - /** Minimum value of slider */ - private double min = 0; - - /** Maximum value of slider */ - private double max = 100; - - /** - * Resolution, how many digits are considered relevant after the decimal - * point. Must be a non-negative value - */ - private int resolution = 0; - - /** - * Slider orientation (horizontal/vertical), defaults . - */ - private int orientation = ORIENTATION_HORIZONTAL; - - /** - * Default slider constructor. Sets all values to defaults and the slide - * handle at minimum value. - * - */ - public Slider() { - super(); - super.setValue(new Double(min)); - } - - /** - * Create a new slider with the caption given as parameter. - * - * The range of the slider is set to 0-100 and only integer values are - * allowed. - * - * @param caption - * The caption for this slider (e.g. "Volume"). - */ - public Slider(String caption) { - this(); - setCaption(caption); - } - - /** - * Create a new slider with the given range and resolution. - * - * @param min - * The minimum value of the slider - * @param max - * The maximum value of the slider - * @param resolution - * The number of digits after the decimal point. - */ - public Slider(double min, double max, int resolution) { - this(); - setMin(min); - setMax(max); - setResolution(resolution); - } - - /** - * Create a new slider with the given range that only allows integer values. - * - * @param min - * The minimum value of the slider - * @param max - * The maximum value of the slider - */ - public Slider(int min, int max) { - this(); - setMin(min); - setMax(max); - setResolution(0); - } - - /** - * Create a new slider with the given caption and range that only allows - * integer values. - * - * @param caption - * The caption for the slider - * @param min - * The minimum value of the slider - * @param max - * The maximum value of the slider - */ - public Slider(String caption, int min, int max) { - this(min, max); - setCaption(caption); - } - - /** - * Gets the maximum slider value - * - * @return the largest value the slider can have - */ - public double getMax() { - return max; - } - - /** - * Set the maximum slider value. If the current value of the slider is - * larger than this, the value is set to the new maximum. - * - * @param max - * The new maximum slider value - */ - public void setMax(double max) { - this.max = max; - if (getValue() > max) { - setValue(max); - } - requestRepaint(); - } - - /** - * Gets the minimum slider value - * - * @return the smallest value the slider can have - */ - public double getMin() { - return min; - } - - /** - * Set the minimum slider value. If the current value of the slider is - * smaller than this, the value is set to the new minimum. - * - * @param max - * The new minimum slider value - */ - public void setMin(double min) { - this.min = min; - if (getValue() < min) { - setValue(min); - } - requestRepaint(); - } - - /** - * Get the current orientation of the slider (horizontal or vertical). - * - * @return {@link #ORIENTATION_HORIZONTAL} or - * {@link #ORIENTATION_HORIZONTAL} - */ - public int getOrientation() { - return orientation; - } - - /** - * Set the orientation of the slider. - * - * @param The - * new orientation, either {@link #ORIENTATION_HORIZONTAL} or - * {@link #ORIENTATION_VERTICAL} - */ - public void setOrientation(int orientation) { - this.orientation = orientation; - requestRepaint(); - } - - /** - * Get the current resolution of the slider. The resolution is the number of - * digits after the decimal point. - * - * @return resolution - */ - public int getResolution() { - return resolution; - } - - /** - * Set a new resolution for the slider. The resolution is the number of - * digits after the decimal point. - * - * @param resolution - */ - public void setResolution(int resolution) { - if (resolution < 0) { - return; - } - this.resolution = resolution; - requestRepaint(); - } - - /** - * Sets the value of the slider. - * - * @param value - * The new value of the slider. - * @param repaintIsNotNeeded - * If true, client-side is not requested to repaint itself. - * @throws ValueOutOfBoundsException - * If the given value is not inside the range of the slider. - * @see #setMin(double) {@link #setMax(double)} - */ - @Override - protected void setValue(Double value, boolean repaintIsNotNeeded) { - final double v = value.doubleValue(); - double newValue; - if (resolution > 0) { - // Round up to resolution - newValue = (int) (v * Math.pow(10, resolution)); - newValue = newValue / Math.pow(10, resolution); - if (min > newValue || max < newValue) { - throw new ValueOutOfBoundsException(value); - } - } else { - newValue = (int) v; - if (min > newValue || max < newValue) { - throw new ValueOutOfBoundsException(value); - } - } - super.setValue(newValue, repaintIsNotNeeded); - } - - @Override - public void setValue(Object newFieldValue) - throws com.vaadin.data.Property.ReadOnlyException { - if (newFieldValue != null && newFieldValue instanceof Number - && !(newFieldValue instanceof Double)) { - // Support setting all types of Numbers - newFieldValue = ((Number) newFieldValue).doubleValue(); - } - - super.setValue(newFieldValue); - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - - target.addAttribute("min", min); - if (max > min) { - target.addAttribute("max", max); - } else { - target.addAttribute("max", min); - } - target.addAttribute("resolution", resolution); - - if (resolution > 0) { - target.addVariable(this, "value", getValue().doubleValue()); - } else { - target.addVariable(this, "value", getValue().intValue()); - } - - if (orientation == ORIENTATION_VERTICAL) { - target.addAttribute("vertical", true); - } - - } - - /** - * Invoked when the value of a variable has changed. Slider listeners are - * notified if the slider value has changed. - * - * @param source - * @param variables - */ - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - if (variables.containsKey("value")) { - final Object value = variables.get("value"); - final Double newValue = new Double(value.toString()); - if (newValue != null && newValue != getValue() - && !newValue.equals(getValue())) { - try { - setValue(newValue, true); - } catch (final ValueOutOfBoundsException e) { - // Convert to nearest bound - double out = e.getValue().doubleValue(); - if (out < min) { - out = min; - } - if (out > max) { - out = max; - } - super.setValue(new Double(out), false); - } - } - } - } - - /** - * Thrown when the value of the slider is about to be set to a value that is - * outside the valid range of the slider. - * - * @author Vaadin Ltd. - * - */ - public class ValueOutOfBoundsException extends RuntimeException { - - private final Double value; - - /** - * Constructs an <code>ValueOutOfBoundsException</code> with the - * specified detail message. - * - * @param valueOutOfBounds - */ - public ValueOutOfBoundsException(Double valueOutOfBounds) { - value = valueOutOfBounds; - } - - /** - * Gets the value that is outside the valid range of the slider. - * - * @return the value that is out of bounds - */ - public Double getValue() { - return value; - } - - } - - @Override - public Class<Double> getType() { - return Double.class; - } - -} diff --git a/src/com/vaadin/ui/TabSheet.java b/src/com/vaadin/ui/TabSheet.java deleted file mode 100644 index c52e9394c0..0000000000 --- a/src/com/vaadin/ui/TabSheet.java +++ /dev/null @@ -1,1328 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import com.vaadin.event.FieldEvents.BlurEvent; -import com.vaadin.event.FieldEvents.BlurListener; -import com.vaadin.event.FieldEvents.BlurNotifier; -import com.vaadin.event.FieldEvents.FocusEvent; -import com.vaadin.event.FieldEvents.FocusListener; -import com.vaadin.event.FieldEvents.FocusNotifier; -import com.vaadin.terminal.ErrorMessage; -import com.vaadin.terminal.KeyMapper; -import com.vaadin.terminal.LegacyPaint; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.gwt.client.ui.tabsheet.TabsheetBaseConnector; -import com.vaadin.terminal.gwt.client.ui.tabsheet.VTabsheet; -import com.vaadin.ui.Component.Focusable; -import com.vaadin.ui.themes.Reindeer; -import com.vaadin.ui.themes.Runo; - -/** - * TabSheet component. - * - * Tabs are typically identified by the component contained on the tab (see - * {@link ComponentContainer}), and tab metadata (including caption, icon, - * visibility, enabledness, closability etc.) is kept in separate {@link Tab} - * instances. - * - * Tabs added with {@link #addComponent(Component)} get the caption and the icon - * of the component at the time when the component is created, and these are not - * automatically updated after tab creation. - * - * A tab sheet can have multiple tab selection listeners and one tab close - * handler ({@link CloseHandler}), which by default removes the tab from the - * TabSheet. - * - * The {@link TabSheet} can be styled with the .v-tabsheet, .v-tabsheet-tabs and - * .v-tabsheet-content styles. Themes may also have pre-defined variations of - * the tab sheet presentation, such as {@link Reindeer#TABSHEET_BORDERLESS}, - * {@link Runo#TABSHEET_SMALL} and several other styles in {@link Reindeer}. - * - * The current implementation does not load the tabs to the UI before the first - * time they are shown, but this may change in future releases. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -public class TabSheet extends AbstractComponentContainer implements Focusable, - FocusNotifier, BlurNotifier, Vaadin6Component { - - /** - * List of component tabs (tab contents). In addition to being on this list, - * there is a {@link Tab} object in tabs for each tab with meta-data about - * the tab. - */ - private final ArrayList<Component> components = new ArrayList<Component>(); - - /** - * Map containing information related to the tabs (caption, icon etc). - */ - private final HashMap<Component, Tab> tabs = new HashMap<Component, Tab>(); - - /** - * Selected tab content component. - */ - private Component selected = null; - - /** - * Mapper between server-side component instances (tab contents) and keys - * given to the client that identify tabs. - */ - private final KeyMapper<Component> keyMapper = new KeyMapper<Component>(); - - /** - * When true, the tab selection area is not displayed to the user. - */ - private boolean tabsHidden; - - /** - * Handler to be called when a tab is closed. - */ - private CloseHandler closeHandler; - - private int tabIndex; - - /** - * Constructs a new Tabsheet. Tabsheet is immediate by default, and the - * default close handler removes the tab being closed. - */ - public TabSheet() { - super(); - // expand horizontally by default - setWidth(100, UNITS_PERCENTAGE); - setImmediate(true); - setCloseHandler(new CloseHandler() { - - @Override - public void onTabClose(TabSheet tabsheet, Component c) { - tabsheet.removeComponent(c); - } - }); - } - - /** - * Gets the component container iterator for going through all the - * components (tab contents). - * - * @return the unmodifiable Iterator of the tab content components - */ - - @Override - public Iterator<Component> getComponentIterator() { - return Collections.unmodifiableList(components).iterator(); - } - - /** - * Gets the number of contained components (tabs). Consistent with the - * iterator returned by {@link #getComponentIterator()}. - * - * @return the number of contained components - */ - - @Override - public int getComponentCount() { - return components.size(); - } - - /** - * Removes a component and its corresponding tab. - * - * If the tab was selected, the first eligible (visible and enabled) - * remaining tab is selected. - * - * @param c - * the component to be removed. - */ - - @Override - public void removeComponent(Component c) { - if (c != null && components.contains(c)) { - super.removeComponent(c); - keyMapper.remove(c); - components.remove(c); - tabs.remove(c); - if (c.equals(selected)) { - if (components.isEmpty()) { - setSelected(null); - } else { - // select the first enabled and visible tab, if any - updateSelection(); - fireSelectedTabChange(); - } - } - requestRepaint(); - } - } - - /** - * Removes a {@link Tab} and the component associated with it, as previously - * added with {@link #addTab(Component)}, - * {@link #addTab(Component, String, Resource)} or - * {@link #addComponent(Component)}. - * <p> - * If the tab was selected, the first eligible (visible and enabled) - * remaining tab is selected. - * </p> - * - * @see #addTab(Component) - * @see #addTab(Component, String, Resource) - * @see #addComponent(Component) - * @see #removeComponent(Component) - * @param tab - * the Tab to remove - */ - public void removeTab(Tab tab) { - removeComponent(tab.getComponent()); - } - - /** - * Adds a new tab into TabSheet. Component caption and icon are copied to - * the tab metadata at creation time. - * - * @see #addTab(Component) - * - * @param c - * the component to be added. - */ - - @Override - public void addComponent(Component c) { - addTab(c); - } - - /** - * Adds a new tab into TabSheet. - * - * The first tab added to a tab sheet is automatically selected and a tab - * selection event is fired. - * - * If the component is already present in the tab sheet, changes its caption - * and returns the corresponding (old) tab, preserving other tab metadata. - * - * @param c - * the component to be added onto tab - should not be null. - * @param caption - * the caption to be set for the component and used rendered in - * tab bar - * @return the created {@link Tab} - */ - public Tab addTab(Component c, String caption) { - return addTab(c, caption, null); - } - - /** - * Adds a new tab into TabSheet. - * - * The first tab added to a tab sheet is automatically selected and a tab - * selection event is fired. - * - * If the component is already present in the tab sheet, changes its caption - * and icon and returns the corresponding (old) tab, preserving other tab - * metadata. - * - * @param c - * the component to be added onto tab - should not be null. - * @param caption - * the caption to be set for the component and used rendered in - * tab bar - * @param icon - * the icon to be set for the component and used rendered in tab - * bar - * @return the created {@link Tab} - */ - public Tab addTab(Component c, String caption, Resource icon) { - return addTab(c, caption, icon, components.size()); - } - - /** - * Adds a new tab into TabSheet. - * - * The first tab added to a tab sheet is automatically selected and a tab - * selection event is fired. - * - * If the component is already present in the tab sheet, changes its caption - * and icon and returns the corresponding (old) tab, preserving other tab - * metadata like the position. - * - * @param c - * the component to be added onto tab - should not be null. - * @param caption - * the caption to be set for the component and used rendered in - * tab bar - * @param icon - * the icon to be set for the component and used rendered in tab - * bar - * @param position - * the position at where the the tab should be added. - * @return the created {@link Tab} - */ - public Tab addTab(Component c, String caption, Resource icon, int position) { - if (c == null) { - return null; - } else if (tabs.containsKey(c)) { - Tab tab = tabs.get(c); - tab.setCaption(caption); - tab.setIcon(icon); - return tab; - } else { - components.add(position, c); - - Tab tab = new TabSheetTabImpl(caption, icon); - - tabs.put(c, tab); - if (selected == null) { - setSelected(c); - fireSelectedTabChange(); - } - super.addComponent(c); - requestRepaint(); - return tab; - } - } - - /** - * Adds a new tab into TabSheet. Component caption and icon are copied to - * the tab metadata at creation time. - * - * If the tab sheet already contains the component, its tab is returned. - * - * @param c - * the component to be added onto tab - should not be null. - * @return the created {@link Tab} - */ - public Tab addTab(Component c) { - return addTab(c, components.size()); - } - - /** - * Adds a new tab into TabSheet. Component caption and icon are copied to - * the tab metadata at creation time. - * - * If the tab sheet already contains the component, its tab is returned. - * - * @param c - * the component to be added onto tab - should not be null. - * @param position - * The position where the tab should be added - * @return the created {@link Tab} - */ - public Tab addTab(Component c, int position) { - if (c == null) { - return null; - } else if (tabs.containsKey(c)) { - return tabs.get(c); - } else { - return addTab(c, c.getCaption(), c.getIcon(), position); - } - } - - /** - * Moves all components from another container to this container. The - * components are removed from the other container. - * - * If the source container is a {@link TabSheet}, component captions and - * icons are copied from it. - * - * @param source - * the container components are removed from. - */ - - @Override - public void moveComponentsFrom(ComponentContainer source) { - for (final Iterator<Component> i = source.getComponentIterator(); i - .hasNext();) { - final Component c = i.next(); - String caption = null; - Resource icon = null; - if (TabSheet.class.isAssignableFrom(source.getClass())) { - caption = ((TabSheet) source).getTabCaption(c); - icon = ((TabSheet) source).getTabIcon(c); - } - source.removeComponent(c); - addTab(c, caption, icon); - - } - } - - /** - * Paints the content of this component. - * - * @param target - * the paint target - * @throws PaintException - * if the paint operation failed. - */ - - @Override - public void paintContent(PaintTarget target) throws PaintException { - - if (areTabsHidden()) { - target.addAttribute("hidetabs", true); - } - - if (tabIndex != 0) { - target.addAttribute("tabindex", tabIndex); - } - - target.startTag("tabs"); - - for (final Iterator<Component> i = getComponentIterator(); i.hasNext();) { - final Component component = i.next(); - - Tab tab = tabs.get(component); - - target.startTag("tab"); - if (!tab.isEnabled() && tab.isVisible()) { - target.addAttribute( - TabsheetBaseConnector.ATTRIBUTE_TAB_DISABLED, true); - } - - if (!tab.isVisible()) { - target.addAttribute("hidden", true); - } - - if (tab.isClosable()) { - target.addAttribute("closable", true); - } - - // tab icon, caption and description, but used via - // VCaption.updateCaption(uidl) - final Resource icon = tab.getIcon(); - if (icon != null) { - target.addAttribute(TabsheetBaseConnector.ATTRIBUTE_TAB_ICON, - icon); - } - final String caption = tab.getCaption(); - if (caption != null && caption.length() > 0) { - target.addAttribute( - TabsheetBaseConnector.ATTRIBUTE_TAB_CAPTION, caption); - } - ErrorMessage tabError = tab.getComponentError(); - if (tabError != null) { - target.addAttribute( - TabsheetBaseConnector.ATTRIBUTE_TAB_ERROR_MESSAGE, - tabError.getFormattedHtmlMessage()); - } - final String description = tab.getDescription(); - if (description != null) { - target.addAttribute( - TabsheetBaseConnector.ATTRIBUTE_TAB_DESCRIPTION, - description); - } - - final String styleName = tab.getStyleName(); - if (styleName != null && styleName.length() != 0) { - target.addAttribute(VTabsheet.TAB_STYLE_NAME, styleName); - } - - target.addAttribute("key", keyMapper.key(component)); - if (component.equals(selected)) { - target.addAttribute("selected", true); - LegacyPaint.paint(component, target); - } - target.endTag("tab"); - } - - target.endTag("tabs"); - - if (selected != null) { - target.addVariable(this, "selected", keyMapper.key(selected)); - } - - } - - /** - * Are the tab selection parts ("tabs") hidden. - * - * @return true if the tabs are hidden in the UI - */ - public boolean areTabsHidden() { - return tabsHidden; - } - - /** - * Hides or shows the tab selection parts ("tabs"). - * - * @param tabsHidden - * true if the tabs should be hidden - */ - public void hideTabs(boolean tabsHidden) { - this.tabsHidden = tabsHidden; - requestRepaint(); - } - - /** - * Gets tab caption. The tab is identified by the tab content component. - * - * @param c - * the component in the tab - * @deprecated Use {@link #getTab(Component)} and {@link Tab#getCaption()} - * instead. - */ - @Deprecated - public String getTabCaption(Component c) { - Tab info = tabs.get(c); - if (info == null) { - return ""; - } else { - return info.getCaption(); - } - } - - /** - * Sets tab caption. The tab is identified by the tab content component. - * - * @param c - * the component in the tab - * @param caption - * the caption to set. - * @deprecated Use {@link #getTab(Component)} and - * {@link Tab#setCaption(String)} instead. - */ - @Deprecated - public void setTabCaption(Component c, String caption) { - Tab info = tabs.get(c); - if (info != null) { - info.setCaption(caption); - requestRepaint(); - } - } - - /** - * Gets the icon for a tab. The tab is identified by the tab content - * component. - * - * @param c - * the component in the tab - * @deprecated Use {@link #getTab(Component)} and {@link Tab#getIcon()} - * instead. - */ - @Deprecated - public Resource getTabIcon(Component c) { - Tab info = tabs.get(c); - if (info == null) { - return null; - } else { - return info.getIcon(); - } - } - - /** - * Sets icon for the given component. The tab is identified by the tab - * content component. - * - * @param c - * the component in the tab - * @param icon - * the icon to set - * @deprecated Use {@link #getTab(Component)} and - * {@link Tab#setIcon(Resource)} instead. - */ - @Deprecated - public void setTabIcon(Component c, Resource icon) { - Tab info = tabs.get(c); - if (info != null) { - info.setIcon(icon); - requestRepaint(); - } - } - - /** - * Returns the {@link Tab} (metadata) for a component. The {@link Tab} - * object can be used for setting caption,icon, etc for the tab. - * - * @param c - * the component - * @return The tab instance associated with the given component, or null if - * the tabsheet does not contain the component. - */ - public Tab getTab(Component c) { - return tabs.get(c); - } - - /** - * Returns the {@link Tab} (metadata) for a component. The {@link Tab} - * object can be used for setting caption,icon, etc for the tab. - * - * @param position - * the position of the tab - * @return The tab in the given position, or null if the position is out of - * bounds. - */ - public Tab getTab(int position) { - if (position >= 0 && position < getComponentCount()) { - return getTab(components.get(position)); - } else { - return null; - } - } - - /** - * Sets the selected tab. The tab is identified by the tab content - * component. Does nothing if the tabsheet doesn't contain the component. - * - * @param c - */ - public void setSelectedTab(Component c) { - if (c != null && components.contains(c) && !c.equals(selected)) { - setSelected(c); - updateSelection(); - fireSelectedTabChange(); - requestRepaint(); - } - } - - /** - * Sets the selected tab in the TabSheet. Ensures that the selected tab is - * repainted if needed. - * - * @param c - * The new selection or null for no selection - */ - private void setSelected(Component c) { - selected = c; - // Repaint of the selected component is needed as only the selected - // component is communicated to the client. Otherwise this will be a - // "cached" update even though the client knows nothing about the - // connector - if (selected instanceof ComponentContainer) { - ((ComponentContainer) selected).requestRepaintAll(); - } else if (selected instanceof Table) { - // Workaround until there's a generic way of telling a component - // that there is no client side state to rely on. See #8642 - ((Table) selected).refreshRowCache(); - } else if (selected != null) { - selected.requestRepaint(); - } - - } - - /** - * Sets the selected tab. The tab is identified by the corresponding - * {@link Tab Tab} instance. Does nothing if the tabsheet doesn't contain - * the given tab. - * - * @param tab - */ - public void setSelectedTab(Tab tab) { - if (tab != null) { - setSelectedTab(tab.getComponent()); - } - } - - /** - * Sets the selected tab, identified by its position. Does nothing if the - * position is out of bounds. - * - * @param position - */ - public void setSelectedTab(int position) { - setSelectedTab(getTab(position)); - } - - /** - * Checks if the current selection is valid, and updates the selection if - * the previously selected component is not visible and enabled. The first - * visible and enabled tab is selected if the current selection is empty or - * invalid. - * - * This method does not fire tab change events, but the caller should do so - * if appropriate. - * - * @return true if selection was changed, false otherwise - */ - private boolean updateSelection() { - Component originalSelection = selected; - for (final Iterator<Component> i = getComponentIterator(); i.hasNext();) { - final Component component = i.next(); - - Tab tab = tabs.get(component); - - /* - * If we have no selection, if the current selection is invisible or - * if the current selection is disabled (but the whole component is - * not) we select this tab instead - */ - Tab selectedTabInfo = null; - if (selected != null) { - selectedTabInfo = tabs.get(selected); - } - if (selected == null || selectedTabInfo == null - || !selectedTabInfo.isVisible() - || !selectedTabInfo.isEnabled()) { - - // The current selection is not valid so we need to change - // it - if (tab.isEnabled() && tab.isVisible()) { - setSelected(component); - break; - } else { - /* - * The current selection is not valid but this tab cannot be - * selected either. - */ - setSelected(null); - } - } - } - return originalSelection != selected; - } - - /** - * Gets the selected tab content component. - * - * @return the selected tab contents - */ - public Component getSelectedTab() { - return selected; - } - - // inherits javadoc - - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - if (variables.containsKey("selected")) { - setSelectedTab(keyMapper.get((String) variables.get("selected"))); - } - if (variables.containsKey("close")) { - final Component tab = keyMapper - .get((String) variables.get("close")); - if (tab != null) { - closeHandler.onTabClose(this, tab); - } - } - if (variables.containsKey(FocusEvent.EVENT_ID)) { - fireEvent(new FocusEvent(this)); - } - if (variables.containsKey(BlurEvent.EVENT_ID)) { - fireEvent(new BlurEvent(this)); - } - } - - /** - * Replaces a component (tab content) with another. This can be used to - * change tab contents or to rearrange tabs. The tab position and some - * metadata are preserved when moving components within the same - * {@link TabSheet}. - * - * If the oldComponent is not present in the tab sheet, the new one is added - * at the end. - * - * If the oldComponent is already in the tab sheet but the newComponent - * isn't, the old tab is replaced with a new one, and the caption and icon - * of the old one are copied to the new tab. - * - * If both old and new components are present, their positions are swapped. - * - * {@inheritDoc} - */ - - @Override - public void replaceComponent(Component oldComponent, Component newComponent) { - - if (selected == oldComponent) { - // keep selection w/o selectedTabChange event - setSelected(newComponent); - } - - Tab newTab = tabs.get(newComponent); - Tab oldTab = tabs.get(oldComponent); - - // Gets the locations - int oldLocation = -1; - int newLocation = -1; - int location = 0; - for (final Iterator<Component> i = components.iterator(); i.hasNext();) { - final Component component = i.next(); - - if (component == oldComponent) { - oldLocation = location; - } - if (component == newComponent) { - newLocation = location; - } - - location++; - } - - if (oldLocation == -1) { - addComponent(newComponent); - } else if (newLocation == -1) { - removeComponent(oldComponent); - newTab = addTab(newComponent, oldLocation); - // Copy all relevant metadata to the new tab (#8793) - // TODO Should reuse the old tab instance instead? - copyTabMetadata(oldTab, newTab); - } else { - components.set(oldLocation, newComponent); - components.set(newLocation, oldComponent); - - // Tab associations are not changed, but metadata is swapped between - // the instances - // TODO Should reassociate the instances instead? - Tab tmp = new TabSheetTabImpl(null, null); - copyTabMetadata(newTab, tmp); - copyTabMetadata(oldTab, newTab); - copyTabMetadata(tmp, oldTab); - - requestRepaint(); - } - - } - - /* Click event */ - - private static final Method SELECTED_TAB_CHANGE_METHOD; - static { - try { - SELECTED_TAB_CHANGE_METHOD = SelectedTabChangeListener.class - .getDeclaredMethod("selectedTabChange", - new Class[] { SelectedTabChangeEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException( - "Internal error finding methods in TabSheet"); - } - } - - /** - * Selected tab change event. This event is sent when the selected (shown) - * tab in the tab sheet is changed. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public class SelectedTabChangeEvent extends Component.Event { - - /** - * New instance of selected tab change event - * - * @param source - * the Source of the event. - */ - public SelectedTabChangeEvent(Component source) { - super(source); - } - - /** - * TabSheet where the event occurred. - * - * @return the Source of the event. - */ - public TabSheet getTabSheet() { - return (TabSheet) getSource(); - } - } - - /** - * Selected tab change event listener. The listener is called whenever - * another tab is selected, including when adding the first tab to a - * tabsheet. - * - * @author Vaadin Ltd. - * - * @version - * @VERSION@ - * @since 3.0 - */ - public interface SelectedTabChangeListener extends Serializable { - - /** - * Selected (shown) tab in tab sheet has has been changed. - * - * @param event - * the selected tab change event. - */ - public void selectedTabChange(SelectedTabChangeEvent event); - } - - /** - * Adds a tab selection listener - * - * @param listener - * the Listener to be added. - */ - public void addListener(SelectedTabChangeListener listener) { - addListener(SelectedTabChangeEvent.class, listener, - SELECTED_TAB_CHANGE_METHOD); - } - - /** - * Removes a tab selection listener - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(SelectedTabChangeListener listener) { - removeListener(SelectedTabChangeEvent.class, listener, - SELECTED_TAB_CHANGE_METHOD); - } - - /** - * Sends an event that the currently selected tab has changed. - */ - protected void fireSelectedTabChange() { - fireEvent(new SelectedTabChangeEvent(this)); - } - - /** - * Tab meta-data for a component in a {@link TabSheet}. - * - * The meta-data includes the tab caption, icon, visibility and enabledness, - * closability, description (tooltip) and an optional component error shown - * in the tab. - * - * Tabs are identified by the component contained on them in most cases, and - * the meta-data can be obtained with {@link TabSheet#getTab(Component)}. - */ - public interface Tab extends Serializable { - /** - * Returns the visible status for the tab. An invisible tab is not shown - * in the tab bar and cannot be selected. - * - * @return true for visible, false for hidden - */ - public boolean isVisible(); - - /** - * Sets the visible status for the tab. An invisible tab is not shown in - * the tab bar and cannot be selected, selection is changed - * automatically when there is an attempt to select an invisible tab. - * - * @param visible - * true for visible, false for hidden - */ - public void setVisible(boolean visible); - - /** - * Returns the closability status for the tab. - * - * @return true if the tab is allowed to be closed by the end user, - * false for not allowing closing - */ - public boolean isClosable(); - - /** - * Sets the closability status for the tab. A closable tab can be closed - * by the user through the user interface. This also controls if a close - * button is shown to the user or not. - * <p> - * Note! Currently only supported by TabSheet, not Accordion. - * </p> - * - * @param visible - * true if the end user is allowed to close the tab, false - * for not allowing to close. Should default to false. - */ - public void setClosable(boolean closable); - - /** - * Returns the enabled status for the tab. A disabled tab is shown as - * such in the tab bar and cannot be selected. - * - * @return true for enabled, false for disabled - */ - public boolean isEnabled(); - - /** - * Sets the enabled status for the tab. A disabled tab is shown as such - * in the tab bar and cannot be selected. - * - * @param enabled - * true for enabled, false for disabled - */ - public void setEnabled(boolean enabled); - - /** - * Sets the caption for the tab. - * - * @param caption - * the caption to set - */ - public void setCaption(String caption); - - /** - * Gets the caption for the tab. - */ - public String getCaption(); - - /** - * Gets the icon for the tab. - */ - public Resource getIcon(); - - /** - * Sets the icon for the tab. - * - * @param icon - * the icon to set - */ - public void setIcon(Resource icon); - - /** - * Gets the description for the tab. The description can be used to - * briefly describe the state of the tab to the user, and is typically - * shown as a tooltip when hovering over the tab. - * - * @return the description for the tab - */ - public String getDescription(); - - /** - * Sets the description for the tab. The description can be used to - * briefly describe the state of the tab to the user, and is typically - * shown as a tooltip when hovering over the tab. - * - * @param description - * the new description string for the tab. - */ - public void setDescription(String description); - - /** - * Sets an error indicator to be shown in the tab. This can be used e.g. - * to communicate to the user that there is a problem in the contents of - * the tab. - * - * @see AbstractComponent#setComponentError(ErrorMessage) - * - * @param componentError - * error message or null for none - */ - public void setComponentError(ErrorMessage componentError); - - /** - * Gets the current error message shown for the tab. - * - * TODO currently not sent to the client - * - * @see AbstractComponent#setComponentError(ErrorMessage) - */ - public ErrorMessage getComponentError(); - - /** - * Get the component related to the Tab - */ - public Component getComponent(); - - /** - * Sets a style name for the tab. The style name will be rendered as a - * HTML class name, which can be used in a CSS definition. - * - * <pre> - * Tab tab = tabsheet.addTab(tabContent, "Tab text"); - * tab.setStyleName("mystyle"); - * </pre> - * <p> - * The used style name will be prefixed with " - * {@code v-tabsheet-tabitemcell-}". For example, if you give a tab the - * style "{@code mystyle}", the tab will get a " - * {@code v-tabsheet-tabitemcell-mystyle}" style. You could then style - * the component with: - * </p> - * - * <pre> - * .v-tabsheet-tabitemcell-mystyle {font-style: italic;} - * </pre> - * - * <p> - * This method will trigger a {@link RepaintRequestEvent} on the - * TabSheet to which the Tab belongs. - * </p> - * - * @param styleName - * the new style to be set for tab - * @see #getStyleName() - */ - public void setStyleName(String styleName); - - /** - * Gets the user-defined CSS style name of the tab. Built-in style names - * defined in Vaadin or GWT are not returned. - * - * @return the style name or of the tab - * @see #setStyleName(String) - */ - public String getStyleName(); - } - - /** - * TabSheet's implementation of {@link Tab} - tab metadata. - */ - public class TabSheetTabImpl implements Tab { - - private String caption = ""; - private Resource icon = null; - private boolean enabled = true; - private boolean visible = true; - private boolean closable = false; - private String description = null; - private ErrorMessage componentError = null; - private String styleName; - - public TabSheetTabImpl(String caption, Resource icon) { - if (caption == null) { - caption = ""; - } - this.caption = caption; - this.icon = icon; - } - - /** - * Returns the tab caption. Can never be null. - */ - - @Override - public String getCaption() { - return caption; - } - - @Override - public void setCaption(String caption) { - this.caption = caption; - requestRepaint(); - } - - @Override - public Resource getIcon() { - return icon; - } - - @Override - public void setIcon(Resource icon) { - this.icon = icon; - requestRepaint(); - } - - @Override - public boolean isEnabled() { - return enabled; - } - - @Override - public void setEnabled(boolean enabled) { - this.enabled = enabled; - if (updateSelection()) { - fireSelectedTabChange(); - } - requestRepaint(); - } - - @Override - public boolean isVisible() { - return visible; - } - - @Override - public void setVisible(boolean visible) { - this.visible = visible; - if (updateSelection()) { - fireSelectedTabChange(); - } - requestRepaint(); - } - - @Override - public boolean isClosable() { - return closable; - } - - @Override - public void setClosable(boolean closable) { - this.closable = closable; - requestRepaint(); - } - - public void close() { - - } - - @Override - public String getDescription() { - return description; - } - - @Override - public void setDescription(String description) { - this.description = description; - requestRepaint(); - } - - @Override - public ErrorMessage getComponentError() { - return componentError; - } - - @Override - public void setComponentError(ErrorMessage componentError) { - this.componentError = componentError; - requestRepaint(); - } - - @Override - public Component getComponent() { - for (Map.Entry<Component, Tab> entry : tabs.entrySet()) { - if (entry.getValue() == this) { - return entry.getKey(); - } - } - return null; - } - - @Override - public void setStyleName(String styleName) { - this.styleName = styleName; - requestRepaint(); - } - - @Override - public String getStyleName() { - return styleName; - } - } - - /** - * CloseHandler is used to process tab closing events. Default behavior is - * to remove the tab from the TabSheet. - * - * @author Jouni Koivuviita / Vaadin Ltd. - * @since 6.2.0 - * - */ - public interface CloseHandler extends Serializable { - - /** - * Called when a user has pressed the close icon of a tab in the client - * side widget. - * - * @param tabsheet - * the TabSheet to which the tab belongs to - * @param tabContent - * the component that corresponds to the tab whose close - * button was clicked - */ - void onTabClose(final TabSheet tabsheet, final Component tabContent); - } - - /** - * Provide a custom {@link CloseHandler} for this TabSheet if you wish to - * perform some additional tasks when a user clicks on a tabs close button, - * e.g. show a confirmation dialogue before removing the tab. - * - * To remove the tab, if you provide your own close handler, you must call - * {@link #removeComponent(Component)} yourself. - * - * The default CloseHandler for TabSheet will only remove the tab. - * - * @param handler - */ - public void setCloseHandler(CloseHandler handler) { - closeHandler = handler; - } - - /** - * Sets the position of the tab. - * - * @param tab - * The tab - * @param position - * The new position of the tab - */ - public void setTabPosition(Tab tab, int position) { - int oldPosition = getTabPosition(tab); - components.remove(oldPosition); - components.add(position, tab.getComponent()); - requestRepaint(); - } - - /** - * Gets the position of the tab - * - * @param tab - * The tab - * @return - */ - public int getTabPosition(Tab tab) { - return components.indexOf(tab.getComponent()); - } - - @Override - public void focus() { - super.focus(); - } - - @Override - public int getTabIndex() { - return tabIndex; - } - - @Override - public void setTabIndex(int tabIndex) { - this.tabIndex = tabIndex; - requestRepaint(); - } - - @Override - public void addListener(BlurListener listener) { - addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, - BlurListener.blurMethod); - } - - @Override - public void removeListener(BlurListener listener) { - removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); - } - - @Override - public void addListener(FocusListener listener) { - addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, - FocusListener.focusMethod); - } - - @Override - public void removeListener(FocusListener listener) { - removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); - - } - - @Override - public boolean isComponentVisible(Component childComponent) { - return childComponent == getSelectedTab(); - } - - /** - * Copies properties from one Tab to another. - * - * @param from - * The tab whose data to copy. - * @param to - * The tab to which copy the data. - */ - private static void copyTabMetadata(Tab from, Tab to) { - to.setCaption(from.getCaption()); - to.setIcon(from.getIcon()); - to.setDescription(from.getDescription()); - to.setVisible(from.isVisible()); - to.setEnabled(from.isEnabled()); - to.setClosable(from.isClosable()); - to.setStyleName(from.getStyleName()); - to.setComponentError(from.getComponentError()); - } -} diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java deleted file mode 100644 index 39b7fb7473..0000000000 --- a/src/com/vaadin/ui/Table.java +++ /dev/null @@ -1,5449 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.Map; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.vaadin.data.Container; -import com.vaadin.data.Item; -import com.vaadin.data.Property; -import com.vaadin.data.util.ContainerOrderedWrapper; -import com.vaadin.data.util.IndexedContainer; -import com.vaadin.data.util.converter.Converter; -import com.vaadin.data.util.converter.ConverterUtil; -import com.vaadin.event.Action; -import com.vaadin.event.Action.Handler; -import com.vaadin.event.DataBoundTransferable; -import com.vaadin.event.ItemClickEvent; -import com.vaadin.event.ItemClickEvent.ItemClickListener; -import com.vaadin.event.ItemClickEvent.ItemClickNotifier; -import com.vaadin.event.MouseEvents.ClickEvent; -import com.vaadin.event.dd.DragAndDropEvent; -import com.vaadin.event.dd.DragSource; -import com.vaadin.event.dd.DropHandler; -import com.vaadin.event.dd.DropTarget; -import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.terminal.KeyMapper; -import com.vaadin.terminal.LegacyPaint; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.gwt.client.ui.table.VScrollTable; - -/** - * <p> - * <code>Table</code> is used for representing data or components in a pageable - * and selectable table. - * </p> - * - * <p> - * Scalability of the Table is largely dictated by the container. A table does - * not have a limit for the number of items and is just as fast with hundreds of - * thousands of items as with just a few. The current GWT implementation with - * scrolling however limits the number of rows to around 500000, depending on - * the browser and the pixel height of rows. - * </p> - * - * <p> - * Components in a Table will not have their caption nor icon rendered. - * </p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings({ "deprecation" }) -public class Table extends AbstractSelect implements Action.Container, - Container.Ordered, Container.Sortable, ItemClickNotifier, DragSource, - DropTarget, HasComponents { - - private transient Logger logger = null; - - /** - * Modes that Table support as drag sourse. - */ - public enum TableDragMode { - /** - * Table does not start drag and drop events. HTM5 style events started - * by browser may still happen. - */ - NONE, - /** - * Table starts drag with a one row only. - */ - ROW, - /** - * Table drags selected rows, if drag starts on a selected rows. Else it - * starts like in ROW mode. Note, that in Transferable there will still - * be only the row on which the drag started, other dragged rows need to - * be checked from the source Table. - */ - MULTIROW - } - - protected static final int CELL_KEY = 0; - - protected static final int CELL_HEADER = 1; - - protected static final int CELL_ICON = 2; - - protected static final int CELL_ITEMID = 3; - - protected static final int CELL_GENERATED_ROW = 4; - - protected static final int CELL_FIRSTCOL = 5; - - public enum Align { - /** - * Left column alignment. <b>This is the default behaviour. </b> - */ - LEFT("b"), - - /** - * Center column alignment. - */ - CENTER("c"), - - /** - * Right column alignment. - */ - RIGHT("e"); - - private String alignment; - - private Align(String alignment) { - this.alignment = alignment; - } - - @Override - public String toString() { - return alignment; - } - - public Align convertStringToAlign(String string) { - if (string == null) { - return null; - } - if (string.equals("b")) { - return Align.LEFT; - } else if (string.equals("c")) { - return Align.CENTER; - } else if (string.equals("e")) { - return Align.RIGHT; - } else { - return null; - } - } - } - - /** - * @deprecated from 7.0, use {@link Align#LEFT} instead - */ - @Deprecated - public static final Align ALIGN_LEFT = Align.LEFT; - - /** - * @deprecated from 7.0, use {@link Align#CENTER} instead - */ - @Deprecated - public static final Align ALIGN_CENTER = Align.CENTER; - - /** - * @deprecated from 7.0, use {@link Align#RIGHT} instead - */ - @Deprecated - public static final Align ALIGN_RIGHT = Align.RIGHT; - - public enum ColumnHeaderMode { - /** - * Column headers are hidden. - */ - HIDDEN, - /** - * Property ID:s are used as column headers. - */ - ID, - /** - * Column headers are explicitly specified with - * {@link #setColumnHeaders(String[])}. - */ - EXPLICIT, - /** - * Column headers are explicitly specified with - * {@link #setColumnHeaders(String[])}. If a header is not specified for - * a given property, its property id is used instead. - * <p> - * <b>This is the default behavior. </b> - */ - EXPLICIT_DEFAULTS_ID - } - - /** - * @deprecated from 7.0, use {@link ColumnHeaderMode#HIDDEN} instead - */ - @Deprecated - public static final ColumnHeaderMode COLUMN_HEADER_MODE_HIDDEN = ColumnHeaderMode.HIDDEN; - - /** - * @deprecated from 7.0, use {@link ColumnHeaderMode#ID} instead - */ - @Deprecated - public static final ColumnHeaderMode COLUMN_HEADER_MODE_ID = ColumnHeaderMode.ID; - - /** - * @deprecated from 7.0, use {@link ColumnHeaderMode#EXPLICIT} instead - */ - @Deprecated - public static final ColumnHeaderMode COLUMN_HEADER_MODE_EXPLICIT = ColumnHeaderMode.EXPLICIT; - - /** - * @deprecated from 7.0, use {@link ColumnHeaderMode#EXPLICIT_DEFAULTS_ID} - * instead - */ - @Deprecated - public static final ColumnHeaderMode COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID = ColumnHeaderMode.EXPLICIT_DEFAULTS_ID; - - public enum RowHeaderMode { - /** - * Row caption mode: The row headers are hidden. <b>This is the default - * mode. </b> - */ - HIDDEN(null), - /** - * Row caption mode: Items Id-objects toString is used as row caption. - */ - ID(ItemCaptionMode.ID), - /** - * Row caption mode: Item-objects toString is used as row caption. - */ - ITEM(ItemCaptionMode.ITEM), - /** - * Row caption mode: Index of the item is used as item caption. The - * index mode can only be used with the containers implementing the - * {@link com.vaadin.data.Container.Indexed} interface. - */ - INDEX(ItemCaptionMode.INDEX), - /** - * Row caption mode: Item captions are explicitly specified, but if the - * caption is missing, the item id objects <code>toString()</code> is - * used instead. - */ - EXPLICIT_DEFAULTS_ID(ItemCaptionMode.EXPLICIT_DEFAULTS_ID), - /** - * Row caption mode: Item captions are explicitly specified. - */ - EXPLICIT(ItemCaptionMode.EXPLICIT), - /** - * Row caption mode: Only icons are shown, the captions are hidden. - */ - ICON_ONLY(ItemCaptionMode.ICON_ONLY), - /** - * Row caption mode: Item captions are read from property specified with - * {@link #setItemCaptionPropertyId(Object)}. - */ - PROPERTY(ItemCaptionMode.PROPERTY); - - ItemCaptionMode mode; - - private RowHeaderMode(ItemCaptionMode mode) { - this.mode = mode; - } - - public ItemCaptionMode getItemCaptionMode() { - return mode; - } - } - - /** - * @deprecated from 7.0, use {@link RowHeaderMode#HIDDEN} instead - */ - @Deprecated - public static final RowHeaderMode ROW_HEADER_MODE_HIDDEN = RowHeaderMode.HIDDEN; - - /** - * @deprecated from 7.0, use {@link RowHeaderMode#ID} instead - */ - @Deprecated - public static final RowHeaderMode ROW_HEADER_MODE_ID = RowHeaderMode.ID; - - /** - * @deprecated from 7.0, use {@link RowHeaderMode#ITEM} instead - */ - @Deprecated - public static final RowHeaderMode ROW_HEADER_MODE_ITEM = RowHeaderMode.ITEM; - - /** - * @deprecated from 7.0, use {@link RowHeaderMode#INDEX} instead - */ - @Deprecated - public static final RowHeaderMode ROW_HEADER_MODE_INDEX = RowHeaderMode.INDEX; - - /** - * @deprecated from 7.0, use {@link RowHeaderMode#EXPLICIT_DEFAULTS_ID} - * instead - */ - @Deprecated - public static final RowHeaderMode ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID = RowHeaderMode.EXPLICIT_DEFAULTS_ID; - - /** - * @deprecated from 7.0, use {@link RowHeaderMode#EXPLICIT} instead - */ - @Deprecated - public static final RowHeaderMode ROW_HEADER_MODE_EXPLICIT = RowHeaderMode.EXPLICIT; - - /** - * @deprecated from 7.0, use {@link RowHeaderMode#ICON_ONLY} instead - */ - @Deprecated - public static final RowHeaderMode ROW_HEADER_MODE_ICON_ONLY = RowHeaderMode.ICON_ONLY; - - /** - * @deprecated from 7.0, use {@link RowHeaderMode#PROPERTY} instead - */ - @Deprecated - public static final RowHeaderMode ROW_HEADER_MODE_PROPERTY = RowHeaderMode.PROPERTY; - - /** - * The default rate that table caches rows for smooth scrolling. - */ - private static final double CACHE_RATE_DEFAULT = 2; - - private static final String ROW_HEADER_COLUMN_KEY = "0"; - private static final Object ROW_HEADER_FAKE_PROPERTY_ID = new UniqueSerializable() { - }; - - /* Private table extensions to Select */ - - /** - * True if column collapsing is allowed. - */ - private boolean columnCollapsingAllowed = false; - - /** - * True if reordering of columns is allowed on the client side. - */ - private boolean columnReorderingAllowed = false; - - /** - * Keymapper for column ids. - */ - private final KeyMapper<Object> columnIdMap = new KeyMapper<Object>(); - - /** - * Holds visible column propertyIds - in order. - */ - private LinkedList<Object> visibleColumns = new LinkedList<Object>(); - - /** - * Holds noncollapsible columns. - */ - private HashSet<Object> noncollapsibleColumns = new HashSet<Object>(); - - /** - * Holds propertyIds of currently collapsed columns. - */ - private final HashSet<Object> collapsedColumns = new HashSet<Object>(); - - /** - * Holds headers for visible columns (by propertyId). - */ - private final HashMap<Object, String> columnHeaders = new HashMap<Object, String>(); - - /** - * Holds footers for visible columns (by propertyId). - */ - private final HashMap<Object, String> columnFooters = new HashMap<Object, String>(); - - /** - * Holds icons for visible columns (by propertyId). - */ - private final HashMap<Object, Resource> columnIcons = new HashMap<Object, Resource>(); - - /** - * Holds alignments for visible columns (by propertyId). - */ - private HashMap<Object, Align> columnAlignments = new HashMap<Object, Align>(); - - /** - * Holds column widths in pixels (Integer) or expand ratios (Float) for - * visible columns (by propertyId). - */ - private final HashMap<Object, Object> columnWidths = new HashMap<Object, Object>(); - - /** - * Holds column generators - */ - private final HashMap<Object, ColumnGenerator> columnGenerators = new LinkedHashMap<Object, ColumnGenerator>(); - - /** - * Holds value of property pageLength. 0 disables paging. - */ - private int pageLength = 15; - - /** - * Id the first item on the current page. - */ - private Object currentPageFirstItemId = null; - - /** - * Index of the first item on the current page. - */ - private int currentPageFirstItemIndex = 0; - - /** - * Holds value of property selectable. - */ - private boolean selectable = false; - - /** - * Holds value of property columnHeaderMode. - */ - private ColumnHeaderMode columnHeaderMode = ColumnHeaderMode.EXPLICIT_DEFAULTS_ID; - - /** - * Holds value of property rowHeaderMode. - */ - private RowHeaderMode rowHeaderMode = RowHeaderMode.EXPLICIT_DEFAULTS_ID; - - /** - * Should the Table footer be visible? - */ - private boolean columnFootersVisible = false; - - /** - * Page contents buffer used in buffered mode. - */ - private Object[][] pageBuffer = null; - - /** - * Set of properties listened - the list is kept to release the listeners - * later. - */ - private HashSet<Property<?>> listenedProperties = null; - - /** - * Set of visible components - the is used for needsRepaint calculation. - */ - private HashSet<Component> visibleComponents = null; - - /** - * List of action handlers. - */ - private LinkedList<Handler> actionHandlers = null; - - /** - * Action mapper. - */ - private KeyMapper<Action> actionMapper = null; - - /** - * Table cell editor factory. - */ - private TableFieldFactory fieldFactory = DefaultFieldFactory.get(); - - /** - * Is table editable. - */ - private boolean editable = false; - - /** - * Current sorting direction. - */ - private boolean sortAscending = true; - - /** - * Currently table is sorted on this propertyId. - */ - private Object sortContainerPropertyId = null; - - /** - * Is table sorting by the user enabled. - */ - private boolean sortEnabled = true; - - /** - * Number of rows explicitly requested by the client to be painted on next - * paint. This is -1 if no request by the client is made. Painting the - * component will automatically reset this to -1. - */ - private int reqRowsToPaint = -1; - - /** - * Index of the first rows explicitly requested by the client to be painted. - * This is -1 if no request by the client is made. Painting the component - * will automatically reset this to -1. - */ - private int reqFirstRowToPaint = -1; - - private int firstToBeRenderedInClient = -1; - - private int lastToBeRenderedInClient = -1; - - private boolean isContentRefreshesEnabled = true; - - private int pageBufferFirstIndex; - - private boolean containerChangeToBeRendered = false; - - /** - * Table cell specific style generator - */ - private CellStyleGenerator cellStyleGenerator = null; - - /** - * Table cell specific tooltip generator - */ - private ItemDescriptionGenerator itemDescriptionGenerator; - - /* - * EXPERIMENTAL feature: will tell the client to re-calculate column widths - * if set to true. Currently no setter: extend to enable. - */ - protected boolean alwaysRecalculateColumnWidths = false; - - private double cacheRate = CACHE_RATE_DEFAULT; - - private TableDragMode dragMode = TableDragMode.NONE; - - private DropHandler dropHandler; - - private MultiSelectMode multiSelectMode = MultiSelectMode.DEFAULT; - - private boolean rowCacheInvalidated; - - private RowGenerator rowGenerator = null; - - private final Map<Field<?>, Property<?>> associatedProperties = new HashMap<Field<?>, Property<?>>(); - - private boolean painted = false; - - private HashMap<Object, Converter<String, Object>> propertyValueConverters = new HashMap<Object, Converter<String, Object>>(); - - /** - * Set to true if the client-side should be informed that the key mapper has - * been reset so it can avoid sending back references to keys that are no - * longer present. - */ - private boolean keyMapperReset; - - /* Table constructors */ - - /** - * Creates a new empty table. - */ - public Table() { - setRowHeaderMode(ROW_HEADER_MODE_HIDDEN); - } - - /** - * Creates a new empty table with caption. - * - * @param caption - */ - public Table(String caption) { - this(); - setCaption(caption); - } - - /** - * Creates a new table with caption and connect it to a Container. - * - * @param caption - * @param dataSource - */ - public Table(String caption, Container dataSource) { - this(); - setCaption(caption); - setContainerDataSource(dataSource); - } - - /* Table functionality */ - - /** - * Gets the array of visible column id:s, including generated columns. - * - * <p> - * The columns are show in the order of their appearance in this array. - * </p> - * - * @return an array of currently visible propertyIds and generated column - * ids. - */ - public Object[] getVisibleColumns() { - if (visibleColumns == null) { - return null; - } - return visibleColumns.toArray(); - } - - /** - * Sets the array of visible column property id:s. - * - * <p> - * The columns are show in the order of their appearance in this array. - * </p> - * - * @param visibleColumns - * the Array of shown property id:s. - */ - public void setVisibleColumns(Object[] visibleColumns) { - - // Visible columns must exist - if (visibleColumns == null) { - throw new NullPointerException( - "Can not set visible columns to null value"); - } - - // TODO add error check that no duplicate identifiers exist - - // Checks that the new visible columns contains no nulls and properties - // exist - final Collection<?> properties = getContainerPropertyIds(); - for (int i = 0; i < visibleColumns.length; i++) { - if (visibleColumns[i] == null) { - throw new NullPointerException("Ids must be non-nulls"); - } else if (!properties.contains(visibleColumns[i]) - && !columnGenerators.containsKey(visibleColumns[i])) { - throw new IllegalArgumentException( - "Ids must exist in the Container or as a generated column , missing id: " - + visibleColumns[i]); - } - } - - // If this is called before the constructor is finished, it might be - // uninitialized - final LinkedList<Object> newVC = new LinkedList<Object>(); - for (int i = 0; i < visibleColumns.length; i++) { - newVC.add(visibleColumns[i]); - } - - // Removes alignments, icons and headers from hidden columns - if (this.visibleColumns != null) { - boolean disabledHere = disableContentRefreshing(); - try { - for (final Iterator<Object> i = this.visibleColumns.iterator(); i - .hasNext();) { - final Object col = i.next(); - if (!newVC.contains(col)) { - setColumnHeader(col, null); - setColumnAlignment(col, (Align) null); - setColumnIcon(col, null); - } - } - } finally { - if (disabledHere) { - enableContentRefreshing(false); - } - } - } - - this.visibleColumns = newVC; - - // Assures visual refresh - refreshRowCache(); - } - - /** - * Gets the headers of the columns. - * - * <p> - * The headers match the property id:s given my the set visible column - * headers. The table must be set in either - * {@link #COLUMN_HEADER_MODE_EXPLICIT} or - * {@link #COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID} mode to show the - * headers. In the defaults mode any nulls in the headers array are replaced - * with id.toString(). - * </p> - * - * @return the Array of column headers. - */ - public String[] getColumnHeaders() { - if (columnHeaders == null) { - return null; - } - final String[] headers = new String[visibleColumns.size()]; - int i = 0; - for (final Iterator<Object> it = visibleColumns.iterator(); it - .hasNext(); i++) { - headers[i] = getColumnHeader(it.next()); - } - return headers; - } - - /** - * Sets the headers of the columns. - * - * <p> - * The headers match the property id:s given my the set visible column - * headers. The table must be set in either - * {@link #COLUMN_HEADER_MODE_EXPLICIT} or - * {@link #COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID} mode to show the - * headers. In the defaults mode any nulls in the headers array are replaced - * with id.toString() outputs when rendering. - * </p> - * - * @param columnHeaders - * the Array of column headers that match the - * {@link #getVisibleColumns()} method. - */ - public void setColumnHeaders(String[] columnHeaders) { - - if (columnHeaders.length != visibleColumns.size()) { - throw new IllegalArgumentException( - "The length of the headers array must match the number of visible columns"); - } - - this.columnHeaders.clear(); - int i = 0; - for (final Iterator<Object> it = visibleColumns.iterator(); it - .hasNext() && i < columnHeaders.length; i++) { - this.columnHeaders.put(it.next(), columnHeaders[i]); - } - - requestRepaint(); - } - - /** - * Gets the icons of the columns. - * - * <p> - * The icons in headers match the property id:s given my the set visible - * column headers. The table must be set in either - * {@link #COLUMN_HEADER_MODE_EXPLICIT} or - * {@link #COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID} mode to show the headers - * with icons. - * </p> - * - * @return the Array of icons that match the {@link #getVisibleColumns()}. - */ - public Resource[] getColumnIcons() { - if (columnIcons == null) { - return null; - } - final Resource[] icons = new Resource[visibleColumns.size()]; - int i = 0; - for (final Iterator<Object> it = visibleColumns.iterator(); it - .hasNext(); i++) { - icons[i] = columnIcons.get(it.next()); - } - - return icons; - } - - /** - * Sets the icons of the columns. - * - * <p> - * The icons in headers match the property id:s given my the set visible - * column headers. The table must be set in either - * {@link #COLUMN_HEADER_MODE_EXPLICIT} or - * {@link #COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID} mode to show the headers - * with icons. - * </p> - * - * @param columnIcons - * the Array of icons that match the {@link #getVisibleColumns()} - * . - */ - public void setColumnIcons(Resource[] columnIcons) { - - if (columnIcons.length != visibleColumns.size()) { - throw new IllegalArgumentException( - "The length of the icons array must match the number of visible columns"); - } - - this.columnIcons.clear(); - int i = 0; - for (final Iterator<Object> it = visibleColumns.iterator(); it - .hasNext() && i < columnIcons.length; i++) { - this.columnIcons.put(it.next(), columnIcons[i]); - } - - requestRepaint(); - } - - /** - * Gets the array of column alignments. - * - * <p> - * The items in the array must match the properties identified by - * {@link #getVisibleColumns()}. The possible values for the alignments - * include: - * <ul> - * <li>{@link Align#LEFT}: Left alignment</li> - * <li>{@link Align#CENTER}: Centered</li> - * <li>{@link Align#RIGHT}: Right alignment</li> - * </ul> - * The alignments default to {@link Align#LEFT}: any null values are - * rendered as align lefts. - * </p> - * - * @return the Column alignments array. - */ - public Align[] getColumnAlignments() { - if (columnAlignments == null) { - return null; - } - final Align[] alignments = new Align[visibleColumns.size()]; - int i = 0; - for (final Iterator<Object> it = visibleColumns.iterator(); it - .hasNext(); i++) { - alignments[i] = getColumnAlignment(it.next()); - } - - return alignments; - } - - /** - * Sets the column alignments. - * - * <p> - * The amount of items in the array must match the amount of properties - * identified by {@link #getVisibleColumns()}. The possible values for the - * alignments include: - * <ul> - * <li>{@link Align#LEFT}: Left alignment</li> - * <li>{@link Align#CENTER}: Centered</li> - * <li>{@link Align#RIGHT}: Right alignment</li> - * </ul> - * The alignments default to {@link Align#LEFT} - * </p> - * - * @param columnAlignments - * the Column alignments array. - */ - public void setColumnAlignments(Align... columnAlignments) { - - if (columnAlignments.length != visibleColumns.size()) { - throw new IllegalArgumentException( - "The length of the alignments array must match the number of visible columns"); - } - - // Resets the alignments - final HashMap<Object, Align> newCA = new HashMap<Object, Align>(); - int i = 0; - for (final Iterator<Object> it = visibleColumns.iterator(); it - .hasNext() && i < columnAlignments.length; i++) { - newCA.put(it.next(), columnAlignments[i]); - } - this.columnAlignments = newCA; - - // Assures the visual refresh. No need to reset the page buffer before - // as the content has not changed, only the alignments. - refreshRenderedCells(); - } - - /** - * Sets columns width (in pixels). Theme may not necessary respect very - * small or very big values. Setting width to -1 (default) means that theme - * will make decision of width. - * - * <p> - * Column can either have a fixed width or expand ratio. The latter one set - * is used. See @link {@link #setColumnExpandRatio(Object, float)}. - * - * @param propertyId - * colunmns property id - * @param width - * width to be reserved for colunmns content - * @since 4.0.3 - */ - public void setColumnWidth(Object propertyId, int width) { - if (propertyId == null) { - // Since propertyId is null, this is the row header. Use the magic - // id to store the width of the row header. - propertyId = ROW_HEADER_FAKE_PROPERTY_ID; - } - if (width < 0) { - columnWidths.remove(propertyId); - } else { - columnWidths.put(propertyId, Integer.valueOf(width)); - } - requestRepaint(); - } - - /** - * Sets the column expand ratio for given column. - * <p> - * Expand ratios can be defined to customize the way how excess space is - * divided among columns. Table can have excess space if it has its width - * defined and there is horizontally more space than columns consume - * naturally. Excess space is the space that is not used by columns with - * explicit width (see {@link #setColumnWidth(Object, int)}) or with natural - * width (no width nor expand ratio). - * - * <p> - * By default (without expand ratios) the excess space is divided - * proportionally to columns natural widths. - * - * <p> - * Only expand ratios of visible columns are used in final calculations. - * - * <p> - * Column can either have a fixed width or expand ratio. The latter one set - * is used. - * - * <p> - * A column with expand ratio is considered to be minimum width by default - * (if no excess space exists). The minimum width is defined by terminal - * implementation. - * - * <p> - * If terminal implementation supports re-sizable columns the column becomes - * fixed width column if users resizes the column. - * - * @param propertyId - * columns property id - * @param expandRatio - * the expandRatio used to divide excess space for this column - */ - public void setColumnExpandRatio(Object propertyId, float expandRatio) { - if (expandRatio < 0) { - columnWidths.remove(propertyId); - } else { - columnWidths.put(propertyId, new Float(expandRatio)); - } - } - - public float getColumnExpandRatio(Object propertyId) { - final Object width = columnWidths.get(propertyId); - if (width == null || !(width instanceof Float)) { - return -1; - } - final Float value = (Float) width; - return value.floatValue(); - - } - - /** - * Gets the pixel width of column - * - * @param propertyId - * @return width of column or -1 when value not set - */ - public int getColumnWidth(Object propertyId) { - if (propertyId == null) { - // Since propertyId is null, this is the row header. Use the magic - // id to retrieve the width of the row header. - propertyId = ROW_HEADER_FAKE_PROPERTY_ID; - } - final Object width = columnWidths.get(propertyId); - if (width == null || !(width instanceof Integer)) { - return -1; - } - final Integer value = (Integer) width; - return value.intValue(); - } - - /** - * Gets the page length. - * - * <p> - * Setting page length 0 disables paging. - * </p> - * - * @return the Length of one page. - */ - public int getPageLength() { - return pageLength; - } - - /** - * Sets the page length. - * - * <p> - * Setting page length 0 disables paging. The page length defaults to 15. - * </p> - * - * <p> - * If Table has width set ({@link #setWidth(float, int)} ) the client side - * may update the page length automatically the correct value. - * </p> - * - * @param pageLength - * the length of one page. - */ - public void setPageLength(int pageLength) { - if (pageLength >= 0 && this.pageLength != pageLength) { - this.pageLength = pageLength; - // Assures the visual refresh - refreshRowCache(); - } - } - - /** - * This method adjusts a possible caching mechanism of table implementation. - * - * <p> - * Table component may fetch and render some rows outside visible area. With - * complex tables (for example containing layouts and components), the - * client side may become unresponsive. Setting the value lower, UI will - * become more responsive. With higher values scrolling in client will hit - * server less frequently. - * - * <p> - * The amount of cached rows will be cacheRate multiplied with pageLength ( - * {@link #setPageLength(int)} both below and above visible area.. - * - * @param cacheRate - * a value over 0 (fastest rendering time). Higher value will - * cache more rows on server (smoother scrolling). Default value - * is 2. - */ - public void setCacheRate(double cacheRate) { - if (cacheRate < 0) { - throw new IllegalArgumentException( - "cacheRate cannot be less than zero"); - } - if (this.cacheRate != cacheRate) { - this.cacheRate = cacheRate; - requestRepaint(); - } - } - - /** - * @see #setCacheRate(double) - * - * @return the current cache rate value - */ - public double getCacheRate() { - return cacheRate; - } - - /** - * Getter for property currentPageFirstItem. - * - * @return the Value of property currentPageFirstItem. - */ - public Object getCurrentPageFirstItemId() { - - // Priorise index over id if indexes are supported - if (items instanceof Container.Indexed) { - final int index = getCurrentPageFirstItemIndex(); - Object id = null; - if (index >= 0 && index < size()) { - id = getIdByIndex(index); - } - if (id != null && !id.equals(currentPageFirstItemId)) { - currentPageFirstItemId = id; - } - } - - // If there is no item id at all, use the first one - if (currentPageFirstItemId == null) { - currentPageFirstItemId = firstItemId(); - } - - return currentPageFirstItemId; - } - - protected Object getIdByIndex(int index) { - return ((Container.Indexed) items).getIdByIndex(index); - } - - /** - * Setter for property currentPageFirstItemId. - * - * @param currentPageFirstItemId - * the New value of property currentPageFirstItemId. - */ - public void setCurrentPageFirstItemId(Object currentPageFirstItemId) { - - // Gets the corresponding index - int index = -1; - if (items instanceof Container.Indexed) { - index = indexOfId(currentPageFirstItemId); - } else { - // If the table item container does not have index, we have to - // calculates the index by hand - Object id = firstItemId(); - while (id != null && !id.equals(currentPageFirstItemId)) { - index++; - id = nextItemId(id); - } - if (id == null) { - index = -1; - } - } - - // If the search for item index was successful - if (index >= 0) { - /* - * The table is not capable of displaying an item in the container - * as the first if there are not enough items following the selected - * item so the whole table (pagelength) is filled. - */ - int maxIndex = size() - pageLength; - if (maxIndex < 0) { - maxIndex = 0; - } - - if (index > maxIndex) { - // Note that we pass index, not maxIndex, letting - // setCurrentPageFirstItemIndex handle the situation. - setCurrentPageFirstItemIndex(index); - return; - } - - this.currentPageFirstItemId = currentPageFirstItemId; - currentPageFirstItemIndex = index; - } - - // Assures the visual refresh - refreshRowCache(); - - } - - protected int indexOfId(Object itemId) { - return ((Container.Indexed) items).indexOfId(itemId); - } - - /** - * Gets the icon Resource for the specified column. - * - * @param propertyId - * the propertyId indentifying the column. - * @return the icon for the specified column; null if the column has no icon - * set, or if the column is not visible. - */ - public Resource getColumnIcon(Object propertyId) { - return columnIcons.get(propertyId); - } - - /** - * Sets the icon Resource for the specified column. - * <p> - * Throws IllegalArgumentException if the specified column is not visible. - * </p> - * - * @param propertyId - * the propertyId identifying the column. - * @param icon - * the icon Resource to set. - */ - public void setColumnIcon(Object propertyId, Resource icon) { - - if (icon == null) { - columnIcons.remove(propertyId); - } else { - columnIcons.put(propertyId, icon); - } - - requestRepaint(); - } - - /** - * Gets the header for the specified column. - * - * @param propertyId - * the propertyId identifying the column. - * @return the header for the specified column if it has one. - */ - public String getColumnHeader(Object propertyId) { - if (getColumnHeaderMode() == ColumnHeaderMode.HIDDEN) { - return null; - } - - String header = columnHeaders.get(propertyId); - if ((header == null && getColumnHeaderMode() == ColumnHeaderMode.EXPLICIT_DEFAULTS_ID) - || getColumnHeaderMode() == ColumnHeaderMode.ID) { - header = propertyId.toString(); - } - - return header; - } - - /** - * Sets the column header for the specified column; - * - * @param propertyId - * the propertyId identifying the column. - * @param header - * the header to set. - */ - public void setColumnHeader(Object propertyId, String header) { - - if (header == null) { - columnHeaders.remove(propertyId); - } else { - columnHeaders.put(propertyId, header); - } - - requestRepaint(); - } - - /** - * Gets the specified column's alignment. - * - * @param propertyId - * the propertyID identifying the column. - * @return the specified column's alignment if it as one; null otherwise. - */ - public Align getColumnAlignment(Object propertyId) { - final Align a = columnAlignments.get(propertyId); - return a == null ? Align.LEFT : a; - } - - /** - * Sets the specified column's alignment. - * - * <p> - * Throws IllegalArgumentException if the alignment is not one of the - * following: {@link Align#LEFT}, {@link Align#CENTER} or - * {@link Align#RIGHT} - * </p> - * - * @param propertyId - * the propertyID identifying the column. - * @param alignment - * the desired alignment. - */ - public void setColumnAlignment(Object propertyId, Align alignment) { - if (alignment == null || alignment == Align.LEFT) { - columnAlignments.remove(propertyId); - } else { - columnAlignments.put(propertyId, alignment); - } - - // Assures the visual refresh. No need to reset the page buffer before - // as the content has not changed, only the alignments. - refreshRenderedCells(); - } - - /** - * Checks if the specified column is collapsed. - * - * @param propertyId - * the propertyID identifying the column. - * @return true if the column is collapsed; false otherwise; - */ - public boolean isColumnCollapsed(Object propertyId) { - return collapsedColumns != null - && collapsedColumns.contains(propertyId); - } - - /** - * Sets whether the specified column is collapsed or not. - * - * - * @param propertyId - * the propertyID identifying the column. - * @param collapsed - * the desired collapsedness. - * @throws IllegalStateException - * if column collapsing is not allowed - */ - public void setColumnCollapsed(Object propertyId, boolean collapsed) - throws IllegalStateException { - if (!isColumnCollapsingAllowed()) { - throw new IllegalStateException("Column collapsing not allowed!"); - } - if (collapsed && noncollapsibleColumns.contains(propertyId)) { - throw new IllegalStateException("The column is noncollapsible!"); - } - - if (collapsed) { - collapsedColumns.add(propertyId); - } else { - collapsedColumns.remove(propertyId); - } - - // Assures the visual refresh - refreshRowCache(); - } - - /** - * Checks if column collapsing is allowed. - * - * @return true if columns can be collapsed; false otherwise. - */ - public boolean isColumnCollapsingAllowed() { - return columnCollapsingAllowed; - } - - /** - * Sets whether column collapsing is allowed or not. - * - * @param collapsingAllowed - * specifies whether column collapsing is allowed. - */ - public void setColumnCollapsingAllowed(boolean collapsingAllowed) { - columnCollapsingAllowed = collapsingAllowed; - - if (!collapsingAllowed) { - collapsedColumns.clear(); - } - - // Assures the visual refresh. No need to reset the page buffer before - // as the content has not changed, only the alignments. - refreshRenderedCells(); - } - - /** - * Sets whether the given column is collapsible. Note that collapsible - * columns can only be actually collapsed (via UI or with - * {@link #setColumnCollapsed(Object, boolean) setColumnCollapsed()}) if - * {@link #isColumnCollapsingAllowed()} is true. By default all columns are - * collapsible. - * - * @param propertyId - * the propertyID identifying the column. - * @param collapsible - * true if the column should be collapsible, false otherwise. - */ - public void setColumnCollapsible(Object propertyId, boolean collapsible) { - if (collapsible) { - noncollapsibleColumns.remove(propertyId); - } else { - noncollapsibleColumns.add(propertyId); - collapsedColumns.remove(propertyId); - } - refreshRowCache(); - } - - /** - * Checks if the given column is collapsible. Note that even if this method - * returns <code>true</code>, the column can only be actually collapsed (via - * UI or with {@link #setColumnCollapsed(Object, boolean) - * setColumnCollapsed()}) if {@link #isColumnCollapsingAllowed()} is also - * true. - * - * @return true if the column can be collapsed; false otherwise. - */ - public boolean isColumnCollapsible(Object propertyId) { - return !noncollapsibleColumns.contains(propertyId); - } - - /** - * Checks if column reordering is allowed. - * - * @return true if columns can be reordered; false otherwise. - */ - public boolean isColumnReorderingAllowed() { - return columnReorderingAllowed; - } - - /** - * Sets whether column reordering is allowed or not. - * - * @param columnReorderingAllowed - * specifies whether column reordering is allowed. - */ - public void setColumnReorderingAllowed(boolean columnReorderingAllowed) { - if (columnReorderingAllowed != this.columnReorderingAllowed) { - this.columnReorderingAllowed = columnReorderingAllowed; - requestRepaint(); - } - } - - /* - * Arranges visible columns according to given columnOrder. Silently ignores - * colimnId:s that are not visible columns, and keeps the internal order of - * visible columns left out of the ordering (trailing). Silently does - * nothing if columnReordering is not allowed. - */ - private void setColumnOrder(Object[] columnOrder) { - if (columnOrder == null || !isColumnReorderingAllowed()) { - return; - } - final LinkedList<Object> newOrder = new LinkedList<Object>(); - for (int i = 0; i < columnOrder.length; i++) { - if (columnOrder[i] != null - && visibleColumns.contains(columnOrder[i])) { - visibleColumns.remove(columnOrder[i]); - newOrder.add(columnOrder[i]); - } - } - for (final Iterator<Object> it = visibleColumns.iterator(); it - .hasNext();) { - final Object columnId = it.next(); - if (!newOrder.contains(columnId)) { - newOrder.add(columnId); - } - } - visibleColumns = newOrder; - - // Assure visual refresh - refreshRowCache(); - } - - /** - * Getter for property currentPageFirstItem. - * - * @return the Value of property currentPageFirstItem. - */ - public int getCurrentPageFirstItemIndex() { - return currentPageFirstItemIndex; - } - - void setCurrentPageFirstItemIndex(int newIndex, boolean needsPageBufferReset) { - - if (newIndex < 0) { - newIndex = 0; - } - - /* - * minimize Container.size() calls which may be expensive. For example - * it may cause sql query. - */ - final int size = size(); - - /* - * The table is not capable of displaying an item in the container as - * the first if there are not enough items following the selected item - * so the whole table (pagelength) is filled. - */ - int maxIndex = size - pageLength; - if (maxIndex < 0) { - maxIndex = 0; - } - - /* - * FIXME #7607 Take somehow into account the case where we want to - * scroll to the bottom so that the last row is completely visible even - * if (table height) / (row height) is not an integer. Reverted the - * original fix because of #8662 regression. - */ - if (newIndex > maxIndex) { - newIndex = maxIndex; - } - - // Refresh first item id - if (items instanceof Container.Indexed) { - try { - currentPageFirstItemId = getIdByIndex(newIndex); - } catch (final IndexOutOfBoundsException e) { - currentPageFirstItemId = null; - } - currentPageFirstItemIndex = newIndex; - } else { - - // For containers not supporting indexes, we must iterate the - // container forwards / backwards - // next available item forward or backward - - currentPageFirstItemId = firstItemId(); - - // Go forwards in the middle of the list (respect borders) - while (currentPageFirstItemIndex < newIndex - && !isLastId(currentPageFirstItemId)) { - currentPageFirstItemIndex++; - currentPageFirstItemId = nextItemId(currentPageFirstItemId); - } - - // If we did hit the border - if (isLastId(currentPageFirstItemId)) { - currentPageFirstItemIndex = size - 1; - } - - // Go backwards in the middle of the list (respect borders) - while (currentPageFirstItemIndex > newIndex - && !isFirstId(currentPageFirstItemId)) { - currentPageFirstItemIndex--; - currentPageFirstItemId = prevItemId(currentPageFirstItemId); - } - - // If we did hit the border - if (isFirstId(currentPageFirstItemId)) { - currentPageFirstItemIndex = 0; - } - - // Go forwards once more - while (currentPageFirstItemIndex < newIndex - && !isLastId(currentPageFirstItemId)) { - currentPageFirstItemIndex++; - currentPageFirstItemId = nextItemId(currentPageFirstItemId); - } - - // If for some reason we do hit border again, override - // the user index request - if (isLastId(currentPageFirstItemId)) { - newIndex = currentPageFirstItemIndex = size - 1; - } - } - if (needsPageBufferReset) { - // Assures the visual refresh - refreshRowCache(); - } - } - - /** - * Setter for property currentPageFirstItem. - * - * @param newIndex - * the New value of property currentPageFirstItem. - */ - public void setCurrentPageFirstItemIndex(int newIndex) { - setCurrentPageFirstItemIndex(newIndex, true); - } - - /** - * Getter for property pageBuffering. - * - * @deprecated functionality is not needed in ajax rendering model - * - * @return the Value of property pageBuffering. - */ - @Deprecated - public boolean isPageBufferingEnabled() { - return true; - } - - /** - * Setter for property pageBuffering. - * - * @deprecated functionality is not needed in ajax rendering model - * - * @param pageBuffering - * the New value of property pageBuffering. - */ - @Deprecated - public void setPageBufferingEnabled(boolean pageBuffering) { - - } - - /** - * Getter for property selectable. - * - * <p> - * The table is not selectable by default. - * </p> - * - * @return the Value of property selectable. - */ - public boolean isSelectable() { - return selectable; - } - - /** - * Setter for property selectable. - * - * <p> - * The table is not selectable by default. - * </p> - * - * @param selectable - * the New value of property selectable. - */ - public void setSelectable(boolean selectable) { - if (this.selectable != selectable) { - this.selectable = selectable; - requestRepaint(); - } - } - - /** - * Getter for property columnHeaderMode. - * - * @return the Value of property columnHeaderMode. - */ - public ColumnHeaderMode getColumnHeaderMode() { - return columnHeaderMode; - } - - /** - * Setter for property columnHeaderMode. - * - * @param columnHeaderMode - * the New value of property columnHeaderMode. - */ - public void setColumnHeaderMode(ColumnHeaderMode columnHeaderMode) { - if (columnHeaderMode == null) { - throw new IllegalArgumentException( - "Column header mode can not be null"); - } - if (columnHeaderMode != this.columnHeaderMode) { - this.columnHeaderMode = columnHeaderMode; - requestRepaint(); - } - - } - - /** - * Refreshes the rows in the internal cache. Only if - * {@link #resetPageBuffer()} is called before this then all values are - * guaranteed to be recreated. - */ - protected void refreshRenderedCells() { - if (getParent() == null) { - return; - } - - if (!isContentRefreshesEnabled) { - return; - } - - // Collects the basic facts about the table page - final int pagelen = getPageLength(); - int rows, totalRows; - rows = totalRows = size(); - int firstIndex = Math - .min(getCurrentPageFirstItemIndex(), totalRows - 1); - if (rows > 0 && firstIndex >= 0) { - rows -= firstIndex; - } - if (pagelen > 0 && pagelen < rows) { - rows = pagelen; - } - - // If "to be painted next" variables are set, use them - if (lastToBeRenderedInClient - firstToBeRenderedInClient > 0) { - rows = lastToBeRenderedInClient - firstToBeRenderedInClient + 1; - } - if (firstToBeRenderedInClient >= 0) { - if (firstToBeRenderedInClient < totalRows) { - firstIndex = firstToBeRenderedInClient; - } else { - firstIndex = totalRows - 1; - } - } else { - // initial load - - // #8805 send one extra row in the beginning in case a partial - // row is shown on the UI - if (firstIndex > 0) { - firstIndex = firstIndex - 1; - rows = rows + 1; - } - firstToBeRenderedInClient = firstIndex; - } - if (totalRows > 0) { - if (rows + firstIndex > totalRows) { - rows = totalRows - firstIndex; - } - } else { - rows = 0; - } - - // Saves the results to internal buffer - pageBuffer = getVisibleCellsNoCache(firstIndex, rows, true); - - if (rows > 0) { - pageBufferFirstIndex = firstIndex; - } - - setRowCacheInvalidated(true); - requestRepaint(); - } - - /** - * Requests that the Table should be repainted as soon as possible. - * - * Note that a {@code Table} does not necessarily repaint its contents when - * this method has been called. See {@link #refreshRowCache()} for forcing - * an update of the contents. - */ - - @Override - public void requestRepaint() { - // Overridden only for javadoc - super.requestRepaint(); - } - - @Override - public void requestRepaintAll() { - super.requestRepaintAll(); - - // Avoid sending a partial repaint (#8714) - refreshRowCache(); - } - - private void removeRowsFromCacheAndFillBottom(int firstIndex, int rows) { - int totalCachedRows = pageBuffer[CELL_ITEMID].length; - int totalRows = size(); - int firstIndexInPageBuffer = firstIndex - pageBufferFirstIndex; - - /* - * firstIndexInPageBuffer is the first row to be removed. "rows" rows - * after that should be removed. If the page buffer does not contain - * that many rows, we only remove the rows that actually are in the page - * buffer. - */ - if (firstIndexInPageBuffer + rows > totalCachedRows) { - rows = totalCachedRows - firstIndexInPageBuffer; - } - - /* - * Unregister components that will no longer be in the page buffer to - * make sure that no components leak. - */ - unregisterComponentsAndPropertiesInRows(firstIndex, rows); - - /* - * The number of rows that should be in the cache after this operation - * is done (pageBuffer currently contains the expanded items). - */ - int newCachedRowCount = totalCachedRows; - if (newCachedRowCount + pageBufferFirstIndex > totalRows) { - newCachedRowCount = totalRows - pageBufferFirstIndex; - } - - /* - * The index at which we should render the first row that does not come - * from the previous page buffer. - */ - int firstAppendedRowInPageBuffer = totalCachedRows - rows; - int firstAppendedRow = firstAppendedRowInPageBuffer - + pageBufferFirstIndex; - - /* - * Calculate the maximum number of new rows that we can add to the page - * buffer. Less than the rows we removed if the container does not - * contain that many items afterwards. - */ - int maxRowsToRender = (totalRows - firstAppendedRow); - int rowsToAdd = rows; - if (rowsToAdd > maxRowsToRender) { - rowsToAdd = maxRowsToRender; - } - - Object[][] cells = null; - if (rowsToAdd > 0) { - cells = getVisibleCellsNoCache(firstAppendedRow, rowsToAdd, false); - } - /* - * Create the new cache buffer by copying the first rows from the old - * buffer, moving the following rows upwards and appending more rows if - * applicable. - */ - Object[][] newPageBuffer = new Object[pageBuffer.length][newCachedRowCount]; - - for (int i = 0; i < pageBuffer.length; i++) { - for (int row = 0; row < firstIndexInPageBuffer; row++) { - // Copy the first rows - newPageBuffer[i][row] = pageBuffer[i][row]; - } - for (int row = firstIndexInPageBuffer; row < firstAppendedRowInPageBuffer; row++) { - // Move the rows that were after the expanded rows - newPageBuffer[i][row] = pageBuffer[i][row + rows]; - } - for (int row = firstAppendedRowInPageBuffer; row < newCachedRowCount; row++) { - // Add the newly rendered rows. Only used if rowsToAdd > 0 - // (cells != null) - newPageBuffer[i][row] = cells[i][row - - firstAppendedRowInPageBuffer]; - } - } - pageBuffer = newPageBuffer; - } - - private Object[][] getVisibleCellsUpdateCacheRows(int firstIndex, int rows) { - Object[][] cells = getVisibleCellsNoCache(firstIndex, rows, false); - int cacheIx = firstIndex - pageBufferFirstIndex; - // update the new rows in the cache. - int totalCachedRows = pageBuffer[CELL_ITEMID].length; - int end = Math.min(cacheIx + rows, totalCachedRows); - for (int ix = cacheIx; ix < end; ix++) { - for (int i = 0; i < pageBuffer.length; i++) { - pageBuffer[i][ix] = cells[i][ix - cacheIx]; - } - } - return cells; - } - - /** - * @param firstIndex - * The position where new rows should be inserted - * @param rows - * The maximum number of rows that should be inserted at position - * firstIndex. Less rows will be inserted if the page buffer is - * too small. - * @return - */ - private Object[][] getVisibleCellsInsertIntoCache(int firstIndex, int rows) { - getLogger().finest( - "Insert " + rows + " rows at index " + firstIndex - + " to existing page buffer requested"); - - // Page buffer must not become larger than pageLength*cacheRate before - // or after the current page - int minPageBufferIndex = getCurrentPageFirstItemIndex() - - (int) (getPageLength() * getCacheRate()); - if (minPageBufferIndex < 0) { - minPageBufferIndex = 0; - } - - int maxPageBufferIndex = getCurrentPageFirstItemIndex() - + (int) (getPageLength() * (1 + getCacheRate())); - int maxBufferSize = maxPageBufferIndex - minPageBufferIndex; - - if (getPageLength() == 0) { - // If pageLength == 0 then all rows should be rendered - maxBufferSize = pageBuffer[0].length + rows; - } - /* - * Number of rows that were previously cached. This is not necessarily - * the same as pageLength if we do not have enough rows in the - * container. - */ - int currentlyCachedRowCount = pageBuffer[CELL_ITEMID].length; - - /* - * firstIndexInPageBuffer is the offset in pageBuffer where the new rows - * will be inserted (firstIndex is the index in the whole table). - * - * E.g. scrolled down to row 1000: firstIndex==1010, - * pageBufferFirstIndex==1000 -> cacheIx==10 - */ - int firstIndexInPageBuffer = firstIndex - pageBufferFirstIndex; - - /* If rows > size available in page buffer */ - if (firstIndexInPageBuffer + rows > maxBufferSize) { - rows = maxBufferSize - firstIndexInPageBuffer; - } - - /* - * "rows" rows will be inserted at firstIndex. Find out how many old - * rows fall outside the new buffer so we can unregister components in - * the cache. - */ - - /* All rows until the insertion point remain, always. */ - int firstCacheRowToRemoveInPageBuffer = firstIndexInPageBuffer; - - /* - * IF there is space remaining in the buffer after the rows have been - * inserted, we can keep more rows. - */ - int numberOfOldRowsAfterInsertedRows = maxBufferSize - - firstIndexInPageBuffer - rows; - if (numberOfOldRowsAfterInsertedRows > 0) { - firstCacheRowToRemoveInPageBuffer += numberOfOldRowsAfterInsertedRows; - } - - if (firstCacheRowToRemoveInPageBuffer <= currentlyCachedRowCount) { - /* - * Unregister all components that fall beyond the cache limits after - * inserting the new rows. - */ - unregisterComponentsAndPropertiesInRows( - firstCacheRowToRemoveInPageBuffer + pageBufferFirstIndex, - currentlyCachedRowCount - firstCacheRowToRemoveInPageBuffer - + pageBufferFirstIndex); - } - - // Calculate the new cache size - int newCachedRowCount = currentlyCachedRowCount; - if (maxBufferSize == 0 || currentlyCachedRowCount < maxBufferSize) { - newCachedRowCount = currentlyCachedRowCount + rows; - if (maxBufferSize > 0 && newCachedRowCount > maxBufferSize) { - newCachedRowCount = maxBufferSize; - } - } - - /* Paint the new rows into a separate buffer */ - Object[][] cells = getVisibleCellsNoCache(firstIndex, rows, false); - - /* - * Create the new cache buffer and fill it with the data from the old - * buffer as well as the inserted rows. - */ - Object[][] newPageBuffer = new Object[pageBuffer.length][newCachedRowCount]; - - for (int i = 0; i < pageBuffer.length; i++) { - for (int row = 0; row < firstIndexInPageBuffer; row++) { - // Copy the first rows - newPageBuffer[i][row] = pageBuffer[i][row]; - } - for (int row = firstIndexInPageBuffer; row < firstIndexInPageBuffer - + rows; row++) { - // Copy the newly created rows - newPageBuffer[i][row] = cells[i][row - firstIndexInPageBuffer]; - } - for (int row = firstIndexInPageBuffer + rows; row < newCachedRowCount; row++) { - // Move the old rows down below the newly inserted rows - newPageBuffer[i][row] = pageBuffer[i][row - rows]; - } - } - pageBuffer = newPageBuffer; - getLogger().finest( - "Page Buffer now contains " - + pageBuffer[CELL_ITEMID].length - + " rows (" - + pageBufferFirstIndex - + "-" - + (pageBufferFirstIndex - + pageBuffer[CELL_ITEMID].length - 1) + ")"); - return cells; - } - - /** - * Render rows with index "firstIndex" to "firstIndex+rows-1" to a new - * buffer. - * - * Reuses values from the current page buffer if the rows are found there. - * - * @param firstIndex - * @param rows - * @param replaceListeners - * @return - */ - private Object[][] getVisibleCellsNoCache(int firstIndex, int rows, - boolean replaceListeners) { - getLogger().finest( - "Render visible cells for rows " + firstIndex + "-" - + (firstIndex + rows - 1)); - final Object[] colids = getVisibleColumns(); - final int cols = colids.length; - - HashSet<Property<?>> oldListenedProperties = listenedProperties; - HashSet<Component> oldVisibleComponents = visibleComponents; - - if (replaceListeners) { - // initialize the listener collections, this should only be done if - // the entire cache is refreshed (through refreshRenderedCells) - listenedProperties = new HashSet<Property<?>>(); - visibleComponents = new HashSet<Component>(); - } - - Object[][] cells = new Object[cols + CELL_FIRSTCOL][rows]; - if (rows == 0) { - unregisterPropertiesAndComponents(oldListenedProperties, - oldVisibleComponents); - return cells; - } - - // Gets the first item id - Object id; - if (items instanceof Container.Indexed) { - id = getIdByIndex(firstIndex); - } else { - id = firstItemId(); - for (int i = 0; i < firstIndex; i++) { - id = nextItemId(id); - } - } - - final RowHeaderMode headmode = getRowHeaderMode(); - final boolean[] iscomponent = new boolean[cols]; - for (int i = 0; i < cols; i++) { - iscomponent[i] = columnGenerators.containsKey(colids[i]) - || Component.class.isAssignableFrom(getType(colids[i])); - } - int firstIndexNotInCache; - if (pageBuffer != null && pageBuffer[CELL_ITEMID].length > 0) { - firstIndexNotInCache = pageBufferFirstIndex - + pageBuffer[CELL_ITEMID].length; - } else { - firstIndexNotInCache = -1; - } - - // Creates the page contents - int filledRows = 0; - for (int i = 0; i < rows && id != null; i++) { - cells[CELL_ITEMID][i] = id; - cells[CELL_KEY][i] = itemIdMapper.key(id); - if (headmode != ROW_HEADER_MODE_HIDDEN) { - switch (headmode) { - case INDEX: - cells[CELL_HEADER][i] = String.valueOf(i + firstIndex + 1); - break; - default: - cells[CELL_HEADER][i] = getItemCaption(id); - } - cells[CELL_ICON][i] = getItemIcon(id); - } - - GeneratedRow generatedRow = rowGenerator != null ? rowGenerator - .generateRow(this, id) : null; - cells[CELL_GENERATED_ROW][i] = generatedRow; - - for (int j = 0; j < cols; j++) { - if (isColumnCollapsed(colids[j])) { - continue; - } - Property<?> p = null; - Object value = ""; - boolean isGeneratedRow = generatedRow != null; - boolean isGeneratedColumn = columnGenerators - .containsKey(colids[j]); - boolean isGenerated = isGeneratedRow || isGeneratedColumn; - - if (!isGenerated) { - p = getContainerProperty(id, colids[j]); - } - - if (isGeneratedRow) { - if (generatedRow.isSpanColumns() && j > 0) { - value = null; - } else if (generatedRow.isSpanColumns() && j == 0 - && generatedRow.getValue() instanceof Component) { - value = generatedRow.getValue(); - } else if (generatedRow.getText().length > j) { - value = generatedRow.getText()[j]; - } - } else { - // check in current pageBuffer already has row - int index = firstIndex + i; - if (p != null || isGenerated) { - int indexInOldBuffer = index - pageBufferFirstIndex; - if (index < firstIndexNotInCache - && index >= pageBufferFirstIndex - && pageBuffer[CELL_GENERATED_ROW][indexInOldBuffer] == null - && id.equals(pageBuffer[CELL_ITEMID][indexInOldBuffer])) { - // we already have data in our cache, - // recycle it instead of fetching it via - // getValue/getPropertyValue - value = pageBuffer[CELL_FIRSTCOL + j][indexInOldBuffer]; - if (!isGeneratedColumn && iscomponent[j] - || !(value instanceof Component)) { - listenProperty(p, oldListenedProperties); - } - } else { - if (isGeneratedColumn) { - ColumnGenerator cg = columnGenerators - .get(colids[j]); - value = cg.generateCell(this, id, colids[j]); - if (value != null - && !(value instanceof Component) - && !(value instanceof String)) { - // Avoid errors if a generator returns - // something - // other than a Component or a String - value = value.toString(); - } - } else if (iscomponent[j]) { - value = p.getValue(); - listenProperty(p, oldListenedProperties); - } else if (p != null) { - value = getPropertyValue(id, colids[j], p); - /* - * If returned value is Component (via - * fieldfactory or overridden getPropertyValue) - * we excpect it to listen property value - * changes. Otherwise if property emits value - * change events, table will start to listen - * them and refresh content when needed. - */ - if (!(value instanceof Component)) { - listenProperty(p, oldListenedProperties); - } - } else { - value = getPropertyValue(id, colids[j], null); - } - } - } - } - - if (value instanceof Component) { - registerComponent((Component) value); - } - cells[CELL_FIRSTCOL + j][i] = value; - } - - // Gets the next item id - if (items instanceof Container.Indexed) { - int index = firstIndex + i + 1; - if (index < size()) { - id = getIdByIndex(index); - } else { - id = null; - } - } else { - id = nextItemId(id); - } - - filledRows++; - } - - // Assures that all the rows of the cell-buffer are valid - if (filledRows != cells[0].length) { - final Object[][] temp = new Object[cells.length][filledRows]; - for (int i = 0; i < cells.length; i++) { - for (int j = 0; j < filledRows; j++) { - temp[i][j] = cells[i][j]; - } - } - cells = temp; - } - - unregisterPropertiesAndComponents(oldListenedProperties, - oldVisibleComponents); - - return cells; - } - - protected void registerComponent(Component component) { - getLogger().finest( - "Registered " + component.getClass().getSimpleName() + ": " - + component.getCaption()); - if (component.getParent() != this) { - component.setParent(this); - } - visibleComponents.add(component); - } - - private void listenProperty(Property<?> p, - HashSet<Property<?>> oldListenedProperties) { - if (p instanceof Property.ValueChangeNotifier) { - if (oldListenedProperties == null - || !oldListenedProperties.contains(p)) { - ((Property.ValueChangeNotifier) p).addListener(this); - } - /* - * register listened properties, so we can do proper cleanup to free - * memory. Essential if table has loads of data and it is used for a - * long time. - */ - listenedProperties.add(p); - - } - } - - /** - * @param firstIx - * Index of the first row to process. Global index, not relative - * to page buffer. - * @param count - */ - private void unregisterComponentsAndPropertiesInRows(int firstIx, int count) { - getLogger().finest( - "Unregistering components in rows " + firstIx + "-" - + (firstIx + count - 1)); - Object[] colids = getVisibleColumns(); - if (pageBuffer != null && pageBuffer[CELL_ITEMID].length > 0) { - int bufSize = pageBuffer[CELL_ITEMID].length; - int ix = firstIx - pageBufferFirstIndex; - ix = ix < 0 ? 0 : ix; - if (ix < bufSize) { - count = count > bufSize - ix ? bufSize - ix : count; - for (int i = 0; i < count; i++) { - for (int c = 0; c < colids.length; c++) { - Object cellVal = pageBuffer[CELL_FIRSTCOL + c][i + ix]; - if (cellVal instanceof Component - && visibleComponents.contains(cellVal)) { - visibleComponents.remove(cellVal); - unregisterComponent((Component) cellVal); - } else { - Property<?> p = getContainerProperty( - pageBuffer[CELL_ITEMID][i + ix], colids[c]); - if (p instanceof ValueChangeNotifier - && listenedProperties.contains(p)) { - listenedProperties.remove(p); - ((ValueChangeNotifier) p).removeListener(this); - } - } - } - } - } - } - } - - /** - * Helper method to remove listeners and maintain correct component - * hierarchy. Detaches properties and components if those are no more - * rendered in client. - * - * @param oldListenedProperties - * set of properties that where listened in last render - * @param oldVisibleComponents - * set of components that where attached in last render - */ - private void unregisterPropertiesAndComponents( - HashSet<Property<?>> oldListenedProperties, - HashSet<Component> oldVisibleComponents) { - if (oldVisibleComponents != null) { - for (final Iterator<Component> i = oldVisibleComponents.iterator(); i - .hasNext();) { - Component c = i.next(); - if (!visibleComponents.contains(c)) { - unregisterComponent(c); - } - } - } - - if (oldListenedProperties != null) { - for (final Iterator<Property<?>> i = oldListenedProperties - .iterator(); i.hasNext();) { - Property.ValueChangeNotifier o = (ValueChangeNotifier) i.next(); - if (!listenedProperties.contains(o)) { - o.removeListener(this); - } - } - } - } - - /** - * This method cleans up a Component that has been generated when Table is - * in editable mode. The component needs to be detached from its parent and - * if it is a field, it needs to be detached from its property data source - * in order to allow garbage collection to take care of removing the unused - * component from memory. - * - * Override this method and getPropertyValue(Object, Object, Property) with - * custom logic if you need to deal with buffered fields. - * - * @see #getPropertyValue(Object, Object, Property) - * - * @param oldVisibleComponents - * a set of components that should be unregistered. - */ - protected void unregisterComponent(Component component) { - getLogger().finest( - "Unregistered " + component.getClass().getSimpleName() + ": " - + component.getCaption()); - component.setParent(null); - /* - * Also remove property data sources to unregister listeners keeping the - * fields in memory. - */ - if (component instanceof Field) { - Field<?> field = (Field<?>) component; - Property<?> associatedProperty = associatedProperties - .remove(component); - if (associatedProperty != null - && field.getPropertyDataSource() == associatedProperty) { - // Remove the property data source only if it's the one we - // added in getPropertyValue - field.setPropertyDataSource(null); - } - } - } - - /** - * Refreshes the current page contents. - * - * @deprecated should not need to be used - */ - @Deprecated - public void refreshCurrentPage() { - - } - - /** - * Sets the row header mode. - * <p> - * The mode can be one of the following ones: - * <ul> - * <li>{@link #ROW_HEADER_MODE_HIDDEN}: The row captions are hidden.</li> - * <li>{@link #ROW_HEADER_MODE_ID}: Items Id-objects <code>toString()</code> - * is used as row caption. - * <li>{@link #ROW_HEADER_MODE_ITEM}: Item-objects <code>toString()</code> - * is used as row caption. - * <li>{@link #ROW_HEADER_MODE_PROPERTY}: Property set with - * {@link #setItemCaptionPropertyId(Object)} is used as row header. - * <li>{@link #ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID}: Items Id-objects - * <code>toString()</code> is used as row header. If caption is explicitly - * specified, it overrides the id-caption. - * <li>{@link #ROW_HEADER_MODE_EXPLICIT}: The row headers must be explicitly - * specified.</li> - * <li>{@link #ROW_HEADER_MODE_INDEX}: The index of the item is used as row - * caption. The index mode can only be used with the containers implementing - * <code>Container.Indexed</code> interface.</li> - * </ul> - * The default value is {@link #ROW_HEADER_MODE_HIDDEN} - * </p> - * - * @param mode - * the One of the modes listed above. - */ - public void setRowHeaderMode(RowHeaderMode mode) { - if (mode != null) { - rowHeaderMode = mode; - if (mode != RowHeaderMode.HIDDEN) { - setItemCaptionMode(mode.getItemCaptionMode()); - } - // Assures the visual refresh. No need to reset the page buffer - // before - // as the content has not changed, only the alignments. - refreshRenderedCells(); - } - } - - /** - * Gets the row header mode. - * - * @return the Row header mode. - * @see #setRowHeaderMode(int) - */ - public RowHeaderMode getRowHeaderMode() { - return rowHeaderMode; - } - - /** - * Adds the new row to table and fill the visible cells (except generated - * columns) with given values. - * - * @param cells - * the Object array that is used for filling the visible cells - * new row. The types must be settable to visible column property - * types. - * @param itemId - * the Id the new row. If null, a new id is automatically - * assigned. If given, the table cant already have a item with - * given id. - * @return Returns item id for the new row. Returns null if operation fails. - */ - public Object addItem(Object[] cells, Object itemId) - throws UnsupportedOperationException { - - // remove generated columns from the list of columns being assigned - final LinkedList<Object> availableCols = new LinkedList<Object>(); - for (Iterator<Object> it = visibleColumns.iterator(); it.hasNext();) { - Object id = it.next(); - if (!columnGenerators.containsKey(id)) { - availableCols.add(id); - } - } - // Checks that a correct number of cells are given - if (cells.length != availableCols.size()) { - return null; - } - - // Creates new item - Item item; - if (itemId == null) { - itemId = items.addItem(); - if (itemId == null) { - return null; - } - item = items.getItem(itemId); - } else { - item = items.addItem(itemId); - } - if (item == null) { - return null; - } - - // Fills the item properties - for (int i = 0; i < availableCols.size(); i++) { - item.getItemProperty(availableCols.get(i)).setValue(cells[i]); - } - - if (!(items instanceof Container.ItemSetChangeNotifier)) { - refreshRowCache(); - } - - return itemId; - } - - /** - * Discards and recreates the internal row cache. Call this if you make - * changes that affect the rows but the information about the changes are - * not automatically propagated to the Table. - * <p> - * Do not call this e.g. if you have updated the data model through a - * Property. These types of changes are automatically propagated to the - * Table. - * <p> - * A typical case when this is needed is if you update a generator (e.g. - * CellStyleGenerator) and want to ensure that the rows are redrawn with new - * styles. - * <p> - * <i>Note that calling this method is not cheap so avoid calling it - * unnecessarily.</i> - * - * @since 6.7.2 - */ - public void refreshRowCache() { - resetPageBuffer(); - refreshRenderedCells(); - } - - @Override - public void setContainerDataSource(Container newDataSource) { - - disableContentRefreshing(); - - if (newDataSource == null) { - newDataSource = new IndexedContainer(); - } - - // Assures that the data source is ordered by making unordered - // containers ordered by wrapping them - if (newDataSource instanceof Container.Ordered) { - super.setContainerDataSource(newDataSource); - } else { - super.setContainerDataSource(new ContainerOrderedWrapper( - newDataSource)); - } - - // Resets page position - currentPageFirstItemId = null; - currentPageFirstItemIndex = 0; - - // Resets column properties - if (collapsedColumns != null) { - collapsedColumns.clear(); - } - - // columnGenerators 'override' properties, don't add the same id twice - Collection<Object> col = new LinkedList<Object>(); - for (Iterator<?> it = getContainerPropertyIds().iterator(); it - .hasNext();) { - Object id = it.next(); - if (columnGenerators == null || !columnGenerators.containsKey(id)) { - col.add(id); - } - } - // generators added last - if (columnGenerators != null && columnGenerators.size() > 0) { - col.addAll(columnGenerators.keySet()); - } - - setVisibleColumns(col.toArray()); - - // Assure visual refresh - resetPageBuffer(); - - enableContentRefreshing(true); - } - - /** - * Gets items ids from a range of key values - * - * @param startRowKey - * The start key - * @param endRowKey - * The end key - * @return - */ - private LinkedHashSet<Object> getItemIdsInRange(Object itemId, - final int length) { - LinkedHashSet<Object> ids = new LinkedHashSet<Object>(); - for (int i = 0; i < length; i++) { - assert itemId != null; // should not be null unless client-server - // are out of sync - ids.add(itemId); - itemId = nextItemId(itemId); - } - return ids; - } - - /** - * Handles selection if selection is a multiselection - * - * @param variables - * The variables - */ - private void handleSelectedItems(Map<String, Object> variables) { - final String[] ka = (String[]) variables.get("selected"); - final String[] ranges = (String[]) variables.get("selectedRanges"); - - Set<Object> renderedButNotSelectedItemIds = getCurrentlyRenderedItemIds(); - - @SuppressWarnings("unchecked") - HashSet<Object> newValue = new LinkedHashSet<Object>( - (Collection<Object>) getValue()); - - if (variables.containsKey("clearSelections")) { - // the client side has instructed to swipe all previous selections - newValue.clear(); - } - - /* - * Then add (possibly some of them back) rows that are currently - * selected on the client side (the ones that the client side is aware - * of). - */ - for (int i = 0; i < ka.length; i++) { - // key to id - final Object id = itemIdMapper.get(ka[i]); - if (!isNullSelectionAllowed() - && (id == null || id == getNullSelectionItemId())) { - // skip empty selection if nullselection is not allowed - requestRepaint(); - } else if (id != null && containsId(id)) { - newValue.add(id); - renderedButNotSelectedItemIds.remove(id); - } - } - - /* Add range items aka shift clicked multiselection areas */ - if (ranges != null) { - for (String range : ranges) { - String[] split = range.split("-"); - Object startItemId = itemIdMapper.get(split[0]); - int length = Integer.valueOf(split[1]); - LinkedHashSet<Object> itemIdsInRange = getItemIdsInRange( - startItemId, length); - newValue.addAll(itemIdsInRange); - renderedButNotSelectedItemIds.removeAll(itemIdsInRange); - } - } - /* - * finally clear all currently rendered rows (the ones that the client - * side counterpart is aware of) that the client didn't send as selected - */ - newValue.removeAll(renderedButNotSelectedItemIds); - - if (!isNullSelectionAllowed() && newValue.isEmpty()) { - // empty selection not allowed, keep old value - requestRepaint(); - return; - } - - setValue(newValue, true); - - } - - private Set<Object> getCurrentlyRenderedItemIds() { - HashSet<Object> ids = new HashSet<Object>(); - if (pageBuffer != null) { - for (int i = 0; i < pageBuffer[CELL_ITEMID].length; i++) { - ids.add(pageBuffer[CELL_ITEMID][i]); - } - } - return ids; - } - - /* Component basics */ - - /** - * Invoked when the value of a variable has changed. - * - * @see com.vaadin.ui.Select#changeVariables(java.lang.Object, - * java.util.Map) - */ - - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - - boolean clientNeedsContentRefresh = false; - - handleClickEvent(variables); - - handleColumnResizeEvent(variables); - - handleColumnWidthUpdates(variables); - - disableContentRefreshing(); - - if (!isSelectable() && variables.containsKey("selected")) { - // Not-selectable is a special case, AbstractSelect does not support - // TODO could be optimized. - variables = new HashMap<String, Object>(variables); - variables.remove("selected"); - } - - /* - * The AbstractSelect cannot handle the multiselection properly, instead - * we handle it ourself - */ - else if (isSelectable() && isMultiSelect() - && variables.containsKey("selected") - && multiSelectMode == MultiSelectMode.DEFAULT) { - handleSelectedItems(variables); - variables = new HashMap<String, Object>(variables); - variables.remove("selected"); - } - - super.changeVariables(source, variables); - - // Client might update the pagelength if Table height is fixed - if (variables.containsKey("pagelength")) { - // Sets pageLength directly to avoid repaint that setter causes - pageLength = (Integer) variables.get("pagelength"); - } - - // Page start index - if (variables.containsKey("firstvisible")) { - final Integer value = (Integer) variables.get("firstvisible"); - if (value != null) { - setCurrentPageFirstItemIndex(value.intValue(), false); - } - } - - // Sets requested firstrow and rows for the next paint - if (variables.containsKey("reqfirstrow") - || variables.containsKey("reqrows")) { - - try { - firstToBeRenderedInClient = ((Integer) variables - .get("firstToBeRendered")).intValue(); - lastToBeRenderedInClient = ((Integer) variables - .get("lastToBeRendered")).intValue(); - } catch (Exception e) { - // FIXME: Handle exception - getLogger().log(Level.FINER, - "Could not parse the first and/or last rows.", e); - } - - // respect suggested rows only if table is not otherwise updated - // (row caches emptied by other event) - if (!containerChangeToBeRendered) { - Integer value = (Integer) variables.get("reqfirstrow"); - if (value != null) { - reqFirstRowToPaint = value.intValue(); - } - value = (Integer) variables.get("reqrows"); - if (value != null) { - reqRowsToPaint = value.intValue(); - // sanity check - if (reqFirstRowToPaint + reqRowsToPaint > size()) { - reqRowsToPaint = size() - reqFirstRowToPaint; - } - } - } - getLogger().finest( - "Client wants rows " + reqFirstRowToPaint + "-" - + (reqFirstRowToPaint + reqRowsToPaint - 1)); - clientNeedsContentRefresh = true; - } - - if (isSortEnabled()) { - // Sorting - boolean doSort = false; - if (variables.containsKey("sortcolumn")) { - final String colId = (String) variables.get("sortcolumn"); - if (colId != null && !"".equals(colId) && !"null".equals(colId)) { - final Object id = columnIdMap.get(colId); - setSortContainerPropertyId(id, false); - doSort = true; - } - } - if (variables.containsKey("sortascending")) { - final boolean state = ((Boolean) variables.get("sortascending")) - .booleanValue(); - if (state != sortAscending) { - setSortAscending(state, false); - doSort = true; - } - } - if (doSort) { - this.sort(); - resetPageBuffer(); - } - } - - // Dynamic column hide/show and order - // Update visible columns - if (isColumnCollapsingAllowed()) { - if (variables.containsKey("collapsedcolumns")) { - try { - final Object[] ids = (Object[]) variables - .get("collapsedcolumns"); - for (final Iterator<Object> it = visibleColumns.iterator(); it - .hasNext();) { - setColumnCollapsed(it.next(), false); - } - for (int i = 0; i < ids.length; i++) { - setColumnCollapsed(columnIdMap.get(ids[i].toString()), - true); - } - } catch (final Exception e) { - // FIXME: Handle exception - getLogger().log(Level.FINER, - "Could not determine column collapsing state", e); - } - clientNeedsContentRefresh = true; - } - } - if (isColumnReorderingAllowed()) { - if (variables.containsKey("columnorder")) { - try { - final Object[] ids = (Object[]) variables - .get("columnorder"); - // need a real Object[], ids can be a String[] - final Object[] idsTemp = new Object[ids.length]; - for (int i = 0; i < ids.length; i++) { - idsTemp[i] = columnIdMap.get(ids[i].toString()); - } - setColumnOrder(idsTemp); - if (hasListeners(ColumnReorderEvent.class)) { - fireEvent(new ColumnReorderEvent(this)); - } - } catch (final Exception e) { - // FIXME: Handle exception - getLogger().log(Level.FINER, - "Could not determine column reordering state", e); - } - clientNeedsContentRefresh = true; - } - } - - enableContentRefreshing(clientNeedsContentRefresh); - - // Actions - if (variables.containsKey("action")) { - final StringTokenizer st = new StringTokenizer( - (String) variables.get("action"), ","); - if (st.countTokens() == 2) { - final Object itemId = itemIdMapper.get(st.nextToken()); - final Action action = actionMapper.get(st.nextToken()); - - if (action != null && (itemId == null || containsId(itemId)) - && actionHandlers != null) { - for (Handler ah : actionHandlers) { - ah.handleAction(action, this, itemId); - } - } - } - } - - } - - /** - * Handles click event - * - * @param variables - */ - private void handleClickEvent(Map<String, Object> variables) { - - // Item click event - if (variables.containsKey("clickEvent")) { - String key = (String) variables.get("clickedKey"); - Object itemId = itemIdMapper.get(key); - Object propertyId = null; - String colkey = (String) variables.get("clickedColKey"); - // click is not necessary on a property - if (colkey != null) { - propertyId = columnIdMap.get(colkey); - } - MouseEventDetails evt = MouseEventDetails - .deSerialize((String) variables.get("clickEvent")); - Item item = getItem(itemId); - if (item != null) { - fireEvent(new ItemClickEvent(this, item, itemId, propertyId, - evt)); - } - } - - // Header click event - else if (variables.containsKey("headerClickEvent")) { - - MouseEventDetails details = MouseEventDetails - .deSerialize((String) variables.get("headerClickEvent")); - - Object cid = variables.get("headerClickCID"); - Object propertyId = null; - if (cid != null) { - propertyId = columnIdMap.get(cid.toString()); - } - fireEvent(new HeaderClickEvent(this, propertyId, details)); - } - - // Footer click event - else if (variables.containsKey("footerClickEvent")) { - MouseEventDetails details = MouseEventDetails - .deSerialize((String) variables.get("footerClickEvent")); - - Object cid = variables.get("footerClickCID"); - Object propertyId = null; - if (cid != null) { - propertyId = columnIdMap.get(cid.toString()); - } - fireEvent(new FooterClickEvent(this, propertyId, details)); - } - } - - /** - * Handles the column resize event sent by the client. - * - * @param variables - */ - private void handleColumnResizeEvent(Map<String, Object> variables) { - if (variables.containsKey("columnResizeEventColumn")) { - Object cid = variables.get("columnResizeEventColumn"); - Object propertyId = null; - if (cid != null) { - propertyId = columnIdMap.get(cid.toString()); - - Object prev = variables.get("columnResizeEventPrev"); - int previousWidth = -1; - if (prev != null) { - previousWidth = Integer.valueOf(prev.toString()); - } - - Object curr = variables.get("columnResizeEventCurr"); - int currentWidth = -1; - if (curr != null) { - currentWidth = Integer.valueOf(curr.toString()); - } - - fireColumnResizeEvent(propertyId, previousWidth, currentWidth); - } - } - } - - private void fireColumnResizeEvent(Object propertyId, int previousWidth, - int currentWidth) { - /* - * Update the sizes on the server side. If a column previously had a - * expand ratio and the user resized the column then the expand ratio - * will be turned into a static pixel size. - */ - setColumnWidth(propertyId, currentWidth); - - fireEvent(new ColumnResizeEvent(this, propertyId, previousWidth, - currentWidth)); - } - - private void handleColumnWidthUpdates(Map<String, Object> variables) { - if (variables.containsKey("columnWidthUpdates")) { - String[] events = (String[]) variables.get("columnWidthUpdates"); - for (String str : events) { - String[] eventDetails = str.split(":"); - Object propertyId = columnIdMap.get(eventDetails[0]); - if (propertyId == null) { - propertyId = ROW_HEADER_FAKE_PROPERTY_ID; - } - int width = Integer.valueOf(eventDetails[1]); - setColumnWidth(propertyId, width); - } - } - } - - /** - * Go to mode where content updates are not done. This is due we want to - * bypass expensive content for some reason (like when we know we may have - * other content changes on their way). - * - * @return true if content refresh flag was enabled prior this call - */ - protected boolean disableContentRefreshing() { - boolean wasDisabled = isContentRefreshesEnabled; - isContentRefreshesEnabled = false; - return wasDisabled; - } - - /** - * Go to mode where content content refreshing has effect. - * - * @param refreshContent - * true if content refresh needs to be done - */ - protected void enableContentRefreshing(boolean refreshContent) { - isContentRefreshesEnabled = true; - if (refreshContent) { - refreshRenderedCells(); - // Ensure that client gets a response - requestRepaint(); - } - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.AbstractSelect#paintContent(com.vaadin. - * terminal.PaintTarget) - */ - - @Override - public void paintContent(PaintTarget target) throws PaintException { - /* - * Body actions - Actions which has the target null and can be invoked - * by right clicking on the table body. - */ - final Set<Action> actionSet = findAndPaintBodyActions(target); - - final Object[][] cells = getVisibleCells(); - int rows = findNumRowsToPaint(target, cells); - - int total = size(); - if (shouldHideNullSelectionItem()) { - total--; - rows--; - } - - // Table attributes - paintTableAttributes(target, rows, total); - - paintVisibleColumnOrder(target); - - // Rows - if (isPartialRowUpdate() && painted && !target.isFullRepaint()) { - paintPartialRowUpdate(target, actionSet); - /* - * Send the page buffer indexes to ensure that the client side stays - * in sync. Otherwise we _might_ have the situation where the client - * side discards too few or too many rows, causing out of sync - * issues. - * - * This could probably be done for full repaints also to simplify - * the client side. - */ - int pageBufferLastIndex = pageBufferFirstIndex - + pageBuffer[CELL_ITEMID].length - 1; - target.addAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_FIRST, - pageBufferFirstIndex); - target.addAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_LAST, - pageBufferLastIndex); - } else if (target.isFullRepaint() || isRowCacheInvalidated()) { - paintRows(target, cells, actionSet); - setRowCacheInvalidated(false); - } - - paintSorting(target); - - resetVariablesAndPageBuffer(target); - - // Actions - paintActions(target, actionSet); - - paintColumnOrder(target); - - // Available columns - paintAvailableColumns(target); - - paintVisibleColumns(target); - - if (keyMapperReset) { - keyMapperReset = false; - target.addAttribute(VScrollTable.ATTRIBUTE_KEY_MAPPER_RESET, true); - } - - if (dropHandler != null) { - dropHandler.getAcceptCriterion().paint(target); - } - - painted = true; - } - - private void setRowCacheInvalidated(boolean invalidated) { - rowCacheInvalidated = invalidated; - } - - protected boolean isRowCacheInvalidated() { - return rowCacheInvalidated; - } - - private void paintPartialRowUpdate(PaintTarget target, Set<Action> actionSet) - throws PaintException { - paintPartialRowUpdates(target, actionSet); - paintPartialRowAdditions(target, actionSet); - } - - private void paintPartialRowUpdates(PaintTarget target, - Set<Action> actionSet) throws PaintException { - final boolean[] iscomponent = findCellsWithComponents(); - - int firstIx = getFirstUpdatedItemIndex(); - int count = getUpdatedRowCount(); - - target.startTag("urows"); - target.addAttribute("firsturowix", firstIx); - target.addAttribute("numurows", count); - - // Partial row updates bypass the normal caching mechanism. - Object[][] cells = getVisibleCellsUpdateCacheRows(firstIx, count); - for (int indexInRowbuffer = 0; indexInRowbuffer < count; indexInRowbuffer++) { - final Object itemId = cells[CELL_ITEMID][indexInRowbuffer]; - - if (shouldHideNullSelectionItem()) { - // Remove null selection item if null selection is not allowed - continue; - } - - paintRow(target, cells, isEditable(), actionSet, iscomponent, - indexInRowbuffer, itemId); - } - target.endTag("urows"); - } - - private void paintPartialRowAdditions(PaintTarget target, - Set<Action> actionSet) throws PaintException { - final boolean[] iscomponent = findCellsWithComponents(); - - int firstIx = getFirstAddedItemIndex(); - int count = getAddedRowCount(); - - target.startTag("prows"); - - if (!shouldHideAddedRows()) { - getLogger().finest( - "Paint rows for add. Index: " + firstIx + ", count: " - + count + "."); - - // Partial row additions bypass the normal caching mechanism. - Object[][] cells = getVisibleCellsInsertIntoCache(firstIx, count); - if (cells[0].length < count) { - // delete the rows below, since they will fall beyond the cache - // page. - target.addAttribute("delbelow", true); - count = cells[0].length; - } - - for (int indexInRowbuffer = 0; indexInRowbuffer < count; indexInRowbuffer++) { - final Object itemId = cells[CELL_ITEMID][indexInRowbuffer]; - if (shouldHideNullSelectionItem()) { - // Remove null selection item if null selection is not - // allowed - continue; - } - - paintRow(target, cells, isEditable(), actionSet, iscomponent, - indexInRowbuffer, itemId); - } - } else { - getLogger().finest( - "Paint rows for remove. Index: " + firstIx + ", count: " - + count + "."); - removeRowsFromCacheAndFillBottom(firstIx, count); - target.addAttribute("hide", true); - } - - target.addAttribute("firstprowix", firstIx); - target.addAttribute("numprows", count); - target.endTag("prows"); - } - - /** - * Subclass and override this to enable partial row updates and additions, - * which bypass the normal caching mechanism. This is useful for e.g. - * TreeTable. - * - * @return true if this update is a partial row update, false if not. For - * plain Table it is always false. - */ - protected boolean isPartialRowUpdate() { - return false; - } - - /** - * Subclass and override this to enable partial row additions, bypassing the - * normal caching mechanism. This is useful for e.g. TreeTable, where - * expanding a node should only fetch and add the items inside of that node. - * - * @return The index of the first added item. For plain Table it is always - * 0. - */ - protected int getFirstAddedItemIndex() { - return 0; - } - - /** - * Subclass and override this to enable partial row additions, bypassing the - * normal caching mechanism. This is useful for e.g. TreeTable, where - * expanding a node should only fetch and add the items inside of that node. - * - * @return the number of rows to be added, starting at the index returned by - * {@link #getFirstAddedItemIndex()}. For plain Table it is always - * 0. - */ - protected int getAddedRowCount() { - return 0; - } - - /** - * Subclass and override this to enable removing of rows, bypassing the - * normal caching and lazy loading mechanism. This is useful for e.g. - * TreeTable, when you need to hide certain rows as a node is collapsed. - * - * This should return true if the rows pointed to by - * {@link #getFirstAddedItemIndex()} and {@link #getAddedRowCount()} should - * be hidden instead of added. - * - * @return whether the rows to add (see {@link #getFirstAddedItemIndex()} - * and {@link #getAddedRowCount()}) should be added or hidden. For - * plain Table it is always false. - */ - protected boolean shouldHideAddedRows() { - return false; - } - - /** - * Subclass and override this to enable partial row updates, bypassing the - * normal caching and lazy loading mechanism. This is useful for updating - * the state of certain rows, e.g. in the TreeTable the collapsed state of a - * single node is updated using this mechanism. - * - * @return the index of the first item to be updated. For plain Table it is - * always 0. - */ - protected int getFirstUpdatedItemIndex() { - return 0; - } - - /** - * Subclass and override this to enable partial row updates, bypassing the - * normal caching and lazy loading mechanism. This is useful for updating - * the state of certain rows, e.g. in the TreeTable the collapsed state of a - * single node is updated using this mechanism. - * - * @return the number of rows to update, starting at the index returned by - * {@link #getFirstUpdatedItemIndex()}. For plain table it is always - * 0. - */ - protected int getUpdatedRowCount() { - return 0; - } - - private void paintTableAttributes(PaintTarget target, int rows, int total) - throws PaintException { - paintTabIndex(target); - paintDragMode(target); - paintSelectMode(target); - - if (cacheRate != CACHE_RATE_DEFAULT) { - target.addAttribute("cr", cacheRate); - } - - target.addAttribute("cols", getVisibleColumns().length); - target.addAttribute("rows", rows); - - target.addAttribute("firstrow", - (reqFirstRowToPaint >= 0 ? reqFirstRowToPaint - : firstToBeRenderedInClient)); - target.addAttribute("totalrows", total); - if (getPageLength() != 0) { - target.addAttribute("pagelength", getPageLength()); - } - if (areColumnHeadersEnabled()) { - target.addAttribute("colheaders", true); - } - if (rowHeadersAreEnabled()) { - target.addAttribute("rowheaders", true); - } - - target.addAttribute("colfooters", columnFootersVisible); - - // The cursors are only shown on pageable table - if (getCurrentPageFirstItemIndex() != 0 || getPageLength() > 0) { - target.addVariable(this, "firstvisible", - getCurrentPageFirstItemIndex()); - } - } - - /** - * Resets and paints "to be painted next" variables. Also reset pageBuffer - */ - private void resetVariablesAndPageBuffer(PaintTarget target) - throws PaintException { - reqFirstRowToPaint = -1; - reqRowsToPaint = -1; - containerChangeToBeRendered = false; - target.addVariable(this, "reqrows", reqRowsToPaint); - target.addVariable(this, "reqfirstrow", reqFirstRowToPaint); - } - - private boolean areColumnHeadersEnabled() { - return getColumnHeaderMode() != ColumnHeaderMode.HIDDEN; - } - - private void paintVisibleColumns(PaintTarget target) throws PaintException { - target.startTag("visiblecolumns"); - if (rowHeadersAreEnabled()) { - target.startTag("column"); - target.addAttribute("cid", ROW_HEADER_COLUMN_KEY); - paintColumnWidth(target, ROW_HEADER_FAKE_PROPERTY_ID); - target.endTag("column"); - } - final Collection<?> sortables = getSortableContainerPropertyIds(); - for (Object colId : visibleColumns) { - if (colId != null) { - target.startTag("column"); - target.addAttribute("cid", columnIdMap.key(colId)); - final String head = getColumnHeader(colId); - target.addAttribute("caption", (head != null ? head : "")); - final String foot = getColumnFooter(colId); - target.addAttribute("fcaption", (foot != null ? foot : "")); - if (isColumnCollapsed(colId)) { - target.addAttribute("collapsed", true); - } - if (areColumnHeadersEnabled()) { - if (getColumnIcon(colId) != null) { - target.addAttribute("icon", getColumnIcon(colId)); - } - if (sortables.contains(colId)) { - target.addAttribute("sortable", true); - } - } - if (!Align.LEFT.equals(getColumnAlignment(colId))) { - target.addAttribute("align", getColumnAlignment(colId) - .toString()); - } - paintColumnWidth(target, colId); - target.endTag("column"); - } - } - target.endTag("visiblecolumns"); - } - - private void paintAvailableColumns(PaintTarget target) - throws PaintException { - if (columnCollapsingAllowed) { - final HashSet<Object> collapsedCols = new HashSet<Object>(); - for (Object colId : visibleColumns) { - if (isColumnCollapsed(colId)) { - collapsedCols.add(colId); - } - } - final String[] collapsedKeys = new String[collapsedCols.size()]; - int nextColumn = 0; - for (Object colId : visibleColumns) { - if (isColumnCollapsed(colId)) { - collapsedKeys[nextColumn++] = columnIdMap.key(colId); - } - } - target.addVariable(this, "collapsedcolumns", collapsedKeys); - - final String[] noncollapsibleKeys = new String[noncollapsibleColumns - .size()]; - nextColumn = 0; - for (Object colId : noncollapsibleColumns) { - noncollapsibleKeys[nextColumn++] = columnIdMap.key(colId); - } - target.addVariable(this, "noncollapsiblecolumns", - noncollapsibleKeys); - } - - } - - private void paintActions(PaintTarget target, final Set<Action> actionSet) - throws PaintException { - if (!actionSet.isEmpty()) { - target.addVariable(this, "action", ""); - target.startTag("actions"); - for (Action a : actionSet) { - target.startTag("action"); - if (a.getCaption() != null) { - target.addAttribute("caption", a.getCaption()); - } - if (a.getIcon() != null) { - target.addAttribute("icon", a.getIcon()); - } - target.addAttribute("key", actionMapper.key(a)); - target.endTag("action"); - } - target.endTag("actions"); - } - } - - private void paintColumnOrder(PaintTarget target) throws PaintException { - if (columnReorderingAllowed) { - final String[] colorder = new String[visibleColumns.size()]; - int i = 0; - for (Object colId : visibleColumns) { - colorder[i++] = columnIdMap.key(colId); - } - target.addVariable(this, "columnorder", colorder); - } - } - - private void paintSorting(PaintTarget target) throws PaintException { - // Sorting - if (getContainerDataSource() instanceof Container.Sortable) { - target.addVariable(this, "sortcolumn", - columnIdMap.key(sortContainerPropertyId)); - target.addVariable(this, "sortascending", sortAscending); - } - } - - private void paintRows(PaintTarget target, final Object[][] cells, - final Set<Action> actionSet) throws PaintException { - final boolean[] iscomponent = findCellsWithComponents(); - - target.startTag("rows"); - // cells array contains all that are supposed to be visible on client, - // but we'll start from the one requested by client - int start = 0; - if (reqFirstRowToPaint != -1 && firstToBeRenderedInClient != -1) { - start = reqFirstRowToPaint - firstToBeRenderedInClient; - } - int end = cells[0].length; - if (reqRowsToPaint != -1) { - end = start + reqRowsToPaint; - } - // sanity check - if (lastToBeRenderedInClient != -1 && lastToBeRenderedInClient < end) { - end = lastToBeRenderedInClient + 1; - } - if (start > cells[CELL_ITEMID].length || start < 0) { - start = 0; - } - if (end > cells[CELL_ITEMID].length) { - end = cells[CELL_ITEMID].length; - } - - for (int indexInRowbuffer = start; indexInRowbuffer < end; indexInRowbuffer++) { - final Object itemId = cells[CELL_ITEMID][indexInRowbuffer]; - - if (shouldHideNullSelectionItem()) { - // Remove null selection item if null selection is not allowed - continue; - } - - paintRow(target, cells, isEditable(), actionSet, iscomponent, - indexInRowbuffer, itemId); - } - target.endTag("rows"); - } - - private boolean[] findCellsWithComponents() { - final boolean[] isComponent = new boolean[visibleColumns.size()]; - int ix = 0; - for (Object columnId : visibleColumns) { - if (columnGenerators.containsKey(columnId)) { - isComponent[ix++] = true; - } else { - final Class<?> colType = getType(columnId); - isComponent[ix++] = colType != null - && Component.class.isAssignableFrom(colType); - } - } - return isComponent; - } - - private void paintVisibleColumnOrder(PaintTarget target) { - // Visible column order - final ArrayList<String> visibleColOrder = new ArrayList<String>(); - for (Object columnId : visibleColumns) { - if (!isColumnCollapsed(columnId)) { - visibleColOrder.add(columnIdMap.key(columnId)); - } - } - target.addAttribute("vcolorder", visibleColOrder.toArray()); - } - - private Set<Action> findAndPaintBodyActions(PaintTarget target) { - Set<Action> actionSet = new LinkedHashSet<Action>(); - if (actionHandlers != null) { - final ArrayList<String> keys = new ArrayList<String>(); - for (Handler ah : actionHandlers) { - // Getting actions for the null item, which in this case means - // the body item - final Action[] actions = ah.getActions(null, this); - if (actions != null) { - for (Action action : actions) { - actionSet.add(action); - keys.add(actionMapper.key(action)); - } - } - } - target.addAttribute("alb", keys.toArray()); - } - return actionSet; - } - - private boolean shouldHideNullSelectionItem() { - return !isNullSelectionAllowed() && getNullSelectionItemId() != null - && containsId(getNullSelectionItemId()); - } - - private int findNumRowsToPaint(PaintTarget target, final Object[][] cells) - throws PaintException { - int rows; - if (reqRowsToPaint >= 0) { - rows = reqRowsToPaint; - } else { - rows = cells[0].length; - if (alwaysRecalculateColumnWidths) { - // TODO experimental feature for now: tell the client to - // recalculate column widths. - // We'll only do this for paints that do not originate from - // table scroll/cache requests (i.e when reqRowsToPaint<0) - target.addAttribute("recalcWidths", true); - } - } - return rows; - } - - private void paintSelectMode(PaintTarget target) throws PaintException { - if (multiSelectMode != MultiSelectMode.DEFAULT) { - target.addAttribute("multiselectmode", multiSelectMode.ordinal()); - } - if (isSelectable()) { - target.addAttribute("selectmode", (isMultiSelect() ? "multi" - : "single")); - } else { - target.addAttribute("selectmode", "none"); - } - if (!isNullSelectionAllowed()) { - target.addAttribute("nsa", false); - } - - // selection support - // The select variable is only enabled if selectable - if (isSelectable()) { - target.addVariable(this, "selected", findSelectedKeys()); - } - } - - private String[] findSelectedKeys() { - LinkedList<String> selectedKeys = new LinkedList<String>(); - if (isMultiSelect()) { - HashSet<?> sel = new HashSet<Object>((Set<?>) getValue()); - Collection<?> vids = getVisibleItemIds(); - for (Iterator<?> it = vids.iterator(); it.hasNext();) { - Object id = it.next(); - if (sel.contains(id)) { - selectedKeys.add(itemIdMapper.key(id)); - } - } - } else { - Object value = getValue(); - if (value == null) { - value = getNullSelectionItemId(); - } - if (value != null) { - selectedKeys.add(itemIdMapper.key(value)); - } - } - return selectedKeys.toArray(new String[selectedKeys.size()]); - } - - private void paintDragMode(PaintTarget target) throws PaintException { - if (dragMode != TableDragMode.NONE) { - target.addAttribute("dragmode", dragMode.ordinal()); - } - } - - private void paintTabIndex(PaintTarget target) throws PaintException { - // The tab ordering number - if (getTabIndex() > 0) { - target.addAttribute("tabindex", getTabIndex()); - } - } - - private void paintColumnWidth(PaintTarget target, final Object columnId) - throws PaintException { - if (columnWidths.containsKey(columnId)) { - if (getColumnWidth(columnId) > -1) { - target.addAttribute("width", - String.valueOf(getColumnWidth(columnId))); - } else { - target.addAttribute("er", getColumnExpandRatio(columnId)); - } - } - } - - private boolean rowHeadersAreEnabled() { - return getRowHeaderMode() != ROW_HEADER_MODE_HIDDEN; - } - - private void paintRow(PaintTarget target, final Object[][] cells, - final boolean iseditable, final Set<Action> actionSet, - final boolean[] iscomponent, int indexInRowbuffer, - final Object itemId) throws PaintException { - target.startTag("tr"); - - paintRowAttributes(target, cells, actionSet, indexInRowbuffer, itemId); - - // cells - int currentColumn = 0; - for (final Iterator<Object> it = visibleColumns.iterator(); it - .hasNext(); currentColumn++) { - final Object columnId = it.next(); - if (columnId == null || isColumnCollapsed(columnId)) { - continue; - } - /* - * For each cell, if a cellStyleGenerator is specified, get the - * specific style for the cell. If there is any, add it to the - * target. - */ - if (cellStyleGenerator != null) { - String cellStyle = cellStyleGenerator - .getStyle(itemId, columnId); - if (cellStyle != null && !cellStyle.equals("")) { - target.addAttribute("style-" + columnIdMap.key(columnId), - cellStyle); - } - } - - if ((iscomponent[currentColumn] || iseditable || cells[CELL_GENERATED_ROW][indexInRowbuffer] != null) - && Component.class.isInstance(cells[CELL_FIRSTCOL - + currentColumn][indexInRowbuffer])) { - final Component c = (Component) cells[CELL_FIRSTCOL - + currentColumn][indexInRowbuffer]; - if (c == null) { - target.addText(""); - paintCellTooltips(target, itemId, columnId); - } else { - LegacyPaint.paint(c, target); - } - } else { - target.addText((String) cells[CELL_FIRSTCOL + currentColumn][indexInRowbuffer]); - paintCellTooltips(target, itemId, columnId); - } - } - - target.endTag("tr"); - } - - private void paintCellTooltips(PaintTarget target, Object itemId, - Object columnId) throws PaintException { - if (itemDescriptionGenerator != null) { - String itemDescription = itemDescriptionGenerator - .generateDescription(this, itemId, columnId); - if (itemDescription != null && !itemDescription.equals("")) { - target.addAttribute("descr-" + columnIdMap.key(columnId), - itemDescription); - } - } - } - - private void paintRowTooltips(PaintTarget target, Object itemId) - throws PaintException { - if (itemDescriptionGenerator != null) { - String rowDescription = itemDescriptionGenerator - .generateDescription(this, itemId, null); - if (rowDescription != null && !rowDescription.equals("")) { - target.addAttribute("rowdescr", rowDescription); - } - } - } - - private void paintRowAttributes(PaintTarget target, final Object[][] cells, - final Set<Action> actionSet, int indexInRowbuffer, - final Object itemId) throws PaintException { - // tr attributes - - paintRowIcon(target, cells, indexInRowbuffer); - paintRowHeader(target, cells, indexInRowbuffer); - paintGeneratedRowInfo(target, cells, indexInRowbuffer); - target.addAttribute("key", - Integer.parseInt(cells[CELL_KEY][indexInRowbuffer].toString())); - - if (isSelected(itemId)) { - target.addAttribute("selected", true); - } - - // Actions - if (actionHandlers != null) { - final ArrayList<String> keys = new ArrayList<String>(); - for (Handler ah : actionHandlers) { - final Action[] aa = ah.getActions(itemId, this); - if (aa != null) { - for (int ai = 0; ai < aa.length; ai++) { - final String key = actionMapper.key(aa[ai]); - actionSet.add(aa[ai]); - keys.add(key); - } - } - } - target.addAttribute("al", keys.toArray()); - } - - /* - * For each row, if a cellStyleGenerator is specified, get the specific - * style for the cell, using null as propertyId. If there is any, add it - * to the target. - */ - if (cellStyleGenerator != null) { - String rowStyle = cellStyleGenerator.getStyle(itemId, null); - if (rowStyle != null && !rowStyle.equals("")) { - target.addAttribute("rowstyle", rowStyle); - } - } - - paintRowTooltips(target, itemId); - - paintRowAttributes(target, itemId); - } - - private void paintGeneratedRowInfo(PaintTarget target, Object[][] cells, - int indexInRowBuffer) throws PaintException { - GeneratedRow generatedRow = (GeneratedRow) cells[CELL_GENERATED_ROW][indexInRowBuffer]; - if (generatedRow != null) { - target.addAttribute("gen_html", generatedRow.isHtmlContentAllowed()); - target.addAttribute("gen_span", generatedRow.isSpanColumns()); - target.addAttribute("gen_widget", - generatedRow.getValue() instanceof Component); - } - } - - protected void paintRowHeader(PaintTarget target, Object[][] cells, - int indexInRowbuffer) throws PaintException { - if (rowHeadersAreEnabled()) { - if (cells[CELL_HEADER][indexInRowbuffer] != null) { - target.addAttribute("caption", - (String) cells[CELL_HEADER][indexInRowbuffer]); - } - } - - } - - protected void paintRowIcon(PaintTarget target, final Object[][] cells, - int indexInRowbuffer) throws PaintException { - if (rowHeadersAreEnabled() - && cells[CELL_ICON][indexInRowbuffer] != null) { - target.addAttribute("icon", - (Resource) cells[CELL_ICON][indexInRowbuffer]); - } - } - - /** - * A method where extended Table implementations may add their custom - * attributes for rows. - * - * @param target - * @param itemId - */ - protected void paintRowAttributes(PaintTarget target, Object itemId) - throws PaintException { - - } - - /** - * Gets the cached visible table contents. - * - * @return the cached visible table contents. - */ - private Object[][] getVisibleCells() { - if (pageBuffer == null) { - refreshRenderedCells(); - } - return pageBuffer; - } - - /** - * Gets the value of property. - * - * By default if the table is editable the fieldFactory is used to create - * editors for table cells. Otherwise formatPropertyValue is used to format - * the value representation. - * - * @param rowId - * the Id of the row (same as item Id). - * @param colId - * the Id of the column. - * @param property - * the Property to be presented. - * @return Object Either formatted value or Component for field. - * @see #setTableFieldFactory(TableFieldFactory) - */ - protected Object getPropertyValue(Object rowId, Object colId, - Property property) { - if (isEditable() && fieldFactory != null) { - final Field<?> f = fieldFactory.createField( - getContainerDataSource(), rowId, colId, this); - if (f != null) { - // Remember that we have made this association so we can remove - // it when the component is removed - associatedProperties.put(f, property); - bindPropertyToField(rowId, colId, property, f); - return f; - } - } - - return formatPropertyValue(rowId, colId, property); - } - - /** - * Binds an item property to a field generated by TableFieldFactory. The - * default behavior is to bind property straight to Field. If - * Property.Viewer type property (e.g. PropertyFormatter) is already set for - * field, the property is bound to that Property.Viewer. - * - * @param rowId - * @param colId - * @param property - * @param field - * @since 6.7.3 - */ - protected void bindPropertyToField(Object rowId, Object colId, - Property property, Field field) { - // check if field has a property that is Viewer set. In that case we - // expect developer has e.g. PropertyFormatter that he wishes to use and - // assign the property to the Viewer instead. - boolean hasFilterProperty = field.getPropertyDataSource() != null - && (field.getPropertyDataSource() instanceof Property.Viewer); - if (hasFilterProperty) { - ((Property.Viewer) field.getPropertyDataSource()) - .setPropertyDataSource(property); - } else { - field.setPropertyDataSource(property); - } - } - - /** - * Formats table cell property values. By default the property.toString() - * and return a empty string for null properties. - * - * @param rowId - * the Id of the row (same as item Id). - * @param colId - * the Id of the column. - * @param property - * the Property to be formatted. - * @return the String representation of property and its value. - * @since 3.1 - */ - protected String formatPropertyValue(Object rowId, Object colId, - Property<?> property) { - if (property == null) { - return ""; - } - Converter<String, Object> converter = null; - - if (hasConverter(colId)) { - converter = getConverter(colId); - } else { - ConverterUtil.getConverter(String.class, property.getType(), - getApplication()); - } - Object value = property.getValue(); - if (converter != null) { - return converter.convertToPresentation(value, getLocale()); - } - return (null != value) ? value.toString() : ""; - } - - /* Action container */ - - /** - * Registers a new action handler for this container - * - * @see com.vaadin.event.Action.Container#addActionHandler(Action.Handler) - */ - - @Override - public void addActionHandler(Action.Handler actionHandler) { - - if (actionHandler != null) { - - if (actionHandlers == null) { - actionHandlers = new LinkedList<Handler>(); - actionMapper = new KeyMapper<Action>(); - } - - if (!actionHandlers.contains(actionHandler)) { - actionHandlers.add(actionHandler); - // Assures the visual refresh. No need to reset the page buffer - // before as the content has not changed, only the action - // handlers. - refreshRenderedCells(); - } - - } - } - - /** - * Removes a previously registered action handler for the contents of this - * container. - * - * @see com.vaadin.event.Action.Container#removeActionHandler(Action.Handler) - */ - - @Override - public void removeActionHandler(Action.Handler actionHandler) { - - if (actionHandlers != null && actionHandlers.contains(actionHandler)) { - - actionHandlers.remove(actionHandler); - - if (actionHandlers.isEmpty()) { - actionHandlers = null; - actionMapper = null; - } - - // Assures the visual refresh. No need to reset the page buffer - // before as the content has not changed, only the action - // handlers. - refreshRenderedCells(); - } - } - - /** - * Removes all action handlers - */ - public void removeAllActionHandlers() { - actionHandlers = null; - actionMapper = null; - // Assures the visual refresh. No need to reset the page buffer - // before as the content has not changed, only the action - // handlers. - refreshRenderedCells(); - } - - /* Property value change listening support */ - - /** - * Notifies this listener that the Property's value has changed. - * - * Also listens changes in rendered items to refresh content area. - * - * @see com.vaadin.data.Property.ValueChangeListener#valueChange(Property.ValueChangeEvent) - */ - - @Override - public void valueChange(Property.ValueChangeEvent event) { - if (event.getProperty() == this - || event.getProperty() == getPropertyDataSource()) { - super.valueChange(event); - } else { - refreshRowCache(); - containerChangeToBeRendered = true; - } - requestRepaint(); - } - - /** - * Clears the current page buffer. Call this before - * {@link #refreshRenderedCells()} to ensure that all content is updated - * from the properties. - */ - protected void resetPageBuffer() { - firstToBeRenderedInClient = -1; - lastToBeRenderedInClient = -1; - reqFirstRowToPaint = -1; - reqRowsToPaint = -1; - pageBuffer = null; - } - - /** - * Notifies the component that it is connected to an application. - * - * @see com.vaadin.ui.Component#attach() - */ - - @Override - public void attach() { - super.attach(); - - refreshRenderedCells(); - } - - /** - * Notifies the component that it is detached from the application - * - * @see com.vaadin.ui.Component#detach() - */ - - @Override - public void detach() { - super.detach(); - } - - /** - * Removes all Items from the Container. - * - * @see com.vaadin.data.Container#removeAllItems() - */ - - @Override - public boolean removeAllItems() { - currentPageFirstItemId = null; - currentPageFirstItemIndex = 0; - return super.removeAllItems(); - } - - /** - * Removes the Item identified by <code>ItemId</code> from the Container. - * - * @see com.vaadin.data.Container#removeItem(Object) - */ - - @Override - public boolean removeItem(Object itemId) { - final Object nextItemId = nextItemId(itemId); - final boolean ret = super.removeItem(itemId); - if (ret && (itemId != null) && (itemId.equals(currentPageFirstItemId))) { - currentPageFirstItemId = nextItemId; - } - if (!(items instanceof Container.ItemSetChangeNotifier)) { - refreshRowCache(); - } - return ret; - } - - /** - * Removes a Property specified by the given Property ID from the Container. - * - * @see com.vaadin.data.Container#removeContainerProperty(Object) - */ - - @Override - public boolean removeContainerProperty(Object propertyId) - throws UnsupportedOperationException { - - // If a visible property is removed, remove the corresponding column - visibleColumns.remove(propertyId); - columnAlignments.remove(propertyId); - columnIcons.remove(propertyId); - columnHeaders.remove(propertyId); - columnFooters.remove(propertyId); - - return super.removeContainerProperty(propertyId); - } - - /** - * Adds a new property to the table and show it as a visible column. - * - * @param propertyId - * the Id of the proprty. - * @param type - * the class of the property. - * @param defaultValue - * the default value given for all existing items. - * @see com.vaadin.data.Container#addContainerProperty(Object, Class, - * Object) - */ - - @Override - public boolean addContainerProperty(Object propertyId, Class<?> type, - Object defaultValue) throws UnsupportedOperationException { - - boolean visibleColAdded = false; - if (!visibleColumns.contains(propertyId)) { - visibleColumns.add(propertyId); - visibleColAdded = true; - } - - if (!super.addContainerProperty(propertyId, type, defaultValue)) { - if (visibleColAdded) { - visibleColumns.remove(propertyId); - } - return false; - } - if (!(items instanceof Container.PropertySetChangeNotifier)) { - refreshRowCache(); - } - return true; - } - - /** - * Adds a new property to the table and show it as a visible column. - * - * @param propertyId - * the Id of the proprty - * @param type - * the class of the property - * @param defaultValue - * the default value given for all existing items - * @param columnHeader - * the Explicit header of the column. If explicit header is not - * needed, this should be set null. - * @param columnIcon - * the Icon of the column. If icon is not needed, this should be - * set null. - * @param columnAlignment - * the Alignment of the column. Null implies align left. - * @throws UnsupportedOperationException - * if the operation is not supported. - * @see com.vaadin.data.Container#addContainerProperty(Object, Class, - * Object) - */ - public boolean addContainerProperty(Object propertyId, Class<?> type, - Object defaultValue, String columnHeader, Resource columnIcon, - Align columnAlignment) throws UnsupportedOperationException { - if (!this.addContainerProperty(propertyId, type, defaultValue)) { - return false; - } - setColumnAlignment(propertyId, columnAlignment); - setColumnHeader(propertyId, columnHeader); - setColumnIcon(propertyId, columnIcon); - return true; - } - - /** - * Adds a generated column to the Table. - * <p> - * A generated column is a column that exists only in the Table, not as a - * property in the underlying Container. It shows up just as a regular - * column. - * </p> - * <p> - * A generated column will override a property with the same id, so that the - * generated column is shown instead of the column representing the - * property. Note that getContainerProperty() will still get the real - * property. - * </p> - * <p> - * Table will not listen to value change events from properties overridden - * by generated columns. If the content of your generated column depends on - * properties that are not directly visible in the table, attach value - * change listener to update the content on all depended properties. - * Otherwise your UI might not get updated as expected. - * </p> - * <p> - * Also note that getVisibleColumns() will return the generated columns, - * while getContainerPropertyIds() will not. - * </p> - * - * @param id - * the id of the column to be added - * @param generatedColumn - * the {@link ColumnGenerator} to use for this column - */ - public void addGeneratedColumn(Object id, ColumnGenerator generatedColumn) { - if (generatedColumn == null) { - throw new IllegalArgumentException( - "Can not add null as a GeneratedColumn"); - } - if (columnGenerators.containsKey(id)) { - throw new IllegalArgumentException( - "Can not add the same GeneratedColumn twice, id:" + id); - } else { - columnGenerators.put(id, generatedColumn); - /* - * add to visible column list unless already there (overriding - * column from DS) - */ - if (!visibleColumns.contains(id)) { - visibleColumns.add(id); - } - refreshRowCache(); - } - } - - /** - * Returns the ColumnGenerator used to generate the given column. - * - * @param columnId - * The id of the generated column - * @return The ColumnGenerator used for the given columnId or null. - */ - public ColumnGenerator getColumnGenerator(Object columnId) - throws IllegalArgumentException { - return columnGenerators.get(columnId); - } - - /** - * Removes a generated column previously added with addGeneratedColumn. - * - * @param columnId - * id of the generated column to remove - * @return true if the column could be removed (existed in the Table) - */ - public boolean removeGeneratedColumn(Object columnId) { - if (columnGenerators.containsKey(columnId)) { - columnGenerators.remove(columnId); - // remove column from visibleColumns list unless it exists in - // container (generator previously overrode this column) - if (!items.getContainerPropertyIds().contains(columnId)) { - visibleColumns.remove(columnId); - } - refreshRowCache(); - return true; - } else { - return false; - } - } - - /** - * Returns item identifiers of the items which are currently rendered on the - * client. - * <p> - * Note, that some due to historical reasons the name of the method is bit - * misleading. Some items may be partly or totally out of the viewport of - * the table's scrollable area. Actually detecting rows which can be - * actually seen by the end user may be problematic due to the client server - * architecture. Using {@link #getCurrentPageFirstItemId()} combined with - * {@link #getPageLength()} may produce good enough estimates in some - * situations. - * - * @see com.vaadin.ui.Select#getVisibleItemIds() - */ - - @Override - public Collection<?> getVisibleItemIds() { - - final LinkedList<Object> visible = new LinkedList<Object>(); - - final Object[][] cells = getVisibleCells(); - // may be null if the table has not been rendered yet (e.g. not attached - // to a layout) - if (null != cells) { - for (int i = 0; i < cells[CELL_ITEMID].length; i++) { - visible.add(cells[CELL_ITEMID][i]); - } - } - - return visible; - } - - /** - * Container datasource item set change. Table must flush its buffers on - * change. - * - * @see com.vaadin.data.Container.ItemSetChangeListener#containerItemSetChange(com.vaadin.data.Container.ItemSetChangeEvent) - */ - - @Override - public void containerItemSetChange(Container.ItemSetChangeEvent event) { - super.containerItemSetChange(event); - - // super method clears the key map, must inform client about this to - // avoid getting invalid keys back (#8584) - keyMapperReset = true; - - // ensure that page still has first item in page, ignore buffer refresh - // (forced in this method) - setCurrentPageFirstItemIndex(getCurrentPageFirstItemIndex(), false); - refreshRowCache(); - } - - /** - * Container datasource property set change. Table must flush its buffers on - * change. - * - * @see com.vaadin.data.Container.PropertySetChangeListener#containerPropertySetChange(com.vaadin.data.Container.PropertySetChangeEvent) - */ - - @Override - public void containerPropertySetChange( - Container.PropertySetChangeEvent event) { - disableContentRefreshing(); - super.containerPropertySetChange(event); - - // sanitetize visibleColumns. note that we are not adding previously - // non-existing properties as columns - Collection<?> containerPropertyIds = getContainerDataSource() - .getContainerPropertyIds(); - - LinkedList<Object> newVisibleColumns = new LinkedList<Object>( - visibleColumns); - for (Iterator<Object> iterator = newVisibleColumns.iterator(); iterator - .hasNext();) { - Object id = iterator.next(); - if (!(containerPropertyIds.contains(id) || columnGenerators - .containsKey(id))) { - iterator.remove(); - } - } - setVisibleColumns(newVisibleColumns.toArray()); - // same for collapsed columns - for (Iterator<Object> iterator = collapsedColumns.iterator(); iterator - .hasNext();) { - Object id = iterator.next(); - if (!(containerPropertyIds.contains(id) || columnGenerators - .containsKey(id))) { - iterator.remove(); - } - } - - resetPageBuffer(); - enableContentRefreshing(true); - } - - /** - * Adding new items is not supported. - * - * @throws UnsupportedOperationException - * if set to true. - * @see com.vaadin.ui.Select#setNewItemsAllowed(boolean) - */ - - @Override - public void setNewItemsAllowed(boolean allowNewOptions) - throws UnsupportedOperationException { - if (allowNewOptions) { - throw new UnsupportedOperationException(); - } - } - - /** - * Gets the ID of the Item following the Item that corresponds to itemId. - * - * @see com.vaadin.data.Container.Ordered#nextItemId(java.lang.Object) - */ - - @Override - public Object nextItemId(Object itemId) { - return ((Container.Ordered) items).nextItemId(itemId); - } - - /** - * Gets the ID of the Item preceding the Item that corresponds to the - * itemId. - * - * @see com.vaadin.data.Container.Ordered#prevItemId(java.lang.Object) - */ - - @Override - public Object prevItemId(Object itemId) { - return ((Container.Ordered) items).prevItemId(itemId); - } - - /** - * Gets the ID of the first Item in the Container. - * - * @see com.vaadin.data.Container.Ordered#firstItemId() - */ - - @Override - public Object firstItemId() { - return ((Container.Ordered) items).firstItemId(); - } - - /** - * Gets the ID of the last Item in the Container. - * - * @see com.vaadin.data.Container.Ordered#lastItemId() - */ - - @Override - public Object lastItemId() { - return ((Container.Ordered) items).lastItemId(); - } - - /** - * Tests if the Item corresponding to the given Item ID is the first Item in - * the Container. - * - * @see com.vaadin.data.Container.Ordered#isFirstId(java.lang.Object) - */ - - @Override - public boolean isFirstId(Object itemId) { - return ((Container.Ordered) items).isFirstId(itemId); - } - - /** - * Tests if the Item corresponding to the given Item ID is the last Item in - * the Container. - * - * @see com.vaadin.data.Container.Ordered#isLastId(java.lang.Object) - */ - - @Override - public boolean isLastId(Object itemId) { - return ((Container.Ordered) items).isLastId(itemId); - } - - /** - * Adds new item after the given item. - * - * @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object) - */ - - @Override - public Object addItemAfter(Object previousItemId) - throws UnsupportedOperationException { - Object itemId = ((Container.Ordered) items) - .addItemAfter(previousItemId); - if (!(items instanceof Container.ItemSetChangeNotifier)) { - refreshRowCache(); - } - return itemId; - } - - /** - * Adds new item after the given item. - * - * @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object, - * java.lang.Object) - */ - - @Override - public Item addItemAfter(Object previousItemId, Object newItemId) - throws UnsupportedOperationException { - Item item = ((Container.Ordered) items).addItemAfter(previousItemId, - newItemId); - if (!(items instanceof Container.ItemSetChangeNotifier)) { - refreshRowCache(); - } - return item; - } - - /** - * Sets the TableFieldFactory that is used to create editor for table cells. - * - * The TableFieldFactory is only used if the Table is editable. By default - * the DefaultFieldFactory is used. - * - * @param fieldFactory - * the field factory to set. - * @see #isEditable - * @see DefaultFieldFactory - */ - public void setTableFieldFactory(TableFieldFactory fieldFactory) { - this.fieldFactory = fieldFactory; - - // Assure visual refresh - refreshRowCache(); - } - - /** - * Gets the TableFieldFactory that is used to create editor for table cells. - * - * The FieldFactory is only used if the Table is editable. - * - * @return TableFieldFactory used to create the Field instances. - * @see #isEditable - */ - public TableFieldFactory getTableFieldFactory() { - return fieldFactory; - } - - /** - * Is table editable. - * - * If table is editable a editor of type Field is created for each table - * cell. The assigned FieldFactory is used to create the instances. - * - * To provide custom editors for table cells create a class implementins the - * FieldFactory interface, and assign it to table, and set the editable - * property to true. - * - * @return true if table is editable, false oterwise. - * @see Field - * @see FieldFactory - * - */ - public boolean isEditable() { - return editable; - } - - /** - * Sets the editable property. - * - * If table is editable a editor of type Field is created for each table - * cell. The assigned FieldFactory is used to create the instances. - * - * To provide custom editors for table cells create a class implementins the - * FieldFactory interface, and assign it to table, and set the editable - * property to true. - * - * @param editable - * true if table should be editable by user. - * @see Field - * @see FieldFactory - * - */ - public void setEditable(boolean editable) { - this.editable = editable; - - // Assure visual refresh - refreshRowCache(); - } - - /** - * Sorts the table. - * - * @throws UnsupportedOperationException - * if the container data source does not implement - * Container.Sortable - * @see com.vaadin.data.Container.Sortable#sort(java.lang.Object[], - * boolean[]) - * - */ - - @Override - public void sort(Object[] propertyId, boolean[] ascending) - throws UnsupportedOperationException { - final Container c = getContainerDataSource(); - if (c instanceof Container.Sortable) { - final int pageIndex = getCurrentPageFirstItemIndex(); - ((Container.Sortable) c).sort(propertyId, ascending); - setCurrentPageFirstItemIndex(pageIndex); - refreshRowCache(); - - } else if (c != null) { - throw new UnsupportedOperationException( - "Underlying Data does not allow sorting"); - } - } - - /** - * Sorts the table by currently selected sorting column. - * - * @throws UnsupportedOperationException - * if the container data source does not implement - * Container.Sortable - */ - public void sort() { - if (getSortContainerPropertyId() == null) { - return; - } - sort(new Object[] { sortContainerPropertyId }, - new boolean[] { sortAscending }); - } - - /** - * Gets the container property IDs, which can be used to sort the item. - * <p> - * Note that the {@link #isSortEnabled()} state affects what this method - * returns. Disabling sorting causes this method to always return an empty - * collection. - * </p> - * - * @see com.vaadin.data.Container.Sortable#getSortableContainerPropertyIds() - */ - - @Override - public Collection<?> getSortableContainerPropertyIds() { - final Container c = getContainerDataSource(); - if (c instanceof Container.Sortable && isSortEnabled()) { - return ((Container.Sortable) c).getSortableContainerPropertyIds(); - } else { - return Collections.EMPTY_LIST; - } - } - - /** - * Gets the currently sorted column property ID. - * - * @return the Container property id of the currently sorted column. - */ - public Object getSortContainerPropertyId() { - return sortContainerPropertyId; - } - - /** - * Sets the currently sorted column property id. - * - * @param propertyId - * the Container property id of the currently sorted column. - */ - public void setSortContainerPropertyId(Object propertyId) { - setSortContainerPropertyId(propertyId, true); - } - - /** - * Internal method to set currently sorted column property id. With doSort - * flag actual sorting may be bypassed. - * - * @param propertyId - * @param doSort - */ - private void setSortContainerPropertyId(Object propertyId, boolean doSort) { - if ((sortContainerPropertyId != null && !sortContainerPropertyId - .equals(propertyId)) - || (sortContainerPropertyId == null && propertyId != null)) { - sortContainerPropertyId = propertyId; - - if (doSort) { - sort(); - // Assures the visual refresh. This should not be necessary as - // sort() calls refreshRowCache - refreshRenderedCells(); - } - } - } - - /** - * Is the table currently sorted in ascending order. - * - * @return <code>true</code> if ascending, <code>false</code> if descending. - */ - public boolean isSortAscending() { - return sortAscending; - } - - /** - * Sets the table in ascending order. - * - * @param ascending - * <code>true</code> if ascending, <code>false</code> if - * descending. - */ - public void setSortAscending(boolean ascending) { - setSortAscending(ascending, true); - } - - /** - * Internal method to set sort ascending. With doSort flag actual sort can - * be bypassed. - * - * @param ascending - * @param doSort - */ - private void setSortAscending(boolean ascending, boolean doSort) { - if (sortAscending != ascending) { - sortAscending = ascending; - if (doSort) { - sort(); - // Assures the visual refresh. This should not be necessary as - // sort() calls refreshRowCache - refreshRenderedCells(); - } - } - } - - /** - * Is sorting disabled altogether. - * - * True iff no sortable columns are given even in the case where data source - * would support this. - * - * @return True iff sorting is disabled. - * @deprecated Use {@link #isSortEnabled()} instead - */ - @Deprecated - public boolean isSortDisabled() { - return !isSortEnabled(); - } - - /** - * Checks if sorting is enabled. - * - * @return true if sorting by the user is allowed, false otherwise - */ - public boolean isSortEnabled() { - return sortEnabled; - } - - /** - * Disables the sorting by the user altogether. - * - * @param sortDisabled - * True iff sorting is disabled. - * @deprecated Use {@link #setSortEnabled(boolean)} instead - */ - @Deprecated - public void setSortDisabled(boolean sortDisabled) { - setSortEnabled(!sortDisabled); - } - - /** - * Enables or disables sorting. - * <p> - * Setting this to false disallows sorting by the user. It is still possible - * to call {@link #sort()}. - * </p> - * - * @param sortEnabled - * true to allow the user to sort the table, false to disallow it - */ - public void setSortEnabled(boolean sortEnabled) { - if (this.sortEnabled != sortEnabled) { - this.sortEnabled = sortEnabled; - requestRepaint(); - } - } - - /** - * Used to create "generated columns"; columns that exist only in the Table, - * not in the underlying Container. Implement this interface and pass it to - * Table.addGeneratedColumn along with an id for the column to be generated. - * - */ - public interface ColumnGenerator extends Serializable { - - /** - * Called by Table when a cell in a generated column needs to be - * generated. - * - * @param source - * the source Table - * @param itemId - * the itemId (aka rowId) for the of the cell to be generated - * @param columnId - * the id for the generated column (as specified in - * addGeneratedColumn) - * @return A {@link Component} that should be rendered in the cell or a - * {@link String} that should be displayed in the cell. Other - * return values are not supported. - */ - public abstract Object generateCell(Table source, Object itemId, - Object columnId); - } - - /** - * Set cell style generator for Table. - * - * @param cellStyleGenerator - * New cell style generator or null to remove generator. - */ - public void setCellStyleGenerator(CellStyleGenerator cellStyleGenerator) { - this.cellStyleGenerator = cellStyleGenerator; - // Assures the visual refresh. No need to reset the page buffer - // before as the content has not changed, only the style generators - refreshRenderedCells(); - - } - - /** - * Get the current cell style generator. - * - */ - public CellStyleGenerator getCellStyleGenerator() { - return cellStyleGenerator; - } - - /** - * Allow to define specific style on cells (and rows) contents. Implements - * this interface and pass it to Table.setCellStyleGenerator. Row styles are - * generated when porpertyId is null. The CSS class name that will be added - * to the cell content is <tt>v-table-cell-content-[style name]</tt>, and - * the row style will be <tt>v-table-row-[style name]</tt>. - */ - public interface CellStyleGenerator extends Serializable { - - /** - * Called by Table when a cell (and row) is painted. - * - * @param itemId - * The itemId of the painted cell - * @param propertyId - * The propertyId of the cell, null when getting row style - * @return The style name to add to this cell or row. (the CSS class - * name will be v-table-cell-content-[style name], or - * v-table-row-[style name] for rows) - */ - public abstract String getStyle(Object itemId, Object propertyId); - } - - @Override - public void addListener(ItemClickListener listener) { - addListener(VScrollTable.ITEM_CLICK_EVENT_ID, ItemClickEvent.class, - listener, ItemClickEvent.ITEM_CLICK_METHOD); - } - - @Override - public void removeListener(ItemClickListener listener) { - removeListener(VScrollTable.ITEM_CLICK_EVENT_ID, ItemClickEvent.class, - listener); - } - - // Identical to AbstractCompoenentContainer.setEnabled(); - - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - if (getParent() != null && !getParent().isEnabled()) { - // some ancestor still disabled, don't update children - return; - } else { - requestRepaintAll(); - } - } - - /** - * Sets the drag start mode of the Table. Drag start mode controls how Table - * behaves as a drag source. - * - * @param newDragMode - */ - public void setDragMode(TableDragMode newDragMode) { - dragMode = newDragMode; - requestRepaint(); - } - - /** - * @return the current start mode of the Table. Drag start mode controls how - * Table behaves as a drag source. - */ - public TableDragMode getDragMode() { - return dragMode; - } - - /** - * Concrete implementation of {@link DataBoundTransferable} for data - * transferred from a table. - * - * @see {@link DataBoundTransferable}. - * - * @since 6.3 - */ - public class TableTransferable extends DataBoundTransferable { - - protected TableTransferable(Map<String, Object> rawVariables) { - super(Table.this, rawVariables); - Object object = rawVariables.get("itemId"); - if (object != null) { - setData("itemId", itemIdMapper.get((String) object)); - } - object = rawVariables.get("propertyId"); - if (object != null) { - setData("propertyId", columnIdMap.get((String) object)); - } - } - - @Override - public Object getItemId() { - return getData("itemId"); - } - - @Override - public Object getPropertyId() { - return getData("propertyId"); - } - - @Override - public Table getSourceComponent() { - return (Table) super.getSourceComponent(); - } - - } - - @Override - public TableTransferable getTransferable(Map<String, Object> rawVariables) { - TableTransferable transferable = new TableTransferable(rawVariables); - return transferable; - } - - @Override - public DropHandler getDropHandler() { - return dropHandler; - } - - public void setDropHandler(DropHandler dropHandler) { - this.dropHandler = dropHandler; - } - - @Override - public AbstractSelectTargetDetails translateDropTargetDetails( - Map<String, Object> clientVariables) { - return new AbstractSelectTargetDetails(clientVariables); - } - - /** - * Sets the behavior of how the multi-select mode should behave when the - * table is both selectable and in multi-select mode. - * <p> - * Note, that on some clients the mode may not be respected. E.g. on touch - * based devices CTRL/SHIFT base selection method is invalid, so touch based - * browsers always use the {@link MultiSelectMode#SIMPLE}. - * - * @param mode - * The select mode of the table - */ - public void setMultiSelectMode(MultiSelectMode mode) { - multiSelectMode = mode; - requestRepaint(); - } - - /** - * Returns the select mode in which multi-select is used. - * - * @return The multi select mode - */ - public MultiSelectMode getMultiSelectMode() { - return multiSelectMode; - } - - /** - * Lazy loading accept criterion for Table. Accepted target rows are loaded - * from server once per drag and drop operation. Developer must override one - * method that decides on which rows the currently dragged data can be - * dropped. - * - * <p> - * Initially pretty much no data is sent to client. On first required - * criterion check (per drag request) the client side data structure is - * initialized from server and no subsequent requests requests are needed - * during that drag and drop operation. - */ - public static abstract class TableDropCriterion extends ServerSideCriterion { - - private Table table; - - private Set<Object> allowedItemIds; - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.event.dd.acceptcriteria.ServerSideCriterion#getIdentifier - * () - */ - - @Override - protected String getIdentifier() { - return TableDropCriterion.class.getCanonicalName(); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.event.dd.acceptcriteria.AcceptCriterion#accepts(com.vaadin - * .event.dd.DragAndDropEvent) - */ - @Override - @SuppressWarnings("unchecked") - public boolean accept(DragAndDropEvent dragEvent) { - AbstractSelectTargetDetails dropTargetData = (AbstractSelectTargetDetails) dragEvent - .getTargetDetails(); - table = (Table) dragEvent.getTargetDetails().getTarget(); - Collection<?> visibleItemIds = table.getVisibleItemIds(); - allowedItemIds = getAllowedItemIds(dragEvent, table, - (Collection<Object>) visibleItemIds); - - return allowedItemIds.contains(dropTargetData.getItemIdOver()); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.event.dd.acceptcriteria.AcceptCriterion#paintResponse( - * com.vaadin.terminal.PaintTarget) - */ - - @Override - public void paintResponse(PaintTarget target) throws PaintException { - /* - * send allowed nodes to client so subsequent requests can be - * avoided - */ - Object[] array = allowedItemIds.toArray(); - for (int i = 0; i < array.length; i++) { - String key = table.itemIdMapper.key(array[i]); - array[i] = key; - } - target.addAttribute("allowedIds", array); - } - - /** - * @param dragEvent - * @param table - * the table for which the allowed item identifiers are - * defined - * @param visibleItemIds - * the list of currently rendered item identifiers, accepted - * item id's need to be detected only for these visible items - * @return the set of identifiers for items on which the dragEvent will - * be accepted - */ - protected abstract Set<Object> getAllowedItemIds( - DragAndDropEvent dragEvent, Table table, - Collection<Object> visibleItemIds); - - } - - /** - * Click event fired when clicking on the Table headers. The event includes - * a reference the the Table the event originated from, the property id of - * the column which header was pressed and details about the mouse event - * itself. - */ - public static class HeaderClickEvent extends ClickEvent { - public static final Method HEADER_CLICK_METHOD; - - static { - try { - // Set the header click method - HEADER_CLICK_METHOD = HeaderClickListener.class - .getDeclaredMethod("headerClick", - new Class[] { HeaderClickEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException(e); - } - } - - // The property id of the column which header was pressed - private final Object columnPropertyId; - - public HeaderClickEvent(Component source, Object propertyId, - MouseEventDetails details) { - super(source, details); - columnPropertyId = propertyId; - } - - /** - * Gets the property id of the column which header was pressed - * - * @return The column propety id - */ - public Object getPropertyId() { - return columnPropertyId; - } - } - - /** - * Click event fired when clicking on the Table footers. The event includes - * a reference the the Table the event originated from, the property id of - * the column which header was pressed and details about the mouse event - * itself. - */ - public static class FooterClickEvent extends ClickEvent { - public static final Method FOOTER_CLICK_METHOD; - - static { - try { - // Set the header click method - FOOTER_CLICK_METHOD = FooterClickListener.class - .getDeclaredMethod("footerClick", - new Class[] { FooterClickEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException(e); - } - } - - // The property id of the column which header was pressed - private final Object columnPropertyId; - - /** - * Constructor - * - * @param source - * The source of the component - * @param propertyId - * The propertyId of the column - * @param details - * The mouse details of the click - */ - public FooterClickEvent(Component source, Object propertyId, - MouseEventDetails details) { - super(source, details); - columnPropertyId = propertyId; - } - - /** - * Gets the property id of the column which header was pressed - * - * @return The column propety id - */ - public Object getPropertyId() { - return columnPropertyId; - } - } - - /** - * Interface for the listener for column header mouse click events. The - * headerClick method is called when the user presses a header column cell. - */ - public interface HeaderClickListener extends Serializable { - - /** - * Called when a user clicks a header column cell - * - * @param event - * The event which contains information about the column and - * the mouse click event - */ - public void headerClick(HeaderClickEvent event); - } - - /** - * Interface for the listener for column footer mouse click events. The - * footerClick method is called when the user presses a footer column cell. - */ - public interface FooterClickListener extends Serializable { - - /** - * Called when a user clicks a footer column cell - * - * @param event - * The event which contains information about the column and - * the mouse click event - */ - public void footerClick(FooterClickEvent event); - } - - /** - * Adds a header click listener which handles the click events when the user - * clicks on a column header cell in the Table. - * <p> - * The listener will receive events which contain information about which - * column was clicked and some details about the mouse event. - * </p> - * - * @param listener - * The handler which should handle the header click events. - */ - public void addListener(HeaderClickListener listener) { - addListener(VScrollTable.HEADER_CLICK_EVENT_ID, HeaderClickEvent.class, - listener, HeaderClickEvent.HEADER_CLICK_METHOD); - } - - /** - * Removes a header click listener - * - * @param listener - * The listener to remove. - */ - public void removeListener(HeaderClickListener listener) { - removeListener(VScrollTable.HEADER_CLICK_EVENT_ID, - HeaderClickEvent.class, listener); - } - - /** - * Adds a footer click listener which handles the click events when the user - * clicks on a column footer cell in the Table. - * <p> - * The listener will receive events which contain information about which - * column was clicked and some details about the mouse event. - * </p> - * - * @param listener - * The handler which should handle the footer click events. - */ - public void addListener(FooterClickListener listener) { - addListener(VScrollTable.FOOTER_CLICK_EVENT_ID, FooterClickEvent.class, - listener, FooterClickEvent.FOOTER_CLICK_METHOD); - } - - /** - * Removes a footer click listener - * - * @param listener - * The listener to remove. - */ - public void removeListener(FooterClickListener listener) { - removeListener(VScrollTable.FOOTER_CLICK_EVENT_ID, - FooterClickEvent.class, listener); - } - - /** - * Gets the footer caption beneath the rows - * - * @param propertyId - * The propertyId of the column * - * @return The caption of the footer or NULL if not set - */ - public String getColumnFooter(Object propertyId) { - return columnFooters.get(propertyId); - } - - /** - * Sets the column footer caption. The column footer caption is the text - * displayed beneath the column if footers have been set visible. - * - * @param propertyId - * The properyId of the column - * - * @param footer - * The caption of the footer - */ - public void setColumnFooter(Object propertyId, String footer) { - if (footer == null) { - columnFooters.remove(propertyId); - } else { - columnFooters.put(propertyId, footer); - } - - requestRepaint(); - } - - /** - * Sets the footer visible in the bottom of the table. - * <p> - * The footer can be used to add column related data like sums to the bottom - * of the Table using setColumnFooter(Object propertyId, String footer). - * </p> - * - * @param visible - * Should the footer be visible - */ - public void setFooterVisible(boolean visible) { - if (visible != columnFootersVisible) { - columnFootersVisible = visible; - requestRepaint(); - } - } - - /** - * Is the footer currently visible? - * - * @return Returns true if visible else false - */ - public boolean isFooterVisible() { - return columnFootersVisible; - } - - /** - * This event is fired when a column is resized. The event contains the - * columns property id which was fired, the previous width of the column and - * the width of the column after the resize. - */ - public static class ColumnResizeEvent extends Component.Event { - public static final Method COLUMN_RESIZE_METHOD; - - static { - try { - COLUMN_RESIZE_METHOD = ColumnResizeListener.class - .getDeclaredMethod("columnResize", - new Class[] { ColumnResizeEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException(e); - } - } - - private final int previousWidth; - private final int currentWidth; - private final Object columnPropertyId; - - /** - * Constructor - * - * @param source - * The source of the event - * @param propertyId - * The columns property id - * @param previous - * The width in pixels of the column before the resize event - * @param current - * The width in pixels of the column after the resize event - */ - public ColumnResizeEvent(Component source, Object propertyId, - int previous, int current) { - super(source); - previousWidth = previous; - currentWidth = current; - columnPropertyId = propertyId; - } - - /** - * Get the column property id of the column that was resized. - * - * @return The column property id - */ - public Object getPropertyId() { - return columnPropertyId; - } - - /** - * Get the width in pixels of the column before the resize event - * - * @return Width in pixels - */ - public int getPreviousWidth() { - return previousWidth; - } - - /** - * Get the width in pixels of the column after the resize event - * - * @return Width in pixels - */ - public int getCurrentWidth() { - return currentWidth; - } - } - - /** - * Interface for listening to column resize events. - */ - public interface ColumnResizeListener extends Serializable { - - /** - * This method is triggered when the column has been resized - * - * @param event - * The event which contains the column property id, the - * previous width of the column and the current width of the - * column - */ - public void columnResize(ColumnResizeEvent event); - } - - /** - * Adds a column resize listener to the Table. A column resize listener is - * called when a user resizes a columns width. - * - * @param listener - * The listener to attach to the Table - */ - public void addListener(ColumnResizeListener listener) { - addListener(VScrollTable.COLUMN_RESIZE_EVENT_ID, - ColumnResizeEvent.class, listener, - ColumnResizeEvent.COLUMN_RESIZE_METHOD); - } - - /** - * Removes a column resize listener from the Table. - * - * @param listener - * The listener to remove - */ - public void removeListener(ColumnResizeListener listener) { - removeListener(VScrollTable.COLUMN_RESIZE_EVENT_ID, - ColumnResizeEvent.class, listener); - } - - /** - * This event is fired when a columns are reordered by the end user user. - */ - public static class ColumnReorderEvent extends Component.Event { - public static final Method METHOD; - - static { - try { - METHOD = ColumnReorderListener.class.getDeclaredMethod( - "columnReorder", - new Class[] { ColumnReorderEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException(e); - } - } - - /** - * Constructor - * - * @param source - * The source of the event - */ - public ColumnReorderEvent(Component source) { - super(source); - } - - } - - /** - * Interface for listening to column reorder events. - */ - public interface ColumnReorderListener extends Serializable { - - /** - * This method is triggered when the column has been reordered - * - * @param event - */ - public void columnReorder(ColumnReorderEvent event); - } - - /** - * Adds a column reorder listener to the Table. A column reorder listener is - * called when a user reorders columns. - * - * @param listener - * The listener to attach to the Table - */ - public void addListener(ColumnReorderListener listener) { - addListener(VScrollTable.COLUMN_REORDER_EVENT_ID, - ColumnReorderEvent.class, listener, ColumnReorderEvent.METHOD); - } - - /** - * Removes a column reorder listener from the Table. - * - * @param listener - * The listener to remove - */ - public void removeListener(ColumnReorderListener listener) { - removeListener(VScrollTable.COLUMN_REORDER_EVENT_ID, - ColumnReorderEvent.class, listener); - } - - /** - * Set the item description generator which generates tooltips for cells and - * rows in the Table - * - * @param generator - * The generator to use or null to disable - */ - public void setItemDescriptionGenerator(ItemDescriptionGenerator generator) { - if (generator != itemDescriptionGenerator) { - itemDescriptionGenerator = generator; - // Assures the visual refresh. No need to reset the page buffer - // before as the content has not changed, only the descriptions - refreshRenderedCells(); - } - } - - /** - * Get the item description generator which generates tooltips for cells and - * rows in the Table. - */ - public ItemDescriptionGenerator getItemDescriptionGenerator() { - return itemDescriptionGenerator; - } - - /** - * Row generators can be used to replace certain items in a table with a - * generated string. The generator is called each time the table is - * rendered, which means that new strings can be generated each time. - * - * Row generators can be used for e.g. summary rows or grouping of items. - */ - public interface RowGenerator extends Serializable { - /** - * Called for every row that is painted in the Table. Returning a - * GeneratedRow object will cause the row to be painted based on the - * contents of the GeneratedRow. A generated row is by default styled - * similarly to a header or footer row. - * <p> - * The GeneratedRow data object contains the text that should be - * rendered in the row. The itemId in the container thus works only as a - * placeholder. - * <p> - * If GeneratedRow.setSpanColumns(true) is used, there will be one - * String spanning all columns (use setText("Spanning text")). Otherwise - * you can define one String per visible column. - * <p> - * If GeneratedRow.setRenderAsHtml(true) is used, the strings can - * contain HTML markup, otherwise all strings will be rendered as text - * (the default). - * <p> - * A "v-table-generated-row" CSS class is added to all generated rows. - * For custom styling of a generated row you can combine a RowGenerator - * with a CellStyleGenerator. - * <p> - * - * @param table - * The Table that is being painted - * @param itemId - * The itemId for the row - * @return A GeneratedRow describing how the row should be painted or - * null to paint the row with the contents from the container - */ - public GeneratedRow generateRow(Table table, Object itemId); - } - - public static class GeneratedRow implements Serializable { - private boolean htmlContentAllowed = false; - private boolean spanColumns = false; - private String[] text = null; - - /** - * Creates a new generated row. If only one string is passed in, columns - * are automatically spanned. - * - * @param text - */ - public GeneratedRow(String... text) { - setHtmlContentAllowed(false); - setSpanColumns(text == null || text.length == 1); - setText(text); - } - - /** - * Pass one String if spanColumns is used, one String for each visible - * column otherwise - */ - public void setText(String... text) { - if (text == null || (text.length == 1 && text[0] == null)) { - text = new String[] { "" }; - } - this.text = text; - } - - protected String[] getText() { - return text; - } - - protected Object getValue() { - return getText(); - } - - protected boolean isHtmlContentAllowed() { - return htmlContentAllowed; - } - - /** - * If set to true, all strings passed to {@link #setText(String...)} - * will be rendered as HTML. - * - * @param htmlContentAllowed - */ - public void setHtmlContentAllowed(boolean htmlContentAllowed) { - this.htmlContentAllowed = htmlContentAllowed; - } - - protected boolean isSpanColumns() { - return spanColumns; - } - - /** - * If set to true, only one string will be rendered, spanning the entire - * row. - * - * @param spanColumns - */ - public void setSpanColumns(boolean spanColumns) { - this.spanColumns = spanColumns; - } - } - - /** - * Assigns a row generator to the table. The row generator will be able to - * replace rows in the table when it is rendered. - * - * @param generator - * the new row generator - */ - public void setRowGenerator(RowGenerator generator) { - rowGenerator = generator; - refreshRowCache(); - } - - /** - * @return the current row generator - */ - public RowGenerator getRowGenerator() { - return rowGenerator; - } - - /** - * Sets a converter for a property id. - * <p> - * The converter is used to format the the data for the given property id - * before displaying it in the table. - * </p> - * - * @param propertyId - * The propertyId to format using the converter - * @param converter - * The converter to use for the property id - */ - public void setConverter(Object propertyId, Converter<String, ?> converter) { - if (!getContainerPropertyIds().contains(propertyId)) { - throw new IllegalArgumentException("PropertyId " + propertyId - + " must be in the container"); - } - // FIXME: This check should be here but primitive types like Boolean - // formatter for boolean property must be handled - - // if (!converter.getSourceType().isAssignableFrom(getType(propertyId))) - // { - // throw new IllegalArgumentException("Property type (" - // + getType(propertyId) - // + ") must match converter source type (" - // + converter.getSourceType() + ")"); - // } - propertyValueConverters.put(propertyId, - (Converter<String, Object>) converter); - refreshRowCache(); - } - - /** - * Checks if there is a converter set explicitly for the given property id. - * - * @param propertyId - * The propertyId to check - * @return true if a converter has been set for the property id, false - * otherwise - */ - protected boolean hasConverter(Object propertyId) { - return propertyValueConverters.containsKey(propertyId); - } - - /** - * Returns the converter used to format the given propertyId. - * - * @param propertyId - * The propertyId to check - * @return The converter used to format the propertyId or null if no - * converter has been set - */ - public Converter<String, Object> getConverter(Object propertyId) { - return propertyValueConverters.get(propertyId); - } - - @Override - public void setVisible(boolean visible) { - if (visible) { - // We need to ensure that the rows are sent to the client when the - // Table is made visible if it has been rendered as invisible. - setRowCacheInvalidated(true); - } - super.setVisible(visible); - } - - @Override - public Iterator<Component> iterator() { - return getComponentIterator(); - } - - @Override - public Iterator<Component> getComponentIterator() { - if (visibleComponents == null) { - Collection<Component> empty = Collections.emptyList(); - return empty.iterator(); - } - - return visibleComponents.iterator(); - } - - @Override - public boolean isComponentVisible(Component childComponent) { - return true; - } - - private final Logger getLogger() { - if (logger == null) { - logger = Logger.getLogger(Table.class.getName()); - } - return logger; - } -} diff --git a/src/com/vaadin/ui/TableFieldFactory.java b/src/com/vaadin/ui/TableFieldFactory.java deleted file mode 100644 index 6c9a641aa8..0000000000 --- a/src/com/vaadin/ui/TableFieldFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import java.io.Serializable; - -import com.vaadin.data.Container; - -/** - * Factory interface for creating new Field-instances based on Container - * (datasource), item id, property id and uiContext (the component responsible - * for displaying fields). Currently this interface is used by {@link Table}, - * but might later be used by some other components for {@link Field} - * generation. - * - * <p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 6.0 - * @see FormFieldFactory - */ -public interface TableFieldFactory extends Serializable { - /** - * Creates a field based on the Container, item id, property id and the - * component responsible for displaying the field (most commonly - * {@link Table}). - * - * @param container - * the Container where the property belongs to. - * @param itemId - * the item Id. - * @param propertyId - * the Id of the property. - * @param uiContext - * the component where the field is presented. - * @return A field suitable for editing the specified data or null if the - * property should not be editable. - */ - Field<?> createField(Container container, Object itemId, Object propertyId, - Component uiContext); - -} diff --git a/src/com/vaadin/ui/TextArea.java b/src/com/vaadin/ui/TextArea.java deleted file mode 100644 index d7837dd33f..0000000000 --- a/src/com/vaadin/ui/TextArea.java +++ /dev/null @@ -1,121 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import com.vaadin.data.Property; -import com.vaadin.shared.ui.textarea.TextAreaState; - -/** - * A text field that supports multi line editing. - */ -public class TextArea extends AbstractTextField { - - /** - * Constructs an empty TextArea. - */ - public TextArea() { - setValue(""); - } - - /** - * Constructs an empty TextArea with given caption. - * - * @param caption - * the caption for the field. - */ - public TextArea(String caption) { - this(); - setCaption(caption); - } - - /** - * Constructs a TextArea with given property data source. - * - * @param dataSource - * the data source for the field - */ - public TextArea(Property dataSource) { - this(); - setPropertyDataSource(dataSource); - } - - /** - * Constructs a TextArea with given caption and property data source. - * - * @param caption - * the caption for the field - * @param dataSource - * the data source for the field - */ - public TextArea(String caption, Property dataSource) { - this(dataSource); - setCaption(caption); - } - - /** - * Constructs a TextArea with given caption and value. - * - * @param caption - * the caption for the field - * @param value - * the value for the field - */ - public TextArea(String caption, String value) { - this(caption); - setValue(value); - - } - - @Override - public TextAreaState getState() { - return (TextAreaState) super.getState(); - } - - /** - * Sets the number of rows in the text area. - * - * @param rows - * the number of rows for this text area. - */ - public void setRows(int rows) { - if (rows < 0) { - rows = 0; - } - getState().setRows(rows); - requestRepaint(); - } - - /** - * Gets the number of rows in the text area. - * - * @return number of explicitly set rows. - */ - public int getRows() { - return getState().getRows(); - } - - /** - * Sets the text area's word-wrap mode on or off. - * - * @param wordwrap - * the boolean value specifying if the text area should be in - * word-wrap mode. - */ - public void setWordwrap(boolean wordwrap) { - getState().setWordwrap(wordwrap); - requestRepaint(); - } - - /** - * Tests if the text area is in word-wrap mode. - * - * @return <code>true</code> if the component is in word-wrap mode, - * <code>false</code> if not. - */ - public boolean isWordwrap() { - return getState().isWordwrap(); - } - -} diff --git a/src/com/vaadin/ui/TextField.java b/src/com/vaadin/ui/TextField.java deleted file mode 100644 index 567e9c1c10..0000000000 --- a/src/com/vaadin/ui/TextField.java +++ /dev/null @@ -1,92 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import com.vaadin.data.Property; - -/** - * <p> - * A text editor component that can be bound to any bindable Property. The text - * editor supports both multiline and single line modes, default is one-line - * mode. - * </p> - * - * <p> - * Since <code>TextField</code> extends <code>AbstractField</code> it implements - * the {@link com.vaadin.data.Buffered} interface. A <code>TextField</code> is - * in write-through mode by default, so - * {@link com.vaadin.ui.AbstractField#setWriteThrough(boolean)} must be called - * to enable buffering. - * </p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public class TextField extends AbstractTextField { - - /** - * Constructs an empty <code>TextField</code> with no caption. - */ - public TextField() { - setValue(""); - } - - /** - * Constructs an empty <code>TextField</code> with given caption. - * - * @param caption - * the caption <code>String</code> for the editor. - */ - public TextField(String caption) { - this(); - setCaption(caption); - } - - /** - * Constructs a new <code>TextField</code> that's bound to the specified - * <code>Property</code> and has no caption. - * - * @param dataSource - * the Property to be edited with this editor. - */ - public TextField(Property dataSource) { - setPropertyDataSource(dataSource); - } - - /** - * Constructs a new <code>TextField</code> that's bound to the specified - * <code>Property</code> and has the given caption <code>String</code>. - * - * @param caption - * the caption <code>String</code> for the editor. - * @param dataSource - * the Property to be edited with this editor. - */ - public TextField(String caption, Property dataSource) { - this(dataSource); - setCaption(caption); - } - - /** - * Constructs a new <code>TextField</code> with the given caption and - * initial text contents. The editor constructed this way will not be bound - * to a Property unless - * {@link com.vaadin.data.Property.Viewer#setPropertyDataSource(Property)} - * is called to bind it. - * - * @param caption - * the caption <code>String</code> for the editor. - * @param value - * the initial text content of the editor. - */ - public TextField(String caption, String value) { - setValue(value); - setCaption(caption); - } - -} diff --git a/src/com/vaadin/ui/Tree.java b/src/com/vaadin/ui/Tree.java deleted file mode 100644 index c15975d879..0000000000 --- a/src/com/vaadin/ui/Tree.java +++ /dev/null @@ -1,1615 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.Map; -import java.util.Set; -import java.util.Stack; -import java.util.StringTokenizer; - -import com.vaadin.data.Container; -import com.vaadin.data.Item; -import com.vaadin.data.util.ContainerHierarchicalWrapper; -import com.vaadin.data.util.IndexedContainer; -import com.vaadin.event.Action; -import com.vaadin.event.Action.Handler; -import com.vaadin.event.DataBoundTransferable; -import com.vaadin.event.ItemClickEvent; -import com.vaadin.event.ItemClickEvent.ItemClickListener; -import com.vaadin.event.ItemClickEvent.ItemClickNotifier; -import com.vaadin.event.Transferable; -import com.vaadin.event.dd.DragAndDropEvent; -import com.vaadin.event.dd.DragSource; -import com.vaadin.event.dd.DropHandler; -import com.vaadin.event.dd.DropTarget; -import com.vaadin.event.dd.TargetDetails; -import com.vaadin.event.dd.acceptcriteria.ClientSideCriterion; -import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion; -import com.vaadin.event.dd.acceptcriteria.TargetDetailIs; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.dd.VerticalDropLocation; -import com.vaadin.terminal.KeyMapper; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.gwt.client.ui.tree.TreeConnector; -import com.vaadin.terminal.gwt.client.ui.tree.VTree; -import com.vaadin.tools.ReflectTools; - -/** - * Tree component. A Tree can be used to select an item (or multiple items) from - * a hierarchical set of items. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings({ "serial", "deprecation" }) -public class Tree extends AbstractSelect implements Container.Hierarchical, - Action.Container, ItemClickNotifier, DragSource, DropTarget { - - /* Private members */ - - /** - * Set of expanded nodes. - */ - private final HashSet<Object> expanded = new HashSet<Object>(); - - /** - * List of action handlers. - */ - private LinkedList<Action.Handler> actionHandlers = null; - - /** - * Action mapper. - */ - private KeyMapper<Action> actionMapper = null; - - /** - * Is the tree selectable on the client side. - */ - private boolean selectable = true; - - /** - * Flag to indicate sub-tree loading - */ - private boolean partialUpdate = false; - - /** - * Holds a itemId which was recently expanded - */ - private Object expandedItemId; - - /** - * a flag which indicates initial paint. After this flag set true partial - * updates are allowed. - */ - private boolean initialPaint = true; - - /** - * Item tooltip generator - */ - private ItemDescriptionGenerator itemDescriptionGenerator; - - /** - * Supported drag modes for Tree. - */ - public enum TreeDragMode { - /** - * When drag mode is NONE, dragging from Tree is not supported. Browsers - * may still support selecting text/icons from Tree which can initiate - * HTML 5 style drag and drop operation. - */ - NONE, - /** - * When drag mode is NODE, users can initiate drag from Tree nodes that - * represent {@link Item}s in from the backed {@link Container}. - */ - NODE - // , SUBTREE - } - - private TreeDragMode dragMode = TreeDragMode.NONE; - - private MultiSelectMode multiSelectMode = MultiSelectMode.DEFAULT; - - /* Tree constructors */ - - /** - * Creates a new empty tree. - */ - public Tree() { - } - - /** - * Creates a new empty tree with caption. - * - * @param caption - */ - public Tree(String caption) { - setCaption(caption); - } - - /** - * Creates a new tree with caption and connect it to a Container. - * - * @param caption - * @param dataSource - */ - public Tree(String caption, Container dataSource) { - setCaption(caption); - setContainerDataSource(dataSource); - } - - /* Expanding and collapsing */ - - /** - * Check is an item is expanded - * - * @param itemId - * the item id. - * @return true iff the item is expanded. - */ - public boolean isExpanded(Object itemId) { - return expanded.contains(itemId); - } - - /** - * Expands an item. - * - * @param itemId - * the item id. - * @return True iff the expand operation succeeded - */ - public boolean expandItem(Object itemId) { - boolean success = expandItem(itemId, true); - requestRepaint(); - return success; - } - - /** - * Expands an item. - * - * @param itemId - * the item id. - * @param sendChildTree - * flag to indicate if client needs subtree or not (may be - * cached) - * @return True iff the expand operation succeeded - */ - private boolean expandItem(Object itemId, boolean sendChildTree) { - - // Succeeds if the node is already expanded - if (isExpanded(itemId)) { - return true; - } - - // Nodes that can not have children are not expandable - if (!areChildrenAllowed(itemId)) { - return false; - } - - // Expands - expanded.add(itemId); - - expandedItemId = itemId; - if (initialPaint) { - requestRepaint(); - } else if (sendChildTree) { - requestPartialRepaint(); - } - fireExpandEvent(itemId); - - return true; - } - - @Override - public void requestRepaint() { - super.requestRepaint(); - partialUpdate = false; - } - - private void requestPartialRepaint() { - super.requestRepaint(); - partialUpdate = true; - } - - /** - * Expands the items recursively - * - * Expands all the children recursively starting from an item. Operation - * succeeds only if all expandable items are expanded. - * - * @param startItemId - * @return True iff the expand operation succeeded - */ - public boolean expandItemsRecursively(Object startItemId) { - - boolean result = true; - - // Initial stack - final Stack<Object> todo = new Stack<Object>(); - todo.add(startItemId); - - // Expands recursively - while (!todo.isEmpty()) { - final Object id = todo.pop(); - if (areChildrenAllowed(id) && !expandItem(id, false)) { - result = false; - } - if (hasChildren(id)) { - todo.addAll(getChildren(id)); - } - } - requestRepaint(); - return result; - } - - /** - * Collapses an item. - * - * @param itemId - * the item id. - * @return True iff the collapse operation succeeded - */ - public boolean collapseItem(Object itemId) { - - // Succeeds if the node is already collapsed - if (!isExpanded(itemId)) { - return true; - } - - // Collapse - expanded.remove(itemId); - requestRepaint(); - fireCollapseEvent(itemId); - - return true; - } - - /** - * Collapses the items recursively. - * - * Collapse all the children recursively starting from an item. Operation - * succeeds only if all expandable items are collapsed. - * - * @param startItemId - * @return True iff the collapse operation succeeded - */ - public boolean collapseItemsRecursively(Object startItemId) { - - boolean result = true; - - // Initial stack - final Stack<Object> todo = new Stack<Object>(); - todo.add(startItemId); - - // Collapse recursively - while (!todo.isEmpty()) { - final Object id = todo.pop(); - if (areChildrenAllowed(id) && !collapseItem(id)) { - result = false; - } - if (hasChildren(id)) { - todo.addAll(getChildren(id)); - } - } - - return result; - } - - /** - * Returns the current selectable state. Selectable determines if the a node - * can be selected on the client side. Selectable does not affect - * {@link #setValue(Object)} or {@link #select(Object)}. - * - * <p> - * The tree is selectable by default. - * </p> - * - * @return the current selectable state. - */ - public boolean isSelectable() { - return selectable; - } - - /** - * Sets the selectable state. Selectable determines if the a node can be - * selected on the client side. Selectable does not affect - * {@link #setValue(Object)} or {@link #select(Object)}. - * - * <p> - * The tree is selectable by default. - * </p> - * - * @param selectable - * The new selectable state. - */ - public void setSelectable(boolean selectable) { - if (this.selectable != selectable) { - this.selectable = selectable; - requestRepaint(); - } - } - - /** - * Sets the behavior of the multiselect mode - * - * @param mode - * The mode to set - */ - public void setMultiselectMode(MultiSelectMode mode) { - if (multiSelectMode != mode && mode != null) { - multiSelectMode = mode; - requestRepaint(); - } - } - - /** - * Returns the mode the multiselect is in. The mode controls how - * multiselection can be done. - * - * @return The mode - */ - public MultiSelectMode getMultiselectMode() { - return multiSelectMode; - } - - /* Component API */ - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.AbstractSelect#changeVariables(java.lang.Object, - * java.util.Map) - */ - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - - if (variables.containsKey("clickedKey")) { - String key = (String) variables.get("clickedKey"); - - Object id = itemIdMapper.get(key); - MouseEventDetails details = MouseEventDetails - .deSerialize((String) variables.get("clickEvent")); - Item item = getItem(id); - if (item != null) { - fireEvent(new ItemClickEvent(this, item, id, null, details)); - } - } - - if (!isSelectable() && variables.containsKey("selected")) { - // Not-selectable is a special case, AbstractSelect does not support - // TODO could be optimized. - variables = new HashMap<String, Object>(variables); - variables.remove("selected"); - } - - // Collapses the nodes - if (variables.containsKey("collapse")) { - final String[] keys = (String[]) variables.get("collapse"); - for (int i = 0; i < keys.length; i++) { - final Object id = itemIdMapper.get(keys[i]); - if (id != null && isExpanded(id)) { - expanded.remove(id); - fireCollapseEvent(id); - } - } - } - - // Expands the nodes - if (variables.containsKey("expand")) { - boolean sendChildTree = false; - if (variables.containsKey("requestChildTree")) { - sendChildTree = true; - } - final String[] keys = (String[]) variables.get("expand"); - for (int i = 0; i < keys.length; i++) { - final Object id = itemIdMapper.get(keys[i]); - if (id != null) { - expandItem(id, sendChildTree); - } - } - } - - // AbstractSelect cannot handle multiselection so we handle - // it ourself - if (variables.containsKey("selected") && isMultiSelect() - && multiSelectMode == MultiSelectMode.DEFAULT) { - handleSelectedItems(variables); - variables = new HashMap<String, Object>(variables); - variables.remove("selected"); - } - - // Selections are handled by the select component - super.changeVariables(source, variables); - - // Actions - if (variables.containsKey("action")) { - final StringTokenizer st = new StringTokenizer( - (String) variables.get("action"), ","); - if (st.countTokens() == 2) { - final Object itemId = itemIdMapper.get(st.nextToken()); - final Action action = actionMapper.get(st.nextToken()); - if (action != null && (itemId == null || containsId(itemId)) - && actionHandlers != null) { - for (Handler ah : actionHandlers) { - ah.handleAction(action, this, itemId); - } - } - } - } - } - - /** - * Handles the selection - * - * @param variables - * The variables sent to the server from the client - */ - private void handleSelectedItems(Map<String, Object> variables) { - final String[] ka = (String[]) variables.get("selected"); - - // Converts the key-array to id-set - final LinkedList<Object> s = new LinkedList<Object>(); - for (int i = 0; i < ka.length; i++) { - final Object id = itemIdMapper.get(ka[i]); - if (!isNullSelectionAllowed() - && (id == null || id == getNullSelectionItemId())) { - // skip empty selection if nullselection is not allowed - requestRepaint(); - } else if (id != null && containsId(id)) { - s.add(id); - } - } - - if (!isNullSelectionAllowed() && s.size() < 1) { - // empty selection not allowed, keep old value - requestRepaint(); - return; - } - - setValue(s, true); - } - - /** - * Paints any needed component-specific things to the given UIDL stream. - * - * @see com.vaadin.ui.AbstractComponent#paintContent(PaintTarget) - */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - initialPaint = false; - - if (partialUpdate) { - target.addAttribute("partialUpdate", true); - target.addAttribute("rootKey", itemIdMapper.key(expandedItemId)); - } else { - getCaptionChangeListener().clear(); - - // The tab ordering number - if (getTabIndex() > 0) { - target.addAttribute("tabindex", getTabIndex()); - } - - // Paint tree attributes - if (isSelectable()) { - target.addAttribute("selectmode", (isMultiSelect() ? "multi" - : "single")); - if (isMultiSelect()) { - target.addAttribute("multiselectmode", - multiSelectMode.ordinal()); - } - } else { - target.addAttribute("selectmode", "none"); - } - if (isNewItemsAllowed()) { - target.addAttribute("allownewitem", true); - } - - if (isNullSelectionAllowed()) { - target.addAttribute("nullselect", true); - } - - if (dragMode != TreeDragMode.NONE) { - target.addAttribute("dragMode", dragMode.ordinal()); - } - - } - - // Initialize variables - final Set<Action> actionSet = new LinkedHashSet<Action>(); - - // rendered selectedKeys - LinkedList<String> selectedKeys = new LinkedList<String>(); - - final LinkedList<String> expandedKeys = new LinkedList<String>(); - - // Iterates through hierarchical tree using a stack of iterators - final Stack<Iterator<?>> iteratorStack = new Stack<Iterator<?>>(); - Collection<?> ids; - if (partialUpdate) { - ids = getChildren(expandedItemId); - } else { - ids = rootItemIds(); - } - - if (ids != null) { - iteratorStack.push(ids.iterator()); - } - - /* - * Body actions - Actions which has the target null and can be invoked - * by right clicking on the Tree body - */ - if (actionHandlers != null) { - final ArrayList<String> keys = new ArrayList<String>(); - for (Handler ah : actionHandlers) { - - // Getting action for the null item, which in this case - // means the body item - final Action[] aa = ah.getActions(null, this); - if (aa != null) { - for (int ai = 0; ai < aa.length; ai++) { - final String akey = actionMapper.key(aa[ai]); - actionSet.add(aa[ai]); - keys.add(akey); - } - } - } - target.addAttribute("alb", keys.toArray()); - } - - while (!iteratorStack.isEmpty()) { - - // Gets the iterator for current tree level - final Iterator<?> i = iteratorStack.peek(); - - // If the level is finished, back to previous tree level - if (!i.hasNext()) { - - // Removes used iterator from the stack - iteratorStack.pop(); - - // Closes node - if (!iteratorStack.isEmpty()) { - target.endTag("node"); - } - } - - // Adds the item on current level - else { - final Object itemId = i.next(); - - // Starts the item / node - final boolean isNode = areChildrenAllowed(itemId); - if (isNode) { - target.startTag("node"); - } else { - target.startTag("leaf"); - } - - if (itemStyleGenerator != null) { - String stylename = itemStyleGenerator.getStyle(itemId); - if (stylename != null) { - target.addAttribute(TreeConnector.ATTRIBUTE_NODE_STYLE, - stylename); - } - } - - if (itemDescriptionGenerator != null) { - String description = itemDescriptionGenerator - .generateDescription(this, itemId, null); - if (description != null && !description.equals("")) { - target.addAttribute("descr", description); - } - } - - // Adds the attributes - target.addAttribute(TreeConnector.ATTRIBUTE_NODE_CAPTION, - getItemCaption(itemId)); - final Resource icon = getItemIcon(itemId); - if (icon != null) { - target.addAttribute(TreeConnector.ATTRIBUTE_NODE_ICON, - getItemIcon(itemId)); - } - final String key = itemIdMapper.key(itemId); - target.addAttribute("key", key); - if (isSelected(itemId)) { - target.addAttribute("selected", true); - selectedKeys.add(key); - } - if (areChildrenAllowed(itemId) && isExpanded(itemId)) { - target.addAttribute("expanded", true); - expandedKeys.add(key); - } - - // Add caption change listener - getCaptionChangeListener().addNotifierForItem(itemId); - - // Actions - if (actionHandlers != null) { - final ArrayList<String> keys = new ArrayList<String>(); - final Iterator<Action.Handler> ahi = actionHandlers - .iterator(); - while (ahi.hasNext()) { - final Action[] aa = ahi.next().getActions(itemId, this); - if (aa != null) { - for (int ai = 0; ai < aa.length; ai++) { - final String akey = actionMapper.key(aa[ai]); - actionSet.add(aa[ai]); - keys.add(akey); - } - } - } - target.addAttribute("al", keys.toArray()); - } - - // Adds the children if expanded, or close the tag - if (isExpanded(itemId) && hasChildren(itemId) - && areChildrenAllowed(itemId)) { - iteratorStack.push(getChildren(itemId).iterator()); - } else { - if (isNode) { - target.endTag("node"); - } else { - target.endTag("leaf"); - } - } - } - } - - // Actions - if (!actionSet.isEmpty()) { - target.addVariable(this, "action", ""); - target.startTag("actions"); - final Iterator<Action> i = actionSet.iterator(); - while (i.hasNext()) { - final Action a = i.next(); - target.startTag("action"); - if (a.getCaption() != null) { - target.addAttribute(TreeConnector.ATTRIBUTE_ACTION_CAPTION, - a.getCaption()); - } - if (a.getIcon() != null) { - target.addAttribute(TreeConnector.ATTRIBUTE_ACTION_ICON, - a.getIcon()); - } - target.addAttribute("key", actionMapper.key(a)); - target.endTag("action"); - } - target.endTag("actions"); - } - - if (partialUpdate) { - partialUpdate = false; - } else { - // Selected - target.addVariable(this, "selected", - selectedKeys.toArray(new String[selectedKeys.size()])); - - // Expand and collapse - target.addVariable(this, "expand", new String[] {}); - target.addVariable(this, "collapse", new String[] {}); - - // New items - target.addVariable(this, "newitem", new String[] {}); - - if (dropHandler != null) { - dropHandler.getAcceptCriterion().paint(target); - } - - } - } - - /* Container.Hierarchical API */ - - /** - * Tests if the Item with given ID can have any children. - * - * @see com.vaadin.data.Container.Hierarchical#areChildrenAllowed(Object) - */ - @Override - public boolean areChildrenAllowed(Object itemId) { - return ((Container.Hierarchical) items).areChildrenAllowed(itemId); - } - - /** - * Gets the IDs of all Items that are children of the specified Item. - * - * @see com.vaadin.data.Container.Hierarchical#getChildren(Object) - */ - @Override - public Collection<?> getChildren(Object itemId) { - return ((Container.Hierarchical) items).getChildren(itemId); - } - - /** - * Gets the ID of the parent Item of the specified Item. - * - * @see com.vaadin.data.Container.Hierarchical#getParent(Object) - */ - @Override - public Object getParent(Object itemId) { - return ((Container.Hierarchical) items).getParent(itemId); - } - - /** - * Tests if the Item specified with <code>itemId</code> has child Items. - * - * @see com.vaadin.data.Container.Hierarchical#hasChildren(Object) - */ - @Override - public boolean hasChildren(Object itemId) { - return ((Container.Hierarchical) items).hasChildren(itemId); - } - - /** - * Tests if the Item specified with <code>itemId</code> is a root Item. - * - * @see com.vaadin.data.Container.Hierarchical#isRoot(Object) - */ - @Override - public boolean isRoot(Object itemId) { - return ((Container.Hierarchical) items).isRoot(itemId); - } - - /** - * Gets the IDs of all Items in the container that don't have a parent. - * - * @see com.vaadin.data.Container.Hierarchical#rootItemIds() - */ - @Override - public Collection<?> rootItemIds() { - return ((Container.Hierarchical) items).rootItemIds(); - } - - /** - * Sets the given Item's capability to have children. - * - * @see com.vaadin.data.Container.Hierarchical#setChildrenAllowed(Object, - * boolean) - */ - @Override - public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) { - final boolean success = ((Container.Hierarchical) items) - .setChildrenAllowed(itemId, areChildrenAllowed); - if (success) { - requestRepaint(); - } - return success; - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.data.Container.Hierarchical#setParent(java.lang.Object , - * java.lang.Object) - */ - @Override - public boolean setParent(Object itemId, Object newParentId) { - final boolean success = ((Container.Hierarchical) items).setParent( - itemId, newParentId); - if (success) { - requestRepaint(); - } - return success; - } - - /* Overriding select behavior */ - - /** - * Sets the Container that serves as the data source of the viewer. - * - * @see com.vaadin.data.Container.Viewer#setContainerDataSource(Container) - */ - @Override - public void setContainerDataSource(Container newDataSource) { - if (newDataSource == null) { - // Note: using wrapped IndexedContainer to match constructor (super - // creates an IndexedContainer, which is then wrapped). - newDataSource = new ContainerHierarchicalWrapper( - new IndexedContainer()); - } - - // Assure that the data source is ordered by making unordered - // containers ordered by wrapping them - if (Container.Hierarchical.class.isAssignableFrom(newDataSource - .getClass())) { - super.setContainerDataSource(newDataSource); - } else { - super.setContainerDataSource(new ContainerHierarchicalWrapper( - newDataSource)); - } - } - - /* Expand event and listener */ - - /** - * Event to fired when a node is expanded. ExapandEvent is fired when a node - * is to be expanded. it can me used to dynamically fill the sub-nodes of - * the node. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public static class ExpandEvent extends Component.Event { - - private final Object expandedItemId; - - /** - * New instance of options change event - * - * @param source - * the Source of the event. - * @param expandedItemId - */ - public ExpandEvent(Component source, Object expandedItemId) { - super(source); - this.expandedItemId = expandedItemId; - } - - /** - * Node where the event occurred. - * - * @return the Source of the event. - */ - public Object getItemId() { - return expandedItemId; - } - } - - /** - * Expand event listener. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface ExpandListener extends Serializable { - - public static final Method EXPAND_METHOD = ReflectTools.findMethod( - ExpandListener.class, "nodeExpand", ExpandEvent.class); - - /** - * A node has been expanded. - * - * @param event - * the Expand event. - */ - public void nodeExpand(ExpandEvent event); - } - - /** - * Adds the expand listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(ExpandListener listener) { - addListener(ExpandEvent.class, listener, ExpandListener.EXPAND_METHOD); - } - - /** - * Removes the expand listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(ExpandListener listener) { - removeListener(ExpandEvent.class, listener, - ExpandListener.EXPAND_METHOD); - } - - /** - * Emits the expand event. - * - * @param itemId - * the item id. - */ - protected void fireExpandEvent(Object itemId) { - fireEvent(new ExpandEvent(this, itemId)); - } - - /* Collapse event */ - - /** - * Collapse event - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public static class CollapseEvent extends Component.Event { - - private final Object collapsedItemId; - - /** - * New instance of options change event. - * - * @param source - * the Source of the event. - * @param collapsedItemId - */ - public CollapseEvent(Component source, Object collapsedItemId) { - super(source); - this.collapsedItemId = collapsedItemId; - } - - /** - * Gets tge Collapsed Item id. - * - * @return the collapsed item id. - */ - public Object getItemId() { - return collapsedItemId; - } - } - - /** - * Collapse event listener. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface CollapseListener extends Serializable { - - public static final Method COLLAPSE_METHOD = ReflectTools.findMethod( - CollapseListener.class, "nodeCollapse", CollapseEvent.class); - - /** - * A node has been collapsed. - * - * @param event - * the Collapse event. - */ - public void nodeCollapse(CollapseEvent event); - } - - /** - * Adds the collapse listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(CollapseListener listener) { - addListener(CollapseEvent.class, listener, - CollapseListener.COLLAPSE_METHOD); - } - - /** - * Removes the collapse listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(CollapseListener listener) { - removeListener(CollapseEvent.class, listener, - CollapseListener.COLLAPSE_METHOD); - } - - /** - * Emits collapse event. - * - * @param itemId - * the item id. - */ - protected void fireCollapseEvent(Object itemId) { - fireEvent(new CollapseEvent(this, itemId)); - } - - /* Action container */ - - /** - * Adds an action handler. - * - * @see com.vaadin.event.Action.Container#addActionHandler(Action.Handler) - */ - @Override - public void addActionHandler(Action.Handler actionHandler) { - - if (actionHandler != null) { - - if (actionHandlers == null) { - actionHandlers = new LinkedList<Action.Handler>(); - actionMapper = new KeyMapper<Action>(); - } - - if (!actionHandlers.contains(actionHandler)) { - actionHandlers.add(actionHandler); - requestRepaint(); - } - } - } - - /** - * Removes an action handler. - * - * @see com.vaadin.event.Action.Container#removeActionHandler(Action.Handler) - */ - @Override - public void removeActionHandler(Action.Handler actionHandler) { - - if (actionHandlers != null && actionHandlers.contains(actionHandler)) { - - actionHandlers.remove(actionHandler); - - if (actionHandlers.isEmpty()) { - actionHandlers = null; - actionMapper = null; - } - - requestRepaint(); - } - } - - /** - * Removes all action handlers - */ - public void removeAllActionHandlers() { - actionHandlers = null; - actionMapper = null; - requestRepaint(); - } - - /** - * Gets the visible item ids. - * - * @see com.vaadin.ui.Select#getVisibleItemIds() - */ - @Override - public Collection<?> getVisibleItemIds() { - - final LinkedList<Object> visible = new LinkedList<Object>(); - - // Iterates trough hierarchical tree using a stack of iterators - final Stack<Iterator<?>> iteratorStack = new Stack<Iterator<?>>(); - final Collection<?> ids = rootItemIds(); - if (ids != null) { - iteratorStack.push(ids.iterator()); - } - while (!iteratorStack.isEmpty()) { - - // Gets the iterator for current tree level - final Iterator<?> i = iteratorStack.peek(); - - // If the level is finished, back to previous tree level - if (!i.hasNext()) { - - // Removes used iterator from the stack - iteratorStack.pop(); - } - - // Adds the item on current level - else { - final Object itemId = i.next(); - - visible.add(itemId); - - // Adds children if expanded, or close the tag - if (isExpanded(itemId) && hasChildren(itemId)) { - iteratorStack.push(getChildren(itemId).iterator()); - } - } - } - - return visible; - } - - /** - * Tree does not support <code>setNullSelectionItemId</code>. - * - * @see com.vaadin.ui.AbstractSelect#setNullSelectionItemId(java.lang.Object) - */ - @Override - public void setNullSelectionItemId(Object nullSelectionItemId) - throws UnsupportedOperationException { - if (nullSelectionItemId != null) { - throw new UnsupportedOperationException(); - } - - } - - /** - * Adding new items is not supported. - * - * @throws UnsupportedOperationException - * if set to true. - * @see com.vaadin.ui.Select#setNewItemsAllowed(boolean) - */ - @Override - public void setNewItemsAllowed(boolean allowNewOptions) - throws UnsupportedOperationException { - if (allowNewOptions) { - throw new UnsupportedOperationException(); - } - } - - /** - * Tree does not support lazy options loading mode. Setting this true will - * throw UnsupportedOperationException. - * - * @see com.vaadin.ui.Select#setLazyLoading(boolean) - */ - public void setLazyLoading(boolean useLazyLoading) { - if (useLazyLoading) { - throw new UnsupportedOperationException( - "Lazy options loading is not supported by Tree."); - } - } - - private ItemStyleGenerator itemStyleGenerator; - - private DropHandler dropHandler; - - @Override - public void addListener(ItemClickListener listener) { - addListener(VTree.ITEM_CLICK_EVENT_ID, ItemClickEvent.class, listener, - ItemClickEvent.ITEM_CLICK_METHOD); - } - - @Override - public void removeListener(ItemClickListener listener) { - removeListener(VTree.ITEM_CLICK_EVENT_ID, ItemClickEvent.class, - listener); - } - - /** - * Sets the {@link ItemStyleGenerator} to be used with this tree. - * - * @param itemStyleGenerator - * item style generator or null to remove generator - */ - public void setItemStyleGenerator(ItemStyleGenerator itemStyleGenerator) { - if (this.itemStyleGenerator != itemStyleGenerator) { - this.itemStyleGenerator = itemStyleGenerator; - requestRepaint(); - } - } - - /** - * @return the current {@link ItemStyleGenerator} for this tree. Null if - * {@link ItemStyleGenerator} is not set. - */ - public ItemStyleGenerator getItemStyleGenerator() { - return itemStyleGenerator; - } - - /** - * ItemStyleGenerator can be used to add custom styles to tree items. The - * CSS class name that will be added to the cell content is - * <tt>v-tree-node-[style name]</tt>. - */ - public interface ItemStyleGenerator extends Serializable { - - /** - * Called by Tree when an item is painted. - * - * @param itemId - * The itemId of the item to be painted - * @return The style name to add to this item. (the CSS class name will - * be v-tree-node-[style name] - */ - public abstract String getStyle(Object itemId); - } - - // Overriden so javadoc comes from Container.Hierarchical - @Override - public boolean removeItem(Object itemId) - throws UnsupportedOperationException { - return super.removeItem(itemId); - } - - @Override - public DropHandler getDropHandler() { - return dropHandler; - } - - public void setDropHandler(DropHandler dropHandler) { - this.dropHandler = dropHandler; - } - - /** - * A {@link TargetDetails} implementation with Tree specific api. - * - * @since 6.3 - */ - public class TreeTargetDetails extends AbstractSelectTargetDetails { - - TreeTargetDetails(Map<String, Object> rawVariables) { - super(rawVariables); - } - - @Override - public Tree getTarget() { - return (Tree) super.getTarget(); - } - - /** - * If the event is on a node that can not have children (see - * {@link Tree#areChildrenAllowed(Object)}), this method returns the - * parent item id of the target item (see {@link #getItemIdOver()} ). - * The identifier of the parent node is also returned if the cursor is - * on the top part of node. Else this method returns the same as - * {@link #getItemIdOver()}. - * <p> - * In other words this method returns the identifier of the "folder" - * into the drag operation is targeted. - * <p> - * If the method returns null, the current target is on a root node or - * on other undefined area over the tree component. - * <p> - * The default Tree implementation marks the targetted tree node with - * CSS classnames v-tree-node-dragfolder and - * v-tree-node-caption-dragfolder (for the caption element). - */ - public Object getItemIdInto() { - - Object itemIdOver = getItemIdOver(); - if (areChildrenAllowed(itemIdOver) - && getDropLocation() == VerticalDropLocation.MIDDLE) { - return itemIdOver; - } - return getParent(itemIdOver); - } - - /** - * If drop is targeted into "folder node" (see {@link #getItemIdInto()} - * ), this method returns the item id of the node after the drag was - * targeted. This method is useful when implementing drop into specific - * location (between specific nodes) in tree. - * - * @return the id of the item after the user targets the drop or null if - * "target" is a first item in node list (or the first in root - * node list) - */ - public Object getItemIdAfter() { - Object itemIdOver = getItemIdOver(); - Object itemIdInto2 = getItemIdInto(); - if (itemIdOver.equals(itemIdInto2)) { - return null; - } - VerticalDropLocation dropLocation = getDropLocation(); - if (VerticalDropLocation.TOP == dropLocation) { - // if on top of the caption area, add before - Collection<?> children; - Object itemIdInto = getItemIdInto(); - if (itemIdInto != null) { - // seek the previous from child list - children = getChildren(itemIdInto); - } else { - children = rootItemIds(); - } - Object ref = null; - for (Object object : children) { - if (object.equals(itemIdOver)) { - return ref; - } - ref = object; - } - } - return itemIdOver; - } - - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.event.dd.DropTarget#translateDropTargetDetails(java.util.Map) - */ - @Override - public TreeTargetDetails translateDropTargetDetails( - Map<String, Object> clientVariables) { - return new TreeTargetDetails(clientVariables); - } - - /** - * Helper API for {@link TreeDropCriterion} - * - * @param itemId - * @return - */ - private String key(Object itemId) { - return itemIdMapper.key(itemId); - } - - /** - * Sets the drag mode that controls how Tree behaves as a {@link DragSource} - * . - * - * @param dragMode - */ - public void setDragMode(TreeDragMode dragMode) { - this.dragMode = dragMode; - requestRepaint(); - } - - /** - * @return the drag mode that controls how Tree behaves as a - * {@link DragSource}. - * - * @see TreeDragMode - */ - public TreeDragMode getDragMode() { - return dragMode; - } - - /** - * Concrete implementation of {@link DataBoundTransferable} for data - * transferred from a tree. - * - * @see {@link DataBoundTransferable}. - * - * @since 6.3 - */ - protected class TreeTransferable extends DataBoundTransferable { - - public TreeTransferable(Component sourceComponent, - Map<String, Object> rawVariables) { - super(sourceComponent, rawVariables); - } - - @Override - public Object getItemId() { - return getData("itemId"); - } - - @Override - public Object getPropertyId() { - return getItemCaptionPropertyId(); - } - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.event.dd.DragSource#getTransferable(java.util.Map) - */ - @Override - public Transferable getTransferable(Map<String, Object> payload) { - TreeTransferable transferable = new TreeTransferable(this, payload); - // updating drag source variables - Object object = payload.get("itemId"); - if (object != null) { - transferable.setData("itemId", itemIdMapper.get((String) object)); - } - - return transferable; - } - - /** - * Lazy loading accept criterion for Tree. Accepted target nodes are loaded - * from server once per drag and drop operation. Developer must override one - * method that decides accepted tree nodes for the whole Tree. - * - * <p> - * Initially pretty much no data is sent to client. On first required - * criterion check (per drag request) the client side data structure is - * initialized from server and no subsequent requests requests are needed - * during that drag and drop operation. - */ - public static abstract class TreeDropCriterion extends ServerSideCriterion { - - private Tree tree; - - private Set<Object> allowedItemIds; - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.event.dd.acceptCriteria.ServerSideCriterion#getIdentifier - * () - */ - @Override - protected String getIdentifier() { - return TreeDropCriterion.class.getCanonicalName(); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.event.dd.acceptCriteria.AcceptCriterion#accepts(com.vaadin - * .event.dd.DragAndDropEvent) - */ - @Override - public boolean accept(DragAndDropEvent dragEvent) { - AbstractSelectTargetDetails dropTargetData = (AbstractSelectTargetDetails) dragEvent - .getTargetDetails(); - tree = (Tree) dragEvent.getTargetDetails().getTarget(); - allowedItemIds = getAllowedItemIds(dragEvent, tree); - - return allowedItemIds.contains(dropTargetData.getItemIdOver()); - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.event.dd.acceptCriteria.AcceptCriterion#paintResponse( - * com.vaadin.terminal.PaintTarget) - */ - @Override - public void paintResponse(PaintTarget target) throws PaintException { - /* - * send allowed nodes to client so subsequent requests can be - * avoided - */ - Object[] array = allowedItemIds.toArray(); - for (int i = 0; i < array.length; i++) { - String key = tree.key(array[i]); - array[i] = key; - } - target.addAttribute("allowedIds", array); - } - - protected abstract Set<Object> getAllowedItemIds( - DragAndDropEvent dragEvent, Tree tree); - - } - - /** - * A criterion that accepts {@link Transferable} only directly on a tree - * node that can have children. - * <p> - * Class is singleton, use {@link TargetItemAllowsChildren#get()} to get the - * instance. - * - * @see Tree#setChildrenAllowed(Object, boolean) - * - * @since 6.3 - */ - public static class TargetItemAllowsChildren extends TargetDetailIs { - - private static TargetItemAllowsChildren instance = new TargetItemAllowsChildren(); - - public static TargetItemAllowsChildren get() { - return instance; - } - - private TargetItemAllowsChildren() { - super("itemIdOverIsNode", Boolean.TRUE); - } - - /* - * Uses enhanced server side check - */ - @Override - public boolean accept(DragAndDropEvent dragEvent) { - try { - // must be over tree node and in the middle of it (not top or - // bottom - // part) - TreeTargetDetails eventDetails = (TreeTargetDetails) dragEvent - .getTargetDetails(); - - Object itemIdOver = eventDetails.getItemIdOver(); - if (!eventDetails.getTarget().areChildrenAllowed(itemIdOver)) { - return false; - } - // return true if directly over - return eventDetails.getDropLocation() == VerticalDropLocation.MIDDLE; - } catch (Exception e) { - return false; - } - } - - } - - /** - * An accept criterion that checks the parent node (or parent hierarchy) for - * the item identifier given in constructor. If the parent is found, content - * is accepted. Criterion can be used to accepts drags on a specific sub - * tree only. - * <p> - * The root items is also consider to be valid target. - */ - public class TargetInSubtree extends ClientSideCriterion { - - private Object rootId; - private int depthToCheck = -1; - - /** - * Constructs a criteria that accepts the drag if the targeted Item is a - * descendant of Item identified by given id - * - * @param parentItemId - * the item identifier of the parent node - */ - public TargetInSubtree(Object parentItemId) { - rootId = parentItemId; - } - - /** - * Constructs a criteria that accepts drops within given level below the - * subtree root identified by given id. - * - * @param rootId - * the item identifier to be sought for - * @param depthToCheck - * the depth that tree is traversed upwards to seek for the - * parent, -1 means that the whole structure should be - * checked - */ - public TargetInSubtree(Object rootId, int depthToCheck) { - this.rootId = rootId; - this.depthToCheck = depthToCheck; - } - - @Override - public boolean accept(DragAndDropEvent dragEvent) { - try { - TreeTargetDetails eventDetails = (TreeTargetDetails) dragEvent - .getTargetDetails(); - - if (eventDetails.getItemIdOver() != null) { - Object itemId = eventDetails.getItemIdOver(); - int i = 0; - while (itemId != null - && (depthToCheck == -1 || i <= depthToCheck)) { - if (itemId.equals(rootId)) { - return true; - } - itemId = getParent(itemId); - i++; - } - } - return false; - } catch (Exception e) { - return false; - } - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - super.paintContent(target); - target.addAttribute("depth", depthToCheck); - target.addAttribute("key", key(rootId)); - } - - } - - /** - * Set the item description generator which generates tooltips for the tree - * items - * - * @param generator - * The generator to use or null to disable - */ - public void setItemDescriptionGenerator(ItemDescriptionGenerator generator) { - if (generator != itemDescriptionGenerator) { - itemDescriptionGenerator = generator; - requestRepaint(); - } - } - - /** - * Get the item description generator which generates tooltips for tree - * items - */ - public ItemDescriptionGenerator getItemDescriptionGenerator() { - return itemDescriptionGenerator; - } - -} diff --git a/src/com/vaadin/ui/TreeTable.java b/src/com/vaadin/ui/TreeTable.java deleted file mode 100644 index 6132b652f7..0000000000 --- a/src/com/vaadin/ui/TreeTable.java +++ /dev/null @@ -1,824 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; - -import com.vaadin.data.Collapsible; -import com.vaadin.data.Container; -import com.vaadin.data.Container.Hierarchical; -import com.vaadin.data.Container.ItemSetChangeEvent; -import com.vaadin.data.util.ContainerHierarchicalWrapper; -import com.vaadin.data.util.HierarchicalContainer; -import com.vaadin.data.util.HierarchicalContainerOrderedWrapper; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.gwt.client.ui.treetable.TreeTableConnector; -import com.vaadin.ui.Tree.CollapseEvent; -import com.vaadin.ui.Tree.CollapseListener; -import com.vaadin.ui.Tree.ExpandEvent; -import com.vaadin.ui.Tree.ExpandListener; - -/** - * TreeTable extends the {@link Table} component so that it can also visualize a - * hierarchy of its Items in a similar manner that {@link Tree} does. The tree - * hierarchy is always displayed in the first actual column of the TreeTable. - * <p> - * The TreeTable supports the usual {@link Table} features like lazy loading, so - * it should be no problem to display lots of items at once. Only required rows - * and some cache rows are sent to the client. - * <p> - * TreeTable supports standard {@link Hierarchical} container interfaces, but - * also a more fine tuned version - {@link Collapsible}. A container - * implementing the {@link Collapsible} interface stores the collapsed/expanded - * state internally and can this way scale better on the server side than with - * standard Hierarchical implementations. Developer must however note that - * {@link Collapsible} containers can not be shared among several users as they - * share UI state in the container. - */ -@SuppressWarnings({ "serial" }) -public class TreeTable extends Table implements Hierarchical { - - private interface ContainerStrategy extends Serializable { - public int size(); - - public boolean isNodeOpen(Object itemId); - - public int getDepth(Object itemId); - - public void toggleChildVisibility(Object itemId); - - public Object getIdByIndex(int index); - - public int indexOfId(Object id); - - public Object nextItemId(Object itemId); - - public Object lastItemId(); - - public Object prevItemId(Object itemId); - - public boolean isLastId(Object itemId); - - public Collection<?> getItemIds(); - - public void containerItemSetChange(ItemSetChangeEvent event); - } - - private abstract class AbstractStrategy implements ContainerStrategy { - - /** - * Consider adding getDepth to {@link Collapsible}, might help - * scalability with some container implementations. - */ - - @Override - public int getDepth(Object itemId) { - int depth = 0; - Hierarchical hierarchicalContainer = getContainerDataSource(); - while (!hierarchicalContainer.isRoot(itemId)) { - depth++; - itemId = hierarchicalContainer.getParent(itemId); - } - return depth; - } - - @Override - public void containerItemSetChange(ItemSetChangeEvent event) { - } - - } - - /** - * This strategy is used if current container implements {@link Collapsible} - * . - * - * open-collapsed logic diverted to container, otherwise use default - * implementations. - */ - private class CollapsibleStrategy extends AbstractStrategy { - - private Collapsible c() { - return (Collapsible) getContainerDataSource(); - } - - @Override - public void toggleChildVisibility(Object itemId) { - c().setCollapsed(itemId, !c().isCollapsed(itemId)); - } - - @Override - public boolean isNodeOpen(Object itemId) { - return !c().isCollapsed(itemId); - } - - @Override - public int size() { - return TreeTable.super.size(); - } - - @Override - public Object getIdByIndex(int index) { - return TreeTable.super.getIdByIndex(index); - } - - @Override - public int indexOfId(Object id) { - return TreeTable.super.indexOfId(id); - } - - @Override - public boolean isLastId(Object itemId) { - // using the default impl - return TreeTable.super.isLastId(itemId); - } - - @Override - public Object lastItemId() { - // using the default impl - return TreeTable.super.lastItemId(); - } - - @Override - public Object nextItemId(Object itemId) { - return TreeTable.super.nextItemId(itemId); - } - - @Override - public Object prevItemId(Object itemId) { - return TreeTable.super.prevItemId(itemId); - } - - @Override - public Collection<?> getItemIds() { - return TreeTable.super.getItemIds(); - } - - } - - /** - * Strategy for Hierarchical but not Collapsible container like - * {@link HierarchicalContainer}. - * - * Store collapsed/open states internally, fool Table to use preorder when - * accessing items from container via Ordered/Indexed methods. - */ - private class HierarchicalStrategy extends AbstractStrategy { - - private final HashSet<Object> openItems = new HashSet<Object>(); - - @Override - public boolean isNodeOpen(Object itemId) { - return openItems.contains(itemId); - } - - @Override - public int size() { - return getPreOrder().size(); - } - - @Override - public Collection<Object> getItemIds() { - return Collections.unmodifiableCollection(getPreOrder()); - } - - @Override - public boolean isLastId(Object itemId) { - if (itemId == null) { - return false; - } - - return itemId.equals(lastItemId()); - } - - @Override - public Object lastItemId() { - if (getPreOrder().size() > 0) { - return getPreOrder().get(getPreOrder().size() - 1); - } else { - return null; - } - } - - @Override - public Object nextItemId(Object itemId) { - int indexOf = getPreOrder().indexOf(itemId); - if (indexOf == -1) { - return null; - } - indexOf++; - if (indexOf == getPreOrder().size()) { - return null; - } else { - return getPreOrder().get(indexOf); - } - } - - @Override - public Object prevItemId(Object itemId) { - int indexOf = getPreOrder().indexOf(itemId); - indexOf--; - if (indexOf < 0) { - return null; - } else { - return getPreOrder().get(indexOf); - } - } - - @Override - public void toggleChildVisibility(Object itemId) { - boolean removed = openItems.remove(itemId); - if (!removed) { - openItems.add(itemId); - getLogger().finest("Item " + itemId + " is now expanded"); - } else { - getLogger().finest("Item " + itemId + " is now collapsed"); - } - clearPreorderCache(); - } - - private void clearPreorderCache() { - preOrder = null; // clear preorder cache - } - - List<Object> preOrder; - - /** - * Preorder of ids currently visible - * - * @return - */ - private List<Object> getPreOrder() { - if (preOrder == null) { - preOrder = new ArrayList<Object>(); - Collection<?> rootItemIds = getContainerDataSource() - .rootItemIds(); - for (Object id : rootItemIds) { - preOrder.add(id); - addVisibleChildTree(id); - } - } - return preOrder; - } - - private void addVisibleChildTree(Object id) { - if (isNodeOpen(id)) { - Collection<?> children = getContainerDataSource().getChildren( - id); - if (children != null) { - for (Object childId : children) { - preOrder.add(childId); - addVisibleChildTree(childId); - } - } - } - - } - - @Override - public int indexOfId(Object id) { - return getPreOrder().indexOf(id); - } - - @Override - public Object getIdByIndex(int index) { - return getPreOrder().get(index); - } - - @Override - public void containerItemSetChange(ItemSetChangeEvent event) { - // preorder becomes invalid on sort, item additions etc. - clearPreorderCache(); - super.containerItemSetChange(event); - } - - } - - /** - * Creates an empty TreeTable with a default container. - */ - public TreeTable() { - super(null, new HierarchicalContainer()); - } - - /** - * Creates an empty TreeTable with a default container. - * - * @param caption - * the caption for the TreeTable - */ - public TreeTable(String caption) { - this(); - setCaption(caption); - } - - /** - * Creates a TreeTable instance with given captions and data source. - * - * @param caption - * the caption for the component - * @param dataSource - * the dataSource that is used to list items in the component - */ - public TreeTable(String caption, Container dataSource) { - super(caption, dataSource); - } - - private ContainerStrategy cStrategy; - private Object focusedRowId = null; - private Object hierarchyColumnId; - - /** - * The item id that was expanded or collapsed during this request. Reset at - * the end of paint and only used for determining if a partial or full paint - * should be done. - * - * Can safely be reset to null whenever a change occurs that would prevent a - * partial update from rendering the correct result, e.g. rows added or - * removed during an expand operation. - */ - private Object toggledItemId; - private boolean animationsEnabled; - private boolean clearFocusedRowPending; - - /** - * If the container does not send item set change events, always do a full - * repaint instead of a partial update when expanding/collapsing nodes. - */ - private boolean containerSupportsPartialUpdates; - - private ContainerStrategy getContainerStrategy() { - if (cStrategy == null) { - if (getContainerDataSource() instanceof Collapsible) { - cStrategy = new CollapsibleStrategy(); - } else { - cStrategy = new HierarchicalStrategy(); - } - } - return cStrategy; - } - - @Override - protected void paintRowAttributes(PaintTarget target, Object itemId) - throws PaintException { - super.paintRowAttributes(target, itemId); - target.addAttribute("depth", getContainerStrategy().getDepth(itemId)); - if (getContainerDataSource().areChildrenAllowed(itemId)) { - target.addAttribute("ca", true); - target.addAttribute("open", - getContainerStrategy().isNodeOpen(itemId)); - } - } - - @Override - protected void paintRowIcon(PaintTarget target, Object[][] cells, - int indexInRowbuffer) throws PaintException { - // always paint if present (in parent only if row headers visible) - if (getRowHeaderMode() == ROW_HEADER_MODE_HIDDEN) { - Resource itemIcon = getItemIcon(cells[CELL_ITEMID][indexInRowbuffer]); - if (itemIcon != null) { - target.addAttribute("icon", itemIcon); - } - } else if (cells[CELL_ICON][indexInRowbuffer] != null) { - target.addAttribute("icon", - (Resource) cells[CELL_ICON][indexInRowbuffer]); - } - } - - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - super.changeVariables(source, variables); - - if (variables.containsKey("toggleCollapsed")) { - String object = (String) variables.get("toggleCollapsed"); - Object itemId = itemIdMapper.get(object); - toggledItemId = itemId; - toggleChildVisibility(itemId, false); - if (variables.containsKey("selectCollapsed")) { - // ensure collapsed is selected unless opened with selection - // head - if (isSelectable()) { - select(itemId); - } - } - } else if (variables.containsKey("focusParent")) { - String key = (String) variables.get("focusParent"); - Object refId = itemIdMapper.get(key); - Object itemId = getParent(refId); - focusParent(itemId); - } - } - - private void focusParent(Object itemId) { - boolean inView = false; - Object inPageId = getCurrentPageFirstItemId(); - for (int i = 0; inPageId != null && i < getPageLength(); i++) { - if (inPageId.equals(itemId)) { - inView = true; - break; - } - inPageId = nextItemId(inPageId); - i++; - } - if (!inView) { - setCurrentPageFirstItemId(itemId); - } - // Select the row if it is selectable. - if (isSelectable()) { - if (isMultiSelect()) { - setValue(Collections.singleton(itemId)); - } else { - setValue(itemId); - } - } - setFocusedRow(itemId); - } - - private void setFocusedRow(Object itemId) { - focusedRowId = itemId; - if (focusedRowId == null) { - // Must still inform the client that the focusParent request has - // been processed - clearFocusedRowPending = true; - } - requestRepaint(); - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - if (focusedRowId != null) { - target.addAttribute("focusedRow", itemIdMapper.key(focusedRowId)); - focusedRowId = null; - } else if (clearFocusedRowPending) { - // Must still inform the client that the focusParent request has - // been processed - target.addAttribute("clearFocusPending", true); - clearFocusedRowPending = false; - } - target.addAttribute("animate", animationsEnabled); - if (hierarchyColumnId != null) { - Object[] visibleColumns2 = getVisibleColumns(); - for (int i = 0; i < visibleColumns2.length; i++) { - Object object = visibleColumns2[i]; - if (hierarchyColumnId.equals(object)) { - target.addAttribute( - TreeTableConnector.ATTRIBUTE_HIERARCHY_COLUMN_INDEX, - i); - break; - } - } - } - super.paintContent(target); - toggledItemId = null; - } - - /* - * Override methods for partial row updates and additions when expanding / - * collapsing nodes. - */ - - @Override - protected boolean isPartialRowUpdate() { - return toggledItemId != null && containerSupportsPartialUpdates - && !isRowCacheInvalidated(); - } - - @Override - protected int getFirstAddedItemIndex() { - return indexOfId(toggledItemId) + 1; - } - - @Override - protected int getAddedRowCount() { - return countSubNodesRecursively(getContainerDataSource(), toggledItemId); - } - - private int countSubNodesRecursively(Hierarchical hc, Object itemId) { - int count = 0; - // we need the number of children for toggledItemId no matter if its - // collapsed or expanded. Other items' children are only counted if the - // item is expanded. - if (getContainerStrategy().isNodeOpen(itemId) - || itemId == toggledItemId) { - Collection<?> children = hc.getChildren(itemId); - if (children != null) { - count += children != null ? children.size() : 0; - for (Object id : children) { - count += countSubNodesRecursively(hc, id); - } - } - } - return count; - } - - @Override - protected int getFirstUpdatedItemIndex() { - return indexOfId(toggledItemId); - } - - @Override - protected int getUpdatedRowCount() { - return 1; - } - - @Override - protected boolean shouldHideAddedRows() { - return !getContainerStrategy().isNodeOpen(toggledItemId); - } - - private void toggleChildVisibility(Object itemId, boolean forceFullRefresh) { - getContainerStrategy().toggleChildVisibility(itemId); - // ensure that page still has first item in page, DON'T clear the - // caches. - setCurrentPageFirstItemIndex(getCurrentPageFirstItemIndex(), false); - - if (isCollapsed(itemId)) { - fireCollapseEvent(itemId); - } else { - fireExpandEvent(itemId); - } - - if (containerSupportsPartialUpdates && !forceFullRefresh) { - requestRepaint(); - } else { - // For containers that do not send item set change events, always do - // full repaint instead of partial row update. - refreshRowCache(); - } - } - - @Override - public int size() { - return getContainerStrategy().size(); - } - - @Override - public Hierarchical getContainerDataSource() { - return (Hierarchical) super.getContainerDataSource(); - } - - @Override - public void setContainerDataSource(Container newDataSource) { - cStrategy = null; - - // FIXME: This disables partial updates until TreeTable is fixed so it - // does not change component hierarchy during paint - containerSupportsPartialUpdates = (newDataSource instanceof ItemSetChangeNotifier) && false; - - if (!(newDataSource instanceof Hierarchical)) { - newDataSource = new ContainerHierarchicalWrapper(newDataSource); - } - - if (!(newDataSource instanceof Ordered)) { - newDataSource = new HierarchicalContainerOrderedWrapper( - (Hierarchical) newDataSource); - } - - super.setContainerDataSource(newDataSource); - } - - @Override - public void containerItemSetChange( - com.vaadin.data.Container.ItemSetChangeEvent event) { - // Can't do partial repaints if items are added or removed during the - // expand/collapse request - toggledItemId = null; - getContainerStrategy().containerItemSetChange(event); - super.containerItemSetChange(event); - } - - @Override - protected Object getIdByIndex(int index) { - return getContainerStrategy().getIdByIndex(index); - } - - @Override - protected int indexOfId(Object itemId) { - return getContainerStrategy().indexOfId(itemId); - } - - @Override - public Object nextItemId(Object itemId) { - return getContainerStrategy().nextItemId(itemId); - } - - @Override - public Object lastItemId() { - return getContainerStrategy().lastItemId(); - } - - @Override - public Object prevItemId(Object itemId) { - return getContainerStrategy().prevItemId(itemId); - } - - @Override - public boolean isLastId(Object itemId) { - return getContainerStrategy().isLastId(itemId); - } - - @Override - public Collection<?> getItemIds() { - return getContainerStrategy().getItemIds(); - } - - @Override - public boolean areChildrenAllowed(Object itemId) { - return getContainerDataSource().areChildrenAllowed(itemId); - } - - @Override - public Collection<?> getChildren(Object itemId) { - return getContainerDataSource().getChildren(itemId); - } - - @Override - public Object getParent(Object itemId) { - return getContainerDataSource().getParent(itemId); - } - - @Override - public boolean hasChildren(Object itemId) { - return getContainerDataSource().hasChildren(itemId); - } - - @Override - public boolean isRoot(Object itemId) { - return getContainerDataSource().isRoot(itemId); - } - - @Override - public Collection<?> rootItemIds() { - return getContainerDataSource().rootItemIds(); - } - - @Override - public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) - throws UnsupportedOperationException { - return getContainerDataSource().setChildrenAllowed(itemId, - areChildrenAllowed); - } - - @Override - public boolean setParent(Object itemId, Object newParentId) - throws UnsupportedOperationException { - return getContainerDataSource().setParent(itemId, newParentId); - } - - /** - * Sets the Item specified by given identifier as collapsed or expanded. If - * the Item is collapsed, its children are not displayed to the user. - * - * @param itemId - * the identifier of the Item - * @param collapsed - * true if the Item should be collapsed, false if expanded - */ - public void setCollapsed(Object itemId, boolean collapsed) { - if (isCollapsed(itemId) != collapsed) { - if (null == toggledItemId && !isRowCacheInvalidated() - && getVisibleItemIds().contains(itemId)) { - // optimization: partial refresh if only one item is - // collapsed/expanded - toggledItemId = itemId; - toggleChildVisibility(itemId, false); - } else { - // make sure a full refresh takes place - otherwise neither - // partial nor full repaint of table content is performed - toggledItemId = null; - toggleChildVisibility(itemId, true); - } - } - } - - /** - * Checks if Item with given identifier is collapsed in the UI. - * - * <p> - * - * @param itemId - * the identifier of the checked Item - * @return true if the Item with given id is collapsed - * @see Collapsible#isCollapsed(Object) - */ - public boolean isCollapsed(Object itemId) { - return !getContainerStrategy().isNodeOpen(itemId); - } - - /** - * Explicitly sets the column in which the TreeTable visualizes the - * hierarchy. If hierarchyColumnId is not set, the hierarchy is visualized - * in the first visible column. - * - * @param hierarchyColumnId - */ - public void setHierarchyColumn(Object hierarchyColumnId) { - this.hierarchyColumnId = hierarchyColumnId; - } - - /** - * @return the identifier of column into which the hierarchy will be - * visualized or null if the column is not explicitly defined. - */ - public Object getHierarchyColumnId() { - return hierarchyColumnId; - } - - /** - * Adds an expand listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(ExpandListener listener) { - addListener(ExpandEvent.class, listener, ExpandListener.EXPAND_METHOD); - } - - /** - * Removes an expand listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(ExpandListener listener) { - removeListener(ExpandEvent.class, listener, - ExpandListener.EXPAND_METHOD); - } - - /** - * Emits an expand event. - * - * @param itemId - * the item id. - */ - protected void fireExpandEvent(Object itemId) { - fireEvent(new ExpandEvent(this, itemId)); - } - - /** - * Adds a collapse listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(CollapseListener listener) { - addListener(CollapseEvent.class, listener, - CollapseListener.COLLAPSE_METHOD); - } - - /** - * Removes a collapse listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(CollapseListener listener) { - removeListener(CollapseEvent.class, listener, - CollapseListener.COLLAPSE_METHOD); - } - - /** - * Emits a collapse event. - * - * @param itemId - * the item id. - */ - protected void fireCollapseEvent(Object itemId) { - fireEvent(new CollapseEvent(this, itemId)); - } - - /** - * @return true if animations are enabled - */ - public boolean isAnimationsEnabled() { - return animationsEnabled; - } - - /** - * Animations can be enabled by passing true to this method. Currently - * expanding rows slide in from the top and collapsing rows slide out the - * same way. NOTE! not supported in Internet Explorer 6 or 7. - * - * @param animationsEnabled - * true or false whether to enable animations or not. - */ - public void setAnimationsEnabled(boolean animationsEnabled) { - this.animationsEnabled = animationsEnabled; - requestRepaint(); - } - - private static final Logger getLogger() { - return Logger.getLogger(TreeTable.class.getName()); - } - -} diff --git a/src/com/vaadin/ui/TwinColSelect.java b/src/com/vaadin/ui/TwinColSelect.java deleted file mode 100644 index 5539236f77..0000000000 --- a/src/com/vaadin/ui/TwinColSelect.java +++ /dev/null @@ -1,180 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.util.Collection; - -import com.vaadin.data.Container; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.gwt.client.ui.twincolselect.VTwinColSelect; - -/** - * Multiselect component with two lists: left side for available items and right - * side for selected items. - */ -@SuppressWarnings("serial") -public class TwinColSelect extends AbstractSelect { - - private int columns = 0; - private int rows = 0; - - private String leftColumnCaption; - private String rightColumnCaption; - - /** - * - */ - public TwinColSelect() { - super(); - setMultiSelect(true); - } - - /** - * @param caption - */ - public TwinColSelect(String caption) { - super(caption); - setMultiSelect(true); - } - - /** - * @param caption - * @param dataSource - */ - public TwinColSelect(String caption, Container dataSource) { - super(caption, dataSource); - setMultiSelect(true); - } - - /** - * Sets the number of columns in the editor. If the number of columns is set - * 0, the actual number of displayed columns is determined implicitly by the - * adapter. - * <p> - * The number of columns overrides the value set by setWidth. Only if - * columns are set to 0 (default) the width set using - * {@link #setWidth(float, int)} or {@link #setWidth(String)} is used. - * - * @param columns - * the number of columns to set. - */ - public void setColumns(int columns) { - if (columns < 0) { - columns = 0; - } - if (this.columns != columns) { - this.columns = columns; - requestRepaint(); - } - } - - public int getColumns() { - return columns; - } - - public int getRows() { - return rows; - } - - /** - * Sets the number of rows in the editor. If the number of rows is set to 0, - * the actual number of displayed rows is determined implicitly by the - * adapter. - * <p> - * If a height if set (using {@link #setHeight(String)} or - * {@link #setHeight(float, int)}) it overrides the number of rows. Leave - * the height undefined to use this method. This is the opposite of how - * {@link #setColumns(int)} work. - * - * - * @param rows - * the number of rows to set. - */ - public void setRows(int rows) { - if (rows < 0) { - rows = 0; - } - if (this.rows != rows) { - this.rows = rows; - requestRepaint(); - } - } - - /** - * @param caption - * @param options - */ - public TwinColSelect(String caption, Collection<?> options) { - super(caption, options); - setMultiSelect(true); - } - - @Override - public void paintContent(PaintTarget target) throws PaintException { - target.addAttribute("type", "twincol"); - // Adds the number of columns - if (columns != 0) { - target.addAttribute("cols", columns); - } - // Adds the number of rows - if (rows != 0) { - target.addAttribute("rows", rows); - } - - // Right and left column captions and/or icons (if set) - String lc = getLeftColumnCaption(); - String rc = getRightColumnCaption(); - if (lc != null) { - target.addAttribute(VTwinColSelect.ATTRIBUTE_LEFT_CAPTION, lc); - } - if (rc != null) { - target.addAttribute(VTwinColSelect.ATTRIBUTE_RIGHT_CAPTION, rc); - } - - super.paintContent(target); - } - - /** - * Sets the text shown above the right column. - * - * @param caption - * The text to show - */ - public void setRightColumnCaption(String rightColumnCaption) { - this.rightColumnCaption = rightColumnCaption; - requestRepaint(); - } - - /** - * Returns the text shown above the right column. - * - * @return The text shown or null if not set. - */ - public String getRightColumnCaption() { - return rightColumnCaption; - } - - /** - * Sets the text shown above the left column. - * - * @param caption - * The text to show - */ - public void setLeftColumnCaption(String leftColumnCaption) { - this.leftColumnCaption = leftColumnCaption; - requestRepaint(); - } - - /** - * Returns the text shown above the left column. - * - * @return The text shown or null if not set. - */ - public String getLeftColumnCaption() { - return leftColumnCaption; - } - -} diff --git a/src/com/vaadin/ui/UniqueSerializable.java b/src/com/vaadin/ui/UniqueSerializable.java deleted file mode 100644 index 828b285538..0000000000 --- a/src/com/vaadin/ui/UniqueSerializable.java +++ /dev/null @@ -1,30 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -import java.io.Serializable; - -/** - * A base class for generating an unique object that is serializable. - * <p> - * This class is abstract but has no abstract methods to force users to create - * an anonymous inner class. Otherwise each instance will not be unique. - * - * @author Vaadin Ltd - * @version @VERSION@ - * @since 7.0 - * - */ -public abstract class UniqueSerializable implements Serializable { - - @Override - public int hashCode() { - return getClass().hashCode(); - } - - @Override - public boolean equals(Object obj) { - return getClass() == obj.getClass(); - } -} diff --git a/src/com/vaadin/ui/Upload.java b/src/com/vaadin/ui/Upload.java deleted file mode 100644 index 9d533b67f6..0000000000 --- a/src/com/vaadin/ui/Upload.java +++ /dev/null @@ -1,1055 +0,0 @@ -/* - * @VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.OutputStream; -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.Map; - -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.StreamVariable.StreamingProgressEvent; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.gwt.server.NoInputStreamException; -import com.vaadin.terminal.gwt.server.NoOutputStreamException; - -/** - * Component for uploading files from client to server. - * - * <p> - * The visible component consists of a file name input box and a browse button - * and an upload submit button to start uploading. - * - * <p> - * The Upload component needs a java.io.OutputStream to write the uploaded data. - * You need to implement the Upload.Receiver interface and return the output - * stream in the receiveUpload() method. - * - * <p> - * You can get an event regarding starting (StartedEvent), progress - * (ProgressEvent), and finishing (FinishedEvent) of upload by implementing - * StartedListener, ProgressListener, and FinishedListener, respectively. The - * FinishedListener is called for both failed and succeeded uploads. If you wish - * to separate between these two cases, you can use SucceededListener - * (SucceededEvenet) and FailedListener (FailedEvent). - * - * <p> - * The upload component does not itself show upload progress, but you can use - * the ProgressIndicator for providing progress feedback by implementing - * ProgressListener and updating the indicator in updateProgress(). - * - * <p> - * Setting upload component immediate initiates the upload as soon as a file is - * selected, instead of the common pattern of file selection field and upload - * button. - * - * <p> - * Note! Because of browser dependent implementations of <input type="file"> - * element, setting size for Upload component is not supported. For some - * browsers setting size may work to some extend. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public class Upload extends AbstractComponent implements Component.Focusable, - Vaadin6Component { - - /** - * Should the field be focused on next repaint? - */ - private final boolean focus = false; - - /** - * The tab order number of this field. - */ - private int tabIndex = 0; - - /** - * The output of the upload is redirected to this receiver. - */ - private Receiver receiver; - - private boolean isUploading; - - private long contentLength = -1; - - private int totalBytes; - - private String buttonCaption = "Upload"; - - /** - * ProgressListeners to which information about progress is sent during - * upload - */ - private LinkedHashSet<ProgressListener> progressListeners; - - private boolean interrupted = false; - - private boolean notStarted; - - private int nextid; - - /** - * Flag to indicate that submitting file has been requested. - */ - private boolean forceSubmit; - - /** - * Creates a new instance of Upload. - * - * The receiver must be set before performing an upload. - */ - public Upload() { - } - - public Upload(String caption, Receiver uploadReceiver) { - setCaption(caption); - receiver = uploadReceiver; - } - - /** - * Invoked when the value of a variable has changed. - * - * @see com.vaadin.ui.AbstractComponent#changeVariables(java.lang.Object, - * java.util.Map) - */ - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - if (variables.containsKey("pollForStart")) { - int id = (Integer) variables.get("pollForStart"); - if (!isUploading && id == nextid) { - notStarted = true; - requestRepaint(); - } else { - } - } - } - - /** - * Paints the content of this component. - * - * @param target - * Target to paint the content on. - * @throws PaintException - * if the paint operation failed. - */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - if (notStarted) { - target.addAttribute("notStarted", true); - notStarted = false; - return; - } - if (forceSubmit) { - target.addAttribute("forceSubmit", true); - forceSubmit = true; - return; - } - // The field should be focused - if (focus) { - target.addAttribute("focus", true); - } - - // The tab ordering number - if (tabIndex >= 0) { - target.addAttribute("tabindex", tabIndex); - } - - target.addAttribute("state", isUploading); - - if (buttonCaption != null) { - target.addAttribute("buttoncaption", buttonCaption); - } - - target.addAttribute("nextid", nextid); - - // Post file to this strean variable - target.addVariable(this, "action", getStreamVariable()); - - } - - /** - * Interface that must be implemented by the upload receivers to provide the - * Upload component an output stream to write the uploaded data. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface Receiver extends Serializable { - - /** - * Invoked when a new upload arrives. - * - * @param filename - * the desired filename of the upload, usually as specified - * by the client. - * @param mimeType - * the MIME type of the uploaded file. - * @return Stream to which the uploaded file should be written. - */ - public OutputStream receiveUpload(String filename, String mimeType); - - } - - /* Upload events */ - - private static final Method UPLOAD_FINISHED_METHOD; - - private static final Method UPLOAD_FAILED_METHOD; - - private static final Method UPLOAD_SUCCEEDED_METHOD; - - private static final Method UPLOAD_STARTED_METHOD; - - static { - try { - UPLOAD_FINISHED_METHOD = FinishedListener.class.getDeclaredMethod( - "uploadFinished", new Class[] { FinishedEvent.class }); - UPLOAD_FAILED_METHOD = FailedListener.class.getDeclaredMethod( - "uploadFailed", new Class[] { FailedEvent.class }); - UPLOAD_STARTED_METHOD = StartedListener.class.getDeclaredMethod( - "uploadStarted", new Class[] { StartedEvent.class }); - UPLOAD_SUCCEEDED_METHOD = SucceededListener.class - .getDeclaredMethod("uploadSucceeded", - new Class[] { SucceededEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException( - "Internal error finding methods in Upload"); - } - } - - /** - * Upload.FinishedEvent is sent when the upload receives a file, regardless - * of whether the reception was successful or failed. If you wish to - * distinguish between the two cases, use either SucceededEvent or - * FailedEvent, which are both subclasses of the FinishedEvent. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public static class FinishedEvent extends Component.Event { - - /** - * Length of the received file. - */ - private final long length; - - /** - * MIME type of the received file. - */ - private final String type; - - /** - * Received file name. - */ - private final String filename; - - /** - * - * @param source - * the source of the file. - * @param filename - * the received file name. - * @param MIMEType - * the MIME type of the received file. - * @param length - * the length of the received file. - */ - public FinishedEvent(Upload source, String filename, String MIMEType, - long length) { - super(source); - type = MIMEType; - this.filename = filename; - this.length = length; - } - - /** - * Uploads where the event occurred. - * - * @return the Source of the event. - */ - public Upload getUpload() { - return (Upload) getSource(); - } - - /** - * Gets the file name. - * - * @return the filename. - */ - public String getFilename() { - return filename; - } - - /** - * Gets the MIME Type of the file. - * - * @return the MIME type. - */ - public String getMIMEType() { - return type; - } - - /** - * Gets the length of the file. - * - * @return the length. - */ - public long getLength() { - return length; - } - - } - - /** - * Upload.FailedEvent event is sent when the upload is received, but the - * reception is interrupted for some reason. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public static class FailedEvent extends FinishedEvent { - - private Exception reason = null; - - /** - * - * @param source - * @param filename - * @param MIMEType - * @param length - * @param exception - */ - public FailedEvent(Upload source, String filename, String MIMEType, - long length, Exception reason) { - this(source, filename, MIMEType, length); - this.reason = reason; - } - - /** - * - * @param source - * @param filename - * @param MIMEType - * @param length - * @param exception - */ - public FailedEvent(Upload source, String filename, String MIMEType, - long length) { - super(source, filename, MIMEType, length); - } - - /** - * Gets the exception that caused the failure. - * - * @return the exception that caused the failure, null if n/a - */ - public Exception getReason() { - return reason; - } - - } - - /** - * FailedEvent that indicates that an output stream could not be obtained. - */ - public static class NoOutputStreamEvent extends FailedEvent { - - /** - * - * @param source - * @param filename - * @param MIMEType - * @param length - */ - public NoOutputStreamEvent(Upload source, String filename, - String MIMEType, long length) { - super(source, filename, MIMEType, length); - } - } - - /** - * FailedEvent that indicates that an input stream could not be obtained. - */ - public static class NoInputStreamEvent extends FailedEvent { - - /** - * - * @param source - * @param filename - * @param MIMEType - * @param length - */ - public NoInputStreamEvent(Upload source, String filename, - String MIMEType, long length) { - super(source, filename, MIMEType, length); - } - - } - - /** - * Upload.SucceededEvent event is sent when the upload is received - * successfully. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public static class SucceededEvent extends FinishedEvent { - - /** - * - * @param source - * @param filename - * @param MIMEType - * @param length - */ - public SucceededEvent(Upload source, String filename, String MIMEType, - long length) { - super(source, filename, MIMEType, length); - } - - } - - /** - * Upload.StartedEvent event is sent when the upload is started to received. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 5.0 - */ - public static class StartedEvent extends Component.Event { - - private final String filename; - private final String type; - /** - * Length of the received file. - */ - private final long length; - - /** - * - * @param source - * @param filename - * @param MIMEType - * @param length - */ - public StartedEvent(Upload source, String filename, String MIMEType, - long contentLength) { - super(source); - this.filename = filename; - type = MIMEType; - length = contentLength; - } - - /** - * Uploads where the event occurred. - * - * @return the Source of the event. - */ - public Upload getUpload() { - return (Upload) getSource(); - } - - /** - * Gets the file name. - * - * @return the filename. - */ - public String getFilename() { - return filename; - } - - /** - * Gets the MIME Type of the file. - * - * @return the MIME type. - */ - public String getMIMEType() { - return type; - } - - /** - * @return the length of the file that is being uploaded - */ - public long getContentLength() { - return length; - } - - } - - /** - * Receives the events when the upload starts. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 5.0 - */ - public interface StartedListener extends Serializable { - - /** - * Upload has started. - * - * @param event - * the Upload started event. - */ - public void uploadStarted(StartedEvent event); - } - - /** - * Receives the events when the uploads are ready. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface FinishedListener extends Serializable { - - /** - * Upload has finished. - * - * @param event - * the Upload finished event. - */ - public void uploadFinished(FinishedEvent event); - } - - /** - * Receives events when the uploads are finished, but unsuccessful. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface FailedListener extends Serializable { - - /** - * Upload has finished unsuccessfully. - * - * @param event - * the Upload failed event. - */ - public void uploadFailed(FailedEvent event); - } - - /** - * Receives events when the uploads are successfully finished. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ - public interface SucceededListener extends Serializable { - - /** - * Upload successfull.. - * - * @param event - * the Upload successfull event. - */ - public void uploadSucceeded(SucceededEvent event); - } - - /** - * Adds the upload started event listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(StartedListener listener) { - addListener(StartedEvent.class, listener, UPLOAD_STARTED_METHOD); - } - - /** - * Removes the upload started event listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(StartedListener listener) { - removeListener(StartedEvent.class, listener, UPLOAD_STARTED_METHOD); - } - - /** - * Adds the upload received event listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(FinishedListener listener) { - addListener(FinishedEvent.class, listener, UPLOAD_FINISHED_METHOD); - } - - /** - * Removes the upload received event listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(FinishedListener listener) { - removeListener(FinishedEvent.class, listener, UPLOAD_FINISHED_METHOD); - } - - /** - * Adds the upload interrupted event listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(FailedListener listener) { - addListener(FailedEvent.class, listener, UPLOAD_FAILED_METHOD); - } - - /** - * Removes the upload interrupted event listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(FailedListener listener) { - removeListener(FailedEvent.class, listener, UPLOAD_FAILED_METHOD); - } - - /** - * Adds the upload success event listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(SucceededListener listener) { - addListener(SucceededEvent.class, listener, UPLOAD_SUCCEEDED_METHOD); - } - - /** - * Removes the upload success event listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(SucceededListener listener) { - removeListener(SucceededEvent.class, listener, UPLOAD_SUCCEEDED_METHOD); - } - - /** - * Adds the upload success event listener. - * - * @param listener - * the Listener to be added. - */ - public void addListener(ProgressListener listener) { - if (progressListeners == null) { - progressListeners = new LinkedHashSet<ProgressListener>(); - } - progressListeners.add(listener); - } - - /** - * Removes the upload success event listener. - * - * @param listener - * the Listener to be removed. - */ - public void removeListener(ProgressListener listener) { - if (progressListeners != null) { - progressListeners.remove(listener); - } - } - - /** - * Emit upload received event. - * - * @param filename - * @param MIMEType - * @param length - */ - protected void fireStarted(String filename, String MIMEType) { - fireEvent(new Upload.StartedEvent(this, filename, MIMEType, - contentLength)); - } - - /** - * Emits the upload failed event. - * - * @param filename - * @param MIMEType - * @param length - */ - protected void fireUploadInterrupted(String filename, String MIMEType, - long length) { - fireEvent(new Upload.FailedEvent(this, filename, MIMEType, length)); - } - - protected void fireNoInputStream(String filename, String MIMEType, - long length) { - fireEvent(new Upload.NoInputStreamEvent(this, filename, MIMEType, - length)); - } - - protected void fireNoOutputStream(String filename, String MIMEType, - long length) { - fireEvent(new Upload.NoOutputStreamEvent(this, filename, MIMEType, - length)); - } - - protected void fireUploadInterrupted(String filename, String MIMEType, - long length, Exception e) { - fireEvent(new Upload.FailedEvent(this, filename, MIMEType, length, e)); - } - - /** - * Emits the upload success event. - * - * @param filename - * @param MIMEType - * @param length - * - */ - protected void fireUploadSuccess(String filename, String MIMEType, - long length) { - fireEvent(new Upload.SucceededEvent(this, filename, MIMEType, length)); - } - - /** - * Emits the progress event. - * - * @param totalBytes - * bytes received so far - * @param contentLength - * actual size of the file being uploaded, if known - * - */ - protected void fireUpdateProgress(long totalBytes, long contentLength) { - // this is implemented differently than other listeners to maintain - // backwards compatibility - if (progressListeners != null) { - for (Iterator<ProgressListener> it = progressListeners.iterator(); it - .hasNext();) { - ProgressListener l = it.next(); - l.updateProgress(totalBytes, contentLength); - } - } - } - - /** - * Returns the current receiver. - * - * @return the StreamVariable. - */ - public Receiver getReceiver() { - return receiver; - } - - /** - * Sets the receiver. - * - * @param receiver - * the receiver to set. - */ - public void setReceiver(Receiver receiver) { - this.receiver = receiver; - } - - /** - * {@inheritDoc} - */ - @Override - public void focus() { - super.focus(); - } - - /** - * Gets the Tabulator index of this Focusable component. - * - * @see com.vaadin.ui.Component.Focusable#getTabIndex() - */ - @Override - public int getTabIndex() { - return tabIndex; - } - - /** - * Sets the Tabulator index of this Focusable component. - * - * @see com.vaadin.ui.Component.Focusable#setTabIndex(int) - */ - @Override - public void setTabIndex(int tabIndex) { - this.tabIndex = tabIndex; - } - - /** - * Go into upload state. This is to prevent double uploading on same - * component. - * - * Warning: this is an internal method used by the framework and should not - * be used by user of the Upload component. Using it results in the Upload - * component going in wrong state and not working. It is currently public - * because it is used by another class. - */ - public void startUpload() { - if (isUploading) { - throw new IllegalStateException("uploading already started"); - } - isUploading = true; - nextid++; - } - - /** - * Interrupts the upload currently being received. The interruption will be - * done by the receiving tread so this method will return immediately and - * the actual interrupt will happen a bit later. - */ - public void interruptUpload() { - if (isUploading) { - interrupted = true; - } - } - - /** - * Go into state where new uploading can begin. - * - * Warning: this is an internal method used by the framework and should not - * be used by user of the Upload component. - */ - private void endUpload() { - isUploading = false; - contentLength = -1; - interrupted = false; - requestRepaint(); - } - - public boolean isUploading() { - return isUploading; - } - - /** - * Gets read bytes of the file currently being uploaded. - * - * @return bytes - */ - public long getBytesRead() { - return totalBytes; - } - - /** - * Returns size of file currently being uploaded. Value sane only during - * upload. - * - * @return size in bytes - */ - public long getUploadSize() { - return contentLength; - } - - /** - * This method is deprecated, use addListener(ProgressListener) instead. - * - * @deprecated Use addListener(ProgressListener) instead. - * @param progressListener - */ - @Deprecated - public void setProgressListener(ProgressListener progressListener) { - addListener(progressListener); - } - - /** - * This method is deprecated. - * - * @deprecated Replaced with addListener/removeListener - * @return listener - * - */ - @Deprecated - public ProgressListener getProgressListener() { - if (progressListeners == null || progressListeners.isEmpty()) { - return null; - } else { - return progressListeners.iterator().next(); - } - } - - /** - * ProgressListener receives events to track progress of upload. - */ - public interface ProgressListener extends Serializable { - /** - * Updates progress to listener - * - * @param readBytes - * bytes transferred - * @param contentLength - * total size of file currently being uploaded, -1 if unknown - */ - public void updateProgress(long readBytes, long contentLength); - } - - /** - * @return String to be rendered into button that fires uploading - */ - public String getButtonCaption() { - return buttonCaption; - } - - /** - * In addition to the actual file chooser, upload components have button - * that starts actual upload progress. This method is used to set text in - * that button. - * <p> - * In case the button text is set to null, the button is hidden. In this - * case developer must explicitly initiate the upload process with - * {@link #submitUpload()}. - * <p> - * In case the Upload is used in immediate mode using - * {@link #setImmediate(boolean)}, the file choose (html input with type - * "file") is hidden and only the button with this text is shown. - * <p> - * - * <p> - * <strong>Note</strong> the string given is set as is to the button. HTML - * formatting is not stripped. Be sure to properly validate your value - * according to your needs. - * - * @param buttonCaption - * text for upload components button. - */ - public void setButtonCaption(String buttonCaption) { - this.buttonCaption = buttonCaption; - requestRepaint(); - } - - /** - * Forces the upload the send selected file to the server. - * <p> - * In case developer wants to use this feature, he/she will most probably - * want to hide the uploads internal submit button by setting its caption to - * null with {@link #setButtonCaption(String)} method. - * <p> - * Note, that the upload runs asynchronous. Developer should use normal - * upload listeners to trac the process of upload. If the field is empty - * uploaded the file name will be empty string and file length 0 in the - * upload finished event. - * <p> - * Also note, that the developer should not remove or modify the upload in - * the same user transaction where the upload submit is requested. The - * upload may safely be hidden or removed once the upload started event is - * fired. - */ - public void submitUpload() { - requestRepaint(); - forceSubmit = true; - } - - @Override - public void requestRepaint() { - forceSubmit = false; - super.requestRepaint(); - } - - /* - * Handle to terminal via Upload monitors and controls the upload during it - * is being streamed. - */ - private com.vaadin.terminal.StreamVariable streamVariable; - - protected com.vaadin.terminal.StreamVariable getStreamVariable() { - if (streamVariable == null) { - streamVariable = new com.vaadin.terminal.StreamVariable() { - private StreamingStartEvent lastStartedEvent; - - @Override - public boolean listenProgress() { - return (progressListeners != null && !progressListeners - .isEmpty()); - } - - @Override - public void onProgress(StreamingProgressEvent event) { - fireUpdateProgress(event.getBytesReceived(), - event.getContentLength()); - } - - @Override - public boolean isInterrupted() { - return interrupted; - } - - @Override - public OutputStream getOutputStream() { - OutputStream receiveUpload = receiver.receiveUpload( - lastStartedEvent.getFileName(), - lastStartedEvent.getMimeType()); - lastStartedEvent = null; - return receiveUpload; - } - - @Override - public void streamingStarted(StreamingStartEvent event) { - startUpload(); - contentLength = event.getContentLength(); - fireStarted(event.getFileName(), event.getMimeType()); - lastStartedEvent = event; - } - - @Override - public void streamingFinished(StreamingEndEvent event) { - fireUploadSuccess(event.getFileName(), event.getMimeType(), - event.getContentLength()); - endUpload(); - requestRepaint(); - } - - @Override - public void streamingFailed(StreamingErrorEvent event) { - Exception exception = event.getException(); - if (exception instanceof NoInputStreamException) { - fireNoInputStream(event.getFileName(), - event.getMimeType(), 0); - } else if (exception instanceof NoOutputStreamException) { - fireNoOutputStream(event.getFileName(), - event.getMimeType(), 0); - } else { - fireUploadInterrupted(event.getFileName(), - event.getMimeType(), 0, exception); - } - endUpload(); - } - }; - } - return streamVariable; - } - - @Override - public java.util.Collection<?> getListeners(java.lang.Class<?> eventType) { - if (StreamingProgressEvent.class.isAssignableFrom(eventType)) { - if (progressListeners == null) { - return Collections.EMPTY_LIST; - } else { - return Collections.unmodifiableCollection(progressListeners); - } - - } - return super.getListeners(eventType); - }; -} diff --git a/src/com/vaadin/ui/VerticalLayout.java b/src/com/vaadin/ui/VerticalLayout.java deleted file mode 100644 index a04d052d98..0000000000 --- a/src/com/vaadin/ui/VerticalLayout.java +++ /dev/null @@ -1,25 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -/** - * Vertical layout - * - * <code>VerticalLayout</code> is a component container, which shows the - * subcomponents in the order of their addition (vertically). A vertical layout - * is by default 100% wide. - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 5.3 - */ -@SuppressWarnings("serial") -public class VerticalLayout extends AbstractOrderedLayout { - - public VerticalLayout() { - setWidth("100%"); - } - -} diff --git a/src/com/vaadin/ui/VerticalSplitPanel.java b/src/com/vaadin/ui/VerticalSplitPanel.java deleted file mode 100644 index 0630240e9c..0000000000 --- a/src/com/vaadin/ui/VerticalSplitPanel.java +++ /dev/null @@ -1,30 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui; - -/** - * A vertical split panel contains two components and lays them vertically. The - * first component is above the second component. - * - * <pre> - * +--------------------------+ - * | | - * | The first component | - * | | - * +==========================+ <-- splitter - * | | - * | The second component | - * | | - * +--------------------------+ - * </pre> - * - */ -public class VerticalSplitPanel extends AbstractSplitPanel { - - public VerticalSplitPanel() { - super(); - setSizeFull(); - } - -} diff --git a/src/com/vaadin/ui/Video.java b/src/com/vaadin/ui/Video.java deleted file mode 100644 index d4f95a5be3..0000000000 --- a/src/com/vaadin/ui/Video.java +++ /dev/null @@ -1,81 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import com.vaadin.shared.ui.video.VideoState; -import com.vaadin.terminal.Resource; -import com.vaadin.terminal.gwt.server.ResourceReference; - -/** - * The Video component translates into an HTML5 <video> element and as - * such is only supported in browsers that support HTML5 media markup. Browsers - * that do not support HTML5 display the text or HTML set by calling - * {@link #setAltText(String)}. - * - * A flash-player fallback can be implemented by setting HTML content allowed ( - * {@link #setHtmlContentAllowed(boolean)} and calling - * {@link #setAltText(String)} with the flash player markup. An example of flash - * fallback can be found at the <a href= - * "https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox#Using_Flash" - * >Mozilla Developer Network</a>. - * - * Multiple sources can be specified. Which of the sources is used is selected - * by the browser depending on which file formats it supports. See <a - * href="http://en.wikipedia.org/wiki/HTML5_video#Table">wikipedia</a> for a - * table of formats supported by different browsers. - * - * @author Vaadin Ltd - * @since 6.7.0 - */ -public class Video extends AbstractMedia { - - @Override - public VideoState getState() { - return (VideoState) super.getState(); - } - - public Video() { - this("", null); - } - - /** - * @param caption - * The caption for this video. - */ - public Video(String caption) { - this(caption, null); - } - - /** - * @param caption - * The caption for this video. - * @param source - * The Resource containing the video to play. - */ - public Video(String caption, Resource source) { - setCaption(caption); - setSource(source); - setShowControls(true); - } - - /** - * Sets the poster image, which is shown in place of the video before the - * user presses play. - * - * @param poster - */ - public void setPoster(Resource poster) { - getState().setPoster(ResourceReference.create(poster)); - requestRepaint(); - } - - /** - * @return The poster image. - */ - public Resource getPoster() { - return ResourceReference.getResource(getState().getPoster()); - } - -} diff --git a/src/com/vaadin/ui/Window.java b/src/com/vaadin/ui/Window.java deleted file mode 100644 index e413d35e6d..0000000000 --- a/src/com/vaadin/ui/Window.java +++ /dev/null @@ -1,853 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.ui; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.Map; - -import com.vaadin.event.FieldEvents.BlurEvent; -import com.vaadin.event.FieldEvents.BlurListener; -import com.vaadin.event.FieldEvents.BlurNotifier; -import com.vaadin.event.FieldEvents.FocusEvent; -import com.vaadin.event.FieldEvents.FocusListener; -import com.vaadin.event.FieldEvents.FocusNotifier; -import com.vaadin.event.MouseEvents.ClickEvent; -import com.vaadin.event.ShortcutAction; -import com.vaadin.event.ShortcutAction.KeyCode; -import com.vaadin.event.ShortcutAction.ModifierKey; -import com.vaadin.event.ShortcutListener; -import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.window.WindowServerRpc; -import com.vaadin.shared.ui.window.WindowState; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.PaintTarget; -import com.vaadin.terminal.Vaadin6Component; -import com.vaadin.terminal.gwt.client.ui.root.VRoot; - -/** - * A component that represents a floating popup window that can be added to a - * {@link Root}. A window is added to a {@code Root} using - * {@link Root#addWindow(Window)}. </p> - * <p> - * The contents of a window is set using {@link #setContent(ComponentContainer)} - * or by using the {@link #Window(String, ComponentContainer)} constructor. The - * contents can in turn contain other components. By default, a - * {@link VerticalLayout} is used as content. - * </p> - * <p> - * A window can be positioned on the screen using absolute coordinates (pixels) - * or set to be centered using {@link #center()} - * </p> - * <p> - * The caption is displayed in the window header. - * </p> - * <p> - * In Vaadin versions prior to 7.0.0, Window was also used as application level - * windows. This function is now covered by the {@link Root} class. - * </p> - * - * @author Vaadin Ltd. - * @version - * @VERSION@ - * @since 3.0 - */ -@SuppressWarnings("serial") -public class Window extends Panel implements FocusNotifier, BlurNotifier, - Vaadin6Component { - - private WindowServerRpc rpc = new WindowServerRpc() { - - @Override - public void click(MouseEventDetails mouseDetails) { - fireEvent(new ClickEvent(Window.this, mouseDetails)); - } - }; - - private int browserWindowWidth = -1; - - private int browserWindowHeight = -1; - - /** - * Creates a new unnamed window with a default layout. - */ - public Window() { - this("", null); - } - - /** - * Creates a new unnamed window with a default layout and given title. - * - * @param caption - * the title of the window. - */ - public Window(String caption) { - this(caption, null); - } - - /** - * Creates a new unnamed window with the given content and title. - * - * @param caption - * the title of the window. - * @param content - * the contents of the window - */ - public Window(String caption, ComponentContainer content) { - super(caption, content); - registerRpc(rpc); - setSizeUndefined(); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Panel#addComponent(com.vaadin.ui.Component) - */ - - @Override - public void addComponent(Component c) { - if (c instanceof Window) { - throw new IllegalArgumentException( - "Window cannot be added to another via addComponent. " - + "Use addWindow(Window) instead."); - } - super.addComponent(c); - } - - /* ********************************************************************* */ - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Panel#paintContent(com.vaadin.terminal.PaintTarget) - */ - - @Override - public synchronized void paintContent(PaintTarget target) - throws PaintException { - if (bringToFront != null) { - target.addAttribute("bringToFront", bringToFront.intValue()); - bringToFront = null; - } - - // Contents of the window panel is painted - super.paintContent(target); - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Panel#changeVariables(java.lang.Object, java.util.Map) - */ - - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - - // TODO Are these for top level windows or sub windows? - boolean sizeHasChanged = false; - // size is handled in super class, but resize events only in windows -> - // so detect if size change occurs before super.changeVariables() - if (variables.containsKey("height") - && (getHeightUnits() != Unit.PIXELS || (Integer) variables - .get("height") != getHeight())) { - sizeHasChanged = true; - } - if (variables.containsKey("width") - && (getWidthUnits() != Unit.PIXELS || (Integer) variables - .get("width") != getWidth())) { - sizeHasChanged = true; - } - Integer browserHeightVar = (Integer) variables - .get(VRoot.BROWSER_HEIGHT_VAR); - if (browserHeightVar != null - && browserHeightVar.intValue() != browserWindowHeight) { - browserWindowHeight = browserHeightVar.intValue(); - sizeHasChanged = true; - } - Integer browserWidthVar = (Integer) variables - .get(VRoot.BROWSER_WIDTH_VAR); - if (browserWidthVar != null - && browserWidthVar.intValue() != browserWindowWidth) { - browserWindowWidth = browserWidthVar.intValue(); - sizeHasChanged = true; - } - - super.changeVariables(source, variables); - - // Positioning - final Integer positionx = (Integer) variables.get("positionx"); - if (positionx != null) { - final int x = positionx.intValue(); - // This is information from the client so it is already using the - // position. No need to repaint. - setPositionX(x < 0 ? -1 : x, false); - } - final Integer positiony = (Integer) variables.get("positiony"); - if (positiony != null) { - final int y = positiony.intValue(); - // This is information from the client so it is already using the - // position. No need to repaint. - setPositionY(y < 0 ? -1 : y, false); - } - - if (isClosable()) { - // Closing - final Boolean close = (Boolean) variables.get("close"); - if (close != null && close.booleanValue()) { - close(); - } - } - - // fire event if size has really changed - if (sizeHasChanged) { - fireResize(); - } - - if (variables.containsKey(FocusEvent.EVENT_ID)) { - fireEvent(new FocusEvent(this)); - } else if (variables.containsKey(BlurEvent.EVENT_ID)) { - fireEvent(new BlurEvent(this)); - } - - } - - /** - * Method that handles window closing (from UI). - * - * <p> - * By default, sub-windows are removed from their respective parent windows - * and thus visually closed on browser-side. Browser-level windows also - * closed on the client-side, but they are not implicitly removed from the - * application. - * </p> - * - * <p> - * To explicitly close a sub-window, use {@link #removeWindow(Window)}. To - * react to a window being closed (after it is closed), register a - * {@link CloseListener}. - * </p> - */ - public void close() { - Root root = getRoot(); - - // Don't do anything if not attached to a root - if (root != null) { - // focus is restored to the parent window - root.focus(); - // subwindow is removed from the root - root.removeWindow(this); - } - } - - /** - * Gets the distance of Window left border in pixels from left border of the - * containing (main window). - * - * @return the Distance of Window left border in pixels from left border of - * the containing (main window). or -1 if unspecified. - * @since 4.0.0 - */ - public int getPositionX() { - return getState().getPositionX(); - } - - /** - * Sets the distance of Window left border in pixels from left border of the - * containing (main window). - * - * @param positionX - * the Distance of Window left border in pixels from left border - * of the containing (main window). or -1 if unspecified. - * @since 4.0.0 - */ - public void setPositionX(int positionX) { - setPositionX(positionX, true); - } - - /** - * Sets the distance of Window left border in pixels from left border of the - * containing (main window). - * - * @param positionX - * the Distance of Window left border in pixels from left border - * of the containing (main window). or -1 if unspecified. - * @param repaintRequired - * true if the window needs to be repainted, false otherwise - * @since 6.3.4 - */ - private void setPositionX(int positionX, boolean repaintRequired) { - getState().setPositionX(positionX); - getState().setCentered(false); - if (repaintRequired) { - requestRepaint(); - } - } - - /** - * Gets the distance of Window top border in pixels from top border of the - * containing (main window). - * - * @return Distance of Window top border in pixels from top border of the - * containing (main window). or -1 if unspecified . - * - * @since 4.0.0 - */ - public int getPositionY() { - return getState().getPositionY(); - } - - /** - * Sets the distance of Window top border in pixels from top border of the - * containing (main window). - * - * @param positionY - * the Distance of Window top border in pixels from top border of - * the containing (main window). or -1 if unspecified - * - * @since 4.0.0 - */ - public void setPositionY(int positionY) { - setPositionY(positionY, true); - } - - /** - * Sets the distance of Window top border in pixels from top border of the - * containing (main window). - * - * @param positionY - * the Distance of Window top border in pixels from top border of - * the containing (main window). or -1 if unspecified - * @param repaintRequired - * true if the window needs to be repainted, false otherwise - * - * @since 6.3.4 - */ - private void setPositionY(int positionY, boolean repaintRequired) { - getState().setPositionY(positionY); - getState().setCentered(false); - if (repaintRequired) { - requestRepaint(); - } - } - - private static final Method WINDOW_CLOSE_METHOD; - static { - try { - WINDOW_CLOSE_METHOD = CloseListener.class.getDeclaredMethod( - "windowClose", new Class[] { CloseEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException( - "Internal error, window close method not found"); - } - } - - public class CloseEvent extends Component.Event { - - /** - * - * @param source - */ - public CloseEvent(Component source) { - super(source); - } - - /** - * Gets the Window. - * - * @return the window. - */ - public Window getWindow() { - return (Window) getSource(); - } - } - - /** - * An interface used for listening to Window close events. Add the - * CloseListener to a browser level window or a sub window and - * {@link CloseListener#windowClose(CloseEvent)} will be called whenever the - * user closes the window. - * - * <p> - * Since Vaadin 6.5, removing a window using {@link #removeWindow(Window)} - * fires the CloseListener. - * </p> - */ - public interface CloseListener extends Serializable { - /** - * Called when the user closes a window. Use - * {@link CloseEvent#getWindow()} to get a reference to the - * {@link Window} that was closed. - * - * @param e - * Event containing - */ - public void windowClose(CloseEvent e); - } - - /** - * Adds a CloseListener to the window. - * - * For a sub window the CloseListener is fired when the user closes it - * (clicks on the close button). - * - * For a browser level window the CloseListener is fired when the browser - * level window is closed. Note that closing a browser level window does not - * mean it will be destroyed. Also note that Opera does not send events like - * all other browsers and therefore the close listener might not be called - * if Opera is used. - * - * <p> - * Since Vaadin 6.5, removing windows using {@link #removeWindow(Window)} - * does fire the CloseListener. - * </p> - * - * @param listener - * the CloseListener to add. - */ - public void addListener(CloseListener listener) { - addListener(CloseEvent.class, listener, WINDOW_CLOSE_METHOD); - } - - /** - * Removes the CloseListener from the window. - * - * <p> - * For more information on CloseListeners see {@link CloseListener}. - * </p> - * - * @param listener - * the CloseListener to remove. - */ - public void removeListener(CloseListener listener) { - removeListener(CloseEvent.class, listener, WINDOW_CLOSE_METHOD); - } - - protected void fireClose() { - fireEvent(new Window.CloseEvent(this)); - } - - /** - * Method for the resize event. - */ - private static final Method WINDOW_RESIZE_METHOD; - static { - try { - WINDOW_RESIZE_METHOD = ResizeListener.class.getDeclaredMethod( - "windowResized", new Class[] { ResizeEvent.class }); - } catch (final java.lang.NoSuchMethodException e) { - // This should never happen - throw new java.lang.RuntimeException( - "Internal error, window resized method not found"); - } - } - - /** - * Resize events are fired whenever the client-side fires a resize-event - * (e.g. the browser window is resized). The frequency may vary across - * browsers. - */ - public class ResizeEvent extends Component.Event { - - /** - * - * @param source - */ - public ResizeEvent(Component source) { - super(source); - } - - /** - * Get the window form which this event originated - * - * @return the window - */ - public Window getWindow() { - return (Window) getSource(); - } - } - - /** - * Listener for window resize events. - * - * @see com.vaadin.ui.Window.ResizeEvent - */ - public interface ResizeListener extends Serializable { - public void windowResized(ResizeEvent e); - } - - /** - * Add a resize listener. - * - * @param listener - */ - public void addListener(ResizeListener listener) { - addListener(ResizeEvent.class, listener, WINDOW_RESIZE_METHOD); - } - - /** - * Remove a resize listener. - * - * @param listener - */ - public void removeListener(ResizeListener listener) { - removeListener(ResizeEvent.class, listener); - } - - /** - * Fire the resize event. - */ - protected void fireResize() { - fireEvent(new ResizeEvent(this)); - } - - /** - * Used to keep the right order of windows if multiple windows are brought - * to front in a single changeset. If this is not used, the order is quite - * random (depends on the order getting to dirty list. e.g. which window got - * variable changes). - */ - private Integer bringToFront = null; - - /** - * If there are currently several windows visible, calling this method makes - * this window topmost. - * <p> - * This method can only be called if this window connected a root. Else an - * illegal state exception is thrown. Also if there are modal windows and - * this window is not modal, and illegal state exception is thrown. - * <p> - */ - public void bringToFront() { - Root root = getRoot(); - if (root == null) { - throw new IllegalStateException( - "Window must be attached to parent before calling bringToFront method."); - } - int maxBringToFront = -1; - for (Window w : root.getWindows()) { - if (!isModal() && w.isModal()) { - throw new IllegalStateException( - "The root contains modal windows, non-modal window cannot be brought to front."); - } - if (w.bringToFront != null) { - maxBringToFront = Math.max(maxBringToFront, - w.bringToFront.intValue()); - } - } - bringToFront = Integer.valueOf(maxBringToFront + 1); - requestRepaint(); - } - - /** - * Sets sub-window modal, so that widgets behind it cannot be accessed. - * <b>Note:</b> affects sub-windows only. - * - * @param modal - * true if modality is to be turned on - */ - public void setModal(boolean modal) { - getState().setModal(modal); - center(); - requestRepaint(); - } - - /** - * @return true if this window is modal. - */ - public boolean isModal() { - return getState().isModal(); - } - - /** - * Sets sub-window resizable. <b>Note:</b> affects sub-windows only. - * - * @param resizable - * true if resizability is to be turned on - */ - public void setResizable(boolean resizable) { - getState().setResizable(resizable); - requestRepaint(); - } - - /** - * - * @return true if window is resizable by the end-user, otherwise false. - */ - public boolean isResizable() { - return getState().isResizable(); - } - - /** - * - * @return true if a delay is used before recalculating sizes, false if - * sizes are recalculated immediately. - */ - public boolean isResizeLazy() { - return getState().isResizeLazy(); - } - - /** - * Should resize operations be lazy, i.e. should there be a delay before - * layout sizes are recalculated. Speeds up resize operations in slow UIs - * with the penalty of slightly decreased usability. - * - * Note, some browser send false resize events for the browser window and - * are therefore always lazy. - * - * @param resizeLazy - * true to use a delay before recalculating sizes, false to - * calculate immediately. - */ - public void setResizeLazy(boolean resizeLazy) { - getState().setResizeLazy(resizeLazy); - requestRepaint(); - } - - /** - * Sets this window to be centered relative to its parent window. Affects - * sub-windows only. If the window is resized as a result of the size of its - * content changing, it will keep itself centered as long as its position is - * not explicitly changed programmatically or by the user. - * <p> - * <b>NOTE:</b> This method has several issues as currently implemented. - * Please refer to http://dev.vaadin.com/ticket/8971 for details. - */ - public void center() { - getState().setCentered(true); - requestRepaint(); - } - - /** - * Returns the closable status of the sub window. If a sub window is - * closable it typically shows an X in the upper right corner. Clicking on - * the X sends a close event to the server. Setting closable to false will - * remove the X from the sub window and prevent the user from closing the - * window. - * - * Note! For historical reasons readonly controls the closability of the sub - * window and therefore readonly and closable affect each other. Setting - * readonly to true will set closable to false and vice versa. - * <p/> - * Closable only applies to sub windows, not to browser level windows. - * - * @return true if the sub window can be closed by the user. - */ - public boolean isClosable() { - return !isReadOnly(); - } - - /** - * Sets the closable status for the sub window. If a sub window is closable - * it typically shows an X in the upper right corner. Clicking on the X - * sends a close event to the server. Setting closable to false will remove - * the X from the sub window and prevent the user from closing the window. - * - * Note! For historical reasons readonly controls the closability of the sub - * window and therefore readonly and closable affect each other. Setting - * readonly to true will set closable to false and vice versa. - * <p/> - * Closable only applies to sub windows, not to browser level windows. - * - * @param closable - * determines if the sub window can be closed by the user. - */ - public void setClosable(boolean closable) { - setReadOnly(!closable); - } - - /** - * Indicates whether a sub window can be dragged or not. By default a sub - * window is draggable. - * <p/> - * Draggable only applies to sub windows, not to browser level windows. - * - * @param draggable - * true if the sub window can be dragged by the user - */ - public boolean isDraggable() { - return getState().isDraggable(); - } - - /** - * Enables or disables that a sub window can be dragged (moved) by the user. - * By default a sub window is draggable. - * <p/> - * Draggable only applies to sub windows, not to browser level windows. - * - * @param draggable - * true if the sub window can be dragged by the user - */ - public void setDraggable(boolean draggable) { - getState().setDraggable(draggable); - requestRepaint(); - } - - /* - * Actions - */ - protected CloseShortcut closeShortcut; - - /** - * Makes is possible to close the window by pressing the given - * {@link KeyCode} and (optional) {@link ModifierKey}s.<br/> - * Note that this shortcut only reacts while the window has focus, closing - * itself - if you want to close a subwindow from a parent window, use - * {@link #addAction(com.vaadin.event.Action)} of the parent window instead. - * - * @param keyCode - * the keycode for invoking the shortcut - * @param modifiers - * the (optional) modifiers for invoking the shortcut, null for - * none - */ - public void setCloseShortcut(int keyCode, int... modifiers) { - if (closeShortcut != null) { - removeAction(closeShortcut); - } - closeShortcut = new CloseShortcut(this, keyCode, modifiers); - addAction(closeShortcut); - } - - /** - * Removes the keyboard shortcut previously set with - * {@link #setCloseShortcut(int, int...)}. - */ - public void removeCloseShortcut() { - if (closeShortcut != null) { - removeAction(closeShortcut); - closeShortcut = null; - } - } - - /** - * A {@link ShortcutListener} specifically made to define a keyboard - * shortcut that closes the window. - * - * <pre> - * <code> - * // within the window using helper - * subWindow.setCloseShortcut(KeyCode.ESCAPE, null); - * - * // or globally - * getWindow().addAction(new Window.CloseShortcut(subWindow, KeyCode.ESCAPE)); - * </code> - * </pre> - * - */ - public static class CloseShortcut extends ShortcutListener { - protected Window window; - - /** - * Creates a keyboard shortcut for closing the given window using the - * shorthand notation defined in {@link ShortcutAction}. - * - * @param window - * to be closed when the shortcut is invoked - * @param shorthandCaption - * the caption with shortcut keycode and modifiers indicated - */ - public CloseShortcut(Window window, String shorthandCaption) { - super(shorthandCaption); - this.window = window; - } - - /** - * Creates a keyboard shortcut for closing the given window using the - * given {@link KeyCode} and {@link ModifierKey}s. - * - * @param window - * to be closed when the shortcut is invoked - * @param keyCode - * KeyCode to react to - * @param modifiers - * optional modifiers for shortcut - */ - public CloseShortcut(Window window, int keyCode, int... modifiers) { - super(null, keyCode, modifiers); - this.window = window; - } - - /** - * Creates a keyboard shortcut for closing the given window using the - * given {@link KeyCode}. - * - * @param window - * to be closed when the shortcut is invoked - * @param keyCode - * KeyCode to react to - */ - public CloseShortcut(Window window, int keyCode) { - this(window, keyCode, null); - } - - @Override - public void handleAction(Object sender, Object target) { - window.close(); - } - } - - /** - * Note, that focus/blur listeners in Window class are only supported by sub - * windows. Also note that Window is not considered focused if its contained - * component currently has focus. - * - * @see com.vaadin.event.FieldEvents.FocusNotifier#addListener(com.vaadin.event.FieldEvents.FocusListener) - */ - - @Override - public void addListener(FocusListener listener) { - addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, - FocusListener.focusMethod); - } - - @Override - public void removeListener(FocusListener listener) { - removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); - } - - /** - * Note, that focus/blur listeners in Window class are only supported by sub - * windows. Also note that Window is not considered focused if its contained - * component currently has focus. - * - * @see com.vaadin.event.FieldEvents.BlurNotifier#addListener(com.vaadin.event.FieldEvents.BlurListener) - */ - - @Override - public void addListener(BlurListener listener) { - addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, - BlurListener.blurMethod); - } - - @Override - public void removeListener(BlurListener listener) { - removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); - } - - /** - * {@inheritDoc} - * - * If the window is a sub-window focusing will cause the sub-window to be - * brought on top of other sub-windows on gain keyboard focus. - */ - - @Override - public void focus() { - /* - * When focusing a sub-window it basically means it should be brought to - * the front. Instead of just moving the keyboard focus we focus the - * window and bring it top-most. - */ - super.focus(); - bringToFront(); - } - - @Override - public WindowState getState() { - return (WindowState) super.getState(); - } -} diff --git a/src/com/vaadin/ui/doc-files/component_class_hierarchy.gif b/src/com/vaadin/ui/doc-files/component_class_hierarchy.gif Binary files differdeleted file mode 100644 index 936c220d11..0000000000 --- a/src/com/vaadin/ui/doc-files/component_class_hierarchy.gif +++ /dev/null diff --git a/src/com/vaadin/ui/doc-files/component_interfaces.gif b/src/com/vaadin/ui/doc-files/component_interfaces.gif Binary files differdeleted file mode 100644 index 44c99826bb..0000000000 --- a/src/com/vaadin/ui/doc-files/component_interfaces.gif +++ /dev/null diff --git a/src/com/vaadin/ui/package.html b/src/com/vaadin/ui/package.html deleted file mode 100644 index 6b19a28fe7..0000000000 --- a/src/com/vaadin/ui/package.html +++ /dev/null @@ -1,76 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<html> -<head> - -</head> - -<body bgcolor="white"> - -<!-- Package summary here --> - -<p>Provides interfaces and classes in Vaadin.</p> - -<h2>Package Specification</h2> - -<p><strong>Interface hierarchy</strong></p> - -<p>The general interface hierarchy looks like this:</p> - -<p style="text-align: center;"><img - src="doc-files/component_interfaces.gif" /></p> - -<p><i>Note that the above picture includes only the main -interfaces. This package includes several other lesser sub-interfaces -which are not significant in this scope. The interfaces not appearing -here are documented with the classes that define them.</i></p> - -<p>The {@link com.vaadin.ui.Component} interface is the top-level -interface which must be implemented by all user interface components in -Vaadin. It defines the common properties of the components and how the -framework will handle them. Most simple components, such as {@link -com.vaadin.ui.Button}, for example, do not need to implement the -lower-level interfaces described below. Notice that also the classes and -interfaces required by the component event framework are defined in -{@link com.vaadin.ui.Component}.</p> - -<p>The next level in the component hierarchy are the classes -implementing the {@link com.vaadin.ui.ComponentContainer} interface. It -adds the capacity to contain other components to {@link -com.vaadin.ui.Component} with a simple API.</p> - -<p>The third and last level is the {@link com.vaadin.ui.Layout}, -which adds the concept of location to the components contained in a -{@link com.vaadin.ui.ComponentContainer}. It can be used to create -containers which contents can be positioned.</p> - -<p><strong>Component class hierarchy</strong></p> - -<p>The actual component classes form a hierarchy like this:</p> - -<center><img src="doc-files/component_class_hierarchy.gif" /></center> -<br /> - -<center><i>Underlined classes are abstract.</i></center> - -<p>At the top level is {@link com.vaadin.ui.AbstractComponent} which -implements the {@link com.vaadin.ui.Component} interface. As the name -suggests it is abstract, but it does include a default implementation -for all methods defined in <code>Component</code> so that a component is -free to override only those functionalities it needs.</p> - -<p>As seen in the picture, <code>AbstractComponent</code> serves as -the superclass for several "real" components, but it also has a some -abstract extensions. {@link com.vaadin.ui.AbstractComponentContainer} -serves as the root class for all components (for example, panels and -windows) who can contain other components. {@link -com.vaadin.ui.AbstractField}, on the other hand, implements several -interfaces to provide a base class for components that are used for data -display and manipulation.</p> - - -<!-- Package spec here --> - -<!-- Put @see and @since tags down here. --> - -</body> -</html> diff --git a/src/com/vaadin/ui/themes/BaseTheme.java b/src/com/vaadin/ui/themes/BaseTheme.java deleted file mode 100644 index 6f448746bf..0000000000 --- a/src/com/vaadin/ui/themes/BaseTheme.java +++ /dev/null @@ -1,59 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui.themes; - -/** - * <p> - * The Base theme is the foundation for all Vaadin themes. Although it is not - * necessary to use it as the starting point for all other themes, it is heavily - * encouraged, since it abstracts and hides away many necessary style properties - * that the Vaadin terminal expects and needs. - * </p> - * <p> - * When creating your own theme, either extend this class and specify the styles - * implemented in your theme here, or extend some other theme that has a class - * file specified (e.g. Reindeer or Runo). - * </p> - * <p> - * All theme class files should follow the convention of specifying the theme - * name as a string constant <code>THEME_NAME</code>. - * - * @since 6.3.0 - * - */ -public class BaseTheme { - - public static final String THEME_NAME = "base"; - - /** - * Creates a button that looks like a regular hypertext link but still acts - * like a normal button. - */ - public static final String BUTTON_LINK = "link"; - - /** - * Removes extra decorations from the panel. - * - * @deprecated Base theme does not implement this style, but it is defined - * here since it has been a part of the framework before - * multiple themes were available. Use the constant provided by - * the theme you're using instead, e.g. - * {@link Reindeer#PANEL_LIGHT} or {@link Runo#PANEL_LIGHT}. - */ - @Deprecated - public static final String PANEL_LIGHT = "light"; - - /** - * Adds the connector lines between a parent node and its child nodes to - * indicate the tree hierarchy better. - */ - public static final String TREE_CONNECTORS = "connectors"; - - /** - * Clips the component so it will be constrained to its given size and not - * overflow. - */ - public static final String CLIP = "v-clip"; - -}
\ No newline at end of file diff --git a/src/com/vaadin/ui/themes/ChameleonTheme.java b/src/com/vaadin/ui/themes/ChameleonTheme.java deleted file mode 100644 index 5ae8cd4e57..0000000000 --- a/src/com/vaadin/ui/themes/ChameleonTheme.java +++ /dev/null @@ -1,365 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui.themes; - -public class ChameleonTheme extends BaseTheme { - - public static final String THEME_NAME = "chameleon"; - - /*************************************************************************** - * Label styles - **************************************************************************/ - - /** - * Large font for main application headings - */ - public static final String LABEL_H1 = "h1"; - - /** - * Large font for different sections in the application - */ - public static final String LABEL_H2 = "h2"; - - /** - * Font for sub-section headers - */ - public static final String LABEL_H3 = "h3"; - - /** - * Font for paragraphs headers - */ - public static final String LABEL_H4 = "h4"; - - /** - * Big font for important or emphasized texts - */ - public static final String LABEL_BIG = "big"; - - /** - * Small and a little lighter font - */ - public static final String LABEL_SMALL = "small"; - - /** - * Very small and lighter font for things such as footnotes and component - * specific informations. Use carefully, since this style will usually - * reduce legibility. - */ - public static final String LABEL_TINY = "tiny"; - - /** - * Adds color to the text (usually the alternate color of the theme) - */ - public static final String LABEL_COLOR = "color"; - - /** - * Adds a warning icon on the left side and a yellow background to the label - */ - public static final String LABEL_WARNING = "warning"; - - /** - * Adds an error icon on the left side and a red background to the label - */ - public static final String LABEL_ERROR = "error"; - - /** - * Adds a spinner icon on the left side of the label - */ - public static final String LABEL_LOADING = "loading"; - - /*************************************************************************** - * Button styles - **************************************************************************/ - - /** - * Default action style for buttons (the button that gets activated when - * user presses 'enter' in a form). Use sparingly, only one default button - * per screen should be visible. - */ - public static final String BUTTON_DEFAULT = "default"; - - /** - * Small sized button, use for context specific actions for example - */ - public static final String BUTTON_SMALL = "small"; - - /** - * Big button, use to get more attention for the button action - */ - public static final String BUTTON_BIG = "big"; - - /** - * Adds more padding on the sides of the button. Makes it easier for the - * user to hit the button. - */ - public static final String BUTTON_WIDE = "wide"; - - /** - * Adds more padding on the top and on the bottom of the button. Makes it - * easier for the user to hit the button. - */ - public static final String BUTTON_TALL = "tall"; - - /** - * Removes all graphics from the button, leaving only the caption and the - * icon visible. Useful for making icon-only buttons and toolbar buttons. - */ - public static final String BUTTON_BORDERLESS = "borderless"; - - /** - * Places the button icon on top of the caption. By default the icon is on - * the left side of the button caption. - */ - public static final String BUTTON_ICON_ON_TOP = "icon-on-top"; - - /** - * Places the button icon on the right side of the caption. By default the - * icon is on the left side of the button caption. - */ - public static final String BUTTON_ICON_ON_RIGHT = "icon-on-right"; - - /** - * Removes the button caption and only shows its icon - */ - public static final String BUTTON_ICON_ONLY = "icon-only"; - - /** - * Makes the button look like it is pressed down. Useful for creating a - * toggle button. - */ - public static final String BUTTON_DOWN = "down"; - - /*************************************************************************** - * TextField styles - **************************************************************************/ - - /** - * Small sized text field with small font - */ - public static final String TEXTFIELD_SMALL = "small"; - - /** - * Large sized text field with big font - */ - public static final String TEXTFIELD_BIG = "big"; - - /** - * Adds a magnifier icon on the left side of the fields text - */ - public static final String TEXTFIELD_SEARCH = "search"; - - /*************************************************************************** - * Select styles - **************************************************************************/ - - /** - * Small sized select with small font - */ - public static final String SELECT_SMALL = "small"; - - /** - * Large sized select with big font - */ - public static final String SELECT_BIG = "big"; - - /** - * Adds a magnifier icon on the left side of the fields text - */ - public static final String COMBOBOX_SEARCH = "search"; - - /** - * Adds a magnifier icon on the left side of the fields text - */ - public static final String COMBOBOX_SELECT_BUTTON = "select-button"; - - /*************************************************************************** - * DateField styles - **************************************************************************/ - - /** - * Small sized date field with small font - */ - public static final String DATEFIELD_SMALL = "small"; - - /** - * Large sized date field with big font - */ - public static final String DATEFIELD_BIG = "big"; - - /*************************************************************************** - * Panel styles - **************************************************************************/ - - /** - * Removes borders and background color from the panel - */ - public static final String PANEL_BORDERLESS = "borderless"; - - /** - * Adds a more vibrant header for the panel, using the alternate color of - * the theme, and adds slight rounded corners (not supported in all - * browsers) - */ - public static final String PANEL_BUBBLE = "bubble"; - - /** - * Removes borders and background color from the panel - */ - public static final String PANEL_LIGHT = "light"; - - /*************************************************************************** - * SplitPanel styles - **************************************************************************/ - - /** - * Reduces the split handle to a minimal size (1 pixel) - */ - public static final String SPLITPANEL_SMALL = "small"; - - /*************************************************************************** - * TabSheet styles - **************************************************************************/ - - /** - * Removes borders and background color from the tab sheet - */ - public static final String TABSHEET_BORDERLESS = "borderless"; - - /*************************************************************************** - * Accordion styles - **************************************************************************/ - - /** - * Makes the accordion background opaque (non-transparent) - */ - public static final String ACCORDION_OPAQUE = "opaque"; - - /*************************************************************************** - * Table styles - **************************************************************************/ - - /** - * Removes borders and background color from the table - */ - public static final String TABLE_BORDERLESS = "borderless"; - - /** - * Makes the column header and content font size smaller inside the table - */ - public static final String TABLE_SMALL = "small"; - - /** - * Makes the column header and content font size bigger inside the table - */ - public static final String TABLE_BIG = "big"; - - /** - * Adds a light alternate background color to even rows in the table. - */ - public static final String TABLE_STRIPED = "striped"; - - /*************************************************************************** - * ProgressIndicator styles - **************************************************************************/ - - /** - * Reduces the height of the progress bar - */ - public static final String PROGRESS_INDICATOR_SMALL = "small"; - - /** - * Increases the height of the progress bar. If the indicator is in - * indeterminate mode, shows a bigger spinner than the regular indeterminate - * indicator. - */ - public static final String PROGRESS_INDICATOR_BIG = "big"; - - /** - * Displays an indeterminate progress indicator as a bar with animated - * background stripes. This style can be used in combination with the - * "small" and "big" styles. - */ - public static final String PROGRESS_INDICATOR_INDETERMINATE_BAR = "bar"; - - /*************************************************************************** - * Window styles - **************************************************************************/ - - /** - * Sub-window style that makes the window background opaque (i.e. not - * semi-transparent). - */ - public static final String WINDOW_OPAQUE = "opaque"; - - /*************************************************************************** - * Compound styles - **************************************************************************/ - - /** - * Creates a context for a segment button control. Place buttons inside the - * segment, and add "<code>first</code>" and "<code>last</code>" style names - * for the first and last button in the segment. Then use the - * {@link #BUTTON_DOWN} style to indicate button states. - * - * E.g. - * - * <pre> - * HorizontalLayout ("segment") - * + Button ("first down") - * + Button ("down") - * + Button - * ... - * + Button ("last") - * </pre> - * - * You can also use most of the different button styles for the contained - * buttons (e.g. {@link #BUTTON_BIG}, {@link #BUTTON_ICON_ONLY} etc.). - */ - public static final String COMPOUND_HORIZONTAL_LAYOUT_SEGMENT = "segment"; - - /** - * Use this mixin-style in combination with the - * {@link #COMPOUND_HORIZONTAL_LAYOUT_SEGMENT} style to make buttons with - * the "down" style use the themes alternate color (e.g. blue instead of - * gray). - * - * E.g. - * - * <pre> - * HorizontalLayout ("segment segment-alternate") - * + Button ("first down") - * + Button ("down") - * + Button - * ... - * + Button ("last") - * </pre> - */ - public static final String COMPOUND_HORIZONTAL_LAYOUT_SEGMENT_ALTERNATE = "segment-alternate"; - - /** - * Creates an iTunes-like menu from a CssLayout or a VerticalLayout. Place - * plain Labels and NativeButtons inside the layout, and you're all set. - * - * E.g. - * - * <pre> - * CssLayout ("sidebar-menu") - * + Label - * + NativeButton - * + NativeButton - * ... - * + Label - * + NativeButton - * </pre> - */ - public static final String COMPOUND_LAYOUT_SIDEBAR_MENU = "sidebar-menu"; - - /** - * Adds a toolbar-like background for the layout, and aligns Buttons and - * Segments horizontally. Feel free to use different buttons styles inside - * the toolbar, like {@link #BUTTON_ICON_ON_TOP} and - * {@link #BUTTON_BORDERLESS} - */ - public static final String COMPOUND_CSSLAYOUT_TOOLBAR = "toolbar"; -} diff --git a/src/com/vaadin/ui/themes/LiferayTheme.java b/src/com/vaadin/ui/themes/LiferayTheme.java deleted file mode 100644 index 9b48306ac2..0000000000 --- a/src/com/vaadin/ui/themes/LiferayTheme.java +++ /dev/null @@ -1,31 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui.themes; - -public class LiferayTheme extends BaseTheme { - - public static final String THEME_NAME = "liferay"; - - /*************************************************************************** - * - * Panel styles - * - **************************************************************************/ - - /** - * Removes borders and background from the panel - */ - public static final String PANEL_LIGHT = "light"; - - /*************************************************************************** - * - * SplitPanel styles - * - **************************************************************************/ - - /** - * Reduces the split handle to a minimal size (1 pixel) - */ - public static final String SPLITPANEL_SMALL = "small"; -} diff --git a/src/com/vaadin/ui/themes/Reindeer.java b/src/com/vaadin/ui/themes/Reindeer.java deleted file mode 100644 index 7aaae8faa2..0000000000 --- a/src/com/vaadin/ui/themes/Reindeer.java +++ /dev/null @@ -1,217 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui.themes; - -import com.vaadin.ui.CssLayout; -import com.vaadin.ui.FormLayout; -import com.vaadin.ui.GridLayout; -import com.vaadin.ui.HorizontalLayout; -import com.vaadin.ui.HorizontalSplitPanel; -import com.vaadin.ui.VerticalLayout; -import com.vaadin.ui.VerticalSplitPanel; - -public class Reindeer extends BaseTheme { - - public static final String THEME_NAME = "reindeer"; - - /*************************************************************************** - * - * Label styles - * - **************************************************************************/ - - /** - * Large font for main application headings - */ - public static final String LABEL_H1 = "h1"; - - /** - * Large font for different sections in the application - */ - public static final String LABEL_H2 = "h2"; - - /** - * Small and a little lighter font - */ - public static final String LABEL_SMALL = "light"; - - /** - * @deprecated Use {@link #LABEL_SMALL} instead. - */ - @Deprecated - public static final String LABEL_LIGHT = "small"; - - /*************************************************************************** - * - * Button styles - * - **************************************************************************/ - - /** - * Default action style for buttons (the button that should get activated - * when the user presses 'enter' in a form). Use sparingly, only one default - * button per view should be visible. - */ - public static final String BUTTON_DEFAULT = "primary"; - - /** - * @deprecated Use {@link #BUTTON_DEFAULT} instead - */ - @Deprecated - public static final String BUTTON_PRIMARY = BUTTON_DEFAULT; - - /** - * Small sized button, use for context specific actions for example - */ - public static final String BUTTON_SMALL = "small"; - - /*************************************************************************** - * - * TextField styles - * - **************************************************************************/ - - /** - * Small sized text field with small font - */ - public static final String TEXTFIELD_SMALL = "small"; - - /*************************************************************************** - * - * Panel styles - * - **************************************************************************/ - - /** - * Removes borders and background color from the panel - */ - public static final String PANEL_LIGHT = "light"; - - /*************************************************************************** - * - * SplitPanel styles - * - **************************************************************************/ - - /** - * Reduces the split handle to a minimal size (1 pixel) - */ - public static final String SPLITPANEL_SMALL = "small"; - - /*************************************************************************** - * - * TabSheet styles - * - **************************************************************************/ - - /** - * Removes borders from the default tab sheet style. - */ - public static final String TABSHEET_BORDERLESS = "borderless"; - - /** - * Removes borders and background color from the tab sheet, and shows the - * tabs as a small bar. - */ - public static final String TABSHEET_SMALL = "bar"; - - /** - * @deprecated Use {@link #TABSHEET_SMALL} instead. - */ - @Deprecated - public static final String TABSHEET_BAR = TABSHEET_SMALL; - - /** - * Removes borders and background color from the tab sheet. The tabs are - * presented with minimal lines indicating the selected tab. - */ - public static final String TABSHEET_MINIMAL = "minimal"; - - /** - * Makes the tab close buttons visible only when the user is hovering over - * the tab. - */ - public static final String TABSHEET_HOVER_CLOSABLE = "hover-closable"; - - /** - * Makes the tab close buttons visible only when the tab is selected. - */ - public static final String TABSHEET_SELECTED_CLOSABLE = "selected-closable"; - - /*************************************************************************** - * - * Table styles - * - **************************************************************************/ - - /** - * Removes borders from the table - */ - public static final String TABLE_BORDERLESS = "borderless"; - - /** - * Makes the table headers dark and more prominent. - */ - public static final String TABLE_STRONG = "strong"; - - /*************************************************************************** - * - * Layout styles - * - **************************************************************************/ - - /** - * Changes the background of a layout to white. Applies to - * {@link VerticalLayout}, {@link HorizontalLayout}, {@link GridLayout}, - * {@link FormLayout}, {@link CssLayout}, {@link VerticalSplitPanel} and - * {@link HorizontalSplitPanel}. - * <p> - * <em>Does not revert any contained components back to normal if some - * parent layout has style {@link #LAYOUT_BLACK} applied.</em> - */ - public static final String LAYOUT_WHITE = "white"; - - /** - * Changes the background of a layout to a shade of blue. Applies to - * {@link VerticalLayout}, {@link HorizontalLayout}, {@link GridLayout}, - * {@link FormLayout}, {@link CssLayout}, {@link VerticalSplitPanel} and - * {@link HorizontalSplitPanel}. - * <p> - * <em>Does not revert any contained components back to normal if some - * parent layout has style {@link #LAYOUT_BLACK} applied.</em> - */ - public static final String LAYOUT_BLUE = "blue"; - - /** - * <p> - * Changes the background of a layout to almost black, and at the same time - * transforms contained components to their black style correspondents when - * available. At least texts, buttons, text fields, selects, date fields, - * tables and a few other component styles should change. - * </p> - * <p> - * Applies to {@link VerticalLayout}, {@link HorizontalLayout}, - * {@link GridLayout}, {@link FormLayout} and {@link CssLayout}. - * </p> - * - */ - public static final String LAYOUT_BLACK = "black"; - - /*************************************************************************** - * - * Window styles - * - **************************************************************************/ - - /** - * Makes the whole window white and increases the font size of the title. - */ - public static final String WINDOW_LIGHT = "light"; - - /** - * Makes the whole window black, and changes contained components in the - * same way as {@link #LAYOUT_BLACK} does. - */ - public static final String WINDOW_BLACK = "black"; -} diff --git a/src/com/vaadin/ui/themes/Runo.java b/src/com/vaadin/ui/themes/Runo.java deleted file mode 100644 index 28a19e8dcd..0000000000 --- a/src/com/vaadin/ui/themes/Runo.java +++ /dev/null @@ -1,183 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ -package com.vaadin.ui.themes; - -public class Runo extends BaseTheme { - - public static final String THEME_NAME = "runo"; - - public static String themeName() { - return THEME_NAME.toLowerCase(); - } - - /*************************************************************************** - * - * Button styles - * - **************************************************************************/ - - /** - * Small sized button, use for context specific actions for example - */ - public static final String BUTTON_SMALL = "small"; - - /** - * Big sized button, use to gather much attention for some particular action - */ - public static final String BUTTON_BIG = "big"; - - /** - * Default action style for buttons (the button that should get activated - * when the user presses 'enter' in a form). Use sparingly, only one default - * button per view should be visible. - */ - public static final String BUTTON_DEFAULT = "default"; - - /*************************************************************************** - * - * Panel styles - * - **************************************************************************/ - - /** - * Removes borders and background color from the panel - */ - public static final String PANEL_LIGHT = "light"; - - /*************************************************************************** - * - * TabSheet styles - * - **************************************************************************/ - - /** - * Smaller tabs, no border and background for content area - */ - public static final String TABSHEET_SMALL = "light"; - - /*************************************************************************** - * - * SplitPanel styles - * - **************************************************************************/ - - /** - * Reduces the width/height of the split handle. Useful when you don't want - * the split handle to touch the sides of the containing layout. - */ - public static final String SPLITPANEL_REDUCED = "rounded"; - - /** - * Reduces the visual size of the split handle to one pixel (the active drag - * size is still larger). - */ - public static final String SPLITPANEL_SMALL = "small"; - - /*************************************************************************** - * - * Label styles - * - **************************************************************************/ - - /** - * Largest title/header size. Use for main sections in your application. - */ - public static final String LABEL_H1 = "h1"; - - /** - * Similar style as in panel captions. Useful for sub-sections within a - * view. - */ - public static final String LABEL_H2 = "h2"; - - /** - * Small font size. Useful for contextual help texts and similar less - * frequently needed information. Use with modesty, since this style will be - * more harder to read due to its smaller size and contrast. - */ - public static final String LABEL_SMALL = "small"; - - /*************************************************************************** - * - * Layout styles - * - **************************************************************************/ - - /** - * An alternative background color for layouts. Use on top of white - * background (e.g. inside Panels, TabSheets and sub-windows). - */ - public static final String LAYOUT_DARKER = "darker"; - - /** - * Add a drop shadow around the layout and its contained components. - * Produces a rectangular shadow, even if the contained component would have - * a different shape. - * <p> - * Note: does not work in Internet Explorer 6 - */ - public static final String CSSLAYOUT_SHADOW = "box-shadow"; - - /** - * Adds necessary styles to the layout to make it look selectable (i.e. - * clickable). Add a click listener for the layout, and toggle the - * {@link #CSSLAYOUT_SELECTABLE_SELECTED} style for the same layout to make - * it look selected or not. - */ - public static final String CSSLAYOUT_SELECTABLE = "selectable"; - public static final String CSSLAYOUT_SELECTABLE_SELECTED = "selectable-selected"; - - /*************************************************************************** - * - * TextField styles - * - **************************************************************************/ - - /** - * Small sized text field with small font - */ - public static final String TEXTFIELD_SMALL = "small"; - - /*************************************************************************** - * - * Table styles - * - **************************************************************************/ - - /** - * Smaller header and item fonts. - */ - public static final String TABLE_SMALL = "small"; - - /** - * Removes the border and background color from the table. Removes - * alternating row background colors as well. - */ - public static final String TABLE_BORDERLESS = "borderless"; - - /*************************************************************************** - * - * Accordion styles - * - **************************************************************************/ - - /** - * A detached looking accordion, providing space around its captions and - * content. Doesn't necessarily need a Panel or other container to wrap it - * in order to make it look right. - */ - public static final String ACCORDION_LIGHT = "light"; - - /*************************************************************************** - * - * Window styles - * - **************************************************************************/ - - /** - * Smaller header and a darker background color for the window. Useful for - * smaller dialog-like windows. - */ - public static final String WINDOW_DIALOG = "dialog"; -} |